From a0a06fb08db1bb4f9a0f5a40f0178b926bea9676 Mon Sep 17 00:00:00 2001 From: "pavel.uhanov" <pavel.uhanov@demlabs.net> Date: Mon, 17 Mar 2025 09:50:48 +0000 Subject: [PATCH] backport-15029 --- dap-sdk | 2 +- modules/chain/dap_chain_policy.c | 375 ++++++++++++++++++ modules/chain/include/dap_chain_policy.h | 109 +++++ modules/common/dap_chain_datum_decree.c | 21 +- .../common/include/dap_chain_datum_decree.h | 20 +- modules/net/dap_chain_net.c | 41 +- modules/net/dap_chain_net_decree.c | 17 + modules/net/dap_chain_node_cli.c | 20 + modules/net/dap_chain_node_cli_cmd.c | 276 +++++++++++++ modules/net/include/dap_chain_node_cli_cmd.h | 5 + 10 files changed, 876 insertions(+), 10 deletions(-) create mode 100644 modules/chain/dap_chain_policy.c create mode 100644 modules/chain/include/dap_chain_policy.h diff --git a/dap-sdk b/dap-sdk index c68d541df0..1df644274f 160000 --- a/dap-sdk +++ b/dap-sdk @@ -1 +1 @@ -Subproject commit c68d541df022ed50c0daef6367ba6b10e1408c90 +Subproject commit 1df644274f2d0aecea9cc46d2c691035ec01a9c3 diff --git a/modules/chain/dap_chain_policy.c b/modules/chain/dap_chain_policy.c new file mode 100644 index 0000000000..2b6e06c41c --- /dev/null +++ b/modules/chain/dap_chain_policy.c @@ -0,0 +1,375 @@ +/* +* Authors: +* Pavel Uhanov <pavel.uhanov@demlabs.net> +* Cellframe https://cellframe.net +* DeM Labs Inc. https://demlabs.net +* Copyright (c) 2017-2025 +* All rights reserved. + +This file is part of CellFrame SDK the open source project + +CellFrame SDK is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +CellFrame SDK is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with any CellFrame SDK based project. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include "dap_chain_policy.h" +#include "dap_chain_datum_decree.h" +#include "dap_list.h" +#include "uthash.h" + +#define LOG_TAG "dap_chain_policy" + +typedef struct dap_chain_net dap_chain_net_t; + +struct net_policy_item { + uint64_t net_id; + uint32_t last_num_policy; + dap_list_t *exception_list; + dap_list_t *policies; + UT_hash_handle hh; +}; + +static struct net_policy_item *s_net_policy_items = NULL; + +/** + * @brief search net element in list by id + * @param a_net_id + * @return pointer if find, NULL if not + */ +DAP_STATIC_INLINE struct net_policy_item *s_net_item_find(uint64_t a_net_id) +{ + struct net_policy_item *l_item = NULL; + HASH_FIND_BYHASHVALUE(hh, s_net_policy_items, &a_net_id, sizeof(a_net_id), a_net_id, l_item); + return l_item; +} + +DAP_STATIC_INLINE int s_policy_num_compare(dap_list_t *a_list1, dap_list_t *a_list2) +{ + dap_chain_policy_t + *l_policy1 = a_list1->data, + *l_policy2 = a_list2->data; + if (l_policy1->type != DAP_CHAIN_POLICY_ACTIVATE || l_policy2->type != DAP_CHAIN_POLICY_ACTIVATE) { + log_it(L_WARNING, "Compare wrong policy type"); + return 0; + } + return ((dap_chain_policy_activate_t *)(l_policy1->data))->num == ((dap_chain_policy_activate_t *)(l_policy2->data))->num ? 0 : + ((dap_chain_policy_activate_t *)(l_policy1->data))->num > ((dap_chain_policy_activate_t *)(l_policy2->data))->num ? 1 : -1; +} + +DAP_STATIC_INLINE bool s_policy_is_cond(dap_chain_policy_t *a_policy) +{ + return a_policy->type == DAP_CHAIN_POLICY_ACTIVATE && + (DAP_FLAG_CHECK(a_policy->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS) || + DAP_FLAG_CHECK(a_policy->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM)); +} + +static bool s_policy_cond_activated(dap_chain_policy_activate_t *a_policy_activate, uint64_t a_flags) +{ + bool l_ret = false; + if (DAP_FLAG_CHECK(a_flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS)) { + time_t l_current_time = dap_time_now(); + l_ret |= l_current_time >= a_policy_activate->ts_start; + } + if (DAP_FLAG_CHECK(a_flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM)) { + if (!a_policy_activate->chain_union.chain) { + log_it(L_ERROR, "Chain is null in policy item with upped DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM flag"); + return l_ret; + } + l_ret |= a_policy_activate->chain_union.chain->atom_num_last >= a_policy_activate->block_start; + } + return l_ret; +} + +/** + * @brief init policy commands + * @return 0 if pass, other if error + */ +int dap_chain_policy_init() +{ + return 0; +} + +/** + * @brief deinit policy commands + */ +void dap_chain_policy_deinit() +{ + struct net_policy_item + *l_temp = NULL, + *l_current = NULL; + HASH_ITER(hh, s_net_policy_items, l_current, l_temp) { + HASH_DEL(s_net_policy_items, l_current); + dap_list_free_full(l_current->policies, NULL); + dap_list_free(l_current->exception_list); + DAP_DELETE(l_current); + } +} + +/** + * @brief add new net to policies list + * @param a_net_id + * @return 0 if pass, other if error + */ +int dap_chain_policy_net_add(uint64_t a_net_id) +{ + dap_return_val_if_pass(!a_net_id, -1); + if(s_net_item_find(a_net_id)) { + log_it(L_ERROR, "Net with id %"DAP_UINT64_FORMAT_X" already added", a_net_id); + return -2; + } + struct net_policy_item *l_new_item = DAP_NEW_Z_RET_VAL_IF_FAIL(struct net_policy_item, -3); + l_new_item->net_id = a_net_id; + HASH_ADD_BYHASHVALUE(hh, s_net_policy_items, net_id, sizeof(l_new_item->net_id), l_new_item->net_id, l_new_item); + return 0; +} + +/** + * @brief remove net from policies list + * @param a_net_id + * @return 0 if pass, other if error + */ +int dap_chain_policy_net_remove(uint64_t a_net_id) +{ + dap_return_val_if_pass(!a_net_id, -1); + struct net_policy_item *l_net_item = s_net_item_find(a_net_id); + if (!l_net_item) { + log_it(L_ERROR, "Can't find net %"DAP_UINT64_FORMAT_X" in policy list", a_net_id); + return -2; + } + HASH_DEL(s_net_policy_items, l_net_item); + dap_list_free_full(l_net_item->policies, NULL); + dap_list_free(l_net_item->exception_list); + DAP_DELETE(l_net_item); + return 0; +} + +/** + * @brief add new policy + * @param a_policy_num + * @param a_net_id net id + * @return 0 if pass, other if error + */ +int dap_chain_policy_add(dap_chain_policy_t *a_policy, uint64_t a_net_id) +{ + dap_return_val_if_pass(!a_policy, -1); + struct net_policy_item *l_net_item = s_net_item_find(a_net_id); + if (!l_net_item) { + log_it(L_ERROR, "Can't find net %"DAP_UINT64_FORMAT_X" in policy list", a_net_id); + return -2; + } + switch (a_policy->type) { + case DAP_CHAIN_POLICY_ACTIVATE: + if (dap_list_find(l_net_item->policies, a_policy, s_policy_num_compare)) { + log_it(L_ERROR, "CN-%u already added to net %"DAP_UINT64_FORMAT_X, ((dap_chain_policy_activate_t *)(a_policy->data))->num, a_net_id); + return -3; + } + l_net_item->policies = dap_list_insert_sorted(l_net_item->policies, a_policy, s_policy_num_compare); + if (!s_policy_is_cond(a_policy)) + l_net_item->last_num_policy = dap_max(((dap_chain_policy_activate_t *)(a_policy->data))->num, l_net_item->last_num_policy); + break; + case DAP_CHAIN_POLICY_DEACTIVATE: + for (size_t i = 0; i < ((dap_chain_policy_deactivate_t *)(a_policy->data))->count; ++i) { + uint32_t l_policy_num = ((dap_chain_policy_deactivate_t *)(a_policy->data))->nums[i]; + if (dap_list_find(l_net_item->exception_list, (const void *)(uintptr_t)l_policy_num, NULL)) { + log_it(L_ERROR, "CN-%u already added to exception list net %"DAP_UINT64_FORMAT_X, l_policy_num, a_net_id); + continue; + } + l_net_item->exception_list = dap_list_append(l_net_item->exception_list, (void *)(uintptr_t)l_policy_num); + } + break; + default: + log_it(L_ERROR, "Unknow policy type %u", a_policy->type); + break; + } + return 0; +} + +/** + * @brief add policy num to exception list + * @param a_policy_num + * @param a_net_id net id + * @return 0 if pass, other if error + */ +int dap_chain_policy_add_to_exception_list(uint32_t a_policy_num, uint64_t a_net_id) +{ + dap_return_val_if_pass(!a_policy_num, -1); + struct net_policy_item *l_net_item = s_net_item_find(a_net_id); + if (!l_net_item) { + log_it(L_ERROR, "Can't find net %"DAP_UINT64_FORMAT_X" in policy list", a_net_id); + return -2; + } + if (dap_list_find(l_net_item->exception_list, (const void *)(uintptr_t)a_policy_num, NULL)) { + log_it(L_ERROR, "CN-%u already added to exception list net %"DAP_UINT64_FORMAT_X, a_policy_num, a_net_id); + return -3; + } + l_net_item->exception_list = dap_list_append(l_net_item->exception_list, (void *)(uintptr_t)a_policy_num); + return 0; +} + +/** + * @brief check policy activation + * @param a_policy_num + * @param a_net_id net id + * @return true if yes, false if no + */ +bool dap_chain_policy_activated(uint32_t a_policy_num, uint64_t a_net_id) +{ + const bool l_ret_false = false; + struct net_policy_item *l_net_item = s_net_item_find(a_net_id); + dap_return_val_if_pass(!l_net_item, l_ret_false); + // exception list check + if (dap_list_find(l_net_item->exception_list, (const void *)(uintptr_t)a_policy_num, NULL)) + return l_ret_false; + // seach politics to condition check + dap_chain_policy_t *l_to_search = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_policy_t, sizeof(dap_chain_policy_t) + sizeof(dap_chain_policy_activate_t), false); + l_to_search->type = DAP_CHAIN_POLICY_ACTIVATE; + ((dap_chain_policy_activate_t *)(l_to_search->data))->num = a_policy_num; + dap_list_t *l_list_item = dap_list_find(l_net_item->policies, l_to_search, s_policy_num_compare); + DAP_DELETE(l_to_search); + if (l_list_item && s_policy_is_cond((dap_chain_policy_t *)l_list_item->data)) { + dap_chain_policy_activate_t *l_activate = (dap_chain_policy_activate_t *)((dap_chain_policy_t *)(l_list_item->data))->data; + bool l_ret = s_policy_cond_activated(l_activate, ((dap_chain_policy_t *)l_list_item->data)->flags); + if (l_ret) + l_net_item->last_num_policy = dap_max(l_activate->num, l_net_item->last_num_policy); + return l_ret; + } + // cumulative return + return a_policy_num <= l_net_item->last_num_policy; +} + +/** + * @brief find policy + * @param a_policy_num + * @param a_net_id net id + * @return true if yes, false if no + */ +dap_chain_policy_t *dap_chain_policy_find(uint32_t a_policy_num, uint64_t a_net_id) +{ + dap_return_val_if_pass(!a_policy_num, NULL); + struct net_policy_item *l_net_item = s_net_item_find(a_net_id); + dap_return_val_if_pass(!l_net_item, NULL); + + dap_chain_policy_t *l_to_search = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_policy_t, sizeof(dap_chain_policy_t) + sizeof(dap_chain_policy_activate_t), false); + l_to_search->type = DAP_CHAIN_POLICY_ACTIVATE; + ((dap_chain_policy_activate_t *)(l_to_search->data))->num = a_policy_num; + dap_list_t *l_find = dap_list_find(l_net_item->policies, l_to_search, s_policy_num_compare); + DAP_DELETE(l_to_search); + if (!l_find) { + log_it(L_DEBUG, "Can't find CN-%u in net %"DAP_UINT64_FORMAT_X, a_policy_num, a_net_id); + return NULL; + } + return (dap_chain_policy_t *)l_find->data; +} + +/** + * @brief return last policy num in enet + * @param a_net_id net id to search + * @return last num + */ +DAP_INLINE uint32_t dap_chain_policy_get_last_num(uint64_t a_net_id) +{ + struct net_policy_item *l_net_item = s_net_item_find(a_net_id); + dap_return_val_if_pass(!l_net_item, 0); + return l_net_item->last_num_policy; +} + + +json_object *dap_chain_policy_list(uint64_t a_net_id) +{ + struct net_policy_item *l_net_item = s_net_item_find(a_net_id); + dap_return_val_if_pass(!l_net_item, NULL); + json_object *l_ret = json_object_new_object(); + + dap_string_t *l_active_str = dap_string_new(""); + dap_string_t *l_inactive_str = dap_string_new(""); + if (l_net_item->last_num_policy) + dap_string_append_printf(l_active_str, "%s CN-%u ", dap_list_find(l_net_item->exception_list, (const void *)(uintptr_t)l_net_item->last_num_policy, NULL) ? "<" : "<=", l_net_item->last_num_policy); + json_object_object_add(l_ret, "cumulative active", json_object_new_string(l_active_str->str)); + dap_string_erase(l_active_str, 0, -1); + for (dap_list_t *l_iter = dap_list_first(l_net_item->policies); l_iter; l_iter = l_iter->next) { + dap_chain_policy_activate_t *l_policy_activate = (dap_chain_policy_activate_t *)((dap_chain_policy_t *)(l_iter->data))->data; + if (dap_list_find(l_net_item->exception_list, (const void *)(uintptr_t)l_policy_activate->num, NULL)) + continue; + if (s_policy_is_cond((dap_chain_policy_t *)(l_iter->data))) { + if (s_policy_cond_activated(l_policy_activate, ((dap_chain_policy_t *)(l_iter->data))->flags)) + dap_string_append_printf(l_active_str, "CN-%u ", l_policy_activate->num); + else + dap_string_append_printf(l_inactive_str, "CN-%u ", l_policy_activate->num); + } + } + json_object_object_add(l_ret, "conditional active", json_object_new_string(l_active_str->str)); + json_object_object_add(l_ret, "conditional inactive", json_object_new_string(l_inactive_str->str)); + + dap_string_free(l_active_str, true); + dap_string_erase(l_inactive_str, 0, -1); + for (dap_list_t *l_iter = dap_list_first(l_net_item->exception_list); l_iter; l_iter = l_iter->next) { + dap_string_append_printf(l_inactive_str, "CN-%u ", (uint32_t)(uintptr_t)l_iter->data); + } + json_object_object_add(l_ret, "exception list", json_object_new_string(l_inactive_str->str)); + dap_string_free(l_inactive_str, true); + return l_ret; +} + +json_object *dap_chain_policy_json_collect(dap_chain_policy_t *a_policy) +{ + dap_return_val_if_pass(!a_policy, NULL); + json_object *l_ret = json_object_new_object(); + + json_object_object_add(l_ret, "version", json_object_new_uint64(a_policy->version)); + json_object_object_add(l_ret, "type", json_object_new_string(dap_chain_policy_to_str(a_policy))); + switch (a_policy->type) { + case DAP_CHAIN_POLICY_ACTIVATE: { + dap_chain_policy_activate_t *l_policy_activate = (dap_chain_policy_activate_t *)a_policy->data; + json_object_object_add(l_ret, "num", json_object_new_uint64(l_policy_activate->num)); + if (l_policy_activate->ts_start) { + char l_time[DAP_TIME_STR_SIZE] = {}; + dap_time_to_str_rfc822(l_time, DAP_TIME_STR_SIZE - 1, l_policy_activate->ts_start); + json_object_object_add(l_ret, "ts_start", json_object_new_string(l_time)); + } else { + json_object_object_add(l_ret, "ts_start", json_object_new_int(0)); + } + json_object_object_add(l_ret, "block_start", json_object_new_uint64(l_policy_activate->block_start)); + if (l_policy_activate->block_start) { + if (!l_policy_activate->chain_union.chain) { + json_object_object_add(l_ret, "chain", json_object_new_string("ERROR pointer chain is NULL")); + } else { + char l_chain_id[32] = { }; + snprintf(l_chain_id, sizeof(l_chain_id) - 1, "0x%016"DAP_UINT64_FORMAT_x, l_policy_activate->chain_union.chain->id.uint64); + json_object_object_add(l_ret, "chain", json_object_new_string(l_chain_id)); + } + } else { + json_object_object_add(l_ret, "chain", json_object_new_string("")); + } + json_object_object_add(l_ret, "description", json_object_new_string("WIKI")); + } + break; + + case DAP_CHAIN_POLICY_DEACTIVATE: { + dap_chain_policy_deactivate_t *l_policy_deactivate = (dap_chain_policy_deactivate_t *)a_policy->data; + if (l_policy_deactivate->count) { + dap_string_t *l_nums_list = dap_string_sized_new(l_policy_deactivate->count * (sizeof(uint32_t) + 4)); + for (size_t i = 0; i < l_policy_deactivate->count; ++i) { + dap_string_append_printf(l_nums_list, "CN-%u ", l_policy_deactivate->nums[i]); + } + json_object_object_add(l_ret, "deactivate", json_object_new_string(l_nums_list->str)); + dap_string_free(l_nums_list, true); + } else { + json_object_object_add(l_ret, "deactivate", json_object_new_string("")); + } + } + break; + default: + break; + } + return l_ret; +} \ No newline at end of file diff --git a/modules/chain/include/dap_chain_policy.h b/modules/chain/include/dap_chain_policy.h new file mode 100644 index 0000000000..883e8469c5 --- /dev/null +++ b/modules/chain/include/dap_chain_policy.h @@ -0,0 +1,109 @@ +/* +* Authors: +* Pavel Uhanov <pavel.uhanov@demlabs.net> +* Cellframe https://cellframe.net +* DeM Labs Inc. https://demlabs.net +* Copyright (c) 2017-2025 +* All rights reserved. + +This file is part of CellFrame SDK the open source project + +CellFrame SDK is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +CellFrame SDK is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with any CellFrame SDK based project. If not, see <http://www.gnu.org/licenses/>. +*/ + +#pragma once + +#include "dap_common.h" +#include "dap_chain.h" + +#define DAP_CHAIN_POLICY_VERSION 1 + +#define DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS BIT(0) +#define DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM BIT(1) +#define DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_CONFIG BIT(2) + + +typedef enum { + DAP_CHAIN_POLICY_DEACTIVATE = 0, + DAP_CHAIN_POLICY_ACTIVATE +} dap_chain_policy_type_t; + +typedef struct dap_chain_policy_deactivate { + uint32_t count; + uint32_t nums[]; +} DAP_ALIGN_PACKED dap_chain_policy_deactivate_t; + + +typedef struct dap_chain_policy_activate { + uint32_t num; + int64_t ts_start; + uint64_t block_start; + union { + dap_chain_id_t chain_id; + dap_chain_t *chain; + } chain_union; + uint16_t generation; +} DAP_ALIGN_PACKED dap_chain_policy_activate_t; + +typedef struct dap_chain_policy { + uint16_t version; + uint16_t type; + uint64_t flags; + uint64_t data_size; + uint8_t data[]; +} DAP_ALIGN_PACKED dap_chain_policy_t; + +int dap_chain_policy_init(); +void dap_chain_policy_deinit(); +int dap_chain_policy_net_add(uint64_t a_net_id); +int dap_chain_policy_net_remove(uint64_t a_net_id); +int dap_chain_policy_add(dap_chain_policy_t *a_policy, uint64_t a_net_id); +int dap_chain_policy_add_to_exception_list(uint32_t a_policy_num, uint64_t a_net_id); +uint32_t dap_chain_policy_get_last_num(uint64_t a_net_id); +dap_chain_policy_t *dap_chain_policy_find(uint32_t a_policy_num, uint64_t a_net_id); +json_object *dap_chain_policy_json_collect(dap_chain_policy_t *a_policy); +json_object *dap_chain_policy_list(uint64_t a_net_id); +bool dap_chain_policy_activated(uint32_t a_policy_num, uint64_t a_net_id); + +DAP_STATIC_INLINE size_t dap_chain_policy_deactivate_calc_size(size_t a_deactivate_count) +{ + return sizeof(dap_chain_policy_t) + sizeof(dap_chain_policy_deactivate_t) + sizeof(uint32_t) * a_deactivate_count; +} + +DAP_STATIC_INLINE size_t dap_chain_policy_get_size(dap_chain_policy_t *a_policy) +{ + return a_policy ? sizeof(dap_chain_policy_t) + a_policy->data_size : 0; +} + +DAP_STATIC_INLINE const char *dap_chain_policy_to_str(dap_chain_policy_t *a_policy) +{ + if(!a_policy) + return "NULL"; + switch (a_policy->type) { + case DAP_CHAIN_POLICY_ACTIVATE: return ("DAP_CHAIN_POLICY_ACTIVATE"); + case DAP_CHAIN_POLICY_DEACTIVATE: return ("DAP_CHAIN_POLICY_DEACTIVATE"); + default: return ("UNKNOWN"); + } +} + +/** + * @brief check policy num + * @param a_num + * @return true if valid, fail if not + */ +DAP_STATIC_INLINE bool dap_chain_policy_num_is_valid(uint64_t a_num) +{ + uint32_t l_num = dap_maxval(l_num); + return (a_num && a_num <= l_num); +} \ No newline at end of file diff --git a/modules/common/dap_chain_datum_decree.c b/modules/common/dap_chain_datum_decree.c index 2f61eab671..be040aaeb6 100644 --- a/modules/common/dap_chain_datum_decree.c +++ b/modules/common/dap_chain_datum_decree.c @@ -28,6 +28,7 @@ #include "dap_chain_datum_decree.h" #include "dap_enc_base58.h" #include "dap_chain_common.h" +#include "dap_chain_policy.h" #ifdef DAP_OS_UNIX #include <arpa/inet.h> #endif @@ -177,9 +178,14 @@ 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; + return (l_tsd && dap_pkey_get_size((dap_pkey_t *)l_tsd->data) == l_tsd->size) ? (dap_pkey_t *)l_tsd->data : NULL; +} + +dap_chain_policy_t *dap_chain_datum_decree_get_policy(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_POLICY_EXECUTE); + return (l_tsd && dap_chain_policy_get_size((dap_chain_policy_t *)l_tsd->data) == l_tsd->size) ? (dap_chain_policy_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) @@ -348,7 +354,14 @@ void dap_chain_datum_decree_dump_json(json_object *a_json_out, dap_chain_datum_d 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; + break; + case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_POLICY_EXECUTE: + if (l_tsd->size != dap_chain_policy_get_size((dap_chain_policy_t *)(l_tsd->data))) { + json_object_object_add(a_json_out, "policy_type", json_object_new_string("WRONG SIZE")); + break; + } + json_object_object_add(a_json_out, "policy_type", json_object_new_string( dap_chain_policy_to_str((dap_chain_policy_t *)(l_tsd->data)))); + break; default: json_object_object_add(a_json_out, "UNKNOWN_TYPE_TSD_SECTION", json_object_new_string("")); break; diff --git a/modules/common/include/dap_chain_datum_decree.h b/modules/common/include/dap_chain_datum_decree.h index f8a49f0a39..fceff87616 100644 --- a/modules/common/include/dap_chain_datum_decree.h +++ b/modules/common/include/dap_chain_datum_decree.h @@ -27,6 +27,7 @@ #include "dap_time.h" #include "dap_list.h" #include "dap_cert.h" +#include "dap_chain_policy.h" #include <stdint.h> #define DAP_CHAIN_DATUM_DECREE_VERSION 0 @@ -75,7 +76,8 @@ DAP_STATIC_INLINE size_t dap_chain_datum_decree_get_size(dap_chain_datum_decree_ #define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_MAX_WEIGHT 0x000C #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_STAKE_PKEY_UPDATE 0x0010 +#define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_PKEY_UPDATE 0x0010 +#define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_POLICY 0x0012 // DECREE TSD types #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_VALUE 0x0100 @@ -94,7 +96,8 @@ DAP_STATIC_INLINE size_t dap_chain_datum_decree_get_size(dap_chain_datum_decree_ #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STRING 0x0115 #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_STAKE_PKEY 0x010D +#define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_PKEY 0x010D +#define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_POLICY_EXECUTE 0x010E #ifdef __cplusplus @@ -132,6 +135,8 @@ DAP_STATIC_INLINE const char *dap_chain_datum_decree_subtype_to_str(uint16_t a_d return "DECREE_COMMON_SUBTYPE_CHECK_SIGNS_STRUCTURE"; case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_PKEY_UPDATE: return "DECREE_COMMON_SUBTYPE_STAKE_UPDATE"; + case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_POLICY: + return "DECREE_COMMON_SUBTYPE_POLICY"; default: return "DECREE_SUBTYPE_UNKNOWN"; } @@ -166,6 +171,8 @@ DAP_STATIC_INLINE uint16_t dap_chain_datum_decree_type_from_str(const char *a_de 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 if (!dap_strcmp(a_decree_type, "policy")) { + return DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_POLICY; } else { return 0; } @@ -207,6 +214,8 @@ DAP_STATIC_INLINE const char *dap_chain_datum_decree_tsd_type_to_str(uint16_t a_ 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"; + case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_POLICY_EXECUTE: + return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_POLICY_EXECUTE"; default: return "DECREE_TSD_TYPE_UNKNOWN"; } @@ -315,6 +324,12 @@ int dap_chain_datum_decree_get_action(dap_chain_datum_decree_t *a_decree, uint8_ 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); +/** + * @brief get policy from decree tsd + * @param a_decree + * @return pointer to dap_chain_policy_t if find, if not or error - NULL + */ +dap_chain_policy_t *dap_chain_datum_decree_get_policy(dap_chain_datum_decree_t *a_decree); /** * @breif dap_chain_datum_decree_dump Dump information about decree @@ -358,7 +373,6 @@ void dap_chain_datum_decree_certs_dump_json(json_object * a_json_out, byte_t * a dap_chain_datum_decree_t* dap_chain_datum_decree_sign_in_cycle(dap_cert_t ** a_certs, dap_chain_datum_decree_t *a_datum_decree, size_t a_certs_count, size_t *a_total_sign_count); - #ifdef __cplusplus } #endif diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index f7cb0fea80..a1950dc342 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -108,6 +108,8 @@ #include "dap_http_ban_list_client.h" #include "dap_net.h" #include "dap_context.h" +#include "dap_chain_cs_esbocs.h" +#include "dap_chain_policy.h" #include <stdio.h> #include <sys/types.h> @@ -775,6 +777,39 @@ static dap_chain_net_t *s_net_new(const char *a_net_name, dap_config_t *a_cfg) l_net_name_str), NULL; log_it (L_NOTICE, "Node role \"%s\" selected for network '%s'", a_node_role, l_net_name_str); + + if (dap_chain_policy_net_add(l_ret->pub.id.uint64)) { + log_it(L_ERROR, "Can't add net %s to policy module", l_ret->pub.name); + DAP_DEL_MULTY(l_ret->pub.name, l_ret); + return NULL; + } + // activate policy + uint64_t l_policy_num = dap_config_get_item_uint64(a_cfg, "policy", "activate"); + dap_chain_policy_t *l_new_policy = NULL; + if (l_policy_num) { + if (!dap_chain_policy_num_is_valid(l_policy_num)) { + log_it(L_ERROR, "Can't add policy CN-%"DAP_UINT64_FORMAT_U, l_policy_num); + } else { + dap_chain_policy_t *l_new_policy = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_policy_t, sizeof(dap_chain_policy_activate_t), NULL, l_ret->pub.name, l_ret); + l_new_policy->type = DAP_CHAIN_POLICY_ACTIVATE; + l_new_policy->version = DAP_CHAIN_POLICY_VERSION; + ((dap_chain_policy_activate_t *)(l_new_policy->data))->num = l_policy_num; + l_new_policy->flags = DAP_FLAG_ADD(l_new_policy->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_CONFIG); + dap_chain_policy_add(l_new_policy, l_ret->pub.id.uint64); + } + } + // deactivate policy + uint16_t l_policy_count = 0; + const char **l_policy_str = dap_config_get_array_str(a_cfg, "policy", "deactivate", &l_policy_count); + for (uint16_t i = 0; i < l_policy_count; ++i) { + l_policy_num = strtoull(l_policy_str[i], NULL, 10); + if (!dap_chain_policy_num_is_valid(l_policy_num)) { + log_it(L_ERROR, "Can't add policy CN-%"DAP_UINT64_FORMAT_U" to exception list", l_policy_num); + } else { + dap_chain_policy_add_to_exception_list(l_policy_num, l_ret->pub.id.uint64); + } + } + l_ret->pub.config = a_cfg; l_ret->pub.gdb_groups_prefix = dap_config_get_item_str_default( a_cfg, "general", "gdb_groups_prefix", dap_config_get_item_str(a_cfg, "general", "name") ); @@ -1783,6 +1818,7 @@ void dap_chain_net_deinit() dap_chain_net_delete(l_net); } dap_http_ban_list_client_deinit(); + dap_chain_policy_deinit(); } /** @@ -1820,6 +1856,7 @@ void dap_chain_net_delete(dap_chain_net_t *a_net) dap_chain_delete(l_cur); } } + dap_chain_policy_net_remove(a_net->pub.id.uint64); HASH_DEL(s_nets_by_name, a_net); HASH_DELETE(hh2, s_nets_by_id, a_net); DAP_DELETE(a_net); @@ -2511,7 +2548,7 @@ DAP_INLINE dap_chain_net_state_t dap_chain_net_get_state (dap_chain_net_t *a_net return PVT(a_net)->state; } -dap_chain_cell_id_t * dap_chain_net_get_cur_cell( dap_chain_net_t *a_net) +dap_chain_cell_id_t *dap_chain_net_get_cur_cell( dap_chain_net_t *a_net) { return PVT(a_net)->node_info ? &PVT(a_net)->node_info->cell_id: 0; } @@ -2865,7 +2902,7 @@ int dap_chain_datum_remove(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, siz return 0; } -bool dap_chain_net_get_load_mode(dap_chain_net_t * a_net) +DAP_INLINE bool dap_chain_net_get_load_mode(dap_chain_net_t * a_net) { return PVT(a_net)->state == NET_STATE_LOADING; } diff --git a/modules/net/dap_chain_net_decree.c b/modules/net/dap_chain_net_decree.c index 509e4e6af5..cc93696978 100644 --- a/modules/net/dap_chain_net_decree.c +++ b/modules/net/dap_chain_net_decree.c @@ -33,6 +33,7 @@ #include "dap_chain_net_tx.h" #include "dap_chain_net_srv_stake_pos_delegate.h" #include "dap_http_ban_list_client.h" +#include "dap_chain_policy.h" @@ -632,6 +633,22 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain break; dap_chain_esbocs_set_emergency_validator(l_chain, l_action, l_sign_type, &l_hash); } break; + case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_POLICY: { + if (!a_apply) + break; + dap_chain_policy_t *l_policy = NULL; + if ( !(l_policy = dap_chain_datum_decree_get_policy(a_decree)) ){ + log_it(L_WARNING,"Can't get policy from decree."); + return -105; + } + l_policy = DAP_DUP_SIZE_RET_VAL_IF_FAIL(l_policy, dap_chain_policy_get_size(l_policy), -106); + if (l_policy->type == DAP_CHAIN_POLICY_ACTIVATE) { + dap_chain_policy_activate_t *l_policy_activate = (dap_chain_policy_activate_t *)l_policy->data; + if(DAP_FLAG_CHECK(l_policy->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM)) + l_policy_activate->chain_union.chain = dap_chain_find_by_id(a_net->pub.id, l_policy_activate->chain_union.chain_id); + } + return dap_chain_policy_add(l_policy, a_net->pub.id.uint64); + } default: return -1; } diff --git a/modules/net/dap_chain_node_cli.c b/modules/net/dap_chain_node_cli.c index 2ef482d1e9..2f6fe124db 100644 --- a/modules/net/dap_chain_node_cli.c +++ b/modules/net/dap_chain_node_cli.c @@ -354,6 +354,26 @@ int dap_chain_node_cli_init(dap_config_t * g_config) "\tTypes decree: fee, owners, owners_min, stake_approve, stake_invalidate, min_value, " "min_validators_count, ban, unban, reward, validator_max_weight, emergency_validators, check_signs_structure\n"); + + dap_cli_server_cmd_add ("policy", com_policy, "Policy commands", + "policy activate - prepare policy activate decree\n" + "\t[execute] - used to create policy decree, otherwise show policy decree draft\n" + "\t-net <net_name>\n" + "\t-num <policy_num>\n" + "\t[-ts_start <dd/mm/yy-H:M:S>] - date to start policy\n" + "\t[{\n\t\t-block_start <block_num> - block num to start policy\n" + "\t\t-chain <chain_name> - chain name to check blocks num\n\t}]\n" + "\t-certs <cert1[,cert2,...,certN]> - list signing certs\n" + "policy deactivate - prepare policy deactivate decree\n" + "\t[execute] - used to create policy decree, otherwise show policy decree draft\n" + "\t-net <net_name>\n" + "\t-num <num1[,num2,...,numN]> - deactivated policy list\n" + "\t-certs <cert1[,cert2,...,certN]> - list signing certs\n" + "policy find - find info about policy in net\n" + "\t-net <net_name>\n" + "\t-num <policy_num>\n" + "policy list - show all policies from table in net\n" + "\t-net <net_name>\n"); // Exit - always last! dap_cli_server_cmd_add ("exit", com_exit, "Stop application and exit", "exit\n" ); diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c index 0ed75d90af..e68f46be12 100644 --- a/modules/net/dap_chain_node_cli_cmd.c +++ b/modules/net/dap_chain_node_cli_cmd.c @@ -105,6 +105,11 @@ #include "dap_client_pvt.h" #include "dap_enc.h" #include "dap_notify_srv.h" +#include "dap_chain_wallet_cache.h" +#include "dap_chain_net_srv_stake_pos_delegate.h" +#include "dap_chain_policy.h" +#include "dap_time.h" + #include "dap_chain_net_tx.h" @@ -8211,3 +8216,274 @@ int com_exec_cmd(int argc, char **argv, void **reply) { dap_json_rpc_request_free(l_request); return 0; } + +static dap_chain_datum_decree_t *s_decree_policy_execute(dap_chain_net_t *a_net, dap_chain_policy_t *a_policy) +{ + dap_return_val_if_pass(!a_net || !a_policy, NULL); + // create updating decree + size_t l_total_tsd_size = sizeof(dap_tsd_t) + dap_chain_policy_get_size(a_policy); + + dap_chain_t *l_chain = dap_chain_net_get_chain_by_chain_type(a_net, CHAIN_TYPE_DECREE); + if (!l_chain) { + log_it(L_ERROR, "No chain supported decree datum type"); + return NULL; + } + + dap_chain_datum_decree_t *l_decree = dap_chain_datum_decree_new(a_net->pub.id, l_chain->id, *dap_chain_net_get_cur_cell(a_net), l_total_tsd_size); + if (!l_decree) { + log_it(L_CRITICAL, "%s", c_error_memory_alloc); + return NULL; + } + l_decree->header.sub_type = DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_POLICY; + dap_tsd_write((byte_t*)l_decree->data_n_signs, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_POLICY_EXECUTE, a_policy, dap_chain_policy_get_size(a_policy)); + + return l_decree; +} + +// Put the decree to mempool +static char *s_decree_policy_put(dap_chain_datum_decree_t *a_decree, dap_chain_net_t *a_net) +{ + size_t l_decree_size = dap_chain_datum_decree_get_size(a_decree); + dap_chain_datum_t *l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_DECREE, a_decree, l_decree_size); + dap_chain_t *l_chain = dap_chain_net_get_default_chain_by_chain_type(a_net, CHAIN_TYPE_DECREE); + if (!l_chain) + l_chain = dap_chain_net_get_chain_by_chain_type(a_net, CHAIN_TYPE_DECREE); + if (!l_chain) { + log_it(L_ERROR, "No chain supported decree datum type"); + return NULL; + } + // Processing will be made according to autoprocess policy + char *l_ret = dap_chain_mempool_datum_add(l_datum, l_chain, "hex"); + DAP_DELETE(l_datum); + return l_ret; +} + +int com_policy(int argc, char **argv, void **reply) { + json_object ** a_json_arr_reply = (json_object **) reply; + char **l_deactivate_array = NULL; + const char + *l_num_str = NULL, + *l_net_str = NULL, + *l_deactivate_str = NULL, + *l_chain_str = NULL, + *l_ts_start_str = NULL, + *l_block_start_str = NULL, + *l_certs_str = NULL; + size_t + l_deactivate_count = 0, + l_certs_count = 0; + dap_cert_t **l_certs = NULL; + uint64_t l_flags = 0; + bool l_execute = false; + + enum { CMD_NONE = 0, CMD_ACTIVATE, CMD_DEACTIVATE, CMD_FIND, CMD_LIST }; + int l_arg_index = 1; + + int l_cmd = CMD_NONE; + if (dap_cli_server_cmd_find_option_val(argv, 1, 2, "activate", NULL)) + l_cmd = CMD_ACTIVATE; + else if (dap_cli_server_cmd_find_option_val(argv, 1, 2, "deactivate", NULL)) + l_cmd = CMD_DEACTIVATE; + else if (dap_cli_server_cmd_find_option_val(argv, 1, 2, "find", NULL)) + l_cmd = CMD_FIND; + else if (dap_cli_server_cmd_find_option_val(argv, 1, 2, "list", NULL)) + l_cmd = CMD_LIST; + + if (l_cmd == CMD_NONE) { + dap_json_rpc_error_add(*a_json_arr_reply, -4, "Unknown subcommand"); + return -4; + } + + dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-net", &l_net_str); + + if (!l_net_str) { + dap_json_rpc_error_add(*a_json_arr_reply, -3, "Command policy require args -net"); + return -4; + } + 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, -3, "Can't find net %s", l_net_str); + return -4; + } + + if (l_cmd == CMD_LIST) { + json_object *l_answer = dap_chain_policy_list(l_net->pub.id.uint64); + json_object_array_add(*a_json_arr_reply, l_answer); + return 0; + } + + dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-num", &l_num_str); + if (!l_num_str) { + dap_json_rpc_error_add(*a_json_arr_reply, -7, "Command policy require args -num"); + return -7; + } + + void *l_policy_data = NULL; + size_t l_data_size = 0; + uint64_t l_policy_num = 0; + int l_policy_type = -1; + if (l_cmd == CMD_DEACTIVATE) { + l_policy_type = DAP_CHAIN_POLICY_DEACTIVATE; + l_deactivate_count = dap_str_symbol_count(l_num_str, ',') + 1; + l_deactivate_array = dap_strsplit(l_num_str, ",", l_deactivate_count); + l_data_size = sizeof(dap_chain_policy_deactivate_t) + l_deactivate_count * sizeof(uint32_t); + l_policy_data = DAP_NEW_Z_SIZE(void, l_data_size); + if (!l_policy_data) { + dap_json_rpc_error_add(*a_json_arr_reply, -16, "%s", c_error_memory_alloc); + dap_strfreev(l_deactivate_array); + return -16; + } + ((dap_chain_policy_deactivate_t *)l_policy_data)->count = l_deactivate_count; + for (size_t i = 0; i < l_deactivate_count; ++i) { + l_policy_num = strtoull(l_deactivate_array[i], NULL, 10); + if (!dap_chain_policy_num_is_valid(l_policy_num)) { + dap_json_rpc_error_add(*a_json_arr_reply, -16, "Policy nums sould be less or equal than %u and not equal 0", dap_maxval((uint32_t)l_policy_num)); + dap_strfreev(l_deactivate_array); + DAP_DELETE(l_policy_data); + return -16; + } + ((dap_chain_policy_deactivate_t *)l_policy_data)->nums[i] = l_policy_num; + } + dap_strfreev(l_deactivate_array); + } else { + l_policy_num = strtoull(l_num_str, NULL, 10); + if (!dap_chain_policy_num_is_valid(l_policy_num)) { + dap_json_rpc_error_add(*a_json_arr_reply, -16, "Policy num sould be less or equal than %u and not equal 0", dap_maxval((uint32_t)l_policy_num)); + return -16; + } + } + + uint32_t l_last_num = dap_chain_policy_get_last_num(l_net->pub.id.uint64); + + if (l_cmd == CMD_FIND) { + dap_chain_policy_t *l_policy = dap_chain_policy_find(l_policy_num, l_net->pub.id.uint64); + json_object *l_answer = dap_chain_policy_json_collect(l_policy); + if (l_answer) { + json_object_object_add(l_answer, "active", json_object_new_string(dap_chain_policy_activated(((dap_chain_policy_activate_t *)(l_policy->data))->num, l_net->pub.id.uint64) ? "true" : "false")); + json_object_array_add(*a_json_arr_reply, l_answer); + } else { + json_object_array_add(*a_json_arr_reply, json_object_new_string("Detailed information not exist")); + } + return 0; + } + + dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-chain", &l_chain_str); + dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-ts_start", &l_ts_start_str); + dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-block_start", &l_block_start_str); + dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-deactivate", &l_deactivate_str); + dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-certs", &l_certs_str); + l_execute = dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "execute", NULL); + + if (l_execute) { + if (!l_certs_str) { + dap_json_rpc_error_add(*a_json_arr_reply, -4, "Command 'execute' requires parameter -certs"); + DAP_DELETE(l_policy_data); + return -4; + } + dap_cert_parse_str_list(l_certs_str, &l_certs, &l_certs_count); + if (!l_certs || !l_certs_count) { + dap_json_rpc_error_add(*a_json_arr_reply, -5, "Specified certificates not found"); + DAP_DELETE(l_policy_data); + return -5; + } + } + + if (l_cmd == CMD_ACTIVATE) { + if (l_policy_num == l_last_num) { + dap_json_rpc_error_add(*a_json_arr_reply, -15, "Specified policy num already existed"); + return -15; + } + l_policy_type = DAP_CHAIN_POLICY_ACTIVATE; + l_data_size = sizeof(dap_chain_policy_activate_t); + l_policy_data = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(void, l_data_size, -5); + dap_chain_policy_activate_t *l_policy_activate = (dap_chain_policy_activate_t *)l_policy_data; + + l_policy_activate->num = l_policy_num; + if (l_ts_start_str) { + l_policy_activate->ts_start = dap_time_from_str_custom(l_ts_start_str, "%d/%m/%y-%H:%M:%S"); + if (!l_policy_activate->ts_start) { + dap_json_rpc_error_add(*a_json_arr_reply, -13, "Can't read ts_start \"%s\"", l_ts_start_str); + DAP_DELETE(l_policy_activate); + return -13; + } + l_flags = DAP_FLAG_ADD(l_flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS); + } + + if (l_block_start_str) + l_policy_activate->block_start = strtoull(l_block_start_str, NULL, 10); + + if (l_policy_activate->block_start) { + if (!l_chain_str) { + dap_json_rpc_error_add(*a_json_arr_reply, -8, "Command policy create with -block_start require args -chain"); + DAP_DELETE(l_policy_activate); + return -8; + } + dap_chain_t *l_chain = dap_chain_net_get_chain_by_name(l_net, l_chain_str); + if (!l_chain) { + dap_json_rpc_error_add(*a_json_arr_reply, -9, "%s Chain not found", l_chain_str); + DAP_DELETE(l_policy_activate); + return -9; + } + l_policy_activate->chain_union.chain = l_chain; + l_flags = DAP_FLAG_ADD(l_flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM); + } + if (!l_flags && l_policy_activate->num < l_last_num) { + dap_json_rpc_error_add(*a_json_arr_reply, -16, "Specified policy already activated by CN-%u", l_last_num); + DAP_DELETE(l_policy_activate); + return -16; + } + } + + dap_chain_policy_t *l_policy = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_policy_t, l_data_size + sizeof(dap_chain_policy_t), -5, l_policy_data); + l_policy->data_size = l_data_size; + l_policy->version = DAP_CHAIN_POLICY_VERSION; + l_policy->type = l_policy_type; + l_policy->flags = l_flags; + memcpy(l_policy->data, l_policy_data, l_policy->data_size); + DAP_DELETE(l_policy_data); + // if cmd none - only print preaparing result + if (!l_execute) { + json_object *l_answer = dap_chain_policy_json_collect(l_policy); + char l_time[DAP_TIME_STR_SIZE] = {}; + dap_time_to_str_rfc822(l_time, DAP_TIME_STR_SIZE - 1, dap_time_now()); + json_object_object_add(l_answer, "Current time", json_object_new_string(l_time)); + json_object_object_add(l_answer, "Notification", json_object_new_string("It's policy draft, check and use 'execute' command to apply")); + if (l_answer) { + json_object_array_add(*a_json_arr_reply, l_answer); + } else { + dap_json_rpc_error_add(*a_json_arr_reply, -11, "Policy draft creation failed"); + DAP_DELETE(l_policy); + return -11; + } + DAP_DELETE(l_policy); + return 0; + } + // change pointer to id to decree + if (l_policy->type == DAP_CHAIN_POLICY_ACTIVATE && ((dap_chain_policy_activate_t *)(l_policy->data))->chain_union.chain) { + ((dap_chain_policy_activate_t *)(l_policy->data))->chain_union.chain_id = ((dap_chain_policy_activate_t *)(l_policy->data))->chain_union.chain->id; + } + + dap_chain_datum_decree_t *l_decree = s_decree_policy_execute(l_net, l_policy); + DAP_DELETE(l_policy); + size_t l_total_signs_success = 0; + l_decree = dap_chain_datum_decree_sign_in_cycle(l_certs, l_decree, l_certs_count, &l_total_signs_success); + + if (!l_decree || l_total_signs_success == 0){ + dap_json_rpc_error_add(*a_json_arr_reply, -11, "Decree creation failed. Successful count of certificate signing is 0"); + return -11; + } + + char *l_decree_hash_str = NULL;; + if (!(l_decree_hash_str = s_decree_policy_put(l_decree, l_net))) { + dap_json_rpc_error_add(*a_json_arr_reply, -12, "Policy decree error"); + return -12; + } + DAP_DELETE(l_decree); + + char l_approve_str[128]; + snprintf(l_approve_str, sizeof(l_approve_str), "Policy decree %s successfully created", l_decree_hash_str); + json_object_array_add(*a_json_arr_reply, json_object_new_string(l_approve_str)); + DAP_DELETE(l_decree_hash_str); + + return 0; +} diff --git a/modules/net/include/dap_chain_node_cli_cmd.h b/modules/net/include/dap_chain_node_cli_cmd.h index 7f8a39ea7d..fba416a4c8 100644 --- a/modules/net/include/dap_chain_node_cli_cmd.h +++ b/modules/net/include/dap_chain_node_cli_cmd.h @@ -474,6 +474,11 @@ void dap_notify_new_client_send_info(dap_events_socket_t *a_es, void *a_arg); int com_exec_cmd(int argc, char **argv, void **reply); +/** + * Policy management + */ +int com_policy(int a_argc, char **a_argv, void **a_str_reply); + #ifdef __cplusplus } #endif \ No newline at end of file -- GitLab