diff --git a/dap-sdk b/dap-sdk index 0e5303fbfc0a646d157117d451ac3e98e5a5752d..6184e49af5e0e2536696eab1a520ad3536e40cc7 160000 --- a/dap-sdk +++ b/dap-sdk @@ -1 +1 @@ -Subproject commit 0e5303fbfc0a646d157117d451ac3e98e5a5752d +Subproject commit 6184e49af5e0e2536696eab1a520ad3536e40cc7 diff --git a/modules/chain/dap_chain_common.c b/modules/chain/dap_chain_common.c index 3830f97d8d8c43e0841650612cfb0d626fe307d7..388b636759917153524e12aa2148ec88fad1d5e9 100644 --- a/modules/chain/dap_chain_common.c +++ b/modules/chain/dap_chain_common.c @@ -76,25 +76,73 @@ dap_chain_addr_str_t dap_chain_addr_to_str_static_(const dap_chain_addr_t *a_add return res; } +/** + * @brief s_addr_from_str + * @param [out] a_addr - pointer to addr fill + * @param [in] a_str - string with one addr + * @return 0 if pass, other if error + */ +static int s_addr_from_str(dap_chain_addr_t *a_addr, const char *a_str) +{ + dap_return_val_if_pass(!a_addr || !a_str || !a_str[0], -1); + if (!dap_strcmp(a_str, "null") || !dap_strcmp(a_str, "0")) { + memset(a_addr, 0, sizeof(dap_chain_addr_t)); + return 0; + } + int l_ret = 0; + size_t l_ret_size = DAP_ENC_BASE58_DECODE_SIZE(strlen(a_str)); + dap_chain_addr_t *l_addr_cur = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_addr_t, l_ret_size, -2); + if (dap_enc_base58_decode(a_str, l_addr_cur) == sizeof(dap_chain_addr_t) && !dap_chain_addr_check_sum(l_addr_cur)) { + memcpy(a_addr, l_addr_cur, sizeof(dap_chain_addr_t)); + } else { + l_ret = -3; + } + DAP_DELETE(l_addr_cur); + return l_ret; +} + /** * @brief dap_chain_str_to_addr - * @param a_addr - * @return + * @param a_str - string with one addr + * @return pointer to dap_chain_addr_t if pass, if not - NULL */ -dap_chain_addr_t* dap_chain_addr_from_str(const char *a_str) +dap_chain_addr_t *dap_chain_addr_from_str(const char *a_str) { - size_t l_str_len = (a_str) ? strlen(a_str) : 0; - if(l_str_len <= 0) + dap_chain_addr_t *l_ret = DAP_NEW_Z_RET_VAL_IF_FAIL(dap_chain_addr_t, NULL); + if (s_addr_from_str(l_ret, a_str)) { + DAP_DELETE(l_ret); return NULL; - if (!dap_strcmp(a_str, "null") || !dap_strcmp(a_str, "0")) { - return DAP_NEW_Z(dap_chain_addr_t); } - size_t l_ret_size = DAP_ENC_BASE58_DECODE_SIZE(l_str_len); - dap_chain_addr_t *l_addr = DAP_NEW_Z_SIZE(dap_chain_addr_t, l_ret_size); - return ( dap_enc_base58_decode(a_str, l_addr) == sizeof(dap_chain_addr_t) ) - && !dap_chain_addr_check_sum(l_addr) - ? l_addr - : ( DAP_DELETE(l_addr), NULL ); + return l_ret; +} + + +/** + * @brief parce addrs string div by ',', alloc memory to addrs + * @param a_addr_str - ddrs string div by ',' + * @param a_addr - pointer to memory alloc + * @return addr count + */ +size_t dap_chain_addr_from_str_array(const char *a_addr_str, dap_chain_addr_t **a_addr) +{ + dap_return_val_if_pass(!a_addr_str || !a_addr, 0); + size_t l_count = dap_str_symbol_count(a_addr_str, ',') + 1; + dap_chain_addr_t *l_addr = DAP_NEW_Z_COUNT_RET_VAL_IF_FAIL(dap_chain_addr_t, l_count, 0); + char **l_addr_str_array = dap_strsplit(a_addr_str, ",", l_count); + if (!l_addr_str_array) { + DAP_DELETE(l_addr); + return 0; + } + for (size_t i = 0; i < l_count; ++i) { + if (s_addr_from_str(l_addr + i, l_addr_str_array[i])) { + DAP_DELETE(l_addr); + dap_strfreev(l_addr_str_array); + return 0; + } + } + dap_strfreev(l_addr_str_array); + *a_addr = l_addr; + return l_count; } bool dap_chain_addr_is_blank(const dap_chain_addr_t *a_addr) diff --git a/modules/chain/dap_chain_policy.c b/modules/chain/dap_chain_policy.c index 5f687069319ab8dc9f780d70e4e80d6e65bf64ad..4094f761fc14b6621f609919f301baa1932840ba 100644 --- a/modules/chain/dap_chain_policy.c +++ b/modules/chain/dap_chain_policy.c @@ -55,8 +55,41 @@ DAP_STATIC_INLINE struct policy_net_list_item *s_net_find(uint64_t a_net_id) DAP_STATIC_INLINE int s_policy_num_compare(dap_list_t *a_list1, dap_list_t *a_list2) { - return ((dap_chain_policy_t *)(a_list1->data))->activate.num == ((dap_chain_policy_t *)(a_list2->data))->activate.num ? 0 : - ((dap_chain_policy_t *)(a_list1->data))->activate.num > ((dap_chain_policy_t *)(a_list2->data))->activate.num ? 1 : -1; + 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(((dap_chain_policy_activate_t *)(a_policy->data))->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS) || + DAP_FLAG_CHECK(((dap_chain_policy_activate_t *)(a_policy->data))->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM)); +} + +static bool s_policy_cond_activated(dap_chain_policy_activate_t *a_policy_activate) +{ + bool l_ret = false; + if (DAP_FLAG_CHECK(a_policy_activate->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS)) { + time_t l_current_time = dap_time_now(); + if (l_current_time >= a_policy_activate->ts_start && (!a_policy_activate->ts_stop || l_current_time <= a_policy_activate->ts_stop)) + l_ret |= true; + } + if (DAP_FLAG_CHECK(a_policy_activate->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; + } + if ( a_policy_activate->chain_union.chain->atom_num_last >= a_policy_activate->block_start && (!a_policy_activate->block_stop || a_policy_activate->chain_union.chain->atom_num_last <= a_policy_activate->block_stop)) + l_ret |= true; + } + return l_ret; } /** @@ -122,20 +155,30 @@ int dap_chain_policy_add(dap_chain_policy_t *a_policy, uint64_t a_net_id) 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->policies, a_policy, s_policy_num_compare)) { - log_it(L_ERROR, "CN-%u already added to net %"DAP_UINT64_FORMAT_X, a_policy->activate.num, a_net_id); - return -3; + 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; } - l_net_item->policies = dap_list_insert_sorted(l_net_item->policies, a_policy, s_policy_num_compare); - for (size_t i = 0; i < a_policy->deactivate.count; ++i) { - uint32_t l_policy_num = a_policy->deactivate.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); - } - l_net_item->last_num_policy = dap_max(a_policy->activate.num, l_net_item->last_num_policy); return 0; } @@ -147,6 +190,7 @@ 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) { + dap_return_val_if_pass(!a_policy_num, -1); struct policy_net_list_item *l_net_item = s_net_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); @@ -168,40 +212,23 @@ int dap_chain_policy_add_to_exception_list(uint32_t a_policy_num, uint64_t a_net */ bool dap_chain_policy_activated(uint32_t a_policy_num, uint64_t a_net_id) { - bool l_ret = false; + const bool l_ret_false = false; struct policy_net_list_item *l_net_item = s_net_find(a_net_id); - dap_return_val_if_pass(!l_net_item, l_ret); - if (l_net_item->last_num_policy < a_policy_num) - return l_ret; + 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; + return l_ret_false; // seach politics to condition check - dap_chain_policy_t l_to_search = { - .activate.num = a_policy_num - }; - dap_list_t *l_list_item = dap_list_find(l_net_item->policies, &l_to_search, s_policy_num_compare); - if (!l_list_item) { - if (l_net_item->last_num_policy > a_policy_num) // use cumulative principle without check conditions - return true; - return l_ret; - } - dap_chain_policy_t *l_policy_item = (dap_chain_policy_t *)l_list_item->data; - // condition check - if (DAP_FLAG_CHECK(l_policy_item->activate.flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS)) { - time_t l_current_time = dap_time_now(); - if (l_current_time < l_policy_item->activate.ts_start || (l_policy_item->activate.ts_stop && l_current_time > l_policy_item->activate.ts_stop)) - return l_ret; + 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)) { + return s_policy_cond_activated((dap_chain_policy_activate_t *)((dap_chain_policy_t *)(l_list_item->data))->data); } - if (DAP_FLAG_CHECK(l_policy_item->activate.flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM)) { - if (!l_policy_item->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; - } - if ( l_policy_item->activate.chain_union.chain->atom_num_last < l_policy_item->activate.block_start || (l_policy_item->activate.block_stop && l_policy_item->activate.chain_union.chain->atom_num_last > l_policy_item->activate.block_stop)) - return l_ret; - } - return true; + // cumulative return + return a_policy_num <= l_net_item->last_num_policy; } /** @@ -212,14 +239,15 @@ bool dap_chain_policy_activated(uint32_t a_policy_num, uint64_t a_net_id) */ 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 policy_net_list_item *l_net_item = s_net_find(a_net_id); dap_return_val_if_pass(!l_net_item, NULL); - if (l_net_item->last_num_policy < a_policy_num) - return NULL; - dap_chain_policy_t l_to_search = { - .activate.num = a_policy_num - }; - dap_list_t *l_find = dap_list_find(l_net_item->policies, &l_to_search, s_policy_num_compare); + + 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; @@ -248,21 +276,30 @@ json_object *dap_chain_policy_list(uint64_t a_net_id) 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) { - if (dap_chain_policy_activated(((dap_chain_policy_t *)l_iter->data)->activate.num, a_net_id)) - dap_string_append_printf(l_active_str, "CN-%u ", ((dap_chain_policy_t *)l_iter->data)->activate.num); - else - dap_string_append_printf(l_inactive_str, "CN-%u ", ((dap_chain_policy_t *)l_iter->data)->activate.num); + 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_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, "active", json_object_new_string(l_active_str->str)); - json_object_object_add(l_ret, "inactive", json_object_new_string(l_inactive_str->str)); + 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, "in exception list", json_object_new_string(l_inactive_str->str)); + 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; } @@ -273,44 +310,58 @@ json_object *dap_chain_policy_json_collect(dap_chain_policy_t *a_policy) 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, "num", json_object_new_uint64(a_policy->activate.num)); - if (a_policy->activate.ts_start) { - char l_time[DAP_TIME_STR_SIZE] = {}; - dap_time_to_str_rfc822(l_time, DAP_TIME_STR_SIZE - 1, a_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)); - } - if (a_policy->activate.ts_stop) { - char l_time[DAP_TIME_STR_SIZE] = {}; - dap_time_to_str_rfc822(l_time, DAP_TIME_STR_SIZE - 1, a_policy->activate.ts_stop); - json_object_object_add(l_ret, "ts_stop", json_object_new_string(l_time)); - } else { - json_object_object_add(l_ret, "ts_stop", json_object_new_int(0)); - } - json_object_object_add(l_ret, "block_start", json_object_new_uint64(a_policy->activate.block_start)); - json_object_object_add(l_ret, "block_stop", json_object_new_uint64(a_policy->activate.block_stop)); - if (a_policy->activate.block_start || a_policy->activate.block_stop) { - if (!a_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, a_policy->activate.chain_union.chain->id.uint64); - json_object_object_add(l_ret, "chain", json_object_new_string(l_chain_id)); + 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)); + } + if (l_policy_activate->ts_stop) { + char l_time[DAP_TIME_STR_SIZE] = {}; + dap_time_to_str_rfc822(l_time, DAP_TIME_STR_SIZE - 1, l_policy_activate->ts_stop); + json_object_object_add(l_ret, "ts_stop", json_object_new_string(l_time)); + } else { + json_object_object_add(l_ret, "ts_stop", json_object_new_int(0)); + } + json_object_object_add(l_ret, "block_start", json_object_new_uint64(l_policy_activate->block_start)); + json_object_object_add(l_ret, "block_stop", json_object_new_uint64(l_policy_activate->block_stop)); + if (l_policy_activate->block_start || l_policy_activate->block_stop) { + 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")); } - } else { - json_object_object_add(l_ret, "chain", json_object_new_string("")); - } - if (a_policy->deactivate.count) { - dap_string_t *l_nums_list = dap_string_sized_new(a_policy->deactivate.count * (sizeof(uint32_t) + 4)); - for (size_t i = 0; i < a_policy->deactivate.count; ++i) { - dap_string_append_printf(l_nums_list, "CN-%u ", a_policy->deactivate.nums[i]); + 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("")); + } } - 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; } - json_object_object_add(l_ret, "description", json_object_new_string("WIKI")); return l_ret; } \ No newline at end of file diff --git a/modules/chain/include/dap_chain_common.h b/modules/chain/include/dap_chain_common.h index 1e758ae7c6274802cc826e989f0028ccabc7cd78..974b8e7e8b5793312e79cc177ac4f7570e822494 100644 --- a/modules/chain/include/dap_chain_common.h +++ b/modules/chain/include/dap_chain_common.h @@ -227,6 +227,7 @@ dap_chain_addr_str_t dap_chain_addr_to_str_static_(const dap_chain_addr_t *a_add #define dap_chain_addr_to_str dap_chain_addr_to_str_static dap_chain_addr_t* dap_chain_addr_from_str(const char *str); +size_t dap_chain_addr_from_str_array(const char *a_addr_str, dap_chain_addr_t **a_addr); bool dap_chain_addr_is_blank(const dap_chain_addr_t *a_addr); dap_chain_srv_uid_t dap_chain_net_srv_uid_from_str(const char* a_str); diff --git a/modules/chain/include/dap_chain_policy.h b/modules/chain/include/dap_chain_policy.h index e526e4267117fa315599c1431ca9214d22a06a16..5184524ab718af7b246b5cc23899dfa74383155c 100644 --- a/modules/chain/include/dap_chain_policy.h +++ b/modules/chain/include/dap_chain_policy.h @@ -29,32 +29,43 @@ along with any CellFrame SDK based project. If not, see <http://www.gnu.org/lic #define DAP_CHAIN_POLICY_VERSION 1 -#define DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS 1 -#define DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM (1 << 1) -#define DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_CONFIG (1 << 2) +#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) #define DAP_CHAIN_POLICY_PUBLIC_KEY_HASH_SIGN_VALIDATORS 0x1 #define DAP_CHAIN_POLICY_OUT_EXT_USE_ENSURE 0x2 +typedef enum { + DAP_CHAIN_POLICY_ACTIVATE = 0, + DAP_CHAIN_POLICY_DEACTIVATE +} dap_chain_policy_type_t; + +typedef struct dap_chain_policy_activate { + uint64_t flags; + uint32_t num; + int64_t ts_start; + int64_t ts_stop; + uint64_t block_start; + uint64_t block_stop; + union { + dap_chain_id_t chain_id; + dap_chain_t *chain; + } chain_union; +} DAP_ALIGN_PACKED dap_chain_policy_activate_t; + +typedef struct dap_chain_policy_deactivate { + uint64_t flags; + uint32_t count; + uint32_t nums[]; +} dap_chain_policy_deactivate_t; + typedef struct dap_chain_policy { uint16_t version; - struct { - uint32_t num; - uint64_t flags; - int64_t ts_start; - int64_t ts_stop; - uint64_t block_start; - uint64_t block_stop; - union { - dap_chain_id_t chain_id; - dap_chain_t *chain; - } chain_union; - } activate; - struct { - uint32_t count; - uint32_t nums[]; - } deactivate; -} dap_chain_policy_t; + uint16_t type; + uint64_t data_size; + uint8_t data[]; +} DAP_ALIGN_PACKED dap_chain_policy_t; int dap_chain_policy_init(); int dap_chain_policy_net_add(uint64_t a_net_id); @@ -67,7 +78,39 @@ 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_activate_calc_size() +{ + return sizeof(dap_chain_policy_t) + sizeof(dap_chain_policy_activate_t); +} + DAP_STATIC_INLINE size_t dap_chain_policy_get_size(dap_chain_policy_t *a_policy) { - return a_policy ? a_policy->deactivate.count * sizeof(uint32_t) + sizeof(dap_chain_policy_t) : 0; + 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); } diff --git a/modules/datum/dap_chain_datum_decree.c b/modules/datum/dap_chain_datum_decree.c index 18f4d1fd54f57a80e5dc7acbb9e37981747aa465..54ed21956470ce7d37a399f33668e9e5b22e9a29 100644 --- a/modules/datum/dap_chain_datum_decree.c +++ b/modules/datum/dap_chain_datum_decree.c @@ -397,10 +397,10 @@ void dap_chain_datum_decree_dump_json(json_object *a_json_out, dap_chain_datum_d 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_num", json_object_new_string("WRONG SIZE")); + json_object_object_add(a_json_out, "policy_type", json_object_new_string("WRONG SIZE")); break; } - json_object_object_add(a_json_out, "policy_num", json_object_new_uint64(((dap_chain_policy_t *)(l_tsd->data))->activate.num)); + 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: diff --git a/modules/datum/dap_chain_datum_tx_items.c b/modules/datum/dap_chain_datum_tx_items.c index 23ff6f240fb089de18f1c0824be865a585a221b6..9b41c87123a7b87fd99c603789243167b14c3a8b 100644 --- a/modules/datum/dap_chain_datum_tx_items.c +++ b/modules/datum/dap_chain_datum_tx_items.c @@ -376,11 +376,11 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_stake_lock( dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_emit_delegate(dap_chain_srv_uid_t a_srv_uid, uint256_t a_value, uint32_t a_signs_min, dap_hash_fast_t *a_pkey_hashes, - size_t a_pkey_hashes_count) + size_t a_pkey_hashes_count, const char *a_tag_str) { if (IS_ZERO_256(a_value)) return NULL; - size_t l_tsd_total_size = a_pkey_hashes_count * (sizeof(dap_hash_fast_t) + sizeof(dap_tsd_t)); + size_t l_tsd_total_size = a_pkey_hashes_count * (sizeof(dap_hash_fast_t) + sizeof(dap_tsd_t)) + (a_tag_str ? sizeof(dap_tsd_t) + strlen(a_tag_str) + 1 : 0); dap_chain_tx_out_cond_t *l_item = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_tx_out_cond_t, sizeof(dap_chain_tx_out_cond_t) + l_tsd_total_size, NULL); l_item->header.item_type = TX_ITEM_TYPE_OUT_COND; l_item->header.value = a_value; @@ -391,6 +391,8 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_emit_delega byte_t *l_next_tsd_ptr = l_item->tsd; for (size_t i = 0; i < a_pkey_hashes_count; i++) l_next_tsd_ptr = dap_tsd_write(l_next_tsd_ptr, DAP_CHAIN_TX_OUT_COND_TSD_HASH, a_pkey_hashes + i, sizeof(dap_hash_fast_t)); + if (a_tag_str) + l_next_tsd_ptr = dap_tsd_write(l_next_tsd_ptr, DAP_CHAIN_TX_OUT_COND_TSD_STR, (const void*)a_tag_str, strlen(a_tag_str) + 1); return l_item; } diff --git a/modules/datum/include/dap_chain_datum_token.h b/modules/datum/include/dap_chain_datum_token.h index 9c331e3844f1f5fd194b955e6b695e645a4ace21..a36b5ee5acece83ca9f1d7d6fef133c230add795 100644 --- a/modules/datum/include/dap_chain_datum_token.h +++ b/modules/datum/include/dap_chain_datum_token.h @@ -341,7 +341,6 @@ typedef struct dap_chain_datum_token_emission { #define DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_SIGNATURS 0x000E #define DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_UNIQUE_ID 0x000F #define DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_BASE_TX_HASH 0x0010 -#define DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_TAG 0x0011 // TSD sections with transfer additional params #define DAP_CHAIN_DATUM_TRANSFER_TSD_TYPE_OUT_COUNT 0x0013 diff --git a/modules/datum/include/dap_chain_datum_tx_items.h b/modules/datum/include/dap_chain_datum_tx_items.h index 8b43e5aab5bbe1499bec73f83743765b7d9f8d76..85518a3df347a2979f1fd4ec33e3852d55f165d8 100644 --- a/modules/datum/include/dap_chain_datum_tx_items.h +++ b/modules/datum/include/dap_chain_datum_tx_items.h @@ -188,7 +188,8 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_stake_lock( dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_emit_delegate(dap_chain_srv_uid_t a_srv_uid, uint256_t a_value, uint32_t a_signs_min, dap_hash_fast_t *a_pkey_hashes, - size_t a_pkey_hashes_count); + size_t a_pkey_hashes_count, const char *a_tag_str); + /** * Create item dap_chain_tx_sig_t * 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 a15e582664de1c43161e2cc1b4fa75b3101b4b22..f98f1a472f808b868f0e898383627f872aa76c4d 100644 --- a/modules/datum/include/dap_chain_datum_tx_out_cond.h +++ b/modules/datum/include/dap_chain_datum_tx_out_cond.h @@ -57,6 +57,8 @@ typedef byte_t dap_chain_tx_out_cond_subtype_t; #define DAP_CHAIN_TX_OUT_COND_TSD_ADDR 0xf001 // Chain hash #define DAP_CHAIN_TX_OUT_COND_TSD_HASH 0xf002 +// Custom str +#define DAP_CHAIN_TX_OUT_COND_TSD_STR 0xf003 /** * @struct dap_chain_tx_out diff --git a/modules/ledger/dap_chain_ledger_decree.c b/modules/ledger/dap_chain_ledger_decree.c index cb6aa5de91129dfe836206544e01d71c177e6bbf..3c84131a0c0a11879cfc2f443d160d5c2f5951ea 100644 --- a/modules/ledger/dap_chain_ledger_decree.c +++ b/modules/ledger/dap_chain_ledger_decree.c @@ -670,8 +670,11 @@ const char *l_ban_addr; return -105; } l_policy = DAP_DUP_SIZE_RET_VAL_IF_FAIL(l_policy, dap_chain_policy_get_size(l_policy), -106); - if (DAP_FLAG_CHECK(l_policy->activate.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); + 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_activate->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: diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index e9d516eeb3f9608293c59ec218c902d71bc67306..c5c51207c05216a63ad69ab99c2a55b61467fab9 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -774,19 +774,30 @@ static dap_chain_net_t *s_net_new(const char *a_net_name, dap_config_t *a_cfg) return NULL; } // activate policy - uint32_t l_policy_num = dap_config_get_item_uint32(a_cfg, "policy", "activate"); + 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) { - dap_chain_policy_t *l_new_policy = DAP_NEW_Z_RET_VAL_IF_FAIL(dap_chain_policy_t, NULL, l_ret->pub.name, l_ret); - l_new_policy->version = DAP_CHAIN_POLICY_VERSION; - l_new_policy->activate.num = l_policy_num; - l_new_policy->activate.flags = DAP_FLAG_ADD(l_new_policy->activate.flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_CONFIG); - dap_chain_policy_add(l_new_policy, l_ret->pub.id.uint64); + 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 = NULL; + l_new_policy = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_policy_t, dap_chain_policy_activate_calc_size(), NULL, l_ret->pub.name, l_ret); + l_new_policy->version = DAP_CHAIN_POLICY_VERSION; + ((dap_chain_policy_activate_t *)(l_new_policy->data))->num = l_policy_num; + ((dap_chain_policy_activate_t *)(l_new_policy->data))->flags = DAP_FLAG_ADD(((dap_chain_policy_activate_t *)(l_new_policy->data))->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) { - dap_chain_policy_add_to_exception_list(strtoll(l_policy_str[i], NULL, 10), l_ret->pub.id.uint64); + 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; diff --git a/modules/node-cli/dap_chain_node_cli.c b/modules/node-cli/dap_chain_node_cli.c index b4492e3f95e3245e0c57e90c52b1746edf8d82c3..1563297a62b241882d9e497de9a5dc892d3a983f 100644 --- a/modules/node-cli/dap_chain_node_cli.c +++ b/modules/node-cli/dap_chain_node_cli.c @@ -381,21 +381,27 @@ int dap_chain_node_cli_init(dap_config_t * g_config) "file clear_log\n" "\t CAUTION !!! This command will clear the entire log file\n"); - dap_cli_server_cmd_add ("policy", com_policy, "Policy commands", "policy [execute] - prepare or create policy execute decree\n" - "\t-net <net_name> - net name to policy apply\n" - "\t-num <policy_num> - policy num\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[-ts_stop <dd/mm/yy-H:M:S>] - date to stop policy\n" "\t{\n\t\t[-block_start <block_num>] - block num to start policy\n" "\t\t[-block_stop <block_num>] - block num to stop policy\n" "\t\t-chain <chain_name> - chain name to check blocks num\n\t}\n" - "\t[-deactivate <deactivate_nums>] - list deactivated policy, example: 1,4,6\n" - "\t[-certs <certs_name>] - list signing certs, example: foobar.root.pvt.0,foobar.root.pvt.1\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> - net name to policy search\n" - "\t-num <policy_num> - policy num\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> - net name to policy search\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/node-cli/dap_chain_node_cli_cmd.c b/modules/node-cli/dap_chain_node_cli_cmd.c index 4b62ba1375116de8e03792995d19496a693f7ec8..d64b1318ae8a42a1b30880471f3a26ac53f31487 100644 --- a/modules/node-cli/dap_chain_node_cli_cmd.c +++ b/modules/node-cli/dap_chain_node_cli_cmd.c @@ -5927,19 +5927,26 @@ int com_policy(int argc, char **argv, void **reply) { l_deactivate_count = 0, l_certs_count = 0; dap_cert_t **l_certs = NULL; + bool l_execute = false; - enum { CMD_NONE=0, CMD_EXECUTE, CMD_FIND, CMD_LIST }; + 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, "execute", NULL)) - l_cmd = CMD_EXECUTE; + 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; - dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-num", &l_num_str); + 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) { @@ -5958,32 +5965,57 @@ int com_policy(int argc, char **argv, void **reply) { 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) { - uint32_t l_policy_num = strtoull(l_num_str, NULL, 10); dap_chain_policy_t *l_policy = dap_chain_policy_find(l_policy_num, l_net->pub.id.uint64); - if (!l_policy) { - if (l_last_num < l_policy_num) { - dap_json_rpc_error_add(*a_json_arr_reply, -15, "Can't find policy CN-%u in net %s", l_policy_num, l_net_str); - return -15; - } - dap_chain_policy_t l_to_print = { - .activate.num = l_policy_num - }; - l_policy = &l_to_print; - } 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(l_policy->activate.num, l_net->pub.id.uint64) ? "true" : "false")); + 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("Empty reply")); + json_object_array_add(*a_json_arr_reply, json_object_new_string("Detailed information not exist")); } return 0; } @@ -5995,114 +6027,119 @@ int com_policy(int argc, char **argv, void **reply) { dap_cli_server_cmd_find_option_val(argv, l_arg_index, argc, "-block_stop", &l_block_stop_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_cmd == CMD_EXECUTE) { + 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 (strtoull(l_num_str, NULL, 10) == l_last_num) { - dap_json_rpc_error_add(*a_json_arr_reply, -15, "Specified policy num already existed"); - return -15; - } - - - if (l_deactivate_str) { - l_deactivate_count = dap_str_symbol_count(l_deactivate_str, ',') + 1; - l_deactivate_array = dap_strsplit(l_deactivate_str, ",", l_deactivate_count); - } - dap_chain_policy_t *l_policy = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_policy_t, sizeof(dap_chain_policy_t) + l_deactivate_count * sizeof(uint32_t), -5); - - l_policy->version = DAP_CHAIN_POLICY_VERSION; - l_policy->activate.num = strtoull(l_num_str, NULL, 10); - - l_policy->deactivate.count = l_deactivate_count; - for (size_t i = 0; i < l_deactivate_count; ++i) { - l_policy->deactivate.nums[i] = strtoul(l_deactivate_array[i], NULL, 10); - } - dap_strfreev(l_deactivate_array); - - - 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); - return -13; + 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; } - } - - if (l_ts_stop_str) { - l_policy->activate.ts_stop = dap_time_from_str_custom(l_ts_stop_str, "%d/%m/%y-%H:%M:%S"); - if (!l_policy->activate.ts_stop) { - dap_json_rpc_error_add(*a_json_arr_reply, -14, "Can't read ts_stop \"%s\"", l_ts_stop_str); - DAP_DELETE(l_policy); - return -14; + 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; + } } - if (l_policy->activate.ts_stop <= l_policy->activate.ts_start) { - dap_json_rpc_error_add(*a_json_arr_reply, -12, "ts_start should less than ts_stop"); - DAP_DELETE(l_policy); - return -12; + + if (l_ts_stop_str) { + l_policy_activate->ts_stop = dap_time_from_str_custom(l_ts_stop_str, "%d/%m/%y-%H:%M:%S"); + if (!l_policy_activate->ts_stop) { + dap_json_rpc_error_add(*a_json_arr_reply, -14, "Can't read ts_stop \"%s\"", l_ts_stop_str); + DAP_DELETE(l_policy_activate); + return -14; + } + if (l_policy_activate->ts_stop <= l_policy_activate->ts_start) { + dap_json_rpc_error_add(*a_json_arr_reply, -12, "ts_start should less than ts_stop"); + DAP_DELETE(l_policy_activate); + return -12; + } } - } - if (l_policy->activate.ts_start || l_policy->activate.ts_stop) { - l_policy->activate.flags = DAP_FLAG_ADD(l_policy->activate.flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_TS); - } + if (l_policy_activate->ts_start || l_policy_activate->ts_stop) { + l_policy_activate->flags = DAP_FLAG_ADD(l_policy_activate->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_block_stop_str) { - l_policy->activate.block_stop = strtoull(l_block_stop_str, NULL, 10); - if (l_policy->activate.block_stop <= l_policy->activate.block_start) { - dap_json_rpc_error_add(*a_json_arr_reply, -13, "block_start should less than block_stop"); - DAP_DELETE(l_policy); - return -13; + if (l_block_start_str) + l_policy_activate->block_start = strtoull(l_block_start_str, NULL, 10); + if (l_block_stop_str) { + l_policy_activate->block_stop = strtoull(l_block_stop_str, NULL, 10); + if (l_policy_activate->block_stop <= l_policy_activate->block_start) { + dap_json_rpc_error_add(*a_json_arr_reply, -13, "block_start should less than block_stop"); + DAP_DELETE(l_policy_activate); + return -13; + } } - } - - if (l_policy->activate.block_start || l_policy->activate.block_stop) { - if (!l_chain_str) { - dap_json_rpc_error_add(*a_json_arr_reply, -8, "Command policy create with -block_start or -block_stop require args -chain"); - DAP_DELETE(l_policy); - return -8; + + if (l_policy_activate->block_start || l_policy_activate->block_stop) { + if (!l_chain_str) { + dap_json_rpc_error_add(*a_json_arr_reply, -8, "Command policy create with -block_start or -block_stop 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_policy_activate->flags = DAP_FLAG_ADD(l_policy_activate->flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM); } - 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); - return -9; + if (!l_policy_activate->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; } - l_policy->activate.chain_union.chain = l_chain; - l_policy->activate.flags = DAP_FLAG_ADD(l_policy->activate.flags, DAP_CHAIN_POLICY_FLAG_ACTIVATE_BY_BLOCK_NUM); - } - if (!l_policy->activate.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); - 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; + 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_cmd == CMD_NONE) { + 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 { - json_object_array_add(*a_json_arr_reply, json_object_new_string("Empty reply")); + 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->activate.chain_union.chain) { - l_policy->activate.chain_union.chain_id = l_policy->activate.chain_union.chain->id; + 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); diff --git a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c index 465ebb9e37859de3a002d25ae8b2990c424592ed..6e735cd22f443e4c445fd4d71d38ed31b0b2bf54 100644 --- a/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c +++ b/modules/service/emit-delegate/dap_chain_net_srv_emit_delegate.c @@ -160,9 +160,9 @@ static int s_emit_delegate_verificator(dap_ledger_t *a_ledger, dap_chain_datum_t } } - if (l_signs_verified < a_cond->subtype.srv_emit_delegate.signers_minimum) { - log_it(L_WARNING, "Not enough valid signs (%u from %u) for delegated emission in tx %s", - l_signs_verified, a_cond->subtype.srv_emit_delegate.signers_minimum, dap_hash_fast_to_str_static(a_tx_in_hash)); + if (l_change_type == DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF && l_signs_verified < a_cond->subtype.srv_emit_delegate.signers_minimum) { + log_it(L_WARNING, "Not enough valid signs (%u from %u) for delegated emission", + l_signs_verified, a_cond->subtype.srv_emit_delegate.signers_minimum); return DAP_CHAIN_CS_VERIFY_CODE_NOT_ENOUGH_SIGNS; } return 0; @@ -200,7 +200,7 @@ static char *s_tx_put(dap_chain_datum_tx_t *a_tx, dap_chain_t *a_chain, const ch #define m_sign_fail(e,s) { dap_json_rpc_error_add(a_json_arr_reply, e, s); log_it(L_ERROR, "%s", s); return NULL; } -#define m_tx_fail(e,s) { DAP_DELETE(l_tx); m_sign_fail(e,s) } +#define m_tx_fail(e,s) { DAP_DELETE(l_tx); m_sign_fail(e,s); log_it(L_ERROR, "%s", s); } static dap_chain_datum_tx_t *s_emitting_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key, const char *a_token_ticker, uint256_t a_value, uint256_t a_fee, @@ -250,7 +250,7 @@ static dap_chain_datum_tx_t *s_emitting_tx_create(json_object *a_json_arr_reply, // add 'out_cond' & 'out_ext' items dap_chain_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_EMIT_DELEGATE_ID }; dap_chain_tx_out_cond_t *l_tx_out = dap_chain_datum_tx_item_out_cond_create_srv_emit_delegate( - l_uid, a_value, a_signs_min, a_pkey_hashes, a_pkey_hashes_count); + l_uid, a_value, a_signs_min, a_pkey_hashes, a_pkey_hashes_count, a_tag_str); if (!l_tx_out) m_tx_fail(ERROR_COMPOSE, "Can't compose the transaction conditional output"); dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_tx_out); @@ -283,22 +283,9 @@ static dap_chain_datum_tx_t *s_emitting_tx_create(json_object *a_json_arr_reply, if (!IS_ZERO_256(l_fee_back) && dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_fee_back, l_native_ticker) != 1) m_tx_fail(ERROR_COMPOSE, "Cant add fee back output"); } - - if (a_tag_str) { - dap_chain_tx_tsd_t *tsd_tag_item = dap_chain_datum_tx_item_tsd_create(a_tag_str, DAP_CHAIN_DATUM_EMISSION_TSD_TYPE_TAG, strlen(a_tag_str) + 1); - if (!tsd_tag_item) - m_tx_fail(ERROR_COMPOSE, "Can't compose the transaction tag"); - if (dap_chain_datum_tx_add_item(&l_tx, tsd_tag_item) != 1) { - DAP_DELETE(tsd_tag_item); - m_tx_fail(ERROR_COMPOSE, "Can't add the transaction tag"); - } - DAP_DELETE(tsd_tag_item); - } // add 'sign' item if (dap_chain_datum_tx_add_sign_item(&l_tx, a_enc_key) != 1) m_tx_fail(ERROR_COMPOSE, "Can't add sign output"); - - return l_tx; } @@ -307,34 +294,46 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_o uint256_t a_value, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* tsd_items) { dap_return_val_if_pass(!a_net || IS_ZERO_256(a_value) || IS_ZERO_256(a_fee), NULL); - // create empty transaction - dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); - dap_ledger_t *l_ledger = a_net->pub.ledger; const char *l_tx_ticker = dap_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, a_tx_in_hash); - bool l_taking_native = !dap_strcmp(a_net->pub.native_ticker, l_tx_ticker); - - uint256_t l_value = a_value, l_value_transfer = {}; // how many coins to refill + bool l_refill_native = !dap_strcmp(a_net->pub.native_ticker, l_tx_ticker); + uint256_t l_value = a_value, l_value_transfer = {}, l_fee_transfer = {}; // how many coins to transfer uint256_t l_net_fee, l_fee_total = a_fee; dap_chain_addr_t l_net_fee_addr; + // create empty transaction + dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); bool l_net_fee_used = dap_chain_net_tx_get_fee(a_net->pub.id, &l_net_fee, &l_net_fee_addr); if (l_net_fee_used && SUM_256_256(l_fee_total, l_net_fee, &l_fee_total)) m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer"); - if (SUM_256_256(l_value, l_fee_total, &l_value)) + if (l_refill_native && SUM_256_256(l_value, l_fee_total, &l_value)) m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer"); + // list of transaction with 'out' items to sell dap_chain_addr_t l_owner_addr; dap_chain_addr_fill_from_key(&l_owner_addr, a_enc_key, a_net->pub.id); - dap_list_t *l_list_fee_out = dap_chain_wallet_get_list_tx_outs_with_val(l_ledger, a_net->pub.native_ticker, - &l_owner_addr, l_value, &l_value_transfer); - if (!l_list_fee_out) - m_tx_fail(ERROR_FUNDS, "Nothing to pay for fee (not enough funds)"); - // add 'in' items to pay fee - uint256_t l_value_fee_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_fee_out); - dap_list_free_full(l_list_fee_out, NULL); - if (!EQUAL_256(l_value_fee_items, l_value_transfer)) - m_tx_fail(ERROR_COMPOSE, "Can't compose the fee transaction input"); + dap_list_t *l_list_used_out = dap_chain_wallet_get_list_tx_outs_with_val(l_ledger, l_tx_ticker, + &l_owner_addr, l_value, &l_value_transfer); + if (!l_list_used_out) + m_tx_fail(ERROR_FUNDS, "Nothing to pay for refill (not enough funds)"); + + // add 'in' items to pay for delegate + uint256_t l_value_to_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_used_out); + dap_list_free_full(l_list_used_out, NULL); + if (!EQUAL_256(l_value_to_items, l_value_transfer)) + m_tx_fail(ERROR_COMPOSE, "Can't compose the transaction input"); + + if (!l_refill_native) { + dap_list_t *l_list_fee_out = dap_chain_wallet_get_list_tx_outs_with_val(l_ledger, a_net->pub.native_ticker, + &l_owner_addr, l_fee_total, &l_fee_transfer); + if (!l_list_fee_out) + m_tx_fail(ERROR_FUNDS, "Nothing to pay for fee (not enough funds)"); + // add 'in' items to pay fee + uint256_t l_value_fee_items = dap_chain_datum_tx_add_in_item_list(&l_tx, l_list_fee_out); + dap_list_free_full(l_list_fee_out, NULL); + if (!EQUAL_256(l_value_fee_items, l_fee_transfer)) + m_tx_fail(ERROR_COMPOSE, "Can't compose the fee transaction input"); + } dap_hash_fast_t l_final_tx_hash = dap_ledger_get_final_chain_tx_hash(l_ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE, a_tx_in_hash, false); if (dap_hash_fast_is_blank(&l_final_tx_hash)) @@ -357,7 +356,6 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_o m_tx_fail(ERROR_COMPOSE, "Cant add conditionsl input"); } - // coin back uint256_t l_value_back = {}; if(SUM_256_256(l_cond_prev->header.value, a_value, &l_value_back)) { m_tx_fail(ERROR_OVERFLOW, "Integer overflow in TX composer"); @@ -373,8 +371,7 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_o } DAP_DELETE(l_out_cond); - - // add track for takeoff from conditional value + // add track for refill from conditional value dap_chain_tx_tsd_t *l_refill_tsd = dap_chain_datum_tx_item_tsd_create(&a_value, DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_REFILL, sizeof(uint256_t)); if (dap_chain_datum_tx_add_item(&l_tx, l_refill_tsd) != 1) { DAP_DELETE(l_refill_tsd); @@ -388,24 +385,30 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_o m_tx_fail(ERROR_COMPOSE, "Can't add custom TSD section item "); } + // coin back + SUBTRACT_256_256(l_value_transfer, l_value, &l_value_back); + if (!IS_ZERO_256(l_value_back)) { + int rc = l_refill_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_owner_addr, l_value_back) + : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_value_back, l_tx_ticker); + if (rc != 1) + m_tx_fail(ERROR_COMPOSE, "Cant add coin back output"); + } + // add fee items if (l_net_fee_used) { - int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_net_fee_addr, l_net_fee) - : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_net_fee_addr, l_net_fee, a_net->pub.native_ticker); + int rc = l_refill_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_net_fee_addr, l_net_fee) + : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_net_fee_addr, l_net_fee, a_net->pub.native_ticker); if (rc != 1) - m_tx_fail(ERROR_COMPOSE, "Cant add net fee output"); + m_tx_fail(ERROR_COMPOSE, "Cant add net fee output"); } if (!IS_ZERO_256(a_fee) && dap_chain_datum_tx_add_fee_item(&l_tx, a_fee) != 1) m_tx_fail(ERROR_COMPOSE, "Cant add validator fee output"); - uint256_t l_fee_back = {}; - // fee coin back - SUBTRACT_256_256(l_value_transfer, l_value, &l_fee_back); - - if (!IS_ZERO_256(l_fee_back)) { - int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, &l_owner_addr, l_fee_back) - : dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_fee_back, a_net->pub.native_ticker); - if (rc != 1) + if (!l_refill_native) { + uint256_t l_fee_back = {}; + // fee coin back + SUBTRACT_256_256(l_fee_transfer, l_fee_total, &l_fee_back); + if (!IS_ZERO_256(l_fee_back) && dap_chain_datum_tx_add_out_ext_item(&l_tx, &l_owner_addr, l_fee_back, a_net->pub.native_ticker) != 1) m_tx_fail(ERROR_COMPOSE, "Cant add fee back output"); } @@ -432,9 +435,13 @@ static bool s_is_key_present(dap_chain_tx_out_cond_t *a_cond, dap_enc_key_t *a_e } dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key, - dap_chain_addr_t **a_to_addr, uint256_t *a_value, size_t a_addr_count, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* a_tsd_items) + dap_chain_addr_t *a_to_addr, uint256_t *a_value, uint32_t a_addr_count /*!not change type!*/, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* a_tsd_items) { - dap_return_val_if_pass(!a_to_addr || !a_value || !a_addr_count || !a_enc_key || !a_tx_in_hash, NULL ); + dap_return_val_if_pass(!a_to_addr, NULL); + dap_return_val_if_pass(!a_value, NULL); + dap_return_val_if_pass(!a_addr_count, NULL); + dap_return_val_if_pass(!a_enc_key, NULL); + dap_return_val_if_pass(!a_tx_in_hash, NULL); // create empty transaction dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); @@ -499,8 +506,8 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje // add 'out' or 'out_ext' item for emission for (size_t i = 0; i < a_addr_count; ++i) { - int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, a_to_addr[i], a_value[i]) : - dap_chain_datum_tx_add_out_ext_item(&l_tx, a_to_addr[i], a_value[i], l_tx_ticker); + int rc = l_taking_native ? dap_chain_datum_tx_add_out_item(&l_tx, a_to_addr + i, a_value[i]) : + dap_chain_datum_tx_add_out_ext_item(&l_tx, a_to_addr + i, a_value[i], l_tx_ticker); if (rc != 1) m_tx_fail(ERROR_COMPOSE, "Cant add tx output"); } @@ -512,12 +519,18 @@ dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_obje if (!l_out_cond) m_tx_fail(ERROR_MEMORY, c_error_memory_alloc); l_out_cond->header.value = l_value_back; + if (-1 == dap_chain_datum_tx_add_item(&l_tx, (const uint8_t *)l_out_cond)) { DAP_DELETE(l_out_cond); m_tx_fail(ERROR_COMPOSE, "Cant add emission cond output"); } DAP_DELETE(l_out_cond); + if (a_addr_count > 1) { + dap_chain_tx_tsd_t * l_addr_cnt_tsd = dap_chain_datum_tx_item_tsd_create(&a_addr_count, DAP_CHAIN_DATUM_TRANSFER_TSD_TYPE_OUT_COUNT, sizeof(uint32_t)); + if (!l_addr_cnt_tsd || dap_chain_datum_tx_add_item(&l_tx, l_addr_cnt_tsd) != 1 ) + m_tx_fail(ERROR_COMPOSE, "Can't add TSD section item with addr count"); + } // add track for takeoff from conditional value dap_chain_tx_tsd_t *l_takeoff_tsd = dap_chain_datum_tx_item_tsd_create(&l_value, DAP_CHAIN_NET_SRV_EMIT_DELEGATE_TSD_WRITEOFF, sizeof(uint256_t)); @@ -822,7 +835,7 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object ** const char *l_tx_in_hash_str = NULL, *l_addr_str = NULL, *l_value_str = NULL, *l_wallet_str = NULL, *l_fee_str = NULL; uint256_t *l_value = NULL; - dap_chain_addr_t **l_to_addr = NULL; + dap_chain_addr_t *l_to_addr = NULL; uint32_t l_addr_el_count = 0, // not change type! use in batching TSD section l_value_el_count = 0; @@ -880,10 +893,11 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object ** return ERROR_PARAM; } - l_addr_el_count = dap_str_symbol_count(l_addr_str, ',') + 1; + l_addr_el_count = dap_chain_addr_from_str_array(l_addr_str, &l_to_addr); l_value_el_count = dap_str_symbol_count(l_value_str, ',') + 1; if (l_addr_el_count != l_value_el_count) { + DAP_DELETE(l_to_addr); dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "num of '-to_addr' and '-value' should be equal"); return ERROR_VALUE; } @@ -910,43 +924,9 @@ static int s_cli_take(int a_argc, char **a_argv, int a_arg_index, json_object ** } dap_strfreev(l_value_array); - l_to_addr = DAP_NEW_Z_COUNT(dap_chain_addr_t *, l_addr_el_count); - if (!l_to_addr) { - log_it(L_CRITICAL, "%s", c_error_memory_alloc); - DAP_DELETE(l_value); - dap_json_rpc_error_add(*a_json_arr_reply, ERROR_MEMORY, c_error_memory_alloc); - return ERROR_MEMORY; - } - char **l_to_addr_str_array = dap_strsplit(l_addr_str, ",", l_addr_el_count); - if (!l_to_addr_str_array) { - DAP_DEL_MULTY(l_to_addr, l_value); - dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PARAM, "Can't read '-to_addr' arg"); - return ERROR_PARAM; - } - for (size_t i = 0; i < l_addr_el_count; ++i) { - l_to_addr[i] = dap_chain_addr_from_str(l_to_addr_str_array[i]); - if(!l_to_addr[i]) { - DAP_DEL_ARRAY(l_to_addr, i); - DAP_DEL_MULTY(l_to_addr, l_value); - dap_strfreev(l_to_addr_str_array); - dap_json_rpc_error_add(*a_json_arr_reply, ERROR_VALUE, "Incorrect addr format for string %s", l_addr_str); - return ERROR_VALUE; - } - } - dap_strfreev(l_to_addr_str_array); - - - if (l_addr_el_count > 1) { - l_tsd_list = dap_list_append(l_tsd_list, dap_chain_datum_tx_item_tsd_create(&l_addr_el_count, DAP_CHAIN_DATUM_TRANSFER_TSD_TYPE_OUT_COUNT, sizeof(uint32_t))); - if (!l_tsd_list) { - dap_json_rpc_error_add(*a_json_arr_reply, ERROR_COMPOSE, "Internal error in tsd list creation"); - return ERROR_COMPOSE; - } - } - // Create emission from conditional transaction + dap_chain_datum_tx_t *l_tx = dap_chain_net_srv_emit_delegate_taking_tx_create(*a_json_arr_reply, a_net, l_enc_key, l_to_addr, l_value, l_addr_el_count, l_fee, &l_tx_in_hash, l_tsd_list); - DAP_DEL_ARRAY(l_to_addr, l_addr_el_count); DAP_DEL_MULTY(l_value, l_to_addr, l_enc_key); dap_list_free_full(l_tsd_list, NULL); if (!l_tx) { @@ -1073,6 +1053,7 @@ static int s_cli_info(int a_argc, char **a_argv, int a_arg_index, json_object ** json_object *l_jobj_token = json_object_new_object(); json_object *l_jobj_take_verify = json_object_new_object(); json_object *l_jobj_pkey_hashes = json_object_new_array(); + json_object *l_jobj_tags = json_object_new_array(); json_object *l_json_jobj_info = json_object_new_object(); bool l_is_base_hash_type = dap_strcmp(a_hash_out_type, "hex"); @@ -1092,11 +1073,15 @@ static int s_cli_info(int a_argc, char **a_argv, int a_arg_index, json_object ** if (l_tsd->type == DAP_CHAIN_TX_OUT_COND_TSD_HASH && l_tsd->size == sizeof(dap_hash_fast_t)) { json_object_array_add(l_jobj_pkey_hashes, json_object_new_string(l_is_base_hash_type ? dap_enc_base58_encode_hash_to_str_static((const dap_chain_hash_fast_t *)l_tsd->data) : dap_hash_fast_to_str_static((const dap_chain_hash_fast_t *)l_tsd->data))); } + if (l_tsd->type == DAP_CHAIN_TX_OUT_COND_TSD_STR) { + json_object_array_add(l_jobj_tags, json_object_new_string((char*)(l_tsd->data))); + } } json_object_object_add(l_jobj_take_verify, "owner_hashes", l_jobj_pkey_hashes); // result block json_object_object_add(l_json_jobj_info, "tx_hash", json_object_new_string(l_is_base_hash_type ? dap_enc_base58_encode_hash_to_str_static(&l_tx_hash) : dap_hash_fast_to_str_static(&l_tx_hash))); json_object_object_add(l_json_jobj_info, "tx_hash_final", json_object_new_string(l_is_base_hash_type ? dap_enc_base58_encode_hash_to_str_static(&l_final_tx_hash) : dap_hash_fast_to_str_static(&l_final_tx_hash))); + json_object_object_add(l_json_jobj_info, "tags", l_jobj_tags); json_object_object_add(l_json_jobj_info, "balance", l_jobj_balance); json_object_object_add(l_json_jobj_info, "take_verify", l_jobj_take_verify); json_object_object_add(l_json_jobj_info, "token", l_jobj_token); diff --git a/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h b/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h index 1e14d527bfe61b6d64b9a3a222462ac3bc1c37de..79f5a47142ec6509eeb39c49788690c8ba45ab3e 100644 --- a/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h +++ b/modules/service/emit-delegate/include/dap_chain_net_srv_emit_delegate.h @@ -14,7 +14,7 @@ int dap_chain_net_srv_emit_delegate_init(); void dap_chain_net_srv_emit_delegate_deinit(); dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_taking_tx_create(json_object *a_json_arr_rweply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key, - dap_chain_addr_t **a_addr_to, uint256_t *a_value, size_t a_addr_count, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t *tsd_items); + dap_chain_addr_t *a_addr_to, uint256_t *a_value, uint32_t a_addr_count, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t *tsd_items); dap_chain_datum_tx_t *dap_chain_net_srv_emit_delegate_refilling_tx_create(json_object *a_json_arr_reply, dap_chain_net_t *a_net, dap_enc_key_t *a_enc_key, uint256_t a_value, uint256_t a_fee, dap_hash_fast_t *a_tx_in_hash, dap_list_t* tsd_items);