diff --git a/dap-sdk b/dap-sdk index 5a92226d095b1df1996c1122de2dbe636b139ffc..5c58976798909feee535cbff8b2b7e80028aad1c 160000 --- a/dap-sdk +++ b/dap-sdk @@ -1 +1 @@ -Subproject commit 5a92226d095b1df1996c1122de2dbe636b139ffc +Subproject commit 5c58976798909feee535cbff8b2b7e80028aad1c diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c index a4d6e53543ca655200af7d631f6aa34e91502328..9ed29c5e98dff8ed0f00037751b948b19843700d 100644 --- a/modules/chain/dap_chain.c +++ b/modules/chain/dap_chain.c @@ -727,7 +727,7 @@ void dap_chain_atom_confirmed_notify_add(dap_chain_t *a_chain, dap_chain_callbac * @param a_atom_hash * @return */ -bool dap_chain_get_atom_last_hash_num(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_atom_hash, uint64_t *a_atom_num) +bool dap_chain_get_atom_last_hash_num_ts(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_atom_hash, uint64_t *a_atom_num, dap_time_t *a_atom_timestamp) { dap_return_val_if_fail(a_atom_hash || a_atom_num, false); dap_chain_atom_iter_t *l_iter = a_chain->callback_atom_iter_create(a_chain, a_cell_id, NULL); @@ -738,6 +738,8 @@ bool dap_chain_get_atom_last_hash_num(dap_chain_t *a_chain, dap_chain_cell_id_t *a_atom_hash = l_iter->cur_hash ? *l_iter->cur_hash : (dap_hash_fast_t){0}; if (a_atom_num) *a_atom_num = l_iter->cur_num; + if (a_atom_timestamp) + *a_atom_timestamp = l_iter->cur_ts; a_chain->callback_atom_iter_delete(l_iter); return true; } diff --git a/modules/chain/dap_chain_srv.c b/modules/chain/dap_chain_srv.c index 9a405ce2d694e8652f260c04d4290547f866abaa..cfd839651c307b6766b0bd6c2aec2eff915925f6 100644 --- a/modules/chain/dap_chain_srv.c +++ b/modules/chain/dap_chain_srv.c @@ -197,14 +197,23 @@ int dap_chain_srv_purge_all(dap_chain_net_id_t a_net_id) * @brief dap_chain_srv_hardfork_all * @param a_net_id */ -void dap_chain_srv_hardfork_all(dap_chain_net_id_t a_net_id) +dap_chain_srv_hardfork_state_t *dap_chain_srv_hardfork_all(dap_chain_net_id_t a_net_id) { + dap_chain_srv_hardfork_state_t *ret = NULL; pthread_mutex_lock(&s_srv_list_mutex); for (struct service_list *it = s_srv_list; it; it = it->hh.next) { - if (s_net_service_find(it, a_net_id) && it->callbacks.hardfork) - it->callbacks.hardfork(a_net_id); + if (s_net_service_find(it, a_net_id) && it->callbacks.hardfork_prepare) { + dap_chain_srv_hardfork_state_t *l_state = DAP_NEW_Z(dap_chain_srv_hardfork_state_t), *cur, *tmp; + if (!l_state) + DL_FOREACH_SAFE(ret, cur, tmp) + DAP_DELETE(cur); + l_state->uid = it->uuid; + l_state->data = it->callbacks.hardfork_prepare(a_net_id, &l_state->size, &l_state->count); + DL_APPEND(ret, l_state); + } } pthread_mutex_unlock(&s_srv_list_mutex); + return ret; } /** diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h index f2fa23094a003f1621b2be0cc640e82d434a873b..467e1b01bbac2863e86fba89f651aa464b813454 100644 --- a/modules/chain/include/dap_chain.h +++ b/modules/chain/include/dap_chain.h @@ -33,7 +33,7 @@ #ifdef DAP_TPS_TEST #define DAP_CHAIN_ATOM_MAX_SIZE (100 * 1024 * 1024) #else -#define DAP_CHAIN_ATOM_MAX_SIZE (256 * 1024) // 256 KB +#define DAP_CHAIN_ATOM_MAX_SIZE (8 * 1024 * 1024) // 8 MB #endif typedef struct dap_chain dap_chain_t; @@ -240,6 +240,7 @@ typedef struct dap_chain { dap_config_t *config; + struct hardfork_states *hardfork_data; void * _pvt; // private data void * _inheritor; // inheritor object } dap_chain_t; @@ -275,6 +276,7 @@ typedef struct dap_chain_pvt { char *cs_type; bool cs_started; bool need_reorder; + } dap_chain_pvt_t; #define DAP_CHAIN_PVT(a) ((dap_chain_pvt_t *)a->_pvt) @@ -315,10 +317,10 @@ void dap_chain_datum_notify(dap_chain_cell_t *a_chain_cell, dap_hash_fast_t *a_ void dap_chain_datum_removed_notify(dap_chain_cell_t *a_chain_cell, dap_hash_fast_t *a_hash); void dap_chain_atom_add_from_threshold(dap_chain_t *a_chain); dap_chain_atom_ptr_t dap_chain_get_atom_by_hash(dap_chain_t * a_chain, dap_chain_hash_fast_t * a_atom_hash, size_t * a_atom_size); -bool dap_chain_get_atom_last_hash_num(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_atom_hash, uint64_t *a_atom_num); +bool dap_chain_get_atom_last_hash_num_ts(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_atom_hash, uint64_t *a_atom_num, dap_time_t *a_atom_timestamp); DAP_STATIC_INLINE bool dap_chain_get_atom_last_hash(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_atom_hash) { - return dap_chain_get_atom_last_hash_num(a_chain, a_cell_id, a_atom_hash, NULL); + return dap_chain_get_atom_last_hash_num_ts(a_chain, a_cell_id, a_atom_hash, NULL, NULL); } ssize_t dap_chain_atom_save(dap_chain_cell_t *a_chain_cell, const uint8_t *a_atom, size_t a_atom_size, dap_hash_fast_t *a_new_atom_hash); int dap_cert_chain_file_save(dap_chain_datum_t *datum, char *net_name); diff --git a/modules/chain/include/dap_chain_srv.h b/modules/chain/include/dap_chain_srv.h index 1ca29339d9f647059cca62b54361ddd682f04f7a..91be1dda009513ffeb53c7e4829bd23049cc28e2 100644 --- a/modules/chain/include/dap_chain_srv.h +++ b/modules/chain/include/dap_chain_srv.h @@ -41,8 +41,10 @@ typedef void (*dap_chain_srv_callback_decree_t)(dap_chain_net_id_t a_net_id, int typedef int (*dap_chain_srv_callback_purge_t)(dap_chain_net_id_t a_net_id); // Get fee service callback typedef json_object * (*dap_chain_srv_callback_get_fee)(dap_chain_net_id_t a_net_id); -// Hardfork service callback -typedef int (*dap_chain_srv_callback_hardfork_t)(dap_chain_net_id_t a_net_id); +// Hardfork prepare service callback +typedef byte_t * (*dap_chain_srv_callback_hardfork_prepare_t)(dap_chain_net_id_t a_net_id, uint64_t *a_state_size, uint32_t *a_state_count); +// Hardfork data load service callback +typedef int (*dap_chain_srv_callback_hardfork_data_t)(dap_chain_net_id_t a_net_id, byte_t *a_state, uint64_t a_state_size, uint32_t a_state_count); // Delete service callback typedef void (*dap_chain_srv_callback_delete_t)(void *); @@ -55,13 +57,23 @@ typedef struct dap_chain_static_srv_callbacks { dap_chain_srv_callback_purge_t purge; // Get service fee dap_chain_srv_callback_get_fee get_fee_descr; - // Hardfork - dap_chain_srv_callback_hardfork_t hardfork; + // Hardfork prepare + dap_chain_srv_callback_hardfork_prepare_t hardfork_prepare; + // Hardfork data load + dap_chain_srv_callback_hardfork_data_t hardfork_load; // Delete for internal service clean exit dap_chain_srv_callback_delete_t delete; // And no more =) } dap_chain_static_srv_callbacks_t; +typedef struct dap_chain_srv_hardfork_state { + dap_chain_srv_uid_t uid; + byte_t *data; + uint64_t size; + uint32_t count; + struct dap_chain_srv_hardfork_state *prev, *next; +} dap_chain_srv_hardfork_state_t; + // Fees section typedef enum dap_chain_srv_fee_tsd_type { TSD_FEE = 0x0001, @@ -107,5 +119,5 @@ dap_list_t *dap_chain_srv_list(dap_chain_net_id_t a_net_id); int dap_chain_srv_purge(dap_chain_net_id_t a_net_id, dap_chain_srv_uid_t a_srv_uid); int dap_chain_srv_purge_all(dap_chain_net_id_t a_net_id); -void dap_chain_srv_hardfork_all(dap_chain_net_id_t a_net_id); +dap_chain_srv_hardfork_state_t *dap_chain_srv_hardfork_all(dap_chain_net_id_t a_net_id); json_object *dap_chain_srv_get_fees(dap_chain_net_id_t a_net_id); diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c index ed9be96ca95993a2c53268eff58167f0e02ac73f..3c9d78d16e0f172639f564dbf2a50b104c900ea0 100644 --- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c +++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c @@ -41,6 +41,8 @@ along with any CellFrame SDK based project. If not, see <http://www.gnu.org/lic #define LOG_TAG "dap_chain_cs_esbocs" +static const dap_chain_cell_id_t c_cell_id_hardfork = { .uint64 = INT64_MIN }; // 0x800... + enum s_esbocs_session_state { DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_START, DAP_CHAIN_ESBOCS_SESSION_STATE_WAIT_PROC, @@ -213,11 +215,11 @@ void dap_chain_cs_esbocs_deinit(void) { } -void dap_chain_esbocs_change_debug_mode(dap_chain_t *a_chain, bool a_enable){ - dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain); - dap_chain_esbocs_t *l_esbocs = l_blocks->_inheritor; - dap_chain_esbocs_pvt_t * l_esbocs_pvt = PVT(l_esbocs); - l_esbocs_pvt->debug = a_enable; +void dap_chain_esbocs_change_debug_mode(dap_chain_t *a_chain, bool a_enable) +{ + dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain); + dap_chain_esbocs_t *l_esbocs = DAP_CHAIN_ESBOCS(l_blocks); + PVT(l_esbocs)->debug = a_enable; } static int s_callback_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg) @@ -736,6 +738,16 @@ int dap_chain_esbocs_set_min_validators_count(dap_chain_t *a_chain, uint16_t a_n return 0; } +int dap_chain_esbocs_set_hardfork_prepare(dap_chain_t *a_chain, uint64_t a_block_num, dap_list_t *a_trusted_addrs) +{ + uint64_t l_last_num = a_chain->callback_count_atom(a_chain); + dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain); + dap_chain_esbocs_t *l_esbocs = DAP_CHAIN_ESBOCS(l_blocks); + l_esbocs->hardfork_from = dap_max(l_last_num, a_block_num); + l_esbocs->hardfork_trusted_addrs = a_trusted_addrs; + return a_block_num && a_block_num < l_last_num ? 1 : 0; +} + static int s_callback_purge(dap_chain_t *a_chain) { dap_return_val_if_fail(a_chain && !strcmp(dap_chain_get_cs_type(a_chain), DAP_CHAIN_ESBOCS_CS_TYPE_STR), -1); @@ -1121,7 +1133,7 @@ static bool s_session_round_new(void *a_arg) a_session->ts_stage_entry = 0; dap_hash_fast_t l_last_block_hash; - dap_chain_get_atom_last_hash(a_session->chain, c_dap_chain_cell_id_null, &l_last_block_hash); + dap_chain_get_atom_last_hash(a_session->chain, a_session->is_hardfork ? c_dap_chain_cell_id_null : c_cell_id_hardfork, &l_last_block_hash); if (!dap_hash_fast_compare(&l_last_block_hash, &a_session->cur_round.last_block_hash) || (!dap_hash_fast_is_blank(&l_last_block_hash) && dap_hash_fast_is_blank(&a_session->cur_round.last_block_hash))) { @@ -1192,6 +1204,13 @@ static bool s_session_round_new(void *a_arg) a_session->new_round_enqueued = false; a_session->sync_failed = false; a_session->listen_ensure = 0; + uint64_t l_cur_atom_count = a_session->chain->callback_count_atom(a_session->chain); + a_session->is_hardfork = a_session->esbocs->hardfork_from && l_cur_atom_count >= a_session->esbocs->hardfork_from; + if (l_cur_atom_count && l_cur_atom_count == a_session->esbocs->hardfork_from) { + dap_time_t l_last_block_timestamp = 0; + dap_chain_get_atom_last_hash_num_ts(a_session->chain, c_cell_id_hardfork, NULL, NULL, &l_last_block_timestamp); + dap_chain_node_hardfork_prepare(a_session->chain, l_last_block_timestamp, a_session->esbocs->hardfork_trusted_addrs); + } return false; } @@ -1648,7 +1667,10 @@ static void s_session_candidate_submit(dap_chain_esbocs_session_t *a_session) dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(l_chain); size_t l_candidate_size = 0; dap_hash_fast_t l_candidate_hash = {0}; - dap_chain_node_mempool_process_all(a_session->chain, false); + if (a_session->is_hardfork) + dap_chain_node_hardfork_process(a_session->chain); + else + dap_chain_node_mempool_process_all(a_session->chain, false); dap_chain_block_t *l_candidate = l_blocks->callback_new_block_move(l_blocks, &l_candidate_size); if (l_candidate && l_candidate_size) { if (PVT(a_session->esbocs)->emergency_mode) @@ -1707,8 +1729,7 @@ static void s_session_candidate_verify(dap_chain_esbocs_session_t *a_session, da } // Process candidate a_session->processing_candidate = a_candidate; - dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_session->chain); - dap_chain_atom_verify_res_t l_verify_status = l_blocks->chain->callback_atom_verify(l_blocks->chain, a_candidate, a_candidate_size, a_candidate_hash); + dap_chain_atom_verify_res_t l_verify_status = a_session->chain->callback_atom_verify(a_session->chain, a_candidate, a_candidate_size, a_candidate_hash); if (l_verify_status == ATOM_ACCEPT || l_verify_status == ATOM_FORK) { // validation - OK, gen event Approve s_message_send(a_session, DAP_CHAIN_ESBOCS_MSG_TYPE_APPROVE, a_candidate_hash, @@ -2837,9 +2858,17 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl dap_chain_esbocs_t *l_esbocs = DAP_CHAIN_ESBOCS(a_blocks); dap_chain_esbocs_pvt_t *l_esbocs_pvt = PVT(l_esbocs); - if (l_esbocs->session && l_esbocs->session->processing_candidate == a_block) + if (l_esbocs->session && l_esbocs->session->processing_candidate == a_block) { // It's a block candidate, don't check signs - return a_block->hdr.version > 1 ? 0 : -3; + if (a_block->hdr.version <= 1) { + log_it(L_WARNING, "Illegal block version %d", a_block->hdr.version); + return -3; + } + if (a_blocks->is_hardfork_state) { + // Addtionally verify datums vs internal states + + } + } size_t l_block_size = a_block_size; // /* Can't calc it for many old bugged blocks */ dap_chain_block_get_size(a_block); size_t l_signs_count = 0; diff --git a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h index 643bcc2c1f192acdc4277d741cac22bfcdd11216..c86591e1b449daf6a4aa4beb6a036140c6f0d324 100644 --- a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h +++ b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h @@ -23,7 +23,6 @@ along with any CellFrame SDK based project. If not, see <http://www.gnu.org/lic */ #pragma once -#include "dap_timerfd.h" #include "dap_chain.h" #include "dap_chain_block.h" #include "dap_chain_cs_blocks.h" @@ -124,6 +123,8 @@ typedef struct dap_chain_esbocs { dap_chain_t *chain; dap_chain_cs_blocks_t *blocks; dap_chain_esbocs_session_t *session; + uint64_t hardfork_from; + dap_list_t *hardfork_trusted_addrs; dap_time_t last_directive_vote_timestamp, last_directive_accept_timestamp, last_submitted_candidate_timestamp, last_accepted_block_timestamp; void *_pvt; @@ -197,7 +198,8 @@ typedef struct dap_chain_esbocs_session { unsigned int listen_ensure; dap_chain_node_addr_t my_addr; uint8_t state, old_state; - bool cs_timer, round_fast_forward, sync_failed, new_round_enqueued, is_actual_hash; + bool cs_timer, round_fast_forward, sync_failed, + new_round_enqueued, is_actual_hash, is_hardfork; dap_global_db_driver_hash_t db_hash; dap_chain_addr_t my_signing_addr; } dap_chain_esbocs_session_t; @@ -266,5 +268,5 @@ int dap_chain_esbocs_set_min_validators_count(dap_chain_t *a_chain, uint16_t a_n uint16_t dap_chain_esbocs_get_min_validators_count(dap_chain_net_id_t a_net_id); int dap_chain_esbocs_set_emergency_validator(dap_chain_t *a_chain, bool a_add, uint32_t a_sign_type, dap_hash_fast_t *a_validator_hash); int dap_chain_esbocs_set_signs_struct_check(dap_chain_t *a_chain, bool a_enable); - +int dap_chain_esbocs_set_hardfork_prepare(dap_chain_t *a_chain, uint64_t a_block_num, dap_list_t *a_trusted_addrs); void dap_chain_esbocs_change_debug_mode(dap_chain_t *a_chain, bool a_enable); diff --git a/modules/datum/dap_chain_datum_decree.c b/modules/datum/dap_chain_datum_decree.c index e2f613465fc7df5721c6a5c110a3f366ed4c6283..bb2798467b37d176babd469dd35a60a7ae7294b3 100644 --- a/modules/datum/dap_chain_datum_decree.c +++ b/modules/datum/dap_chain_datum_decree.c @@ -71,7 +71,16 @@ int dap_chain_datum_decree_get_fee_addr(dap_chain_datum_decree_t *a_decree, dap_ dap_list_t *dap_chain_datum_decree_get_owners(dap_chain_datum_decree_t *a_decree, uint16_t *a_owners_num) { dap_return_val_if_fail(a_decree && a_owners_num, NULL); - dap_list_t *l_ret = dap_tsd_find_all(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER); + dap_list_t *l_ret = dap_tsd_find_all(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER, 0); + dap_list_t *it, *tmp; + DL_FOREACH_SAFE(l_ret, it, tmp) { + dap_tsd_t *l_tsd = it->data; + if (l_tsd->size < sizeof(dap_pkey_t) || l_tsd->size != sizeof(dap_pkey_t) + ((dap_pkey_t *)l_tsd->data)->header.size) { + log_it(L_ERROR, "Incorrect size %u of owner pkey", l_tsd->size); + DL_DELETE(l_ret, it); + DAP_DEL_MULTY(it->data, it); + } + } if (a_owners_num) *a_owners_num = (uint16_t)dap_list_length(l_ret); return l_ret; @@ -105,7 +114,7 @@ int dap_chain_datum_decree_get_stake_signing_addr(dap_chain_datum_decree_t *a_de return l_tsd && l_tsd->size == sizeof(dap_chain_addr_t) ? ( _dap_tsd_get_scalar(l_tsd, a_signing_addr), 0 ) : 1; } -int dap_chain_datum_decree_get_stake_signer_node_addr(dap_chain_datum_decree_t *a_decree, dap_chain_node_addr_t *a_node_addr) +int dap_chain_datum_decree_get_node_addr(dap_chain_datum_decree_t *a_decree, dap_chain_node_addr_t *a_node_addr) { dap_return_val_if_fail(a_decree && a_node_addr, -1); dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR); @@ -149,6 +158,13 @@ int dap_chain_datum_decree_get_ban_addr(dap_chain_datum_decree_t *a_decree, cons return l_tsd ? ( *a_addr = dap_tsd_get_string_const(l_tsd), !dap_strcmp(*a_addr, DAP_TSD_CORRUPTED_STRING) ) : 1; } +int dap_chain_datum_decree_get_atom_num(dap_chain_datum_decree_t *a_decree, uint64_t *a_atom_num) +{ + dap_return_val_if_fail(a_decree && a_atom_num, -1); + dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_BLOCK_NUM); + return l_tsd && l_tsd->size == sizeof(uint64_t) ? ( _dap_tsd_get_scalar(l_tsd, a_atom_num), 0 ) : 1; +} + /** * @brief get pkey from decree tsd * @param a_decree @@ -329,7 +345,16 @@ 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_BLOCK_NUM: + if (l_tsd->size != sizeof(uint64_t)) { + json_object_object_add(a_json_out, "Signature type", json_object_new_string("WRONG SIZE")); + break; + } + uint64_t l_num = 0; + _dap_tsd_get_scalar(l_tsd, &l_type); + json_object_object_add(a_json_out, "Signature type", json_object_new_uint64(l_num)); + break; default: json_object_object_add(a_json_out, "UNKNOWN_TYPE_TSD_SECTION", json_object_new_string("")); break; diff --git a/modules/datum/dap_chain_datum_tx_items.c b/modules/datum/dap_chain_datum_tx_items.c index b3c066ad7f26b745de70611dd0a5f4076427a0d8..67c32bbaecdabcba5cc45bb24e1aeff0b3f8c772 100644 --- a/modules/datum/dap_chain_datum_tx_items.c +++ b/modules/datum/dap_chain_datum_tx_items.c @@ -191,7 +191,8 @@ dap_chain_tx_in_reward_t *dap_chain_datum_tx_item_in_reward_create(dap_chain_has /** * Create tsd section */ -dap_chain_tx_tsd_t *dap_chain_datum_tx_item_tsd_create(void *a_data, int a_type, size_t a_size) { +dap_chain_tx_tsd_t *dap_chain_datum_tx_item_tsd_create(const void *a_data, int a_type, size_t a_size) +{ if (!a_data || !a_size) { return NULL; } @@ -279,6 +280,16 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_fee(uint256_t a return l_item; } +dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_fee_stack(uint256_t a_value) +{ + dap_return_val_if_pass(IS_ZERO_256(a_value), NULL); + dap_chain_tx_out_cond_t *l_item = DAP_NEW_Z_RET_VAL_IF_FAIL(dap_chain_tx_out_cond_t, NULL, NULL); + l_item->header.item_type = TX_ITEM_TYPE_OUT_COND; + l_item->header.value = a_value; + l_item->header.subtype = DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE_STACK; + return l_item; +} + /** * Create item dap_chain_tx_out_cond_t * @@ -426,6 +437,19 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_emit_delega return l_item; } +dap_chain_tx_sig_t *dap_chain_tx_sig_create(dap_sign_t *a_sign) +{ + dap_return_val_if_fail(a_sign, NULL); + size_t l_chain_sign_size = dap_sign_get_size(a_sign); // sign data + dap_chain_tx_sig_t *l_tx_sig = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(dap_chain_tx_sig_t, sizeof(dap_chain_tx_sig_t) + + l_chain_sign_size, NULL, NULL); + l_tx_sig->header.type = TX_ITEM_TYPE_SIG; + l_tx_sig->header.version = 1; + l_tx_sig->header.sig_size = (uint32_t)l_chain_sign_size; + memcpy(l_tx_sig->sig, a_sign, l_chain_sign_size); + return l_tx_sig; +} + /** * Create item dap_chain_tx_sig_t * @@ -445,13 +469,9 @@ dap_chain_tx_sig_t *dap_chain_datum_tx_item_sign_create(dap_enc_key_t *a_key, da DAP_DELETE(l_tx); if (!l_chain_sign) return NULL; - size_t l_chain_sign_size = dap_sign_get_size(l_chain_sign); // sign data - dap_chain_tx_sig_t *l_tx_sig = DAP_NEW_Z_SIZE(dap_chain_tx_sig_t, - sizeof(dap_chain_tx_sig_t) + l_chain_sign_size); - l_tx_sig->header.type = TX_ITEM_TYPE_SIG; - l_tx_sig->header.version = 1; - l_tx_sig->header.sig_size = (uint32_t)l_chain_sign_size; - memcpy(l_tx_sig->sig, l_chain_sign, l_chain_sign_size); + dap_chain_tx_sig_t *l_tx_sig = dap_chain_tx_sig_create(l_chain_sign); + if (!l_tx_sig) + return NULL; DAP_DELETE(l_chain_sign); return l_tx_sig; } diff --git a/modules/datum/include/dap_chain_datum_decree.h b/modules/datum/include/dap_chain_datum_decree.h index da4a463cad660ee3718795f59a5f2fd6fa506273..9cb2ddda2942eb6d772dec69c76b27b14a8531c6 100644 --- a/modules/datum/include/dap_chain_datum_decree.h +++ b/modules/datum/include/dap_chain_datum_decree.h @@ -129,12 +129,15 @@ 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_HARDFORK: + return "DECREE_COMMON_SUBTYPE_HARDFORK"; default: return "DECREE_SUBTYPE_UNKNOWN"; } } -DAP_STATIC_INLINE uint16_t dap_chain_datum_decree_type_from_str(const char *a_decree_type) { +DAP_STATIC_INLINE uint16_t dap_chain_datum_decree_type_from_str(const char *a_decree_type) +{ if (!dap_strcmp(a_decree_type, "fee")){ return DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_FEE; } else if (!dap_strcmp(a_decree_type, "owners")) { @@ -163,6 +166,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, "hardfork_prepare")) { + return DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_HARDFORK; } else { return 0; } @@ -204,6 +209,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_BLOCK_NUM: + return "DAP_CHAIN_DATUM_DECREE_TSD_TYPE_BLOCK_NUM"; default: return "DECREE_TSD_TYPE_UNKNOWN"; } @@ -286,12 +293,12 @@ int dap_chain_datum_decree_get_value(dap_chain_datum_decree_t *a_decree, uint256 int dap_chain_datum_decree_get_stake_signing_addr(dap_chain_datum_decree_t *a_decree, dap_chain_addr_t *a_signing_addr); /** - * @brief dap_chain_datum_decree_get_stake_signer_node_addr get signer node address + * @brief dap_chain_datum_decree_get_node_addr get signer node address * @param a_decree pointer to decree * @param a_node_addr pointer to signer node address buffer * @return result code. 0 - success */ -int dap_chain_datum_decree_get_stake_signer_node_addr(dap_chain_datum_decree_t *a_decree, dap_chain_node_addr_t *a_node_addr); +int dap_chain_datum_decree_get_node_addr(dap_chain_datum_decree_t *a_decree, dap_chain_node_addr_t *a_node_addr); /** * @brief dap_chain_datum_decree_get_stake_min_value get minimum stake value @@ -312,6 +319,7 @@ 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); +int dap_chain_datum_decree_get_atom_num(dap_chain_datum_decree_t *a_decree, uint64_t *a_atom_num); /** * @breif dap_chain_datum_decree_dump Dump information about decree diff --git a/modules/datum/include/dap_chain_datum_tx_items.h b/modules/datum/include/dap_chain_datum_tx_items.h index c8be707da1c3666b5b0c959d4097b450c8d99f08..397a10cdc243ebf0ad9f35f458c52de4b273ab0a 100644 --- a/modules/datum/include/dap_chain_datum_tx_items.h +++ b/modules/datum/include/dap_chain_datum_tx_items.h @@ -109,7 +109,7 @@ dap_chain_tx_in_t* dap_chain_datum_tx_item_in_create(dap_chain_hash_fast_t *a_tx dap_chain_tx_in_reward_t *dap_chain_datum_tx_item_in_reward_create(dap_chain_hash_fast_t *a_block_hash); -dap_chain_tx_tsd_t *dap_chain_datum_tx_item_tsd_create(void *a_data, int a_type, size_t a_size); +dap_chain_tx_tsd_t *dap_chain_datum_tx_item_tsd_create(const void *a_data, int a_type, size_t a_size); dap_chain_tx_in_cond_t* dap_chain_datum_tx_item_in_cond_create(dap_chain_hash_fast_t *a_tx_prev_hash, uint32_t a_tx_out_prev_idx, uint32_t a_receipt_idx); @@ -135,6 +135,13 @@ dap_chain_tx_out_ext_t* dap_chain_datum_tx_item_out_ext_create(const dap_chain_a */ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_fee(uint256_t a_value); +/** + * Create item dap_chain_tx_out_cond_t with fee_stack subtype + * + * return item, NULL Error + */ +dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_fee_stack(uint256_t a_value); + /** * Create item dap_chain_tx_out_cond_t * @@ -178,6 +185,13 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_emit_delega uint32_t a_signs_min, dap_hash_fast_t *a_pkey_hashes, size_t a_pkey_hashes_count); +/** + * Create item dap_chain_tx_sig_t + * + * return item, NULL Error + */ +dap_chain_tx_sig_t *dap_chain_tx_sig_create(dap_sign_t *a_sign); + /** * 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 c765295b495278e152d52381d88bf6054204e2b3..e743afd559f710946ff73fe4ad8f0b1eecf057c0 100644 --- a/modules/datum/include/dap_chain_datum_tx_out_cond.h +++ b/modules/datum/include/dap_chain_datum_tx_out_cond.h @@ -37,6 +37,7 @@ enum dap_chain_tx_out_cond_subtype { DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE = 0x04, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK = 0x06, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_EMIT_DELEGATE = 0x07, + DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE_STACK = 0x08, DAP_CHAIN_TX_OUT_COND_SUBTYPE_ALL = 0xFF }; typedef byte_t dap_chain_tx_out_cond_subtype_t; diff --git a/modules/datum/include/dap_chain_datum_tx_tsd.h b/modules/datum/include/dap_chain_datum_tx_tsd.h index 810988af0fe298a81232abe52b13ed9f66350c12..d63d96d244fe09be2fbf7e147ba323748bcb70b3 100644 --- a/modules/datum/include/dap_chain_datum_tx_tsd.h +++ b/modules/datum/include/dap_chain_datum_tx_tsd.h @@ -4,6 +4,10 @@ #include "dap_chain_common.h" #include "dap_tsd.h" +#define DAP_CHAIN_DATUM_TX_TSD_TYPE_HARDFORK_TICKER 0xf001 +#define DAP_CHAIN_DATUM_TX_TSD_TYPE_HARDFORK_TX_HASH 0xf002 +#define DAP_CHAIN_DATUM_TX_TSD_TYPE_HARDFORK_TRACKER 0xf0fa + typedef struct dap_chain_tx_tsd { struct { dap_chain_tx_item_type_t type; diff --git a/modules/ledger/dap_chain_ledger_decree.c b/modules/ledger/dap_chain_ledger_decree.c index 1756af8d5eb44af543d41e2c8e43ecf1e2e0e5af..e30532b2698792cdbe9f00d92e37f39ac9c80dd7 100644 --- a/modules/ledger/dap_chain_ledger_decree.c +++ b/modules/ledger/dap_chain_ledger_decree.c @@ -328,15 +328,16 @@ static bool s_verify_pkey (dap_sign_t *a_sign, dap_chain_net_t *a_net) static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain_net_t *a_net, bool a_apply, bool a_anchored) { - uint256_t l_value; - uint32_t l_sign_type; - uint16_t l_owners_num; - uint8_t l_action; - dap_chain_addr_t l_addr = {}; - dap_hash_fast_t l_hash = {}; - dap_chain_node_addr_t l_node_addr = {}; - dap_list_t *l_owners_list = NULL; - const char *l_ban_addr; +uint256_t l_value; +uint64_t l_block_num; +uint32_t l_sign_type; +uint16_t l_owners_num; +uint8_t l_action; +dap_chain_addr_t l_addr = {}; +dap_hash_fast_t l_hash = {}; +dap_chain_node_addr_t l_node_addr = {}; +dap_list_t *l_owners_list = NULL; +const char *l_ban_addr; dap_return_val_if_fail(a_decree && a_net, -112); @@ -398,7 +399,7 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain log_it(L_WARNING,"Can't get signing address from decree."); return -107; } - if (dap_chain_datum_decree_get_stake_signer_node_addr(a_decree, &l_node_addr)){ + if (dap_chain_datum_decree_get_node_addr(a_decree, &l_node_addr)){ log_it(L_WARNING,"Can't get signer node address from decree."); return -108; } @@ -525,8 +526,8 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain if (!a_apply) break; uint64_t l_cur_block_num = l_chain->callback_count_atom(l_chain); - dap_chain_net_add_reward(a_net, l_value, l_cur_block_num); - } break; + return dap_chain_net_add_reward(a_net, l_value, l_cur_block_num); + } case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_MAX_WEIGHT: { if (dap_chain_datum_decree_get_value(a_decree, &l_value)) { log_it(L_WARNING,"Can't get value from decree."); @@ -548,10 +549,11 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain if (!a_apply) break; dap_chain_net_srv_stake_set_percent_max(a_net->pub.id, l_value); - } break; + return 0; + } case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_CHECK_SIGNS_STRUCTURE: { if (dap_chain_datum_decree_get_action(a_decree, &l_action)) { - log_it(L_WARNING,"Can't get action from decree."); + log_it(L_WARNING, "Can't get action from decree."); return -103; } dap_chain_t *l_chain = dap_chain_find_by_id(a_net->pub.id, a_decree->header.common_decree_params.chain_id); @@ -565,8 +567,8 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain } if (!a_apply) break; - dap_chain_esbocs_set_signs_struct_check(l_chain, l_action); - } break; + return dap_chain_esbocs_set_signs_struct_check(l_chain, l_action); + } case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_EMERGENCY_VALIDATORS: { if (dap_chain_datum_decree_get_action(a_decree, &l_action)) { log_it(L_WARNING,"Can't get action from decree."); @@ -591,8 +593,27 @@ static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain } if (!a_apply) break; - dap_chain_esbocs_set_emergency_validator(l_chain, l_action, l_sign_type, &l_hash); - } break; + return dap_chain_esbocs_set_emergency_validator(l_chain, l_action, l_sign_type, &l_hash); + } + case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_HARDFORK: + if (dap_chain_datum_decree_get_atom_num(a_decree, &l_block_num)) { + log_it(L_WARNING, "Can't get atom number from hardfork prepare decree"); + return -103; + } + dap_chain_t *l_chain = dap_chain_find_by_id(a_net->pub.id, a_decree->header.common_decree_params.chain_id); + if (!l_chain) { + log_it(L_WARNING, "Specified chain not found"); + return -106; + } + if (dap_strcmp(dap_chain_get_cs_type(l_chain), "esbocs")) { + log_it(L_WARNING, "Can't apply this decree to specified chain"); + return -115; + } + if (!a_apply) + break; + dap_list_t *l_addrs = dap_tsd_find_all(a_decree->data_n_signs, a_decree->header.data_size, + DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR, sizeof(dap_stream_node_addr_t)); + return dap_chain_esbocs_set_hardfork_prepare(l_chain, l_block_num, l_addrs); default: return -1; } @@ -632,26 +653,75 @@ const dap_list_t *dap_ledger_decree_get_owners_pkeys(dap_ledger_t *a_ledger) return PVT(a_ledger)->decree_owners_pkeys; } -static int s_compare_anchors(dap_ledger_hardfork_anchors_t *a_list1, dap_ledger_hardfork_anchors_t *a_list2) +static bool s_compare_anchors(dap_ledger_t *a_ledger, dap_ledger_hardfork_anchors_t *a_exist, dap_ledger_hardfork_anchors_t *a_comp) { - return a_list1->decree_subtype != a_list2->decree_subtype; + bool l_stake_type = false, l_ban_type = false; + switch (a_comp->decree_subtype) { + case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_APPROVE: + case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_INVALIDATE: + if (a_exist->decree_subtype != DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_APPROVE && + a_exist->decree_subtype != DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_INVALIDATE) + return false; + l_stake_type = true; + break; + case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_BAN: + case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_UNBAN: + if (a_exist->decree_subtype != DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_BAN && + a_exist->decree_subtype != DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_UNBAN) + return false; + l_ban_type = true; + break; + default: + return a_exist->decree_subtype == a_comp->decree_subtype; + } + dap_hash_fast_t l_exist_hash = {}, l_comp_hash = {}; + dap_chain_datum_anchor_get_hash_from_data(a_comp->anchor, &l_comp_hash); + dap_chain_datum_anchor_get_hash_from_data(a_exist->anchor, &l_exist_hash); + dap_chain_datum_decree_t *l_comp_decree = dap_ledger_decree_get_by_hash(a_ledger->net, &l_comp_hash, NULL); + dap_chain_datum_decree_t *l_exist_decree = dap_ledger_decree_get_by_hash(a_ledger->net, &l_exist_hash, NULL); + if (l_ban_type) { + const char *l_comp_ban_addr = NULL, *l_exist_ban_addr = NULL; + dap_chain_datum_decree_get_ban_addr(l_comp_decree, &l_comp_ban_addr); + dap_chain_datum_decree_get_ban_addr(l_exist_decree, &l_exist_ban_addr); + if (!dap_strcmp(l_comp_ban_addr, l_exist_ban_addr)) + return true; + return false; + } + if (l_stake_type) { + dap_chain_addr_t l_comp_addr = {}, l_exist_addr = {}; + dap_chain_datum_decree_get_stake_signing_addr(l_comp_decree, &l_comp_addr); + dap_chain_datum_decree_get_stake_signing_addr(l_exist_decree, &l_exist_addr); + if (!dap_chain_addr_is_blank(&l_comp_addr) && dap_chain_addr_compare(&l_comp_addr, &l_exist_addr)) + return true; + return false; + } + return assert(false), false; } -int s_aggregate_anchor(dap_ledger_hardfork_anchors_t **a_out_list, uint16_t a_subtype, dap_chain_datum_anchor_t *a_anchor) +int s_aggregate_anchor(dap_ledger_t *a_ledger, dap_ledger_hardfork_anchors_t **a_out_list, uint16_t a_subtype, dap_chain_datum_anchor_t *a_anchor) { dap_ledger_hardfork_anchors_t l_new_anchor = { .anchor = a_anchor, .decree_subtype = a_subtype }; - dap_ledger_hardfork_anchors_t *l_exist = NULL; - DL_SEARCH(*a_out_list, l_exist, &l_new_anchor, s_compare_anchors); + dap_ledger_hardfork_anchors_t *l_exist = NULL, *l_tmp; + DL_FOREACH_SAFE(*a_out_list, l_exist, l_tmp) + if (s_compare_anchors(a_ledger, l_exist, &l_new_anchor)) + break; if (!l_exist) { l_exist = DAP_DUP(&l_new_anchor); if (!l_exist) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); return -1; } - DL_APPEND(*a_out_list, l_exist); - } else - l_exist->anchor = a_anchor; + if (a_subtype != DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_INVALIDATE && a_subtype != DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_UNBAN) + DL_APPEND(*a_out_list, l_exist); + } else { + if (l_exist->decree_subtype == DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_APPROVE || + l_exist->decree_subtype == DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_BAN) { + assert(a_subtype == DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_INVALIDATE || a_subtype == DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_UNBAN); + DL_DELETE(*a_out_list, l_exist); + } else + l_exist->anchor = a_anchor; + } return 0; } @@ -670,7 +740,12 @@ dap_ledger_hardfork_anchors_t *dap_ledger_anchors_aggregate(dap_ledger_t *a_ledg l_anchor_hash_str, dap_hash_fast_to_str_static(&it->decree_hash)); continue; } - s_aggregate_anchor(&ret, it->decree->header.sub_type, l_anchor); + dap_hash_fast_t l_decree_hash; + if (dap_chain_datum_anchor_get_hash_from_data(l_anchor, &l_decree_hash)) { + log_it(L_ERROR, "Corrupted datum anchor %s, can't get decree hash from it", dap_hash_fast_to_str_static(&it->anchor_hash)); + continue; + } + s_aggregate_anchor(a_ledger, &ret, it->decree->header.sub_type, l_anchor); } pthread_rwlock_unlock(&l_ledger_pvt->decrees_rwlock); return ret; diff --git a/modules/ledger/dap_chain_ledger_tx.c b/modules/ledger/dap_chain_ledger_tx.c index 3808b0dbedecaba09d52a74628374f129aa92c84..5a199adf42e02b4978571122a494021a3491d1ad 100644 --- a/modules/ledger/dap_chain_ledger_tx.c +++ b/modules/ledger/dap_chain_ledger_tx.c @@ -1175,7 +1175,7 @@ int s_compare_trackers(dap_list_t *a_tracker1, dap_list_t *a_tracker2) return memcmp(&l_tracker1->voting_hash, &l_tracker2->voting_hash, sizeof(dap_hash_fast_t)); } -dap_list_t *s_trackers_concatenate(dap_ledger_t *a_ledger, dap_list_t *a_trackers, dap_list_t *a_added, dap_time_t a_ts_creation_time) +dap_list_t *s_trackers_aggregate(dap_ledger_t *a_ledger, dap_list_t *a_trackers, dap_list_t *a_added, dap_time_t a_ts_creation_time) { if (!s_voting_callbacks.voting_expire_callback) return a_trackers; @@ -1363,7 +1363,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha // Gather colour information from previous outputs dap_ledger_tx_item_t *l_prev_item_out = l_bound_item->prev_item; l_prev_item_out->out_metadata[l_bound_item->prev_out_idx].tx_spent_hash_fast = *a_tx_hash; - l_trackers_mover = s_trackers_concatenate(a_ledger, l_trackers_mover, + l_trackers_mover = s_trackers_aggregate(a_ledger, l_trackers_mover, l_prev_item_out->out_metadata[l_bound_item->prev_out_idx].trackers, a_tx->header.ts_created); // add a used output l_prev_item_out->cache_data.n_outs_used++; @@ -1401,7 +1401,7 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha assert(l_vote_tx_item); l_new_tracker->voting_hash = l_vote_tx_item->voting_hash; dap_list_t *l_new_vote = dap_list_append(NULL, l_new_tracker); - l_trackers_mover = s_trackers_concatenate(a_ledger, l_trackers_mover, l_new_vote, a_tx->header.ts_created); + l_trackers_mover = s_trackers_aggregate(a_ledger, l_trackers_mover, l_new_vote, a_tx->header.ts_created); } //Update balance : raise @@ -1951,7 +1951,30 @@ int dap_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_c return dap_ledger_tx_add(a_ledger, a_tx, a_tx_hash, false, a_datum_index_data); } +int dap_ledger_tx_load_hardfork_data(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_hash_fast_t *a_tx_hash, dap_ledger_datum_iter_data_t *a_datum_index_data) +{ + dap_return_val_if_fail(a_ledger && a_tx && a_tx_hash, -1); + byte_t *l_item = NULL; + size_t l_tx_item_size = 0; + TX_ITEM_ITER_TX(l_item, l_tx_item_size, a_tx) { + if (*l_item != TX_ITEM_TYPE_TSD) + continue; + dap_tsd_t *l_tsd = (dap_tsd_t *)((dap_chain_tx_tsd_t *)l_item)->tsd; + if (l_tsd->type != DAP_CHAIN_DATUM_TX_TSD_TYPE_HARDFORK_TRACKER) + continue; + if (l_tsd->size != sizeof(dap_ledger_tracker_t)) + return log_it(L_ERROR, "Incorrect size of TSD tracker section %u (need %zu)", l_tsd->size, sizeof(dap_ledger_tracker_t)), -2; + dap_ledger_tx_item_t *l_item_tx = NULL; + s_tx_find_by_hash(a_ledger, a_tx_hash, &l_item_tx, true); + if (!l_item_tx) + return log_it(L_ERROR, "Can't find hardfork tx %s in ledger", dap_hash_fast_to_str_static(a_tx_hash)), -3; + if (l_item_tx->cache_data.n_outs != 1) + return log_it(L_ERROR, "Can't add hardfork data to tx %s cause it's not a single-out tx", dap_hash_fast_to_str_static(a_tx_hash)), -4; + l_item_tx->out_metadata[0].trackers = dap_list_append(l_item_tx->out_metadata[0].trackers, l_tsd->data); + } + return 0; +} static void s_ledger_stake_lock_cache_update(dap_ledger_t *a_ledger, dap_ledger_stake_lock_item_t *a_stake_lock_item) { @@ -2423,27 +2446,27 @@ static int s_aggregate_out(dap_ledger_hardfork_balances_t **a_out_list, dap_ledg dap_chain_addr_to_str_static(a_addr), a_ticker, dap_uint256_to_char(a_value, NULL)); return -2; } - l_exist->trackers = s_trackers_concatenate(a_ledger, l_exist->trackers, a_trackers, a_hardfork_start_time); + l_exist->trackers = s_trackers_aggregate(a_ledger, l_exist->trackers, a_trackers, a_hardfork_start_time); return 0; } static int s_aggregate_out_cond(dap_ledger_hardfork_condouts_t **a_ret_list, dap_ledger_t *a_ledger, - dap_chain_tx_out_cond_t *a_out_cond, dap_sign_t *a_sign, - dap_hash_fast_t *a_tx_hash, dap_time_t a_hardfork_start_time, - dap_list_t *a_trackers) + dap_chain_tx_out_cond_t *a_out_cond, dap_chain_tx_sig_t *a_sign, + dap_hash_fast_t *a_tx_hash, const char *a_token_ticker, + dap_time_t a_hardfork_start_time, dap_list_t *a_trackers) { dap_ledger_hardfork_condouts_t *l_new_condout = DAP_NEW_Z(dap_ledger_hardfork_condouts_t); if (!l_new_condout) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); return -1; } - *l_new_condout = (dap_ledger_hardfork_condouts_t) { .hash = *a_tx_hash, .cond = a_out_cond, .sign = a_sign }; - l_new_condout->trackers = s_trackers_concatenate(a_ledger, NULL, a_trackers, a_hardfork_start_time); + *l_new_condout = (dap_ledger_hardfork_condouts_t) { .hash = *a_tx_hash, .cond = a_out_cond, .sign = a_sign, .ticker = a_token_ticker }; + l_new_condout->trackers = s_trackers_aggregate(a_ledger, NULL, a_trackers, a_hardfork_start_time); DL_APPEND(*a_ret_list, l_new_condout); return 0; } -dap_ledger_hardfork_balances_t *dap_ledger_states_aggregate(dap_ledger_t *a_ledger, dap_time_t a_hardfork_decree_creatiom_time, dap_ledger_hardfork_condouts_t **l_cond_outs_list) +dap_ledger_hardfork_balances_t *dap_ledger_states_aggregate(dap_ledger_t *a_ledger, dap_time_t a_hardfork_decree_creation_time, dap_ledger_hardfork_condouts_t **l_cond_outs_list) { dap_ledger_hardfork_balances_t *ret = NULL; dap_ledger_hardfork_condouts_t *l_cond_ret = NULL; @@ -2465,17 +2488,17 @@ dap_ledger_hardfork_balances_t *dap_ledger_states_aggregate(dap_ledger_t *a_ledg switch(l_tx_item_type) { case TX_ITEM_TYPE_OUT: { dap_chain_tx_out_t *l_out = (dap_chain_tx_out_t *)l_tx_item; - s_aggregate_out(&ret, a_ledger, it->cache_data.token_ticker, &l_out->addr, l_out->header.value, a_hardfork_decree_creatiom_time, l_trackers); + s_aggregate_out(&ret, a_ledger, it->cache_data.token_ticker, &l_out->addr, l_out->header.value, a_hardfork_decree_creation_time, l_trackers); break; } case TX_ITEM_TYPE_OUT_OLD: { dap_chain_tx_out_old_t *l_out = (dap_chain_tx_out_old_t *)l_tx_item; - s_aggregate_out(&ret, a_ledger, it->cache_data.token_ticker, &l_out->addr, GET_256_FROM_64(l_out->header.value), a_hardfork_decree_creatiom_time, l_trackers); + s_aggregate_out(&ret, a_ledger, it->cache_data.token_ticker, &l_out->addr, GET_256_FROM_64(l_out->header.value), a_hardfork_decree_creation_time, l_trackers); break; } case TX_ITEM_TYPE_OUT_EXT: { dap_chain_tx_out_ext_t *l_out = (dap_chain_tx_out_ext_t *)l_tx_item; - s_aggregate_out(&ret, a_ledger, l_out->token, &l_out->addr, l_out->header.value, a_hardfork_decree_creatiom_time, l_trackers); + s_aggregate_out(&ret, a_ledger, l_out->token, &l_out->addr, l_out->header.value, a_hardfork_decree_creation_time, l_trackers); break; } case TX_ITEM_TYPE_OUT_COND: { @@ -2489,12 +2512,12 @@ dap_ledger_hardfork_balances_t *dap_ledger_states_aggregate(dap_ledger_t *a_ledg log_it(L_ERROR, "Can't find header TX for conditional TX %s", dap_hash_fast_to_str_static(&it->tx_hash_fast)); continue; } - dap_sign_t *l_tx_sign = dap_chain_datum_tx_get_sign(l_tx, 0); + dap_chain_tx_sig_t *l_tx_sign = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get_nth(l_tx, TX_ITEM_TYPE_SIG, 0); if (!l_tx_sign) { log_it(L_ERROR, "Can't find sign for conditional TX %s", dap_hash_fast_to_str_static(&l_first_tx_hash)); continue; } - s_aggregate_out_cond(&l_cond_ret, a_ledger, l_out, l_tx_sign, &it->tx_hash_fast, a_hardfork_decree_creatiom_time, l_trackers); + s_aggregate_out_cond(&l_cond_ret, a_ledger, l_out, l_tx_sign, &it->tx_hash_fast, it->cache_data.token_ticker, a_hardfork_decree_creation_time, l_trackers); } default: log_it(L_ERROR, "Unexpected item type %hhu", l_tx_item_type); diff --git a/modules/ledger/include/dap_chain_ledger.h b/modules/ledger/include/dap_chain_ledger.h index 5892b17f3d862b2ef54242663b61c111e5386823..e68e2e839592742856f68162a63283516012af90 100644 --- a/modules/ledger/include/dap_chain_ledger.h +++ b/modules/ledger/include/dap_chain_ledger.h @@ -43,13 +43,14 @@ typedef struct dap_ledger { dap_chain_net_t *net; + bool is_hardfork_state; void *_internal; } dap_ledger_t; typedef struct dap_ledger_tracker { dap_hash_fast_t voting_hash; uint256_t colored_value; -} dap_ledger_tracker_t; +} DAP_ALIGN_PACKED dap_ledger_tracker_t; typedef struct dap_ledger_hardfork_balances { dap_chain_addr_t addr; @@ -62,7 +63,8 @@ typedef struct dap_ledger_hardfork_balances { typedef struct dap_ledger_hardfork_condouts { dap_hash_fast_t hash; dap_chain_tx_out_cond_t *cond; - dap_sign_t *sign; + dap_chain_tx_sig_t *sign; + const char *ticker; dap_list_t *trackers; struct dap_ledger_hardfork_condouts *prev, *next; } dap_ledger_hardfork_condouts_t; @@ -304,9 +306,9 @@ DAP_STATIC_INLINE char *dap_ledger_get_gdb_group(dap_ledger_t *a_ledger, const c * return 1 OK, -1 error */ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, bool a_from_threshold, dap_ledger_datum_iter_data_t *a_datum_index_data); +int dap_ledger_tx_load_hardfork_data(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_hash_fast_t *a_tx_hash, dap_ledger_datum_iter_data_t *a_datum_index_data); int dap_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_hash_fast_t *a_tx_hash, dap_ledger_datum_iter_data_t *a_datum_index_data); int dap_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash); - int dap_ledger_tx_add_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, size_t a_datum_size, dap_hash_fast_t *a_datum_hash); /** @@ -501,7 +503,7 @@ int dap_ledger_anchor_load(dap_chain_datum_anchor_t * a_anchor, dap_chain_t *a_c int dap_ledger_anchor_unload(dap_chain_datum_anchor_t * a_anchor, dap_chain_t *a_chain, dap_hash_fast_t *a_anchor_hash); dap_chain_datum_anchor_t *dap_ledger_anchor_find(dap_ledger_t *a_ledger, dap_hash_fast_t *a_anchor_hash); -dap_ledger_hardfork_balances_t *dap_ledger_states_aggregate(dap_ledger_t *a_ledger, dap_time_t a_hardfork_decree_creatiom_time, dap_ledger_hardfork_condouts_t **l_cond_outs_list); +dap_ledger_hardfork_balances_t *dap_ledger_states_aggregate(dap_ledger_t *a_ledger, dap_time_t a_hardfork_decree_creation_time, dap_ledger_hardfork_condouts_t **l_cond_outs_list); dap_ledger_hardfork_anchors_t *dap_ledger_anchors_aggregate(dap_ledger_t *a_ledger); uint256_t dap_ledger_coin_get_uncoloured_value(dap_ledger_t *a_ledger, dap_hash_fast_t *a_voting_hash, dap_hash_fast_t *a_tx_prev_hash, int a_out_idx); diff --git a/modules/mempool/dap_chain_mempool.c b/modules/mempool/dap_chain_mempool.c index 393cf39417947c1a9754f26247b2a98999308db4..8555094d68e2ce8f143b3229570525ece92a5282 100644 --- a/modules/mempool/dap_chain_mempool.c +++ b/modules/mempool/dap_chain_mempool.c @@ -124,7 +124,7 @@ char *dap_chain_mempool_datum_add(const dap_chain_datum_t *a_datum, dap_chain_t DAP_DATUM_TYPE_STR(a_datum->header.type_id, l_type_str); } - char *l_gdb_group = dap_chain_net_get_gdb_group_mempool_new(a_chain); + char *l_gdb_group = dap_chain_mempool_group_new(a_chain); int l_res = dap_global_db_set_sync(l_gdb_group, l_key_str, a_datum, dap_chain_datum_size(a_datum), false);//, NULL, NULL); if (l_res == DAP_GLOBAL_DB_RC_SUCCESS) log_it(L_NOTICE, "Datum %s with hash %s was placed in mempool group %s", l_type_str, l_key_str_out, l_gdb_group); @@ -748,7 +748,7 @@ int dap_chain_mempool_tx_create_massive( dap_chain_t * a_chain, dap_enc_key_t *a } dap_list_free_full(l_list_used_out, NULL); - char *l_gdb_group = dap_chain_net_get_gdb_group_mempool_new(a_chain); + char *l_gdb_group = dap_chain_mempool_group_new(a_chain); dap_global_db_set_multiple_zc(l_gdb_group, l_objs, a_tx_num, s_tx_create_massive_gdb_save_callback, NULL); DAP_DEL_Z(l_gdb_group); return 0; @@ -1162,7 +1162,7 @@ dap_chain_datum_token_emission_t *dap_chain_mempool_emission_get(dap_chain_t *a_ dap_chain_datum_t *dap_chain_mempool_datum_get(dap_chain_t *a_chain, const char *a_datum_hash_str) { size_t l_datum_size; - char *l_gdb_group = dap_chain_net_get_gdb_group_mempool_new(a_chain); + char *l_gdb_group = dap_chain_mempool_group_new(a_chain); dap_chain_datum_t *l_datum = (dap_chain_datum_t *)dap_global_db_get_sync(l_gdb_group, a_datum_hash_str, &l_datum_size, NULL, NULL ); if (!l_datum) { @@ -1223,245 +1223,6 @@ dap_chain_datum_token_emission_t *dap_chain_mempool_datum_emission_extract(dap_c return DAP_DUP_SIZE(l_emission, l_datum->header.data_size); } -uint8_t* dap_datum_mempool_serialize(dap_datum_mempool_t *datum_mempool, size_t *size) -{ - size_t a_request_size = 2 * sizeof(uint16_t), shift_size = 0; - for(int i = 0; i < datum_mempool->datum_count; i++) { - a_request_size += dap_chain_datum_size(datum_mempool->data[i]) + sizeof(uint16_t); - } - uint8_t *l_ret = DAP_NEW_Z_SIZE_RET_VAL_IF_FAIL(uint8_t, a_request_size, NULL); - uint8_t *l_pos = dap_mempcpy(l_ret, &datum_mempool->version, sizeof(uint16_t)); - l_pos = dap_mempcpy(l_pos, &datum_mempool->datum_count, sizeof(uint16_t)); - for(int i = 0; i < datum_mempool->datum_count; i++) { - size_t size_one = dap_chain_datum_size(datum_mempool->data[i]); - l_pos = dap_mempcpy( dap_mempcpy(l_pos, &size_one, sizeof(uint16_t)), datum_mempool->data[i], size_one ); - } - assert((size_t)(l_pos - l_ret) == a_request_size); - if(size) - *size = a_request_size; - return l_ret; -} - -dap_datum_mempool_t * dap_datum_mempool_deserialize(uint8_t *a_datum_mempool_ser, size_t a_datum_mempool_ser_size) -{ - size_t shift_size = 0; - //uint8_t *a_datum_mempool_ser = DAP_NEW_Z_SIZE(uint8_t, datum_mempool_size / 2 + 1); - //datum_mempool_size = hex2bin(a_datum_mempool_ser, datum_mempool_str_in, datum_mempool_size) / 2; - dap_datum_mempool_t *datum_mempool = DAP_NEW_Z(dap_datum_mempool_t); - if (!datum_mempool) { - log_it(L_CRITICAL, "%s", c_error_memory_alloc); - return NULL; - } - datum_mempool->version = *(uint16_t*)(a_datum_mempool_ser + shift_size); - shift_size += sizeof(uint16_t); - datum_mempool->datum_count = *(uint16_t*)(a_datum_mempool_ser + shift_size); - shift_size += sizeof(uint16_t); - datum_mempool->data = DAP_NEW_Z_SIZE(dap_chain_datum_t*, datum_mempool->datum_count * sizeof(dap_chain_datum_t*)); - for(int i = 0; i < datum_mempool->datum_count; i++) { - uint16_t size_one = *(uint16_t*)(a_datum_mempool_ser + shift_size); - shift_size += sizeof(uint16_t); - datum_mempool->data[i] = DAP_DUP((dap_chain_datum_t*)(a_datum_mempool_ser + shift_size)); - shift_size += size_one; - } - assert(shift_size == a_datum_mempool_ser_size); - return datum_mempool; -} - -void dap_datum_mempool_clean(dap_datum_mempool_t *datum) -{ - if(!datum) - return; - for(int i = 0; i < datum->datum_count; i++) { - DAP_DELETE(datum->data[i]); - } - DAP_DELETE(datum->data); - datum->data = NULL; -} - -void dap_datum_mempool_free(dap_datum_mempool_t *datum) -{ - dap_datum_mempool_clean(datum); - DAP_DELETE(datum); -} - -/** - * - */ -static char* s_calc_datum_hash(const void *a_datum_str, size_t datum_size) -{ - dap_chain_hash_fast_t a_hash; - dap_hash_fast( a_datum_str, datum_size, &a_hash); - size_t a_str_max = (sizeof(a_hash.raw) + 1) * 2 + 2; /* heading 0x */ - char *a_str = DAP_NEW_Z_SIZE(char, a_str_max); - -// size_t hash_len = dap_chain_hash_fast_to_str(&a_hash, a_str, a_str_max); - dap_chain_hash_fast_to_str(&a_hash, a_str, a_str_max); - -// if(!hash_len) { -// DAP_DELETE(a_str); -// return NULL; -// } - - return a_str; -} - -static void enc_http_reply_encode_new(struct dap_http_simple *a_http_simple, dap_enc_key_t * key, - enc_http_delegate_t * a_http_delegate) -{ - //dap_enc_key_t * key = dap_enc_ks_find_http(a_http_simple->http); - if(key == NULL) { - log_it(L_ERROR, "Can't find http key."); - return; - } - if(a_http_delegate->response) { - - if(a_http_simple->reply) - DAP_DELETE(a_http_simple->reply); - - size_t l_reply_size_max = dap_enc_code_out_size(a_http_delegate->key, - a_http_delegate->response_size, - DAP_ENC_DATA_TYPE_RAW); - - a_http_simple->reply = DAP_NEW_SIZE(void, l_reply_size_max); - a_http_simple->reply_size = dap_enc_code(a_http_delegate->key, - a_http_delegate->response, a_http_delegate->response_size, - a_http_simple->reply, l_reply_size_max, - DAP_ENC_DATA_TYPE_RAW); - - /*/ decode test - size_t l_response_dec_size_max = a_http_simple->reply_size ? a_http_simple->reply_size * 2 + 16 : 0; - char * l_response_dec = a_http_simple->reply_size ? DAP_NEW_Z_SIZE(char, l_response_dec_size_max) : NULL; - size_t l_response_dec_size = 0; - if(a_http_simple->reply_size) - l_response_dec_size = dap_enc_decode(a_http_delegate->key, - a_http_simple->reply, a_http_simple->reply_size, - l_response_dec, l_response_dec_size_max, - DAP_ENC_DATA_TYPE_RAW); - l_response_dec_size_max = 0;*/ - } - -} - -/** - * @brief - * @param cl_st HTTP server instance - * @param arg for return code - */ -void chain_mempool_proc(struct dap_http_simple *cl_st, void * arg) -{ - http_status_code_t * return_code = (http_status_code_t*) arg; - // save key while it alive, i.e. still exist - dap_enc_key_t *l_enc_key = dap_enc_ks_find_http(cl_st->http_client); - //dap_enc_key_serialize_t *key_ser = dap_enc_key_serialize(key_tmp); - //dap_enc_key_t *key = dap_enc_key_deserialize(key_ser, sizeof(dap_enc_key_serialize_t)); - - // read header - dap_http_header_t *hdr_session_close_id = - (cl_st->http_client) ? dap_http_header_find(cl_st->http_client->in_headers, "SessionCloseAfterRequest") : NULL; - dap_http_header_t *hdr_key_id = - (hdr_session_close_id && cl_st->http_client) ? dap_http_header_find(cl_st->http_client->in_headers, "KeyID") : NULL; - - enc_http_delegate_t *l_enc_delegate = enc_http_request_decode(cl_st); - if(l_enc_delegate) { - char *suburl = l_enc_delegate->url_path; - byte_t *l_request_data = l_enc_delegate->request_bytes; - size_t l_request_size = l_enc_delegate->request_size; - const char * l_gdb_datum_pool = dap_config_get_item_str_default(g_config, "mempool", "gdb_group", "datum-pool"); - //printf("!!***!!! chain_mempool_proc arg=%d suburl=%s str=%s len=%d\n", arg, suburl, request_str, request_size); - if(l_request_data && l_request_size > 1) { - // find what to do - uint8_t action = DAP_DATUM_MEMPOOL_NONE; //*(uint8_t*) request_str; - if(l_enc_delegate->url_path_size > 0) { - if(!strcmp(suburl, "add")) - action = DAP_DATUM_MEMPOOL_ADD; - else if(!strcmp(suburl, "check")) - action = DAP_DATUM_MEMPOOL_CHECK; - else if(!strcmp(suburl, "del")) - action = DAP_DATUM_MEMPOOL_DEL; - } - dap_datum_mempool_t *datum_mempool = - (action != DAP_DATUM_MEMPOOL_NONE) ? - dap_datum_mempool_deserialize((uint8_t*) l_request_data, (size_t) l_request_size) : NULL; - if(datum_mempool){ - dap_datum_mempool_free(datum_mempool); - char *a_key = s_calc_datum_hash(l_request_data, (size_t) l_request_size); - switch (action) - { - case DAP_DATUM_MEMPOOL_ADD: // add datum in base - //a_value = DAP_NEW_Z_SIZE(char, request_size * 2); - //bin2hex((char*) a_value, (const unsigned char*) request_str, request_size); - if ( dap_global_db_set_sync(l_gdb_datum_pool, a_key, l_request_data, l_request_size, false) == 0 ) { - *return_code = Http_Status_OK; - } - log_it(L_INFO, "Insert hash: key=%s result:%s", a_key, - (*return_code == Http_Status_OK) ? "OK" : "False!"); - break; - - case DAP_DATUM_MEMPOOL_CHECK: // check datum in base - - strcpy(cl_st->reply_mime, "text/text"); - size_t l_datum_size = 0; - byte_t *l_datum = dap_global_db_get_sync( l_gdb_datum_pool, a_key,&l_datum_size,NULL,NULL ); - if(l_datum) { - l_enc_delegate->response = strdup("1"); - DAP_DEL_Z(l_datum); - log_it(L_INFO, "Check hash: key=%s result: Present", a_key); - } - else { - l_enc_delegate->response = strdup("0"); - log_it(L_INFO, "Check hash: key=%s result: Absent", a_key); - } - l_enc_delegate->response_size = l_datum_size; - *return_code = Http_Status_OK; - enc_http_reply_encode_new(cl_st, l_enc_key, l_enc_delegate); - break; - - case DAP_DATUM_MEMPOOL_DEL: // delete datum in base - strcpy(cl_st->reply_mime, "text/text"); - if (dap_global_db_del_sync(l_gdb_datum_pool, a_key) == 0){ - l_enc_delegate->response = dap_strdup("1"); - log_it(L_INFO, "Delete hash: key=%s result: Ok", a_key); - } else { - l_enc_delegate->response = dap_strdup("0"); - log_it(L_INFO, "Delete hash: key=%s result: False!", a_key); - } - // TODO rework to async processing and return result of delete action - *return_code = Http_Status_OK; - enc_http_reply_encode_new(cl_st, l_enc_key, l_enc_delegate); - break; - - default: // unsupported command - log_it(L_INFO, "Unknown request=%s! key=%s", (suburl) ? suburl : "-", a_key); - enc_http_delegate_delete(l_enc_delegate); - dap_enc_ks_delete(hdr_key_id->value); - *return_code = Http_Status_BadRequest; - return; - } - DAP_DEL_Z(a_key); - } else - *return_code = Http_Status_BadRequest; - } else - *return_code = Http_Status_BadRequest; - - enc_http_delegate_delete(l_enc_delegate); - } else - *return_code = Http_Status_Unauthorized; - - if (hdr_session_close_id && !strcmp(hdr_session_close_id->value, "yes") && hdr_key_id) - // close session - dap_enc_ks_delete(hdr_key_id->value); -} - -/** - * @brief chain_mempool_add_proc - * @param sh HTTP server instance - * @param url URL string - */ -void dap_chain_mempool_add_proc(dap_http_server_t * a_http_server, const char * a_url) -{ - dap_http_simple_proc_add(a_http_server, a_url, 4096, chain_mempool_proc); -} - /** * @breif dap_chain_mempool_filter * @param a_chain chain whose mempool will be filtered. @@ -1474,7 +1235,7 @@ void dap_chain_mempool_filter(dap_chain_t *a_chain, int *a_removed){ return; } int l_removed = 0; - char * l_gdb_group = dap_chain_net_get_gdb_group_mempool_new(a_chain); + char * l_gdb_group = dap_chain_mempool_group_new(a_chain); size_t l_objs_size = 0; dap_time_t l_cut_off_time = dap_time_now() - 3 * 24 * 3600; // 3 days char l_cut_off_time_str[DAP_TIME_STR_SIZE] = {'\0'}; diff --git a/modules/mempool/include/dap_chain_mempool.h b/modules/mempool/include/dap_chain_mempool.h index a62d51a5e1c5971542edbb96c79ce279df9a28d2..ce8bcc98482c430801639835980e5cbd109d9e9e 100644 --- a/modules/mempool/include/dap_chain_mempool.h +++ b/modules/mempool/include/dap_chain_mempool.h @@ -51,11 +51,18 @@ int dap_datum_mempool_init(void); extern const char* c_dap_datum_mempool_gdb_group; -uint8_t* dap_datum_mempool_serialize(dap_datum_mempool_t *datum_mempool, size_t *size); -dap_datum_mempool_t * dap_datum_mempool_deserialize(uint8_t *datum_mempool_str, size_t size); - -void dap_datum_mempool_clean(dap_datum_mempool_t *datum); -void dap_datum_mempool_free(dap_datum_mempool_t *datum); +/** + * @brief dap_chain_net_get_gdb_group_mempool + * @param l_chain + * @return + */ +DAP_STATIC_INLINE char *dap_chain_mempool_group_new(dap_chain_t *a_chain) +{ + dap_chain_net_t *l_net = a_chain ? dap_chain_net_by_id(a_chain->net_id) : NULL; + return l_net + ? dap_strdup_printf("%s.chain-%s.mempool", l_net->pub.gdb_groups_prefix, a_chain->name) + : NULL; +} void dap_chain_mempool_add_proc(dap_http_server_t * a_http_server, const char * a_url); diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index 6e69d4d70d94118643432733a456f8be7e74f125..2d1ea5caf4796dfd11f9877d6f4c4b630ba56135 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -81,6 +81,7 @@ #include "dap_chain_datum_decree.h" #include "dap_chain_datum_anchor.h" #include "dap_chain_node_client.h" +#include "dap_chain_mempool.h" #include "dap_chain_net.h" #include "dap_chain_net_node_list.h" #include "dap_chain_net_tx.h" @@ -2494,7 +2495,7 @@ char * dap_chain_net_get_gdb_group_mempool_by_chain_type(dap_chain_net_t *a_net, { for(int i = 0; i < l_chain->datum_types_count; i++) { if(l_chain->datum_types[i] == a_datum_type) - return dap_chain_net_get_gdb_group_mempool_new(l_chain); + return dap_chain_mempool_group_new(l_chain); } } return NULL; @@ -2802,7 +2803,22 @@ int dap_chain_datum_add(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t case DAP_CHAIN_DATUM_CUSTOM: break; default: - return -666; + return -600; + } + return 0; +} + +int dap_chain_datum_add_hardfork_data(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t a_datum_size, dap_hash_fast_t *a_datum_hash, void *a_datum_index_data) +{ + int ret = dap_chain_datum_add(a_chain, a_datum, a_datum_size, a_datum_hash, a_datum_index_data); + if (ret) + return ret; + dap_ledger_t *l_ledger = dap_chain_net_by_id(a_chain->net_id)->pub.ledger; + switch (a_datum->header.type_id) { + case DAP_CHAIN_DATUM_TX: { + return dap_ledger_tx_load_hardfork_data(l_ledger, (dap_chain_datum_tx_t *)a_datum->data, a_datum_hash, (dap_ledger_datum_iter_data_t *)a_datum_index_data); + } + default: return -601; } return 0; } @@ -3209,12 +3225,13 @@ static void s_sync_timer_callback(void *a_arg) l_net_pvt->sync_context.cur_chain->state = CHAIN_SYNC_STATE_WAITING; dap_chain_ch_sync_request_t l_request = {}; uint64_t l_last_num = 0; - if (!dap_chain_get_atom_last_hash_num(l_net_pvt->sync_context.cur_chain, + if (!dap_chain_get_atom_last_hash_num_ts(l_net_pvt->sync_context.cur_chain, l_net_pvt->sync_context.cur_cell ? l_net_pvt->sync_context.cur_cell->id : c_dap_chain_cell_id_null, &l_request.hash_from, - &l_last_num)) { + &l_last_num, + NULL)) { log_it(L_ERROR, "Can't get last atom hash and number for chain %s with net %s", l_net_pvt->sync_context.cur_chain->name, l_net->pub.name); return; diff --git a/modules/net/dap_chain_node.c b/modules/net/dap_chain_node.c index b240cf8e940daac71e616fe7e9aa65bef46ee953..39ad5ac774bcd427b5284c5de096f902c20af268 100644 --- a/modules/net/dap_chain_node.c +++ b/modules/net/dap_chain_node.c @@ -43,14 +43,19 @@ #include "dap_chain_net.h" #include "dap_global_db.h" #include "dap_chain_node.h" -#include "dap_chain_node_client.h" -#include "dap_chain_cs_esbocs.h" +#include "dap_chain_cs_esbocs.h" // TODO set RPC callbacks for exclude consensus specific dependency +#include "dap_chain_cs_blocks.h" // TODO set RPC callbacks for exclude storage type specific dependency #include "dap_chain_ledger.h" #include "dap_cli_server.h" -#include "dap_chain_net_balancer.h" +#include "dap_chain_srv.h" +#include "dap_chain_mempool.h" +#include "dap_chain_datum_service_state.h" +#include "dap_chain_node_client.h" #define LOG_TAG "dap_chain_node" + #define DAP_CHAIN_NODE_NET_STATES_INFO_CURRENT_VERSION 2 + typedef struct dap_chain_node_net_states_info_v1 { dap_chain_node_addr_t address; uint64_t events_count; @@ -69,6 +74,27 @@ typedef struct dap_chain_node_net_states_info { #define node_info_v1_shift ( sizeof(uint16_t) + 16 + sizeof(dap_chain_node_role_t) ) +enum hardfork_state { + STATE_ANCHORS = 0, + STATE_BALANCES, + STATE_CONDOUTS, + STATE_FEES, + STATE_SERVICES, + STATE_MEMPOOL, + STATE_OVER +}; + +struct hardfork_states { + enum hardfork_state state_current; + size_t iterator; + dap_ledger_hardfork_anchors_t *anchors; + dap_ledger_hardfork_balances_t *balances; + dap_ledger_hardfork_condouts_t *condouts; + dap_chain_cs_blocks_hardfork_fees_t *fees; + dap_chain_srv_hardfork_state_t *service_states; + dap_list_t *trusted_addrs; +}; + static const uint64_t s_cmp_delta_timestamp = (uint64_t)1000 /*sec*/ * (uint64_t)1000000000; static const uint64_t s_cmp_delta_event = 0; static const uint64_t s_cmp_delta_atom = 10; @@ -422,14 +448,14 @@ void dap_chain_node_mempool_process_all(dap_chain_t *a_chain, bool a_force) fclose(l_file); } #endif - char *l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_new(a_chain); - size_t l_objs_size = 0; - dap_global_db_obj_t *l_objs = dap_global_db_get_all_sync(l_gdb_group_mempool, &l_objs_size); - if (l_objs_size) { + char *l_gdb_group_mempool = dap_chain_mempool_group_new(a_chain); + size_t l_objs_count = 0; + dap_global_db_obj_t *l_objs = dap_global_db_get_all_sync(l_gdb_group_mempool, &l_objs_count); + if (l_objs_count) { #ifdef DAP_TPS_TEST - log_it(L_TPS, "Get %zu datums from mempool", l_objs_size); + log_it(L_TPS, "Get %zu datums from mempool", l_objs_count); #endif - for (size_t i = 0; i < l_objs_size; i++) { + for (size_t i = 0; i < l_objs_count; i++) { if (l_objs[i].value_len < sizeof(dap_chain_datum_t)) continue; dap_chain_datum_t *l_datum = (dap_chain_datum_t *)l_objs[i].value; @@ -471,11 +497,305 @@ void dap_chain_node_mempool_process_all(dap_chain_t *a_chain, bool a_force) } } } - dap_global_db_objs_delete(l_objs, l_objs_size); + dap_global_db_objs_delete(l_objs, l_objs_count); } DAP_DELETE(l_gdb_group_mempool); } +dap_chain_datum_t **s_service_state_datums_create(dap_chain_srv_hardfork_state_t *a_state, size_t *a_datums_count) +{ + dap_chain_datum_t **ret = NULL; + size_t l_datums_count = 0; + const uint64_t l_max_step_size = DAP_CHAIN_ATOM_MAX_SIZE - sizeof(dap_chain_datum_service_state_t); + uint64_t l_step_size = dap_min(l_max_step_size, a_state->size); + byte_t *l_offset = a_state->data, *l_ptr = l_offset, *l_end = a_state->data + a_state->size * a_state->count; + while (l_offset < l_end) { + size_t l_cur_step_size = 0, i = 0; + while (l_cur_step_size < l_max_step_size && l_offset < l_end) { + size_t l_addition = dap_min((uint64_t)(l_end - l_offset), l_step_size); + l_cur_step_size += l_addition; + l_offset += l_addition; + i++; + } + dap_chain_datum_t *l_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_SERVICE_STATE, l_ptr, sizeof(dap_chain_datum_service_state_t) + l_cur_step_size); + ((dap_chain_datum_service_state_t *)l_datum->data)->srv_uid = a_state->uid; + ((dap_chain_datum_service_state_t *)l_datum->data)->states_count = i; + ret = DAP_REALLOC_RET_VAL_IF_FAIL(ret, sizeof(dap_chain_datum_t *) * (++l_datums_count), NULL, NULL); + ret[l_datums_count - 1] = l_datum; + l_ptr = l_offset; + } + assert(l_offset == l_end); + if (a_datums_count) + *a_datums_count = l_datums_count; + return ret; +} + +int dap_chain_node_hardfork_prepare(dap_chain_t *a_chain, dap_time_t a_last_block_timestamp, dap_list_t *a_trusted_addrs) +{ + if (dap_strcmp(dap_chain_get_cs_type(a_chain), DAP_CHAIN_ESBOCS_CS_TYPE_STR)) + return log_it(L_ERROR, "Can't prepare harfork for chain type %s is not supported", dap_chain_get_cs_type(a_chain)), -2; + dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id); + assert(l_net); + struct hardfork_states *l_states = DAP_NEW_Z_RET_VAL_IF_FAIL(struct hardfork_states, -1, NULL); + l_states->balances = dap_ledger_states_aggregate(l_net->pub.ledger, a_last_block_timestamp, &l_states->condouts); + l_states->anchors = dap_ledger_anchors_aggregate(l_net->pub.ledger); + l_states->fees = dap_chain_cs_blocks_fees_aggregate(a_chain); + size_t l_state_size = 0; + l_states->service_states = dap_chain_srv_hardfork_all(l_net->pub.id); + dap_chain_srv_hardfork_state_t *it, *tmp; + DL_FOREACH_SAFE(l_states->service_states, it, tmp) { + if (it->uid.uint64 < (uint64_t)INT64_MIN) // MSB is not set + continue; + size_t l_datums_count = 0; + dap_chain_datum_t **l_datums = s_service_state_datums_create(it, &l_datums_count); + for (size_t i = 0; i < l_datums_count; i++) + DAP_DELETE(dap_chain_mempool_datum_add(l_datums[i], a_chain, "hex")); + DL_DELETE(l_states->service_states, it); + DAP_DELETE(it); + } + l_states->trusted_addrs = a_trusted_addrs; + a_chain->hardfork_data = l_states; + DAP_CHAIN_CS_BLOCKS(a_chain)->is_hardfork_state = true; + l_net->pub.ledger->is_hardfork_state = true; + return 0; +} + +dap_chain_datum_t *s_datum_tx_create(dap_chain_addr_t *a_addr, const char *a_ticker, uint256_t a_value, dap_list_t *a_trackers) +{ + dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); + if (!l_tx) + return NULL; + if (dap_chain_datum_tx_add_out_ext_item(&l_tx, a_addr, a_value, a_ticker) != 1) { + dap_chain_datum_tx_delete(l_tx); + return NULL; + } + for (dap_list_t *it = a_trackers; it; it = it->next) { + dap_ledger_tracker_t *l_tracker = it->data; + dap_chain_tx_tsd_t *l_tracker_tsd = dap_chain_datum_tx_item_tsd_create(l_tracker, DAP_CHAIN_DATUM_TX_TSD_TYPE_HARDFORK_TRACKER, sizeof(dap_ledger_tracker_t)); + if (!l_tracker_tsd) { + dap_chain_datum_tx_delete(l_tx); + return NULL; + } + if (dap_chain_datum_tx_add_item(&l_tx, l_tracker_tsd) != 1) { + dap_chain_datum_tx_delete(l_tx); + return NULL; + } + } + dap_chain_datum_t *l_datum_tx = dap_chain_datum_create(DAP_CHAIN_DATUM_TX, l_tx, dap_chain_datum_tx_get_size(l_tx)); + dap_chain_datum_tx_delete(l_tx); + return l_datum_tx; +} + +dap_chain_datum_t *s_cond_tx_create(dap_chain_tx_out_cond_t *a_cond, dap_chain_tx_sig_t *a_sign, dap_hash_fast_t *a_hash, const char *a_ticker, dap_list_t *a_trackers) +{ + dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); + if (!l_tx) + return NULL; + if (dap_chain_datum_tx_add_item(&l_tx, a_cond) != 1) { + dap_chain_datum_tx_delete(l_tx); + return NULL; + } + if (dap_chain_datum_tx_add_item(&l_tx, a_sign) != 1) { + dap_chain_datum_tx_delete(l_tx); + return NULL; + } + dap_chain_tx_tsd_t *l_tx_hash_tsd = dap_chain_datum_tx_item_tsd_create(a_hash, DAP_CHAIN_DATUM_TX_TSD_TYPE_HARDFORK_TX_HASH, sizeof(dap_hash_fast_t)); + if (!l_tx_hash_tsd) { + dap_chain_datum_tx_delete(l_tx); + return NULL; + } + if (dap_chain_datum_tx_add_item(&l_tx, l_tx_hash_tsd) != 1) { + dap_chain_datum_tx_delete(l_tx); + return NULL; + } + dap_chain_tx_tsd_t *l_ticker_tsd = dap_chain_datum_tx_item_tsd_create(a_ticker, DAP_CHAIN_DATUM_TX_TSD_TYPE_HARDFORK_TICKER, DAP_CHAIN_TICKER_SIZE_MAX); + if (!l_ticker_tsd) { + dap_chain_datum_tx_delete(l_tx); + return NULL; + } + if (dap_chain_datum_tx_add_item(&l_tx, l_ticker_tsd) != 1) { + dap_chain_datum_tx_delete(l_tx); + return NULL; + } + for (dap_list_t *it = a_trackers; it; it = it->next) { + dap_ledger_tracker_t *l_tracker = it->data; + dap_chain_tx_tsd_t *l_tracker_tsd = dap_chain_datum_tx_item_tsd_create(l_tracker, DAP_CHAIN_DATUM_TX_TSD_TYPE_HARDFORK_TRACKER, sizeof(dap_ledger_tracker_t)); + if (!l_tracker_tsd) { + dap_chain_datum_tx_delete(l_tx); + return NULL; + } + if (dap_chain_datum_tx_add_item(&l_tx, l_tracker_tsd) != 1) { + dap_chain_datum_tx_delete(l_tx); + return NULL; + } + } + dap_chain_datum_t *l_datum_tx = dap_chain_datum_create(DAP_CHAIN_DATUM_TX, l_tx, dap_chain_datum_tx_get_size(l_tx)); + dap_chain_datum_tx_delete(l_tx); + return l_datum_tx; +} + +dap_chain_datum_t *s_fee_tx_create(uint256_t a_value, dap_sign_t *a_owner_sign) +{ + dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); + if (!l_tx) + return NULL; + dap_chain_tx_out_cond_t *l_cond = dap_chain_datum_tx_item_out_cond_create_fee_stack(a_value); + if (dap_chain_datum_tx_add_item(&l_tx, l_cond) != 1) { + dap_chain_datum_tx_delete(l_tx); + return NULL; + } + dap_chain_tx_sig_t *l_tx_sig = dap_chain_tx_sig_create(a_owner_sign); + if (dap_chain_datum_tx_add_item(&l_tx, l_tx_sig) != 1) { + dap_chain_datum_tx_delete(l_tx); + return NULL; + } + dap_chain_datum_t *l_datum_tx = dap_chain_datum_create(DAP_CHAIN_DATUM_TX, l_tx, dap_chain_datum_tx_get_size(l_tx)); + dap_chain_datum_tx_delete(l_tx); + return l_datum_tx; +} + +int dap_chain_node_hardfork_process(dap_chain_t *a_chain) +{ + dap_return_val_if_fail(a_chain, -1); + if (!dap_chain_net_by_id(a_chain->net_id)->pub.mempool_autoproc) + return -2; + if (!a_chain->hardfork_data) + return log_it(L_ERROR, "Can't process chain with no harfork data. Use dap_chain_node_hardfork_prepare() for collect it first"), -2; + struct hardfork_states *l_states = a_chain->hardfork_data; + switch (l_states->state_current) { + case STATE_ANCHORS: + for (dap_ledger_hardfork_anchors_t *it = l_states->anchors; it; it = it->next) { + dap_chain_datum_t *l_datum_anchor = dap_chain_datum_create(DAP_CHAIN_DATUM_TX, it->anchor, dap_chain_datum_anchor_get_size(it->anchor)); + if (!l_datum_anchor) + return -2; + if (!a_chain->callback_add_datums(a_chain, &l_datum_anchor, 1)) { + dap_hash_fast_t l_decree_hash; + dap_chain_datum_anchor_get_hash_from_data(it->anchor, &l_decree_hash); + log_it(L_NOTICE, "Hardfork processed to datum anchor for decree hash %s", dap_hash_fast_to_str_static(&l_decree_hash)); + DAP_DELETE(l_datum_anchor); + break; + } + DAP_DELETE(l_datum_anchor); + } + break; + case STATE_BALANCES: + for (dap_ledger_hardfork_balances_t *it = l_states->balances; it; it = it->next) { + dap_chain_datum_t *l_tx = s_datum_tx_create(&it->addr, it->ticker, it->value, it->trackers); + if (!l_tx) + return -3; + if (!a_chain->callback_add_datums(a_chain, &l_tx, 1)) { + DAP_DELETE(l_tx); + log_it(L_NOTICE, "Hardfork processed to datum tx with addr %s", dap_chain_addr_to_str_static(&it->addr)); + break; + } + DAP_DELETE(l_tx); + } + break; + case STATE_CONDOUTS: + for (dap_ledger_hardfork_condouts_t *it = l_states->condouts; it; it = it->next) { + dap_chain_datum_t *l_cond_tx = s_cond_tx_create(it->cond, it->sign, &it->hash, it->ticker, it->trackers); + if (!l_cond_tx) + return -4; + if (!a_chain->callback_add_datums(a_chain, &l_cond_tx, 1)) { + DAP_DELETE(l_cond_tx); + log_it(L_NOTICE, "Hardfork processed to datum cond_tx with hash %s", dap_hash_fast_to_str_static(&it->hash)); + break; + } + DAP_DELETE(l_cond_tx); + } + break; + case STATE_FEES: + for (dap_chain_cs_blocks_hardfork_fees_t *it = l_states->fees; it; it = it->next) { + dap_chain_datum_t *l_fee_tx = s_fee_tx_create(it->fees_n_rewards_sum, it->owner_sign); + if (!l_fee_tx) + return -4; + if (!a_chain->callback_add_datums(a_chain, &l_fee_tx, 1)) { + DAP_DELETE(l_fee_tx); + dap_hash_fast_t l_pkey_hash; dap_sign_get_pkey_hash(it->owner_sign, &l_pkey_hash); + log_it(L_NOTICE, "Hardfork processed to datum fee_tx with hash %s", dap_hash_fast_to_str_static(&l_pkey_hash)); + break; + } + DAP_DELETE(l_fee_tx); + } + break; + case STATE_SERVICES: + for (dap_chain_srv_hardfork_state_t *it = l_states->service_states; it; it = it->next) { + if (it->uid.uint64 >= (uint64_t)INT64_MIN) // MSB is set + continue; + bool l_break = false; + size_t l_datums_count = 0; + dap_chain_datum_t **l_datums = s_service_state_datums_create(it, &l_datums_count); + for (size_t i = l_states->iterator; i < l_datums_count; i++) { + if (!a_chain->callback_add_datums(a_chain, l_datums + i, 1)) { + log_it(L_NOTICE, "Hardfork processed to datum service_state with uid %" DAP_UINT64_FORMAT_x " and number %zu", + it->uid.uint64, i); + // save iterator to state machine + l_states->iterator = i; + l_break = true; + break; + } + + } + for (size_t i = 0; i < l_datums_count; i++) + DAP_DELETE(l_datums[i]); + DAP_DEL_Z(l_datums); + if (l_break) + break; + } + break; + case STATE_MEMPOOL: { + char *l_gdb_group_mempool = dap_chain_mempool_group_new(a_chain); + size_t l_objs_count = 0; + dap_store_obj_t *l_objs = dap_global_db_get_all_raw_sync(l_gdb_group_mempool, &l_objs_count); + if (!l_objs_count) { + l_states->state_current = STATE_OVER; + break; + } + bool l_nothing_processed = true; + for (size_t i = 0; i < l_objs_count; i++) { + if (l_objs[i].value_len < sizeof(dap_chain_datum_t)) + continue; + if (!l_objs[i].sign) + continue; + dap_stream_node_addr_t l_addr = dap_stream_node_addr_from_sign(l_objs[i].sign); + bool l_addr_match = false; + for (dap_list_t *it = l_states->trusted_addrs; it; it = it->next) { + if (((dap_stream_node_addr_t *)it->data)->uint64 != l_addr.uint64) + continue; + l_addr_match = true; + break; + } + if (!l_addr_match) { + log_it(L_WARNING, "Trying to inject hardfork service state datum from addr " NODE_ADDR_FP_STR, NODE_ADDR_FP_ARGS_S(l_addr)); + continue; + } + dap_chain_datum_t *l_datum = (dap_chain_datum_t *)l_objs[i].value; + if (dap_chain_datum_size(l_datum) != l_objs[i].value_len) + continue; + if (l_datum->header.type_id != DAP_CHAIN_DATUM_SERVICE_STATE) + continue; + if (dap_chain_node_mempool_process(a_chain, l_datum, l_objs[i].key)) + dap_global_db_del(l_gdb_group_mempool, l_objs[i].key, NULL, NULL); + else + l_nothing_processed = false; + } + dap_store_obj_free(l_objs, l_objs_count); + DAP_DELETE(l_gdb_group_mempool); + if (l_nothing_processed) + l_states->state_current = STATE_OVER; + } + + case STATE_OVER: + break; + // No default here + } + return 0; +} + +int dap_chain_node_hardfork_confirm(dap_chain_t *a_chain, dap_chain_datum_t *a_datum) +{ + return 0; +} /** * @brief diff --git a/modules/net/include/dap_chain_net.h b/modules/net/include/dap_chain_net.h index 2a5b858d68e2692b186f73a26346ae873e8bbd82..9cd99062a7e2ef74a0f84cbd215686b57781ed08 100644 --- a/modules/net/include/dap_chain_net.h +++ b/modules/net/include/dap_chain_net.h @@ -143,19 +143,6 @@ int dap_chain_net_link_add(dap_chain_net_t *a_net, dap_stream_node_addr_t *a_add void dap_chain_net_purge(dap_chain_net_t *l_net); -/** - * @brief dap_chain_net_get_gdb_group_mempool - * @param l_chain - * @return - */ -DAP_STATIC_INLINE char *dap_chain_net_get_gdb_group_mempool_new(dap_chain_t *a_chain) -{ - dap_chain_net_t *l_net = a_chain ? dap_chain_net_by_id(a_chain->net_id) : NULL; - return l_net - ? dap_strdup_printf("%s.chain-%s.mempool", l_net->pub.gdb_groups_prefix, a_chain->name) - : NULL; -} - DAP_STATIC_INLINE char *dap_chain_net_get_gdb_group_nochain_new(dap_chain_t *a_chain) { dap_chain_net_t *l_net = a_chain ? dap_chain_net_by_id(a_chain->net_id) : NULL; @@ -187,6 +174,7 @@ void dap_chain_net_srv_order_add_notify_callback(dap_chain_net_t *a_net, dap_sto dap_list_t *dap_chain_datum_list(dap_chain_net_t *a_net, dap_chain_t *a_chain, dap_chain_datum_filter_func_t *a_filter_func, void *a_filter_func_param); int dap_chain_datum_add(dap_chain_t * a_chain, dap_chain_datum_t *a_datum, size_t a_datum_size, dap_hash_fast_t *a_datum_hash, void *a_datum_index_data); +int dap_chain_datum_add_hardfork_data(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t a_datum_size, dap_hash_fast_t *a_datum_hash, void *a_datum_index_data); int dap_chain_datum_remove(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t a_datum_size, dap_hash_fast_t *a_datum_hash); bool dap_chain_net_get_load_mode(dap_chain_net_t * a_net); diff --git a/modules/net/include/dap_chain_node.h b/modules/net/include/dap_chain_node.h index 28c72a6d4190d5f66c360f9ffd9d48aa1d4538ee..e1a0550c9edd8b70c71e854e752bf4949a2203dd 100644 --- a/modules/net/include/dap_chain_node.h +++ b/modules/net/include/dap_chain_node.h @@ -102,6 +102,10 @@ bool dap_chain_node_mempool_process(dap_chain_t *a_chain, dap_chain_datum_t *a_d void dap_chain_node_mempool_process_all(dap_chain_t *a_chain, bool a_force); bool dap_chain_node_mempool_autoproc_init(); inline static void dap_chain_node_mempool_autoproc_deinit() {} + +int dap_chain_node_hardfork_prepare(dap_chain_t *a_chain, dap_time_t a_last_block_timestamp, dap_list_t *a_trusted_addrs); +int dap_chain_node_hardfork_process(dap_chain_t *a_chain); + dap_list_t *dap_chain_node_get_states_list_sort(dap_chain_net_t *a_net, dap_chain_node_addr_t *a_ignored, size_t a_ignored_count); dap_string_t *dap_chain_node_states_info_read(dap_chain_net_t *a_net, dap_stream_node_addr_t a_addr); int dap_chain_node_cli_cmd_values_parse_net_chain_for_json(json_object* a_json_arr_reply, int *a_arg_index, int a_argc, diff --git a/modules/node-cli/dap_chain_node_cli.c b/modules/node-cli/dap_chain_node_cli.c index 9dde939f6347580165cda57e9ccb6e1f500d0e95..735e71f020a37472e983035f5563a0c4c8e9d895 100644 --- a/modules/node-cli/dap_chain_node_cli.c +++ b/modules/node-cli/dap_chain_node_cli.c @@ -380,7 +380,10 @@ int dap_chain_node_cli_init(dap_config_t * g_config) // Decree create command dap_cli_server_cmd_add ("decree", cmd_decree, "Work with decree", - "decree create [common] -net <net_name> [-chain <chain_name>] -decree_chain <chain_name> -certs <certs_list> {-fee <net_fee_value> -to_addr <net_fee_wallet_addr> | -hardfork_from <atom_number> | -new_certs <new_owners_certs_list> | -signs_verify <value>}\n" + "decree create [common] -net <net_name> [-chain <chain_name>] -decree_chain <chain_name> -certs <certs_list> {-fee <net_fee_value> -to_addr <net_fee_wallet_addr> |" + " -hardfork_from <atom_number> [-trusted_addrs <node_addresses>] |" + " -new_certs <new_owners_certs_list> |" + " -signs_verify <value>}\n" "Creates common network decree in net <net_name>. Decree adds to chain -chain and applies to chain -decree_chain. If -chain and -decree_chain is different you must create anchor in -decree_chain that is connected to this decree." "\nCommon decree parameters:\n" "\t -fee <value>: sets network fee\n" diff --git a/modules/node-cli/dap_chain_node_cli_cmd.c b/modules/node-cli/dap_chain_node_cli_cmd.c index aba036a2148a7f8aa7d3f1d78044e00b7128db5e..dd06c89c80043e39faf7fa03370c7f7f9827db32 100644 --- a/modules/node-cli/dap_chain_node_cli_cmd.c +++ b/modules/node-cli/dap_chain_node_cli_cmd.c @@ -95,7 +95,7 @@ struct json_object *wallet_list_json_collect(); dap_chain_t *s_get_chain_with_datum(dap_chain_net_t *a_net, const char *a_datum_hash) { dap_chain_t *l_chain = NULL; DL_FOREACH(a_net->pub.chains, l_chain) { - char *l_gdb_mempool = dap_chain_net_get_gdb_group_mempool_new(l_chain); + char *l_gdb_mempool = dap_chain_mempool_group_new(l_chain); bool is_hash = dap_global_db_driver_is(l_gdb_mempool, a_datum_hash); DAP_DELETE(l_gdb_mempool); if (is_hash) @@ -2145,7 +2145,7 @@ void s_com_mempool_list_print_for_chain(json_object* a_json_arr_reply, dap_chain DAP_DELETE(l_wallet_addr); return; } - char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_new(a_chain); + char * l_gdb_group_mempool = dap_chain_mempool_group_new(a_chain); if(!l_gdb_group_mempool){ dap_json_rpc_error_add(a_json_arr_reply, DAP_CHAIN_NODE_CLI_COM_MEMPOOL_LIST_CAN_NOT_GET_MEMPOOL_GROUP, "%s.%s: chain not found\n", a_net->pub.name, a_chain->name); @@ -2676,7 +2676,7 @@ void s_com_mempool_list_print_for_chain(json_object* a_json_arr_reply, dap_chain } static int mempool_delete_for_chain(dap_chain_t *a_chain, const char * a_datum_hash_str, json_object **a_json_arr_reply) { - char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_new(a_chain); + char * l_gdb_group_mempool = dap_chain_mempool_group_new(a_chain); uint8_t *l_data_tmp = dap_global_db_get_sync(l_gdb_group_mempool, a_datum_hash_str, NULL, NULL, NULL); if (!l_data_tmp) { @@ -2764,7 +2764,7 @@ dap_chain_datum_t *s_com_mempool_check_datum_in_chain(dap_chain_t *a_chain, cons { if (!a_datum_hash_str) return NULL; - char *l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_new(a_chain); + char *l_gdb_group_mempool = dap_chain_mempool_group_new(a_chain); uint8_t *l_data_tmp = dap_global_db_get_sync(l_gdb_group_mempool, a_datum_hash_str, NULL, NULL, NULL); DAP_DELETE(l_gdb_group_mempool); return (dap_chain_datum_t *)l_data_tmp; @@ -2959,7 +2959,7 @@ int _cmd_mempool_proc(dap_chain_net_t *a_net, dap_chain_t *a_chain, const char * dap_chain_t *l_chain = !a_chain ? s_get_chain_with_datum(a_net, a_datum_hash) : a_chain; int ret = 0; - char *l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_new(l_chain); + char *l_gdb_group_mempool = dap_chain_mempool_group_new(l_chain); if (!l_gdb_group_mempool){ dap_json_rpc_error_add(*a_json_arr_reply, DAP_COM_MEMPOOL_PROC_LIST_ERROR_CAN_NOT_GROUP_NAME, "Failed to get mempool group name on network %s", a_net->pub.name); @@ -3213,13 +3213,13 @@ int _cmd_mempool_dump(dap_chain_net_t *a_net, dap_chain_t *a_chain, const char * return COM_DUMP_ERROR_NULL_IS_ARGUMENT_FUNCTION; } if (a_chain) { - char *l_group_mempool = dap_chain_net_get_gdb_group_mempool_new(a_chain); + char *l_group_mempool = dap_chain_mempool_group_new(a_chain); _cmd_mempool_dump_from_group(a_net->pub.id, l_group_mempool, a_datum_hash, a_hash_out_type, a_json_arr_reply); DAP_DELETE(l_group_mempool); } else { dap_chain_t *l_chain = NULL; DL_FOREACH(a_net->pub.chains, l_chain){ - char *l_group_mempool = dap_chain_net_get_gdb_group_mempool_new(l_chain); + char *l_group_mempool = dap_chain_mempool_group_new(l_chain); if (!_cmd_mempool_dump_from_group(a_net->pub.id, l_group_mempool, a_datum_hash, a_hash_out_type, a_json_arr_reply)){ DAP_DELETE(l_group_mempool); break; @@ -3397,7 +3397,7 @@ int com_mempool(int a_argc, char **a_argv, void **a_str_reply) return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; } if(l_chain) { - l_mempool_group = dap_chain_net_get_gdb_group_mempool_new(l_chain); + l_mempool_group = dap_chain_mempool_group_new(l_chain); size_t l_objs_count = 0; dap_global_db_obj_t *l_objs = dap_global_db_get_all_sync(l_mempool_group, &l_objs_count); dap_global_db_objs_delete(l_objs, l_objs_count); @@ -3419,7 +3419,7 @@ int com_mempool(int a_argc, char **a_argv, void **a_str_reply) json_object_array_add(l_jobj_chains, l_jobj_chain); } else { DL_FOREACH(l_net->pub.chains, l_chain) { - l_mempool_group = dap_chain_net_get_gdb_group_mempool_new(l_chain); + l_mempool_group = dap_chain_mempool_group_new(l_chain); size_t l_objs_count = 0; dap_global_db_obj_t *l_objs = dap_global_db_get_all_sync(l_mempool_group, &l_objs_count); dap_global_db_objs_delete(l_objs, l_objs_count); @@ -3503,7 +3503,7 @@ void _cmd_find_type_decree_in_chain(json_object *a_out, dap_chain_t *a_chain, ui } } if (a_where == ALL || a_where == MEMPOOL) { - char *l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_new(a_chain); + char *l_gdb_group_mempool = dap_chain_mempool_group_new(a_chain); size_t l_mempool_count = 0; dap_global_db_obj_t *l_objs = dap_global_db_get_all_sync(l_gdb_group_mempool, &l_mempool_count); for (size_t i = 0; i < l_mempool_count; i++) { @@ -4066,11 +4066,11 @@ int cmd_decree(int a_argc, char **a_argv, void **a_str_reply) *(uint256_t*)(l_tsd->data) = dap_uint256_scan_uninteger(l_param_value_str); l_tsd_list = dap_list_append(l_tsd_list, l_tsd); } else if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-harfork_from", &l_param_value_str)) { + l_subtype = DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_HARDFORK; l_total_tsd_size += sizeof(dap_tsd_t) + sizeof(uint64_t); l_tsd = DAP_NEW_Z_SIZE(dap_tsd_t, l_total_tsd_size); if (!l_tsd) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - dap_list_free_full(l_tsd_list, NULL); return -1; } l_tsd->type = DAP_CHAIN_DATUM_DECREE_TSD_TYPE_BLOCK_NUM; @@ -4078,10 +4078,35 @@ int cmd_decree(int a_argc, char **a_argv, void **a_str_reply) *(uint64_t*)(l_tsd->data) = strtoll(l_param_value_str, NULL, 10); if (!*(uint64_t*)l_tsd->data && dap_strcmp(l_param_value_str, "0")) { log_it(L_ERROR, "Can't converts %s to atom number", l_param_value_str); - dap_list_free_full(l_tsd_list, NULL); + DAP_DELETE(l_tsd); return -1; } l_tsd_list = dap_list_append(l_tsd_list, l_tsd); + if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-trusted_addrs", &l_param_addr_str)) { + char **l_addrs = dap_strsplit(l_param_addr_str, ",", 256); + for (uint16_t i = 0; l_addrs[i]; i++) { + dap_stream_node_addr_t l_addr_cur; + if (dap_stream_node_addr_from_str(&l_addr_cur, l_addrs[i])) { + log_it(L_ERROR, "Can't convert %s to node addr", l_addrs[i]); + dap_list_free_full(l_tsd_list, NULL); + dap_strfreev(l_addrs); + return -5; + } + l_tsd = DAP_NEW_Z_SIZE(dap_tsd_t, sizeof(dap_tsd_t) + sizeof(dap_stream_node_addr_t)); + if (!l_tsd) { + log_it(L_CRITICAL, "%s", c_error_memory_alloc); + dap_list_free_full(l_tsd_list, NULL); + dap_strfreev(l_addrs); + return -1; + } + l_tsd->type = DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR; + l_tsd->size = sizeof(dap_stream_node_addr_t); + + l_tsd_list = dap_list_append(l_tsd_list, l_tsd); + l_total_tsd_size += sizeof(dap_tsd_t) + sizeof(dap_stream_node_addr_t); + } + dap_strfreev(l_addrs); + } } else if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-new_certs", &l_param_value_str)){ l_subtype = DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_OWNERS; dap_cert_parse_str_list(l_param_value_str, &l_new_certs, &l_new_certs_count); @@ -4232,7 +4257,7 @@ int cmd_decree(int a_argc, char **a_argv, void **a_str_reply) return -105; } - char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_new(l_chain); + char * l_gdb_group_mempool = dap_chain_mempool_group_new(l_chain); if(!l_gdb_group_mempool) { l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_by_chain_type(l_net, CHAIN_TYPE_DECREE); } @@ -5003,7 +5028,7 @@ static int s_check_cmd(int a_arg_index, int a_argc, char **a_argv, void **a_str_ dap_chain_datum_t *l_datum = NULL; char *l_gdb_group = NULL; - l_gdb_group = dap_chain_net_get_gdb_group_mempool_new(l_chain); + l_gdb_group = dap_chain_mempool_group_new(l_chain); if (!l_gdb_group) { dap_cli_server_cmd_set_reply_text(a_str_reply, "Not found network group for chain: %s", l_chain->name); l_ret = -1; diff --git a/modules/node-cli/dap_chain_node_cli_cmd_token.c b/modules/node-cli/dap_chain_node_cli_cmd_token.c index d839b90ce1a07c0ca0e97bec95f0df0525bb9727..938e5f665687f32e91421c10494a5be78c158e6b 100644 --- a/modules/node-cli/dap_chain_node_cli_cmd_token.c +++ b/modules/node-cli/dap_chain_node_cli_cmd_token.c @@ -156,7 +156,7 @@ int com_token_decl_sign(int a_argc, char **a_argv, void **a_str_reply) return -7; } - char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_new(l_chain); + char * l_gdb_group_mempool = dap_chain_mempool_group_new(l_chain); if(!l_gdb_group_mempool) { l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_by_chain_type(l_net, CHAIN_TYPE_TOKEN); } @@ -960,7 +960,7 @@ int com_token_decl(int a_argc, char ** a_argv, void **a_str_reply) // Add datum to mempool with datum_token hash as a key char *l_gdb_group_mempool = l_chain - ? dap_chain_net_get_gdb_group_mempool_new(l_chain) + ? dap_chain_mempool_group_new(l_chain) : dap_chain_net_get_gdb_group_mempool_by_chain_type(l_net, CHAIN_TYPE_TOKEN); if (!l_gdb_group_mempool) { dap_cli_server_cmd_set_reply_text(a_str_reply, "No suitable chain for placing token datum found"); @@ -1141,7 +1141,7 @@ int com_token_update(int a_argc, char ** a_argv, void **a_str_reply) // Add datum to mempool with datum_token hash as a key char *l_gdb_group_mempool = l_chain - ? dap_chain_net_get_gdb_group_mempool_new(l_chain) + ? dap_chain_mempool_group_new(l_chain) : dap_chain_net_get_gdb_group_mempool_by_chain_type(l_net, CHAIN_TYPE_TOKEN); if (!l_gdb_group_mempool) { dap_cli_server_cmd_set_reply_text(a_str_reply, "No suitable chain for placing token datum found"); @@ -1345,7 +1345,7 @@ int com_token_emit(int a_argc, char **a_argv, void **a_str_reply) //remove previous emission datum from mempool if have new signed emission datum if (l_emission_hash_str_remove) { - char *l_gdb_group_mempool_emission = dap_chain_net_get_gdb_group_mempool_new(l_chain_emission); + char *l_gdb_group_mempool_emission = dap_chain_mempool_group_new(l_chain_emission); dap_global_db_del_sync(l_gdb_group_mempool_emission, l_emission_hash_str_remove); DAP_DEL_Z(l_gdb_group_mempool_emission); } diff --git a/modules/node-cli/dap_chain_node_cli_cmd_tx.c b/modules/node-cli/dap_chain_node_cli_cmd_tx.c index 32abe86479941ee114c04513e27af28d7c24aa58..7a00029d9d945c84d07044e891f8fc5b17433e0b 100644 --- a/modules/node-cli/dap_chain_node_cli_cmd_tx.c +++ b/modules/node-cli/dap_chain_node_cli_cmd_tx.c @@ -2242,7 +2242,7 @@ void json_rpc_tx_create(json_object *a_param, json_object *a_reply){ return ; } - char *l_gdb_group_mempool_base_tx = dap_chain_net_get_gdb_group_mempool_new(l_chain);// get group name for mempool + char *l_gdb_group_mempool_base_tx = dap_chain_mempool_group_new(l_chain);// get group name for mempool bool l_placed = !dap_global_db_set(l_gdb_group_mempool_base_tx, l_tx_hash_str, l_datum_tx, l_datum_tx_size, false, NULL, NULL); DAP_DELETE(l_datum_tx); @@ -2396,7 +2396,7 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **reply) return DAP_CHAIN_NODE_CLI_COM_TX_CREATE_JSON_CAN_CHECK_TX_ADD_LEDGER; } - char *l_gdb_group_mempool_base_tx = dap_chain_net_get_gdb_group_mempool_new(l_chain);// get group name for mempool + char *l_gdb_group_mempool_base_tx = dap_chain_mempool_group_new(l_chain);// get group name for mempool bool l_placed = !dap_global_db_set(l_gdb_group_mempool_base_tx, l_tx_hash_str, l_datum_tx, l_datum_tx_size, false, NULL, NULL); DAP_DEL_Z(l_datum_tx); @@ -2822,7 +2822,7 @@ int com_tx_verify(int a_argc, char **a_argv, void **a_str_reply) } } size_t l_datum_size = 0; - char *l_gdb_group = dap_chain_net_get_gdb_group_mempool_new(l_chain); + char *l_gdb_group = dap_chain_mempool_group_new(l_chain); dap_chain_datum_t *l_datum = (dap_chain_datum_t*)dap_global_db_get_sync(l_gdb_group, l_hex_str_from58 ? l_hex_str_from58 : l_tx_hash_str, &l_datum_size, NULL, NULL); DAP_DEL_Z(l_hex_str_from58); if (!l_datum) { diff --git a/modules/service/datum/dap_chain_net_srv_datum.c b/modules/service/datum/dap_chain_net_srv_datum.c index b2e0e30bd10846afd9162ab6a099891e26518bc6..768e158fb136c8f26829c39c618f1cabdfdb5c20 100644 --- a/modules/service/datum/dap_chain_net_srv_datum.c +++ b/modules/service/datum/dap_chain_net_srv_datum.c @@ -131,7 +131,7 @@ static int s_srv_datum_cli(int argc, char ** argv, void **a_str_reply) dap_cli_server_cmd_find_option_val(argv, arg_index, argc, "datum", &l_datum_cmd_str); if ( l_datum_cmd_str != NULL ) { if ( strcmp(l_datum_cmd_str, "save") == 0) { - char * l_gdb_group = dap_chain_net_get_gdb_group_mempool_new(l_chain); + char * l_gdb_group = dap_chain_mempool_group_new(l_chain); size_t l_path_length = strlen(l_system_datum_folder)+8+strlen(l_datum_hash_str); char l_path[l_path_length]; @@ -237,7 +237,7 @@ void s_order_notficator(dap_store_obj_t *a_obj, void *a_arg) dap_chain_datum_tx_t *l_tx_cond = NULL; DL_FOREACH(l_net->pub.chains, l_chain) { size_t l_datum_size; - char *l_gdb_group = dap_chain_net_get_gdb_group_mempool_new(l_chain); + char *l_gdb_group = dap_chain_mempool_group_new(l_chain); l_datum = (dap_chain_datum_t *)dap_global_db_get_sync(l_gdb_group, l_tx_cond_hash_str, &l_datum_size, NULL, NULL); if (l_datum) break; 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 f3681b556a305de6408e1265b576656052b24324..7046bcfb1b5c709a398e32b4fce670ce539d808d 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 @@ -683,7 +683,7 @@ static int s_cli_sign(int a_argc, char **a_argv, int a_arg_index, json_object ** dap_json_rpc_error_add(*a_json_arr_reply, ERROR_PLACE, "Can't place transaction for delegated emission in mempool"); return ERROR_PLACE; } - char *l_mempool_group = dap_chain_net_get_gdb_group_mempool_new(a_chain); + char *l_mempool_group = dap_chain_mempool_group_new(a_chain); dap_global_db_del_sync(l_mempool_group, l_tx_in_hash_str); DAP_DELETE(l_mempool_group); json_object * l_json_obj_create_val = json_object_new_object(); diff --git a/modules/service/voting/dap_chain_net_srv_voting.c b/modules/service/voting/dap_chain_net_srv_voting.c index 96b7ddc57c40266fe237a89bcb65326793dd403f..b6f3cd706d5a5f9713275aa699060c262a6e4fc7 100644 --- a/modules/service/voting/dap_chain_net_srv_voting.c +++ b/modules/service/voting/dap_chain_net_srv_voting.c @@ -64,6 +64,7 @@ struct srv_voting { static void *s_callback_start(dap_chain_net_id_t UNUSED_ARG a_net_id, dap_config_t UNUSED_ARG *a_config); static void s_callback_delete(void *a_service_internal); +static byte_t *s_votings_backup(dap_chain_net_id_t a_net_id, uint64_t *a_state_size, uint32_t *a_state_count); static int s_voting_ledger_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx_in, dap_hash_fast_t *a_tx_hash, bool a_apply); static bool s_datum_tx_voting_verification_delete_callback(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx_in, dap_hash_fast_t *a_tx_hash); @@ -100,7 +101,7 @@ int dap_chain_net_srv_voting_init() dap_chain_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_VOTING_ID }; - dap_chain_static_srv_callbacks_t l_srv_callbacks = { .start = s_callback_start, .delete = s_callback_delete }; + dap_chain_static_srv_callbacks_t l_srv_callbacks = { .start = s_callback_start, .delete = s_callback_delete, .hardfork_prepare = s_votings_backup }; int ret = dap_chain_srv_add(l_uid, "voting", &l_srv_callbacks); if (ret) { log_it(L_ERROR, "Can't register voting service"); @@ -1426,59 +1427,49 @@ static size_t s_voting_serial_size_calc(struct voting *a_voting, size_t *a_votes return ret; } -static int s_voting_dump(dap_chain_datum_t **a_dump_datum, struct voting *a_voting) +static byte_t *s_votings_backup(dap_chain_net_id_t a_net_id, uint64_t *a_state_size, uint32_t *a_state_count) { - size_t l_votes_count = 0; - size_t l_voting_size = s_voting_serial_size_calc(a_voting, &l_votes_count); - dap_chain_datum_t *l_dump_datum = DAP_REALLOC(*a_dump_datum, dap_chain_datum_size(*a_dump_datum) + l_voting_size); - if (!l_dump_datum) { - DAP_DELETE(*a_dump_datum); - return -1; - } - l_dump_datum->header.data_size += l_voting_size; - struct voting_serial *cur = (struct voting_serial *)(l_dump_datum->data + l_dump_datum->header.data_size); - *cur = (struct voting_serial) { - .size = l_voting_size, - .hash = a_voting->hash, - .voting_start = a_voting->start_time, - .voting_expire = a_voting->params->voting_expire, - .votes_max_count = a_voting->params->votes_max_count, - .votes_count = l_votes_count, - .delegate_key_required = a_voting->params->delegate_key_required, - .vote_changing_allowed = a_voting->params->vote_changing_allowed - }; - byte_t *l_tsd = dap_tsd_write(cur->question_n_options_n_votes, VOTING_TSD_TYPE_QUESTION, a_voting->params->question, strlen(a_voting->params->question)); - for (dap_list_t *it = a_voting->params->options; it; it = it->next) - l_tsd = dap_tsd_write(l_tsd, VOTING_TSD_TYPE_OPTION, it->data, strlen(it->data)); - for (dap_list_t *it = a_voting->votes; it; it = it->next) - l_tsd = dap_tsd_write(l_tsd, VOTING_TSD_TYPE_VOTE, it->data, sizeof(struct vote)); - assert(l_tsd == l_dump_datum->data + l_dump_datum->header.data_size); - *a_dump_datum = l_dump_datum; - return 0; -} - -static int s_votings_backup(dap_chain_net_t *a_net) -{ - struct voting *votings_ht = s_votings_ht_get(a_net->pub.id); + if (a_state_count) + *a_state_count = 0; + dap_chain_net_t *l_net = dap_chain_net_by_id(a_net_id); + assert(l_net); + struct voting *votings_ht = s_votings_ht_get(l_net->pub.id); if (!votings_ht) { - log_it(L_INFO, "No data to backup for voting service for net id 0x%016" DAP_UINT64_FORMAT_x, a_net->pub.id.uint64); - return 0; + log_it(L_INFO, "No data to backup for voting service for net id 0x%016" DAP_UINT64_FORMAT_x, l_net->pub.id.uint64); + return NULL; } - dap_chain_datum_t *l_hardfork_state_datum = dap_chain_datum_create(DAP_CHAIN_DATUM_SERVICE_STATE, NULL, sizeof(dap_chain_datum_service_state_t)); - if (!l_hardfork_state_datum) - return -1; - size_t i = 0; - for (struct voting *it = votings_ht; it; it = it->hh.next, i++) { - int ret = s_voting_dump(&l_hardfork_state_datum, it); - if (ret) - return ret; + size_t l_states_count = HASH_COUNT(votings_ht); + byte_t *ret = (byte_t *)DAP_NEW_Z_COUNT_RET_VAL_IF_FAIL(struct voting_serial, l_states_count, NULL, NULL); + size_t l_total_size = 0; + for (struct voting *it = votings_ht; it; it = it->hh.next) { + size_t l_votes_count = 0; + size_t l_voting_size = s_voting_serial_size_calc(it, &l_votes_count); + ret = DAP_REALLOC_RET_VAL_IF_FAIL(ret, l_total_size + l_voting_size, NULL, NULL); + struct voting_serial *cur = (struct voting_serial *)(ret + l_total_size); + l_total_size += l_voting_size; + *cur = (struct voting_serial) { + .size = l_voting_size, + .hash = it->hash, + .voting_start = it->start_time, + .voting_expire = it->params->voting_expire, + .votes_max_count = it->params->votes_max_count, + .votes_count = l_votes_count, + .delegate_key_required = it->params->delegate_key_required, + .vote_changing_allowed = it->params->vote_changing_allowed + }; + byte_t *l_tsd = dap_tsd_write(cur->question_n_options_n_votes, VOTING_TSD_TYPE_QUESTION, it->params->question, strlen(it->params->question)); + for (dap_list_t *lst = it->params->options; lst; lst = lst->next) + l_tsd = dap_tsd_write(l_tsd, VOTING_TSD_TYPE_OPTION, lst->data, strlen(lst->data)); + for (dap_list_t *lst = it->votes; lst; lst = lst->next) + l_tsd = dap_tsd_write(l_tsd, VOTING_TSD_TYPE_VOTE, lst->data, sizeof(struct vote)); + assert(l_tsd == ret + l_total_size); } - ((dap_chain_datum_service_state_t *)l_hardfork_state_datum->data)->srv_uid = (dap_chain_srv_uid_t) { .uint64 = DAP_CHAIN_NET_SRV_VOTING_ID }; - ((dap_chain_datum_service_state_t *)l_hardfork_state_datum->data)->states_count = i; - dap_chain_t *l_chain = dap_chain_net_get_default_chain_by_chain_type(a_net, CHAIN_TYPE_TX); - char *l_datum_hash = dap_chain_mempool_datum_add(l_hardfork_state_datum, l_chain, "hex"); - log_it(L_INFO, "Datum hash %s with voting service states successfully placed in mempool", l_datum_hash); - DAP_DELETE(l_datum_hash); + if (a_state_count) + *a_state_count = l_states_count; + if (a_state_size) + *a_state_size = l_total_size / l_states_count; + if (*a_state_size) + (*a_state_size)--; return 0; } diff --git a/modules/type/blocks/dap_chain_block.c b/modules/type/blocks/dap_chain_block.c index 7b7349c25e037c3dc3d71429fe4384c60bf6b4bf..2f5131931bbde985ec5b32942c79845e96c0cdd0 100644 --- a/modules/type/blocks/dap_chain_block.c +++ b/modules/type/blocks/dap_chain_block.c @@ -517,6 +517,7 @@ static uint8_t *s_meta_extract(dap_chain_block_meta_t *a_meta) s_meta_type_to_string(a_meta->hdr.type), a_meta->hdr.data_size, sizeof(uint8_t)); break; case DAP_CHAIN_BLOCK_META_EXCLUDED_KEYS: + case DAP_CHAIN_BLOCK_META_GENERATION: if (a_meta->hdr.data_size >= sizeof(uint16_t)) { uint16_t l_expected_size = *(uint16_t *)a_meta->data + sizeof(uint16_t); if (!(l_expected_size % sizeof(uint16_t)) && @@ -578,12 +579,13 @@ int dap_chain_block_meta_extract(dap_chain_block_t *a_block, size_t a_block_size size_t *a_block_links_count, bool *a_is_genesis, uint64_t *a_nonce, - uint64_t *a_nonce2) + uint64_t *a_nonce2, + uint16_t *a_generation) { dap_return_val_if_fail(a_block && a_block_size, -1); // Check for meta that could be faced only once bool l_was_prev = false, l_was_genesis = false, l_was_anchor = false, l_was_nonce = false, - l_was_nonce2 = false, l_was_merkle = false, l_was_reward = false; + l_was_nonce2 = false, l_was_merkle = false, l_was_reward = false, l_was_generation = false; // Init links parsing size_t l_links_count = 0, l_links_count_max = 5; if (a_block_size < sizeof(a_block->hdr)) { @@ -703,6 +705,20 @@ int dap_chain_block_meta_extract(dap_chain_block_t *a_block, size_t a_block_size return -4; } break; + case DAP_CHAIN_BLOCK_META_GENERATION: + if (l_was_generation) { + log_it(L_WARNING, "Generaion number could be only one in the block, meta #%zu is ignored ", i); + break; + } + l_was_generation = true; + if (a_generation) { + l_meta_data = s_meta_extract(l_meta); + if (l_meta_data) + *a_generation = *(uint16_t *)l_meta_data; + else + return -4; + } + break; case DAP_CHAIN_BLOCK_META_EMERGENCY: case DAP_CHAIN_BLOCK_META_EXCLUDED_KEYS: case DAP_CHAIN_BLOCK_META_SYNC_ATTEMPT: diff --git a/modules/type/blocks/dap_chain_block_cache.c b/modules/type/blocks/dap_chain_block_cache.c index 707a6d4903d81f7ddbe039249f436c6ff8939b63..f05dea7a552d7c3b1bda961add3f82ca4a00a33f 100644 --- a/modules/type/blocks/dap_chain_block_cache.c +++ b/modules/type/blocks/dap_chain_block_cache.c @@ -115,7 +115,8 @@ int dap_chain_block_cache_update(dap_chain_block_cache_t *a_block_cache, dap_has &a_block_cache->links_hash_count, &a_block_cache->is_genesis, &a_block_cache->nonce, - &a_block_cache->nonce2)) + &a_block_cache->nonce2, + &a_block_cache->generation)) return -1; DAP_DEL_Z(a_block_cache->datum); diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c index b98acbf16dc5d40042b231ee24f7e2181fb59836..67409a44d75efb02e10f5cdbc20bba6378dda6f3 100644 --- a/modules/type/blocks/dap_chain_cs_blocks.c +++ b/modules/type/blocks/dap_chain_cs_blocks.c @@ -694,7 +694,7 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) }break; case SUBCMD_NEW_DATUM_ADD:{ size_t l_datums_count=1; - char * l_gdb_group_mempool = dap_chain_net_get_gdb_group_mempool_new(l_chain); + char * l_gdb_group_mempool = dap_chain_mempool_group_new(l_chain); dap_chain_datum_t ** l_datums = DAP_NEW_Z_SIZE(dap_chain_datum_t*, sizeof(dap_chain_datum_t*)*l_datums_count); if (!l_datums) { @@ -1525,8 +1525,9 @@ static int s_add_atom_datums(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_ca size_t l_block_offset = 0; size_t l_datum_size = 0; - for(size_t i=0; i<a_block_cache->datum_count && l_block_offset +sizeof(a_block_cache->block->hdr) < a_block_cache->block_size ; - i++, l_block_offset += l_datum_size ){ + for (size_t i = 0; + i < a_block_cache->datum_count && l_block_offset + sizeof(a_block_cache->block->hdr) < a_block_cache->block_size; + i++, l_block_offset += l_datum_size) { dap_chain_datum_t *l_datum = a_block_cache->datum[i]; size_t l_datum_data_size = l_datum->header.data_size; l_datum_size = l_datum_data_size + sizeof(l_datum->header); @@ -1538,8 +1539,10 @@ static int s_add_atom_datums(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_ca dap_hash_fast_t *l_datum_hash = a_block_cache->datum_hash + i; dap_ledger_datum_iter_data_t l_datum_index_data = { .token_ticker = "0", .action = DAP_CHAIN_TX_TAG_ACTION_UNKNOWN , .uid.uint64 = 0 }; - int l_res = dap_chain_datum_add(a_blocks->chain, l_datum, l_datum_size, l_datum_hash, &l_datum_index_data); - if (l_datum->header.type_id != DAP_CHAIN_DATUM_TX || l_res != DAP_LEDGER_CHECK_ALREADY_CACHED){ // If this is any datum other than a already cached transaction + int l_res = (a_block_cache->generation && a_block_cache->generation == a_blocks->generation) + ? dap_chain_datum_add_hardfork_data(a_blocks->chain, l_datum, l_datum_size, l_datum_hash, &l_datum_index_data) + : dap_chain_datum_add(a_blocks->chain, l_datum, l_datum_size, l_datum_hash, &l_datum_index_data); + if (l_datum->header.type_id != DAP_CHAIN_DATUM_TX || l_res != DAP_LEDGER_CHECK_ALREADY_CACHED) { // If this is any datum other than a already cached transaction l_ret++; if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX) PVT(a_blocks)->tx_count++; @@ -1561,7 +1564,7 @@ static int s_add_atom_datums(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_ca HASH_ADD(hh, PVT(a_blocks)->datum_index, datum_hash, sizeof(*l_datum_hash), l_datum_index); pthread_rwlock_unlock(&PVT(a_blocks)->datums_rwlock); dap_chain_cell_t *l_cell = dap_chain_cell_find_by_id(a_blocks->chain, a_blocks->chain->active_cell_id); - dap_chain_datum_notify(l_cell, l_datum_hash, &l_datum_index->block_cache->block_hash, (byte_t*)l_datum, l_datum_size, l_res, l_datum_index_data.action, l_datum_index_data.uid); + dap_chain_datum_notify(l_cell, l_datum_hash, &l_datum_index->block_cache->block_hash, (byte_t *)l_datum, l_datum_size, l_res, l_datum_index_data.action, l_datum_index_data.uid); } } debug_if(s_debug_more, L_DEBUG, "Block %s checked, %s", a_block_cache->block_hash_str, @@ -2051,7 +2054,7 @@ static dap_chain_atom_verify_res_t s_callback_atom_verify(dap_chain_t *a_chain, } } - if (ret == ATOM_FORK || ret == ATOM_ACCEPT) { + if (ret == ATOM_ACCEPT || (!l_blocks->is_hardfork_state && ret == ATOM_FORK)) { // 2nd level consensus if (l_blocks->callback_block_verify && l_blocks->callback_block_verify(l_blocks, l_block, a_atom_hash, /* Old bug, crutch for it */ a_atom_size)) { // Hard accept list @@ -2767,12 +2770,12 @@ static int s_aggregate_fees(dap_chain_cs_blocks_hardfork_fees_t **a_out_list, da } switch (a_type) { case DAP_CHAIN_BLOCK_COLLECT_FEES: - if (SUM_256_256(l_exist->fees_sum, a_value, &l_exist->fees_sum)) { + if (SUM_256_256(l_exist->fees_n_rewards_sum, a_value, &l_exist->fees_n_rewards_sum)) { log_it(L_ERROR, "Integer overflow of hardfork aggregated data for not withdrowed fees"); return -2; } break; case DAP_CHAIN_BLOCK_COLLECT_REWARDS: - if (SUM_256_256(l_exist->rewards_sum, a_value, &l_exist->rewards_sum)) { + if (SUM_256_256(l_exist->fees_n_rewards_sum, a_value, &l_exist->fees_n_rewards_sum)) { log_it(L_ERROR, "Integer overflow of hardfork aggregated data for not withdrowed rewards"); return -2; } break; diff --git a/modules/type/blocks/include/dap_chain_block.h b/modules/type/blocks/include/dap_chain_block.h index a0407e390a52d9a2a759d96fd0ee9dca63d17271..c21e531057a10b39334f2337f4cd5476d05d3fdb 100644 --- a/modules/type/blocks/include/dap_chain_block.h +++ b/modules/type/blocks/include/dap_chain_block.h @@ -63,6 +63,7 @@ typedef struct dap_chain_block_meta{ // Block metadata types #define DAP_CHAIN_BLOCK_META_GENESIS 0x01 +#define DAP_CHAIN_BLOCK_META_GENERATION 0x02 #define DAP_CHAIN_BLOCK_META_PREV 0x10 #define DAP_CHAIN_BLOCK_META_ANCHOR 0x11 #define DAP_CHAIN_BLOCK_META_LINK 0x12 @@ -104,7 +105,8 @@ int dap_chain_block_meta_extract(dap_chain_block_t *a_block, size_t a_block_size size_t *a_block_links_count, bool *a_is_genesis, uint64_t *a_nonce, - uint64_t *a_nonce2); + uint64_t *a_nonce2, + uint16_t *a_generation); // Add datum in block size_t dap_chain_block_datum_add(dap_chain_block_t ** a_block_ptr, size_t a_block_size, dap_chain_datum_t * a_datum, size_t a_datum_size); size_t dap_chain_block_datum_del_by_hash(dap_chain_block_t ** a_block_ptr, size_t a_block_size, dap_chain_hash_fast_t* a_datum_hash); diff --git a/modules/type/blocks/include/dap_chain_block_cache.h b/modules/type/blocks/include/dap_chain_block_cache.h index 01d6e5801c22612719d2d873c3ed2b5899fa2f56..24eca3786dd8cc36cd05b4cbb3de864d5d077ec8 100644 --- a/modules/type/blocks/include/dap_chain_block_cache.h +++ b/modules/type/blocks/include/dap_chain_block_cache.h @@ -52,6 +52,7 @@ typedef struct dap_chain_block_cache { uint64_t nonce; uint64_t nonce2; bool is_genesis; + uint16_t generation; // Block's signatures size_t sign_count; // Number of signatures in block's tail diff --git a/modules/type/blocks/include/dap_chain_cs_blocks.h b/modules/type/blocks/include/dap_chain_cs_blocks.h index b792f244e7af083e0cdf77f840edc4d14174974a..d260fdcfa37f4ee110952495ed8a316c80e772c9 100644 --- a/modules/type/blocks/include/dap_chain_cs_blocks.h +++ b/modules/type/blocks/include/dap_chain_cs_blocks.h @@ -39,13 +39,14 @@ typedef dap_chain_block_t * (*dap_chain_cs_blocks_callback_block_create_t)(dap_c dap_chain_datum_t *, dap_chain_hash_fast_t *, size_t, size_t*); -typedef struct dap_chain_cs_blocks -{ - dap_chain_t * chain; - // For new block creating - dap_chain_block_t * block_new; +typedef struct dap_chain_cs_blocks { + dap_chain_t *chain; + dap_chain_block_t *block_new; // For new block creating size_t block_new_size; + bool is_hardfork_state; + uint16_t generation; + dap_chain_cs_blocks_callback_t callback_delete; dap_chain_cs_blocks_callback_block_create_t callback_block_create; dap_chain_cs_blocks_callback_block_verify_t callback_block_verify; @@ -80,8 +81,7 @@ typedef enum s_com_blocks_err{ typedef struct dap_chain_cs_blocks_hardfork_fees { dap_sign_t *owner_sign; - uint256_t fees_sum; - uint256_t rewards_sum; + uint256_t fees_n_rewards_sum; struct dap_chain_cs_blocks_hardfork_fees *prev, *next; } dap_chain_cs_blocks_hardfork_fees_t; @@ -91,6 +91,8 @@ int dap_chain_cs_blocks_init(); void dap_chain_cs_blocks_deinit(); dap_chain_block_cache_t *dap_chain_block_cache_get_by_hash(dap_chain_cs_blocks_t *a_blocks, dap_chain_hash_fast_t *a_block_hash); +dap_chain_cs_blocks_hardfork_fees_t *dap_chain_cs_blocks_fees_aggregate(dap_chain_t *a_chain); + DAP_STATIC_INLINE char *dap_chain_cs_blocks_get_fee_group(const char *a_net_name) { return dap_strdup_printf("local.%s.fees", a_net_name);