diff --git a/modules/chain/dap_chain.c b/modules/chain/dap_chain.c index 29bc7d426a3d387907dd373e41525644440e6298..40dd5a09aac75d5f8d27ad9e3e7d923b3f6c9803 100644 --- a/modules/chain/dap_chain.c +++ b/modules/chain/dap_chain.c @@ -147,7 +147,9 @@ void dap_chain_set_cs_type(dap_chain_t *a_chain, const char *a_cs_type) int dap_chain_purge(dap_chain_t *a_chain) { int ret = dap_chain_cs_class_purge(a_chain); - return ret + dap_chain_cs_purge(a_chain); + ret += dap_chain_cs_purge(a_chain); + dap_chain_cell_close_all(a_chain); + return ret; } /** @@ -348,6 +350,15 @@ static bool s_datum_in_chain_types(uint16_t datum_type, dap_chain_type_t *chain_ return (false); } +bool dap_chain_datum_type_supported_by_chain(dap_chain_t *a_chain, uint16_t a_datum_type) +{ + dap_return_val_if_fail(a_chain, false); + for (uint16_t i = 0; i < a_chain->datum_types_count; i++) + if (s_chain_type_convert(a_chain->datum_types[i]) == a_datum_type) + return true; + return false; +} + /** * @brief dap_chain_load_from_cfg * Loading chain from config file @@ -706,7 +717,8 @@ void dap_chain_atom_confirmed_notify_add(dap_chain_t *a_chain, dap_chain_callbac */ 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_return_val_if_fail(a_chain && a_chain->callback_atom_iter_create && + a_chain->callback_atom_iter_get && a_chain->callback_atom_iter_delete, false); dap_chain_atom_iter_t *l_iter = a_chain->callback_atom_iter_create(a_chain, a_cell_id, NULL); if (!l_iter) return false; diff --git a/modules/chain/dap_chain_srv.c b/modules/chain/dap_chain_srv.c index 7d9d9ce1b34538c1521713ab9ea55b161f8abe61..625026a9967e91decf3a8b26b2e3fdffbb242adb 100644 --- a/modules/chain/dap_chain_srv.c +++ b/modules/chain/dap_chain_srv.c @@ -44,28 +44,28 @@ struct service_list { // list of active services static struct service_list *s_srv_list = NULL; // for separate access to s_srv_list -static pthread_mutex_t s_srv_list_mutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_rwlock_t s_srv_list_lock = PTHREAD_RWLOCK_INITIALIZER; void dap_chain_srv_deinit() { struct service_list *it, *tmp; - pthread_mutex_lock(&s_srv_list_mutex); + int err = pthread_rwlock_wrlock(&s_srv_list_lock); + assert(!err); HASH_ITER(hh, s_srv_list, it, tmp) { // Clang bug at this, l_service_item should change at every loop cycle HASH_DEL(s_srv_list, it); dap_list_t *itl, *tmpl; DL_FOREACH_SAFE(it->networks, itl, tmpl) { struct network_service *l_service = itl->data; - if (it->callbacks.delete) - it->callbacks.delete(l_service->service); - else - DAP_DEL_Z(l_service->service); + if (it->callbacks.purge) + it->callbacks.purge(l_service->net_id, l_service->service); + DAP_DEL_Z(l_service->service); DAP_DELETE(l_service); DAP_DELETE(itl); } DAP_DELETE(it); } - pthread_mutex_unlock(&s_srv_list_mutex); + pthread_rwlock_unlock(&s_srv_list_lock); } @@ -73,17 +73,18 @@ int dap_chain_srv_add(dap_chain_srv_uid_t a_uid, const char *a_name, dap_chain_s { struct service_list *l_service_item = NULL; - pthread_mutex_lock(&s_srv_list_mutex); + int err = pthread_rwlock_wrlock(&s_srv_list_lock); + assert(!err); HASH_FIND(hh, s_srv_list, &a_uid, sizeof(a_uid), l_service_item); if (l_service_item) { log_it(L_ERROR, "Already present service with 0x%016"DAP_UINT64_FORMAT_X, a_uid.uint64); - pthread_mutex_unlock(&s_srv_list_mutex); + pthread_rwlock_unlock(&s_srv_list_lock); return -1; } l_service_item = DAP_NEW_Z(struct service_list); if (!l_service_item) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - pthread_mutex_unlock(&s_srv_list_mutex); + pthread_rwlock_unlock(&s_srv_list_lock); return -2; } l_service_item->uuid = a_uid; @@ -92,7 +93,7 @@ int dap_chain_srv_add(dap_chain_srv_uid_t a_uid, const char *a_name, dap_chain_s if (a_static_callbacks) l_service_item->callbacks = *a_static_callbacks; HASH_ADD(hh, s_srv_list, uuid, sizeof(a_uid), l_service_item); - pthread_mutex_unlock(&s_srv_list_mutex); + pthread_rwlock_unlock(&s_srv_list_lock); return 0; } @@ -109,23 +110,25 @@ static struct network_service *s_net_service_find(struct service_list *a_service static struct service_list *s_service_find(dap_chain_srv_uid_t a_srv_uid) { struct service_list *l_service_item = NULL; - pthread_mutex_lock(&s_srv_list_mutex); + int err = pthread_rwlock_rdlock(&s_srv_list_lock); + assert(!err); HASH_FIND(hh, s_srv_list, &a_srv_uid, sizeof(dap_chain_srv_uid_t), l_service_item); - pthread_mutex_unlock(&s_srv_list_mutex); + pthread_rwlock_unlock(&s_srv_list_lock); return l_service_item; } static struct service_list *s_find_by_name(const char *a_name) { dap_return_val_if_fail(a_name, NULL); - pthread_mutex_lock(&s_srv_list_mutex); + int err = pthread_rwlock_rdlock(&s_srv_list_lock); + assert(!err); for (struct service_list *it = s_srv_list; it; it = it->hh.next) { if (!dap_strcmp(it->name, a_name)) { - pthread_mutex_unlock(&s_srv_list_mutex); + pthread_rwlock_unlock(&s_srv_list_lock); return it; } } - pthread_mutex_unlock(&s_srv_list_mutex); + pthread_rwlock_unlock(&s_srv_list_lock); return NULL; } @@ -146,21 +149,21 @@ int dap_chain_srv_start(dap_chain_net_id_t a_net_id, const char *a_name, dap_con int dap_chain_srv_delete(dap_chain_srv_uid_t a_srv_uid) { struct service_list *l_service_item = NULL; - pthread_mutex_lock(&s_srv_list_mutex); + int err = pthread_rwlock_wrlock(&s_srv_list_lock); + assert(!err); HASH_FIND(hh, s_srv_list, &a_srv_uid, sizeof(a_srv_uid), l_service_item); if (!l_service_item) { - pthread_mutex_unlock(&s_srv_list_mutex); + pthread_rwlock_unlock(&s_srv_list_lock); return -1; } HASH_DEL(s_srv_list, l_service_item); - pthread_mutex_unlock(&s_srv_list_mutex); + pthread_rwlock_unlock(&s_srv_list_lock); dap_list_t *it, *tmp; DL_FOREACH_SAFE(l_service_item->networks, it, tmp) { struct network_service *l_service = it->data; - if (l_service_item->callbacks.delete) - l_service_item->callbacks.delete(l_service->service); - else - DAP_DEL_Z(l_service->service); + if (l_service_item->callbacks.purge) + l_service_item->callbacks.purge(l_service->net_id, l_service->service); + DAP_DEL_Z(l_service->service); DAP_DELETE(l_service); DAP_DELETE(it); } @@ -171,9 +174,9 @@ int dap_chain_srv_delete(dap_chain_srv_uid_t a_srv_uid) int dap_chain_srv_purge(dap_chain_net_id_t a_net_id, dap_chain_srv_uid_t a_srv_uid) { struct service_list *l_service_item = s_service_find(a_srv_uid); - if (l_service_item && s_net_service_find(l_service_item, a_net_id) && - l_service_item->callbacks.purge) - return l_service_item->callbacks.purge(a_net_id); + struct network_service *l_service = s_net_service_find(l_service_item, a_net_id); + if (l_service_item && l_service_item->callbacks.purge && l_service) + return l_service_item->callbacks.purge(l_service->net_id, l_service->service); return 0; } @@ -184,12 +187,17 @@ int dap_chain_srv_purge(dap_chain_net_id_t a_net_id, dap_chain_srv_uid_t a_srv_u int dap_chain_srv_purge_all(dap_chain_net_id_t a_net_id) { int ret = 0; - 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.purge) - ret += it->callbacks.purge(a_net_id); + int err = pthread_rwlock_rdlock(&s_srv_list_lock); + assert(!err); + for (struct service_list *it = s_srv_list; it; it = it->hh.next) { + if (!it->callbacks.purge) + continue; + struct network_service *l_service = s_net_service_find(it, a_net_id); + if (!l_service) + continue; + ret += it->callbacks.purge(l_service->net_id, l_service->service); } - pthread_mutex_unlock(&s_srv_list_mutex); + pthread_rwlock_unlock(&s_srv_list_lock); return ret; } @@ -200,19 +208,26 @@ int dap_chain_srv_purge_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); + int err = pthread_rwlock_rdlock(&s_srv_list_lock); + assert(!err); 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_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); + if (!it->callbacks.hardfork_prepare) + continue; + struct network_service *l_service = s_net_service_find(it, a_net_id); + if (!l_service) + continue; + dap_chain_srv_hardfork_state_t *l_state = DAP_NEW_Z(dap_chain_srv_hardfork_state_t), *cur, *tmp; + if (!l_state) { + log_it(L_CRITICAL, "%s", c_error_memory_alloc); + DL_FOREACH_SAFE(ret, cur, tmp) + DAP_DELETE(cur); + break; } + l_state->uid = it->uuid; + l_state->data = it->callbacks.hardfork_prepare(a_net_id, &l_state->size, &l_state->count, l_service->service); + DL_APPEND(ret, l_state); } - pthread_mutex_unlock(&s_srv_list_mutex); + pthread_rwlock_unlock(&s_srv_list_lock); return ret; } @@ -231,12 +246,13 @@ int dap_chain_srv_load_state(dap_chain_net_id_t a_net_id, dap_chain_srv_uid_t a_ json_object *dap_chain_srv_get_fees(dap_chain_net_id_t a_net_id) { json_object *ret = json_object_new_array(); - pthread_mutex_lock(&s_srv_list_mutex); + int err = pthread_rwlock_rdlock(&s_srv_list_lock); + assert(!err); for (struct service_list *it = s_srv_list; it; it = it->hh.next) { if (s_net_service_find(it, a_net_id) && it->callbacks.get_fee_descr) json_object_array_add(ret, it->callbacks.get_fee_descr(a_net_id)); } - pthread_mutex_unlock(&s_srv_list_mutex); + pthread_rwlock_unlock(&s_srv_list_lock); return ret; } @@ -289,11 +305,12 @@ dap_chain_srv_uid_t dap_chain_srv_get_uid_by_name(const char *a_name) size_t dap_chain_srv_count(dap_chain_net_id_t a_net_id) { size_t l_count = 0; - pthread_mutex_lock(&s_srv_list_mutex); + int err = pthread_rwlock_rdlock(&s_srv_list_lock); + assert(!err); for (struct service_list *it = s_srv_list; it; it = it->hh.next) if (s_net_service_find(it, a_net_id)) l_count++; - pthread_mutex_unlock(&s_srv_list_mutex); + pthread_rwlock_unlock(&s_srv_list_lock); return l_count; } @@ -304,11 +321,12 @@ size_t dap_chain_srv_count(dap_chain_net_id_t a_net_id) dap_list_t *dap_chain_srv_list(dap_chain_net_id_t a_net_id) { dap_list_t *l_list = NULL; - pthread_mutex_lock(&s_srv_list_mutex); + int err = pthread_rwlock_rdlock(&s_srv_list_lock); + assert(!err); // Iterate services and save them to list for (struct service_list *it = s_srv_list; it; it = it->hh.next) if (s_net_service_find(it, a_net_id)) l_list = dap_list_append(l_list, DAP_DUP(&it->uuid)); - pthread_mutex_unlock(&s_srv_list_mutex); + pthread_rwlock_unlock(&s_srv_list_lock); return l_list; } diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h index 0fd5a0b9c519b62a97472ec951c8200263fdb6e4..5dcc3ad3605e902175795ed04595da20cdbc0be0 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 (8 * 1024 * 1024) // 8 MB +#define DAP_CHAIN_ATOM_MAX_SIZE (10 * 1024 * 1024) // 10 MB #endif typedef struct dap_chain dap_chain_t; @@ -330,3 +330,4 @@ int dap_cert_chain_file_save(dap_chain_datum_t *datum, char *net_name); const char *dap_chain_type_to_str(dap_chain_type_t a_chain_type); const char *dap_chain_get_path(dap_chain_t *a_chain); const char *dap_chain_get_cs_type(dap_chain_t *l_chain); +bool dap_chain_datum_type_supported_by_chain(dap_chain_t *a_chain, uint16_t a_datum_type); diff --git a/modules/chain/include/dap_chain_cell.h b/modules/chain/include/dap_chain_cell.h index 93df11693216782639678f536674814efbea8bd2..658a8b90e2ddcd1e4d755218317b5582ec153f2a 100644 --- a/modules/chain/include/dap_chain_cell.h +++ b/modules/chain/include/dap_chain_cell.h @@ -78,6 +78,9 @@ typedef struct dap_chain_cell_decl{ int dap_chain_cell_init(void); int dap_chain_cell_open(dap_chain_t *a_chain, const char *a_filename, const char a_mode); int dap_chain_cell_open_by_id(dap_chain_t *a_chain, const dap_chain_cell_id_t a_cell_id, const char a_mode); +DAP_STATIC_INLINE int dap_chain_cell_create(dap_chain_t *a_chain, const dap_chain_cell_id_t a_cell_id) { + return dap_chain_cell_open_by_id(a_chain, a_cell_id, 'w'); +} DAP_INLINE dap_chain_cell_t *dap_chain_cell_find_by_id(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id) { dap_chain_cell_t *l_cell = NULL; diff --git a/modules/chain/include/dap_chain_srv.h b/modules/chain/include/dap_chain_srv.h index beff7340011130ff7347372d5ab6f9a9008d0998..d016e93204cf6559829423dbd45bf196cb34bdc3 100644 --- a/modules/chain/include/dap_chain_srv.h +++ b/modules/chain/include/dap_chain_srv.h @@ -38,15 +38,13 @@ typedef void * (*dap_chain_srv_callback_start_t)(dap_chain_net_id_t a_net_id, da // Process service decree typedef void (*dap_chain_srv_callback_decree_t)(dap_chain_net_id_t a_net_id, int a_decree_type, dap_tsd_t *a_params, size_t a_params_size); // Purge service callback -typedef int (*dap_chain_srv_callback_purge_t)(dap_chain_net_id_t a_net_id); +typedef int (*dap_chain_srv_callback_purge_t)(dap_chain_net_id_t a_net_id, void *a_service_internal); // Get fee service callback typedef json_object * (*dap_chain_srv_callback_get_fee)(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); +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, void *a_service_internal); // 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 *); typedef struct dap_chain_static_srv_callbacks { // Init @@ -61,8 +59,6 @@ typedef struct dap_chain_static_srv_callbacks { 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; diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c index c7f2dcfab8c58e966f20c2352c79929d8913642d..a5096b6d21f76733413db2eb78d86bbeee8f9862 100644 --- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c +++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c @@ -741,12 +741,21 @@ 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, json_object *a_changed_addrs) +bool dap_chain_esbocs_hardfork_engaged(dap_chain_t *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); + return l_esbocs->hardfork_generation; +} + +int dap_chain_esbocs_set_hardfork_prepare(dap_chain_t *a_chain, uint16_t l_generation, uint64_t a_block_num, dap_list_t *a_trusted_addrs, json_object *a_changed_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); + if (l_generation) + l_esbocs->hardfork_generation = l_generation; if (a_trusted_addrs) l_esbocs->hardfork_trusted_addrs = a_trusted_addrs; if (a_changed_addrs) @@ -763,9 +772,10 @@ int dap_chain_esbocs_set_hardfork_complete(dap_chain_t *a_chain) l_esbocs->hardfork_trusted_addrs = NULL; json_object_put(l_esbocs->hardfork_changed_addrs); l_esbocs->hardfork_changed_addrs = NULL; - l_esbocs->hardfork_from = 0; + l_esbocs->hardfork_generation = l_esbocs->hardfork_from = 0; l_esbocs->session->is_hardfork = false; l_net->pub.ledger->is_hardfork_state = false; + dap_chain_net_srv_stake_hardfork_tx_update(l_net); return 0; } @@ -886,7 +896,7 @@ static dap_list_t *s_get_validators_list(dap_chain_esbocs_t *a_esbocs, dap_hash_ dap_chain_esbocs_pvt_t *l_esbocs_pvt = PVT(a_esbocs); dap_list_t *l_ret = NULL; dap_list_t *l_validators = NULL; - if (l_esbocs_pvt->poa_mode) { // UNDO after debug + if (!l_esbocs_pvt->poa_mode) { if (a_excluded_list_size) { l_validators = dap_chain_net_srv_stake_get_validators(a_esbocs->chain->net_id, false, NULL); uint16_t l_excluded_num = *a_excluded_list; @@ -1059,7 +1069,11 @@ static void s_session_send_startsync(void *a_arg) if (a_session->cur_round.sync_sent) return; // Sync message already was sent dap_chain_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, // Actually not working. TODO implement cells in type storage + a_session->is_hardfork ? c_dap_chain_cell_id_hardfork : c_dap_chain_cell_id_null, + &l_last_block_hash); + if (dap_hash_fast_is_blank(&a_session->cur_round.last_block_hash)) + memset(&l_last_block_hash, 0, sizeof(dap_hash_fast_t)); // Workaround for unimpemented storage cell_id request a_session->ts_round_sync_start = dap_time_now(); if (!dap_hash_fast_compare(&l_last_block_hash, &a_session->cur_round.last_block_hash)) return; // My last block hash has changed, skip sync message @@ -1236,7 +1250,8 @@ static bool s_session_round_new(void *a_arg) if (rc) { log_it(L_ERROR, "Can't start hardfork process with code %d, see log for more details", rc); a_session->is_hardfork = false; - } + } else + a_session->cur_round.last_block_hash = (dap_hash_fast_t) { }; } } return false; @@ -1366,7 +1381,7 @@ static bool s_session_directive_ready(dap_chain_esbocs_session_t *a_session, boo if (l_ready) { size_t l_list_length = dap_list_length(a_session->cur_round.all_validators); if (a_session->cur_round.total_validators_synced * 3 < l_list_length * 2) { - log_it(L_INFO, "Not enough validators online for directive, %u * 3 < %zu * 2", + log_it(L_INFO, "Not enough validators online to issue directive, %u * 3 < %zu * 2", a_session->cur_round.total_validators_synced, l_list_length ); return false; // Not a valid round, less than 2/3 participants } @@ -1713,13 +1728,13 @@ static void s_session_candidate_submit(dap_chain_esbocs_session_t *a_session) l_candidate_size = dap_chain_block_meta_add(&l_candidate, l_candidate_size, DAP_CHAIN_BLOCK_META_EXCLUDED_KEYS, a_session->cur_round.excluded_list, (*a_session->cur_round.excluded_list + 1) * sizeof(uint16_t)); } - if (a_session->is_hardfork) { + if (a_session->is_hardfork && l_candidate_size) { if (dap_chain_block_meta_get(l_candidate, l_candidate_size, DAP_CHAIN_BLOCK_META_GENESIS) && l_candidate_size) l_candidate_size = dap_chain_block_meta_add(&l_candidate, l_candidate_size, DAP_CHAIN_BLOCK_META_LINK, &l_chain->hardfork_decree_hash, sizeof(l_chain->hardfork_decree_hash)); if (l_candidate_size) l_candidate_size = dap_chain_block_meta_add(&l_candidate, l_candidate_size, DAP_CHAIN_BLOCK_META_GENERATION, - &l_chain->generation, sizeof(uint16_t)); + &a_session->esbocs->hardfork_generation, sizeof(uint16_t)); } if (l_candidate_size) { dap_hash_fast(l_candidate, l_candidate_size, &l_candidate_hash); @@ -2911,21 +2926,7 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl return -3; } if (l_esbocs->session->is_hardfork) { - uint8_t *l_generation = dap_chain_block_meta_get(a_block, a_block_size, DAP_CHAIN_BLOCK_META_GENERATION); - if (!l_generation || *(uint16_t *)l_generation != a_blocks->chain->generation) { - log_it(L_WARNING, "Can't process hardfork block %s with incorrect generation meta", dap_hash_fast_to_str_static(a_block_hash)); - return -302; - } - // Addtionally verify datums vs internal states - size_t l_datums_count = 0; - dap_chain_datum_t **l_datums = dap_chain_block_get_datums(a_block, a_block_size, &l_datums_count); - for (size_t i = 0; i < l_datums_count; i++) { - int ret = dap_chain_node_hardfork_check(a_blocks->chain, l_datums[i]); - if (ret) { - log_it(L_WARNING, "Can't process hardfork block %s with datums verification error", dap_hash_fast_to_str_static(a_block_hash)); - return ret; - } - } + uint16_t l_genesis_corr = 0; // compare hardfork decree hashes if (dap_chain_block_meta_get(a_block, a_block_size, DAP_CHAIN_BLOCK_META_GENESIS)) { dap_hash_fast_t *l_hardfork_decree_hash = (dap_hash_fast_t *)dap_chain_block_meta_get(a_block, a_block_size, DAP_CHAIN_BLOCK_META_LINK); @@ -2939,6 +2940,22 @@ static int s_callback_block_verify(dap_chain_cs_blocks_t *a_blocks, dap_chain_bl DAP_DELETE(l_candidate_hash_str); return -301; } + l_genesis_corr = 1; + } + uint8_t *l_generation = dap_chain_block_meta_get(a_block, a_block_size, DAP_CHAIN_BLOCK_META_GENERATION); + if (!l_generation || *(uint16_t *)l_generation != a_blocks->chain->generation + l_genesis_corr) { + log_it(L_WARNING, "Can't process hardfork block %s with incorrect generation meta", dap_hash_fast_to_str_static(a_block_hash)); + return -302; + } + // Addtionally verify datums vs internal states + size_t l_datums_count = 0; + dap_chain_datum_t **l_datums = dap_chain_block_get_datums(a_block, a_block_size, &l_datums_count); + for (size_t i = 0; i < l_datums_count; i++) { + int ret = dap_chain_node_hardfork_check(a_blocks->chain, l_datums[i]); + if (ret) { + log_it(L_WARNING, "Can't process hardfork block %s with datums verification error", dap_hash_fast_to_str_static(a_block_hash)); + return ret; + } } } else if (dap_chain_block_meta_get(a_block, a_block_size, DAP_CHAIN_BLOCK_META_GENERATION)) { log_it(L_WARNING, "Can't process non-hardfork block %s with generation meta", dap_hash_fast_to_str_static(a_block_hash)); diff --git a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h index a2dd6e2c70a53b4257f6ffa17e64030be4a05197..522046373b40c1eff9236df995aa4b34785f1efa 100644 --- a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h +++ b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h @@ -123,6 +123,7 @@ typedef struct dap_chain_esbocs { dap_chain_t *chain; dap_chain_cs_blocks_t *blocks; dap_chain_esbocs_session_t *session; + uint16_t hardfork_generation; uint64_t hardfork_from; json_object *hardfork_changed_addrs; dap_list_t *hardfork_trusted_addrs; @@ -269,6 +270,7 @@ 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, json_object* a_changed_addrs); +int dap_chain_esbocs_set_hardfork_prepare(dap_chain_t *a_chain, uint16_t l_generation, uint64_t a_block_num, dap_list_t *a_trusted_addrs, json_object* a_changed_addrs); int dap_chain_esbocs_set_hardfork_complete(dap_chain_t *a_chain); +bool dap_chain_esbocs_hardfork_engaged(dap_chain_t *a_chain); void dap_chain_esbocs_change_debug_mode(dap_chain_t *a_chain, bool a_enable); diff --git a/modules/datum/include/dap_chain_datum_decree.h b/modules/datum/include/dap_chain_datum_decree.h index 6a00498094c074fb67a9dbbc390ae4748d39c632..c61b645c9b31457a5d3239261788144f6e171b29 100644 --- a/modules/datum/include/dap_chain_datum_decree.h +++ b/modules/datum/include/dap_chain_datum_decree.h @@ -80,7 +80,7 @@ DAP_STATIC_INLINE size_t dap_chain_datum_decree_get_size(dap_chain_datum_decree_ #define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_PKEY_UPDATE 0x0010 #define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_HARDFORK_COMPLETE 0x0011 #define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_POLICY 0x0012 -#define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_HARDFORK_VALIDATORS 0x0013 +#define DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_HARDFORK_RETRY 0x0013 // DECREE TSD types #define DAP_CHAIN_DATUM_DECREE_TSD_TYPE_VALUE 0x0100 diff --git a/modules/ledger/dap_chain_ledger_anchor.c b/modules/ledger/dap_chain_ledger_anchor.c index e7fb5078f3919179abe09ce789c0a908fe4dc61b..56e073d0b4007e8546cb3402cbe6df8bc3ab4bcb 100644 --- a/modules/ledger/dap_chain_ledger_anchor.c +++ b/modules/ledger/dap_chain_ledger_anchor.c @@ -171,13 +171,59 @@ int dap_ledger_anchor_load(dap_chain_datum_anchor_t *a_anchor, dap_chain_t *a_ch return -1; } l_new_anchor->anchor_hash = *a_anchor_hash; - l_new_anchor->anchor = a_anchor; + dap_chain_datum_anchor_t *l_anchor = a_anchor; + if (!a_chain->is_mapped) { + l_anchor = DAP_DUP_SIZE(a_anchor, dap_chain_datum_anchor_get_size(a_anchor)); + if (!l_anchor) { + log_it(L_CRITICAL, "Memory allocation error"); + pthread_rwlock_unlock(&l_ledger_pvt->decrees_rwlock); + return -1; + } + } + l_new_anchor->anchor = l_anchor; + l_new_anchor->storage_chain_id = a_chain->id; HASH_ADD_BYHASHVALUE(hh, l_ledger_pvt->anchors, anchor_hash, sizeof(dap_hash_fast_t), l_hash_value, l_new_anchor); } pthread_rwlock_unlock(&l_ledger_pvt->decrees_rwlock); return ret_val; } +int dap_ledger_anchor_purge(dap_ledger_t *a_ledger, dap_chain_id_t a_chain_id) +{ + dap_return_val_if_fail(a_ledger, -1); + dap_chain_t *l_chain = dap_chain_find_by_id(a_ledger->net->pub.id, a_chain_id); + if (!l_chain) { + log_it(L_ERROR, "Can't find chain 0x016%" DAP_UINT64_FORMAT_x "in net %s", a_chain_id.uint64, a_ledger->net->pub.name); + return -2; + } + if (!dap_chain_datum_type_supported_by_chain(l_chain, DAP_CHAIN_DATUM_ANCHOR)) + return 0; + dap_ledger_anchor_item_t *it = NULL, *tmp; + dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger); + pthread_rwlock_wrlock(&l_ledger_pvt->decrees_rwlock); + HASH_ITER(hh, l_ledger_pvt->anchors, it, tmp) { + if (it->storage_chain_id.uint64 != a_chain_id.uint64) + continue; + HASH_DEL(l_ledger_pvt->anchors, it); + dap_hash_fast_t l_decree_hash; + if (!dap_chain_datum_anchor_get_hash_from_data(it->anchor, &l_decree_hash)) { + dap_ledger_decree_item_t *l_decree = NULL; + HASH_FIND(hh, l_ledger_pvt->decrees, &l_decree_hash, sizeof(dap_hash_fast_t), l_decree); + if (l_decree) { + l_decree->is_applied = l_decree->wait_for_apply = false; + l_decree->anchor_hash = (dap_hash_fast_t) { }; + } else + log_it(L_ERROR, "Corrupted datum anchor, can't get decree by hash %s", dap_hash_fast_to_str_static(&l_decree_hash)); + } else + log_it(L_ERROR, "Corrupted datum anchor %s, can't get decree hash from it", dap_hash_fast_to_str_static(&it->anchor_hash)); + if (!l_chain->is_mapped) + DAP_DELETE(it->anchor); + DAP_DELETE(it); + } + pthread_rwlock_unlock(&l_ledger_pvt->decrees_rwlock); + return 0; +} + static dap_ledger_anchor_item_t *s_find_anchor(dap_ledger_t *a_ledger, dap_hash_fast_t *a_anchor_hash) { dap_ledger_anchor_item_t *l_anchor = NULL; diff --git a/modules/ledger/dap_chain_ledger_decree.c b/modules/ledger/dap_chain_ledger_decree.c index 1e692d3beb198cdc5d79a1df4776317133563a73..cb6aa5de91129dfe836206544e01d71c177e6bbf 100644 --- a/modules/ledger/dap_chain_ledger_decree.c +++ b/modules/ledger/dap_chain_ledger_decree.c @@ -53,15 +53,18 @@ void dap_ledger_decree_init(dap_ledger_t *a_ledger) { log_it(L_WARNING, "PoA certificates for net %s not found", a_ledger->net->pub.name); } -static int s_decree_clear(dap_ledger_t *a_ledger) +static int s_decree_clear(dap_ledger_t *a_ledger, dap_chain_id_t a_chain_id) { dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger); - dap_list_free_full(l_ledger_pvt->decree_owners_pkeys, NULL); dap_ledger_decree_item_t *l_cur_decree, *l_tmp; pthread_rwlock_wrlock(&l_ledger_pvt->decrees_rwlock); HASH_ITER(hh, l_ledger_pvt->decrees, l_cur_decree, l_tmp) { + if (l_cur_decree->storage_chain_id.uint64 != a_chain_id.uint64) + continue; HASH_DEL(l_ledger_pvt->decrees, l_cur_decree); - if ( l_cur_decree->decree && !dap_chain_find_by_id(l_cur_decree->decree->header.common_decree_params.net_id, l_cur_decree->decree->header.common_decree_params.chain_id)->is_mapped ) + if ( l_cur_decree->decree && + !dap_chain_find_by_id(l_cur_decree->decree->header.common_decree_params.net_id, + l_cur_decree->storage_chain_id)->is_mapped ) DAP_DELETE(l_cur_decree->decree); DAP_DELETE(l_cur_decree); } @@ -69,10 +72,18 @@ static int s_decree_clear(dap_ledger_t *a_ledger) return 0; } -void dap_ledger_decree_purge(dap_ledger_t *a_ledger) +int dap_ledger_decree_purge(dap_ledger_t *a_ledger) { - s_decree_clear(a_ledger); - //dap_ledger_decree_create(a_ledger); + dap_return_val_if_fail(a_ledger, -1); + int ret = 0; + for (dap_chain_t *l_chain = a_ledger->net->pub.chains; l_chain; l_chain = l_chain->next) { + if (dap_chain_datum_type_supported_by_chain(l_chain, DAP_CHAIN_DATUM_DECREE)) { + ret += s_decree_clear(a_ledger, l_chain->id); + dap_list_free_full(PVT(a_ledger)->decree_owners_pkeys, NULL); + } else + ret += dap_ledger_anchor_purge(a_ledger, l_chain->id); + } + return ret; } static int s_decree_verify(dap_chain_net_t *a_net, dap_chain_datum_decree_t *a_decree, size_t a_data_size, dap_chain_hash_fast_t *a_decree_hash, bool a_anchored) @@ -205,6 +216,7 @@ int dap_ledger_decree_apply(dap_hash_fast_t *a_decree_hash, dap_chain_datum_decr return -1; } l_new_decree->decree_hash = *a_decree_hash; + l_new_decree->storage_chain_id = a_chain->id; HASH_ADD_BYHASHVALUE(hh, l_ledger_pvt->decrees, decree_hash, sizeof(dap_hash_fast_t), l_hash_value, l_new_decree); } pthread_rwlock_unlock(&l_ledger_pvt->decrees_rwlock); @@ -608,15 +620,17 @@ const char *l_ban_addr; } if (!a_apply) break; - if (*(uint16_t *)l_generation->data < l_chain->generation) + uint16_t l_hardfork_generation = *(uint16_t *)l_generation->data; + if (l_hardfork_generation <= l_chain->generation) return 0; // Old generation hardfork already completed 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)); dap_tsd_t *l_changed_addrs = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HARDFORK_CHANGED_ADDRS); dap_hash_fast(a_decree, dap_chain_datum_decree_get_size(a_decree), &l_chain->hardfork_decree_hash); - return dap_chain_esbocs_set_hardfork_prepare(l_chain, l_block_num, l_addrs, json_tokener_parse((char *)l_changed_addrs->data)); + json_object *l_changed_addrs_json = l_changed_addrs ? json_tokener_parse((char *)l_changed_addrs->data) : NULL; + return dap_chain_esbocs_set_hardfork_prepare(l_chain, l_hardfork_generation, l_block_num, l_addrs, l_changed_addrs_json); } - case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_HARDFORK_VALIDATORS: { + case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_HARDFORK_RETRY: { 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"); @@ -626,17 +640,12 @@ const char *l_ban_addr; log_it(L_WARNING, "Can't apply this decree to specified chain"); return -115; } - dap_tsd_t *l_generation = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_GENERATION); - if (!l_generation || l_generation->size != sizeof(uint16_t)) { - log_it(L_WARNING, "Can't apply this decree, it has no chain generation set"); - return -116; - } if (!a_apply) break; - if (*(uint16_t *)l_generation->data < l_chain->generation) + if (!dap_chain_esbocs_hardfork_engaged(l_chain)) return 0; // Old generation hardfork already completed dap_hash_fast(a_decree, dap_chain_datum_decree_get_size(a_decree), &l_chain->hardfork_decree_hash); - return dap_chain_esbocs_set_hardfork_prepare(l_chain, 0, NULL, NULL); + return dap_chain_esbocs_set_hardfork_prepare(l_chain, 0, 0, NULL, NULL); } case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_HARDFORK_COMPLETE: { dap_chain_t *l_chain = dap_chain_find_by_id(a_net->pub.id, a_decree->header.common_decree_params.chain_id); @@ -763,12 +772,13 @@ int s_aggregate_anchor(dap_ledger_t *a_ledger, dap_ledger_hardfork_anchors_t **a log_it(L_CRITICAL, "%s", c_error_memory_alloc); return -1; } - if (a_subtype != DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_INVALIDATE && a_subtype != DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_UNBAN) + if (a_subtype != DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_INVALIDATE && // Do not aagregate stake anchors, it will be transferred with + a_subtype != DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_APPROVE && // hardfork decree data linked to genesis block + 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); + if (l_exist->decree_subtype == DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_BAN) { + assert(a_subtype == DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_UNBAN); DL_DELETE(*a_out_list, l_exist); } else l_exist->anchor = a_anchor; @@ -776,13 +786,15 @@ int s_aggregate_anchor(dap_ledger_t *a_ledger, dap_ledger_hardfork_anchors_t **a return 0; } -dap_ledger_hardfork_anchors_t *dap_ledger_anchors_aggregate(dap_ledger_t *a_ledger) +dap_ledger_hardfork_anchors_t *dap_ledger_anchors_aggregate(dap_ledger_t *a_ledger, dap_chain_id_t a_chain_id) { dap_ledger_hardfork_anchors_t *ret = NULL; dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger); pthread_rwlock_rdlock(&l_ledger_pvt->decrees_rwlock); for (dap_ledger_decree_item_t *it = l_ledger_pvt->decrees; it; it = it->hh.next) - if (it->is_applied && !dap_hash_fast_is_blank(&it->anchor_hash)) { + if (it->is_applied && + it->decree->header.common_decree_params.chain_id.uint64 == a_chain_id.uint64 && + !dap_hash_fast_is_blank(&it->anchor_hash)) { dap_chain_datum_anchor_t *l_anchor = dap_ledger_anchor_find(a_ledger, &it->anchor_hash); if (!l_anchor) { char l_anchor_hash_str[DAP_HASH_FAST_STR_SIZE]; diff --git a/modules/ledger/dap_chain_ledger_tx.c b/modules/ledger/dap_chain_ledger_tx.c index 461f3dd75a6e3738658cae54cc1febba9f9ea8a3..1706654159538b4bff783a149c5bc6959613992c 100644 --- a/modules/ledger/dap_chain_ledger_tx.c +++ b/modules/ledger/dap_chain_ledger_tx.c @@ -277,7 +277,7 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, int l_prev_tx_count = 0; // 1. Verify signature in current transaction - if (!a_from_threshold && dap_chain_datum_tx_verify_sign(a_tx, 0)) + if (!a_from_threshold && !a_ledger->is_hardfork_state && dap_chain_datum_tx_verify_sign(a_tx, 0)) return DAP_LEDGER_CHECK_NOT_ENOUGH_VALID_SIGNS; // ---------------------------------------------------------------- @@ -2515,7 +2515,8 @@ static int s_aggregate_out_cond(dap_ledger_hardfork_condouts_t **a_ret_list, dap 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, .ticker = a_token_ticker }; + *l_new_condout = (dap_ledger_hardfork_condouts_t) { .hash = *a_tx_hash, .cond = a_out_cond, .sign = a_sign }; + dap_strncpy(l_new_condout->ticker, a_token_ticker, DAP_CHAIN_TICKER_SIZE_MAX); l_new_condout->trackers = s_trackers_aggregate_hardfork(a_ledger, NULL, a_trackers, a_hardfork_start_time); DL_APPEND(*a_ret_list, l_new_condout); return 0; @@ -2536,8 +2537,9 @@ static dap_chain_addr_t* s_change_addr(struct json_object *a_json, dap_chain_add return NULL; } -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, json_object * a_changed_addrs) +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, json_object *a_changed_addrs) { + dap_return_val_if_fail(a_ledger, NULL); dap_ledger_hardfork_balances_t *ret = NULL; dap_ledger_hardfork_condouts_t *l_cond_ret = NULL; dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger); @@ -2594,6 +2596,7 @@ dap_ledger_hardfork_balances_t *dap_ledger_states_aggregate(dap_ledger_t *a_ledg continue; } 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); + break; } default: log_it(L_ERROR, "Unexpected item type %hhu", l_tx_item_type); @@ -2602,5 +2605,7 @@ dap_ledger_hardfork_balances_t *dap_ledger_states_aggregate(dap_ledger_t *a_ledg } } pthread_rwlock_unlock(&l_ledger_pvt->ledger_rwlock); + if (l_cond_outs_list) + *l_cond_outs_list = l_cond_ret; return ret; } diff --git a/modules/ledger/include/dap_chain_ledger.h b/modules/ledger/include/dap_chain_ledger.h index ad3a3a3f2647e0d7dd5c9dd382c5e584661e8990..2de3e3060dd7fe1db3d4ee990a8b05c324e51d33 100644 --- a/modules/ledger/include/dap_chain_ledger.h +++ b/modules/ledger/include/dap_chain_ledger.h @@ -64,7 +64,7 @@ typedef struct dap_ledger_hardfork_condouts { dap_hash_fast_t hash; dap_chain_tx_out_cond_t *cond; dap_chain_tx_sig_t *sign; - const char *ticker; + char ticker[DAP_CHAIN_TICKER_SIZE_MAX]; dap_list_t *trackers; struct dap_ledger_hardfork_condouts *prev, *next; } dap_ledger_hardfork_condouts_t; @@ -498,9 +498,9 @@ dap_chain_tx_out_cond_t* dap_chain_ledger_get_tx_out_cond_linked_to_tx_in_cond(d void dap_ledger_load_end(dap_ledger_t *a_ledger); dap_pkey_t *dap_ledger_find_pkey_by_hash(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_pkey_hash); -//int dap_ledger_decree_create(dap_ledger_t *a_ledger); void dap_ledger_decree_init(dap_ledger_t *a_ledger); -void dap_ledger_decree_purge(dap_ledger_t *a_ledger); +int dap_ledger_decree_purge(dap_ledger_t *a_ledger); +int dap_ledger_anchor_purge(dap_ledger_t *a_ledger, dap_chain_id_t a_chain_id); uint16_t dap_ledger_decree_get_min_num_of_signers(dap_ledger_t *a_ledger); uint16_t dap_ledger_decree_get_num_of_owners(dap_ledger_t *a_ledger); @@ -516,9 +516,10 @@ int dap_ledger_anchor_verify(dap_chain_net_t *a_net, dap_chain_datum_anchor_t * int dap_ledger_anchor_load(dap_chain_datum_anchor_t * a_anchor, dap_chain_t *a_chain, dap_hash_fast_t *a_anchor_hash); 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); +int dap_ledger_anchor_purge(dap_ledger_t *a_ledger, dap_chain_id_t a_chain_id); 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, json_object* a_changed_addrs); -dap_ledger_hardfork_anchors_t *dap_ledger_anchors_aggregate(dap_ledger_t *a_ledger); +dap_ledger_hardfork_anchors_t *dap_ledger_anchors_aggregate(dap_ledger_t *a_ledger, dap_chain_id_t a_chain_id); 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_hash, int a_out_idx); dap_list_t *dap_ledger_tx_get_trackers(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_tx_hash, uint32_t a_out_idx); diff --git a/modules/ledger/include/dap_chain_ledger_pvt.h b/modules/ledger/include/dap_chain_ledger_pvt.h index 5932e43064a235eb73b436ba10536b4bcba967a4..44a4bd50e9332973cb2f3f9e6838888862643097 100644 --- a/modules/ledger/include/dap_chain_ledger_pvt.h +++ b/modules/ledger/include/dap_chain_ledger_pvt.h @@ -149,12 +149,14 @@ typedef struct dap_ledger_decree_item { bool wait_for_apply, is_applied; dap_chain_datum_decree_t *decree; dap_hash_fast_t anchor_hash; + dap_chain_id_t storage_chain_id; UT_hash_handle hh; } dap_ledger_decree_item_t; typedef struct dap_ledger_anchor_item { dap_hash_fast_t anchor_hash; dap_chain_datum_anchor_t *anchor; + dap_chain_id_t storage_chain_id; UT_hash_handle hh; } dap_ledger_anchor_item_t; diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index a32dfbcdbdf2b32d1237cbb62eb0c1030b432a8e..e9d516eeb3f9608293c59ec218c902d71bc67306 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -1656,7 +1656,7 @@ static int s_cli_net(int argc, char **argv, void **reply) } else { json_object_put(l_jobj_list_ca); json_object *l_jobj_str_ret = json_object_new_string("No entries found"); - if (!l_jobj_list_ca) { + if (!l_jobj_str_ret) { json_object_put(l_jobj_return); dap_json_rpc_allocation_error(*a_json_arr_reply); return DAP_JSON_RPC_ERR_CODE_MEMORY_ALLOCATED; diff --git a/modules/net/dap_chain_node.c b/modules/net/dap_chain_node.c index 8c7a2fa1cdc89cadeb2237b5d2e6372554761c16..dc7b67434b7b9bd351fa838849148831aa6cca4a 100644 --- a/modules/net/dap_chain_node.c +++ b/modules/net/dap_chain_node.c @@ -59,14 +59,12 @@ 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_START = 0, - STATE_ANCHORS, + STATE_ANCHORS = 0, STATE_BALANCES, STATE_CONDOUTS, STATE_FEES, STATE_SERVICES, - STATE_MEMPOOL, - STATE_FINISH + STATE_MEMPOOL }; struct hardfork_states { @@ -237,11 +235,10 @@ void dap_chain_node_list_cluster_del_callback(dap_store_obj_t *a_obj, void *a_ar dap_chain_node_client_t *l_client = dap_chain_node_client_connect_default_channels(l_net, l_node_info); if (l_client) l_ret = dap_chain_node_client_wait(l_client, NODE_CLIENT_STATE_ESTABLISHED, 30000); - // dap_chain_node_client_close_unsafe(l_client); del in s_go_stage_on_client_worker_unsafe + // dap_chain_node_client_close_unsafe(l_client); TODO unexpected del in s_go_stage_on_client_worker_unsafe } if (l_ret == 0) { dap_global_db_set_sync(a_obj->group, a_obj->key, a_obj->value, a_obj->value_len, a_obj->flags & DAP_GLOBAL_DB_RECORD_PINNED); - // dap_global_db_set_raw_sync(a_obj, 1); } else { log_it(L_DEBUG, "Can't do handshake with %s [ %s : %u ] delete from node list", a_obj->key, l_node_info->ext_host, l_node_info->ext_port); dap_del_global_db_obj_by_ttl(a_obj); @@ -529,9 +526,10 @@ int dap_chain_node_hardfork_prepare(dap_chain_t *a_chain, dap_time_t a_last_bloc log_it(L_ERROR, "Stake delegate data verifying with hardfork decree failed"); return -3; } + log_it(L_ATT, "Starting data prepare for hardfork of chain '%s' for net '%s'", a_chain->name, l_net->pub.name); 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, a_changed_addrs); - l_states->anchors = dap_ledger_anchors_aggregate(l_net->pub.ledger); + l_states->anchors = dap_ledger_anchors_aggregate(l_net->pub.ledger, a_chain->id); 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); @@ -548,13 +546,7 @@ int dap_chain_node_hardfork_prepare(dap_chain_t *a_chain, dap_time_t a_last_bloc } l_states->trusted_addrs = a_trusted_addrs; a_chain->hardfork_data = l_states; - a_chain->generation++; - dap_chain_purge(a_chain); - dap_ledger_tx_purge(l_net->pub.ledger, false); - dap_chain_srv_purge_all(a_chain->net_id); - dap_chain_cell_close(a_chain, a_chain->cells->id); - dap_chain_cell_open(a_chain, "8000000000000000.dchaincell", 'w'); //dap_chain_cell_create(a_chain, c_dap_chain_cell_id_hardfork); - l_net->pub.ledger->is_hardfork_state = true; + dap_chain_cell_create(a_chain, c_dap_chain_cell_id_hardfork); return 0; } @@ -661,11 +653,9 @@ int dap_chain_node_hardfork_process(dap_chain_t *a_chain) 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_START: - l_states->state_current = STATE_ANCHORS; 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)); + dap_chain_datum_t *l_datum_anchor = dap_chain_datum_create(DAP_CHAIN_DATUM_ANCHOR, 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)) { @@ -677,7 +667,6 @@ int dap_chain_node_hardfork_process(dap_chain_t *a_chain) } DAP_DELETE(l_datum_anchor); } - l_states->state_current = STATE_BALANCES; 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); @@ -690,7 +679,6 @@ int dap_chain_node_hardfork_process(dap_chain_t *a_chain) } DAP_DELETE(l_tx); } - l_states->state_current = STATE_CONDOUTS; 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); @@ -703,7 +691,6 @@ int dap_chain_node_hardfork_process(dap_chain_t *a_chain) } DAP_DELETE(l_cond_tx); } - l_states->state_current = STATE_FEES; 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); @@ -717,7 +704,6 @@ int dap_chain_node_hardfork_process(dap_chain_t *a_chain) } DAP_DELETE(l_fee_tx); } - l_states->state_current = STATE_SERVICES; 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 @@ -742,12 +728,10 @@ int dap_chain_node_hardfork_process(dap_chain_t *a_chain) if (l_break) break; } - l_states->state_current = STATE_MEMPOOL; 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); - bool l_nothing_processed = true; for (size_t i = 0; i < l_objs_count; i++) { if (dap_store_obj_get_type(l_objs +i) == DAP_GLOBAL_DB_OPTYPE_DEL) continue; @@ -782,16 +766,10 @@ int dap_chain_node_hardfork_process(dap_chain_t *a_chain) } if (dap_chain_node_mempool_process(a_chain, l_datum, l_objs[i].key, NULL)) 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_FINISH; - } - case STATE_FINISH: - break; + } break; // No default here } return 0; @@ -885,6 +863,22 @@ int s_hardfork_check(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t a_ } switch (a_datum->header.type_id) { + case DAP_CHAIN_DATUM_ANCHOR: { + dap_ledger_hardfork_anchors_t *l_found = NULL, + l_sought = { .anchor = (dap_chain_datum_anchor_t *)a_datum->data }; + + DL_SEARCH(a_chain->hardfork_data->anchors, l_found, &l_sought, s_compare_anchors); + if (l_found) { + if (a_remove) { + DL_DELETE(a_chain->hardfork_data->anchors, l_found); + DAP_DELETE(l_found); + if (!a_chain->hardfork_data->anchors) + a_chain->hardfork_data->state_current = STATE_BALANCES; + } + break; + } + } break; + case DAP_CHAIN_DATUM_TX: { dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)a_datum->data; if (!l_tx->header.ts_created /* TODO add || l_tx->header.ts_created other criteria */) { @@ -936,15 +930,16 @@ int s_hardfork_check(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t a_ log_it(L_WARNING, "Illegal harfork datum tx TSD TICKER size %u", l_tsd->size); return -8; } - dap_stpcpy((char *)l_conitional.ticker, (char *)l_tsd->data); + dap_strncpy(l_conitional.ticker, (char *)l_tsd->data, DAP_CHAIN_TICKER_SIZE_MAX); break; case DAP_CHAIN_DATUM_TX_TSD_TYPE_HARDFORK_TRACKER: if (l_out) l_regular.trackers = dap_list_append(l_regular.trackers, l_tsd->data); else l_conitional.trackers = dap_list_append(l_conitional.trackers, l_tsd->data); + break; default: - log_it(L_WARNING, "Illegal harfork datum tx TSD item type %d", l_tsd->type); + log_it(L_WARNING, "Illegal harfork datum tx TSD item type 0x%X", l_tsd->type); return -7; } } break; @@ -958,27 +953,41 @@ int s_hardfork_check(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t a_ dap_ledger_hardfork_balances_t *l_found = NULL; DL_SEARCH(a_chain->hardfork_data->balances, l_found, &l_regular, s_compare_balances); if (l_found) { - if (a_remove) + if (a_remove) { DL_DELETE(a_chain->hardfork_data->balances, l_found); + dap_list_free_full(l_found->trackers, NULL); + DAP_DELETE(l_found); + if (!a_chain->hardfork_data->balances) + a_chain->hardfork_data->state_current = STATE_CONDOUTS; + } break; } } else if (l_conitional.cond) { - if (l_conitional.cond->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE_STACK) { + if (l_conitional.cond->header.subtype != DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE_STACK) { + dap_ledger_hardfork_condouts_t *l_found = NULL; + DL_SEARCH(a_chain->hardfork_data->condouts, l_found, &l_conitional, s_compare_condouts); + if (l_found) { + if (a_remove) { + DL_DELETE(a_chain->hardfork_data->condouts, l_found); + dap_list_free_full(l_found->trackers, NULL); + DAP_DELETE(l_found); + if (!a_chain->hardfork_data->condouts) + a_chain->hardfork_data->state_current = STATE_FEES; + } + break; + } + } else { dap_chain_cs_blocks_hardfork_fees_t *l_found = NULL, l_sought = { .fees_n_rewards_sum = l_conitional.cond->header.value, .owner_sign = dap_chain_datum_tx_item_sig_get_sign(l_conitional.sign) }; DL_SEARCH(a_chain->hardfork_data->fees, l_found, &l_sought, s_compare_fees); if (l_found) { - if (a_remove) + if (a_remove) { DL_DELETE(a_chain->hardfork_data->fees, l_found); - break; - } - } else { - dap_ledger_hardfork_condouts_t *l_found = NULL; - DL_SEARCH(a_chain->hardfork_data->condouts, l_found, &l_conitional, s_compare_condouts); - if (l_found) { - if (a_remove) - DL_DELETE(a_chain->hardfork_data->condouts, l_found); + DAP_DELETE(l_found); + if (!a_chain->hardfork_data->fees) + a_chain->hardfork_data->state_current = STATE_SERVICES; + } break; } } @@ -987,19 +996,10 @@ int s_hardfork_check(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t a_ return -8; } // Clean memory - - } break; - - case DAP_CHAIN_DATUM_ANCHOR: { - dap_ledger_hardfork_anchors_t *l_found = NULL, - l_sought = { .anchor = (dap_chain_datum_anchor_t *)a_datum->data }; - - DL_SEARCH(a_chain->hardfork_data->anchors, l_found, &l_sought, s_compare_anchors); - if (l_found) { - if (a_remove) - DL_DELETE(a_chain->hardfork_data->anchors, l_found); - break; - } + if (l_regular.trackers) + dap_list_free(l_regular.trackers); + if (l_conitional.trackers) + dap_list_free(l_conitional.trackers); } break; case DAP_CHAIN_DATUM_SERVICE_STATE: { @@ -1008,8 +1008,12 @@ int s_hardfork_check(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t a_ DL_SEARCH(a_chain->hardfork_data->service_states, l_found, &l_sought, s_compare_service_states); if (l_found) { - if (a_remove) + if (a_remove) { DL_DELETE(a_chain->hardfork_data->service_states, l_found); + DAP_DEL_MULTY(l_found->data, l_found); + if (!a_chain->hardfork_data->service_states) + a_chain->hardfork_data->state_current = STATE_MEMPOOL; + } break; } dap_hash_str_t l_key = dap_get_data_hash_str(a_datum->data, a_datum->header.data_size); @@ -1023,11 +1027,12 @@ int s_hardfork_check(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t a_ dap_global_db_del(l_gdb_group_mempool, l_objs[i].key, NULL, NULL); break; } + #define m_ret(rc) { \ - dap_store_obj_free(l_objs, l_objs_count); \ - DAP_DELETE(l_gdb_group_mempool); \ - return rc; \ -} + dap_store_obj_free(l_objs, l_objs_count); \ + DAP_DELETE(l_gdb_group_mempool); \ + return rc; \ + } if (dap_store_obj_get_type(l_objs +i) == DAP_GLOBAL_DB_OPTYPE_DEL) { log_it(L_WARNING, "Mempool record %s already deleted, can' process", l_objs[i].key); m_ret(-8); diff --git a/modules/node-cli/dap_chain_node_cli_cmd.c b/modules/node-cli/dap_chain_node_cli_cmd.c index bd940670a7bd985a622307f7791ab0e1f3717fc1..4b62ba1375116de8e03792995d19496a693f7ec8 100644 --- a/modules/node-cli/dap_chain_node_cli_cmd.c +++ b/modules/node-cli/dap_chain_node_cli_cmd.c @@ -4120,8 +4120,8 @@ int cmd_decree(int a_argc, char **a_argv, void **a_str_reply) return -1; } l_tsd_list = dap_list_append(l_tsd_list, l_tsd); - - l_tsd = dap_tsd_create(DAP_CHAIN_DATUM_DECREE_TSD_TYPE_GENERATION, &l_chain->generation, sizeof(l_chain->generation)); + uint16_t l_generation = l_chain->generation + 1; + l_tsd = dap_tsd_create(DAP_CHAIN_DATUM_DECREE_TSD_TYPE_GENERATION, &l_generation, sizeof(l_chain->generation)); if (!l_tsd) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); dap_list_free_full(l_tsd_list, NULL); @@ -4174,15 +4174,15 @@ int cmd_decree(int a_argc, char **a_argv, void **a_str_reply) l_tsd_list = dap_list_append(l_tsd_list, l_tsd); } dap_strfreev(l_addrs); + } - if (dap_chain_net_srv_stake_hardfork_data_export(l_net, &l_tsd_list)) { - log_it(L_ERROR, "Can't add stake delegate data to hardfork decree"); - dap_list_free_full(l_tsd_list, NULL); - return -300; - } + if (dap_chain_net_srv_stake_hardfork_data_export(l_net, &l_tsd_list)) { + log_it(L_ERROR, "Can't add stake delegate data to hardfork decree"); + dap_list_free_full(l_tsd_list, NULL); + return -300; } } else if (dap_cli_server_cmd_find_option_val(a_argv, arg_index, a_argc, "-hardfork_retry", &l_param_value_str)) { - l_subtype = DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_HARDFORK_VALIDATORS; + l_subtype = DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_HARDFORK_RETRY; if (dap_chain_net_srv_stake_hardfork_data_export(l_net, &l_tsd_list)) { log_it(L_ERROR, "Can't add stake delegate data to hardfork decree"); dap_list_free_full(l_tsd_list, NULL); diff --git a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c index 63a91272c32ba8d39d78815ade8cf478d8599f6f..835fbbe90f6ea5829f145e78c768745f14d1a7c3 100644 --- a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c +++ b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c @@ -131,8 +131,7 @@ static json_object* s_dap_chain_net_srv_stake_reward_all(json_object* a_json_arr static bool s_debug_more = false; static void *s_pos_delegate_start(dap_chain_net_id_t a_net_id, dap_config_t UNUSED_ARG *a_config); -static void s_pos_delegate_delete(void *a_service_internal); -static int s_pos_delegate_purge(dap_chain_net_id_t a_net_id); +static int s_pos_delegate_purge(dap_chain_net_id_t a_net_id, void *a_service_internal); static json_object *s_pos_delegate_get_fee_validators_json(dap_chain_net_id_t a_net_id); bool s_tax_callback(dap_chain_net_id_t a_net_id, dap_hash_fast_t *a_pkey_hash, dap_chain_addr_t *a_addr_out, uint256_t *a_value_out); @@ -247,7 +246,6 @@ int dap_chain_net_srv_stake_pos_delegate_init() s_debug_more = dap_config_get_item_bool_default(g_config, "stake", "debug_more", s_debug_more); dap_sign_set_pkey_by_hash_callback(s_get_pkey_by_hash_callback); dap_chain_static_srv_callbacks_t l_callbacks = { .start = s_pos_delegate_start, - .delete = s_pos_delegate_delete, .purge = s_pos_delegate_purge, .get_fee_descr = s_pos_delegate_get_fee_validators_json }; dap_chain_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_STAKE_POS_DELEGATE_ID }; @@ -270,33 +268,6 @@ static void *s_pos_delegate_start(dap_chain_net_id_t a_net_id, dap_config_t UNUS return l_srv_stake; } -/** - * @brief delete ht and hh concretic net from s_srv_stake - */ -static void s_pos_delegate_delete(void *a_service_internal) -{ - struct srv_stake *l_srv_stake = a_service_internal; - dap_return_if_fail(l_srv_stake); - dap_chain_net_srv_stake_item_t *l_stake = NULL, *l_tmp = NULL; - HASH_ITER(ht, l_srv_stake->tx_itemlist, l_stake, l_tmp) { - // Clang bug at this, l_stake should change at every loop cycle - HASH_DELETE(ht, l_srv_stake->tx_itemlist, l_stake); - } - HASH_ITER(hh, l_srv_stake->itemlist, l_stake, l_tmp) { - HASH_DEL(l_srv_stake->itemlist, l_stake); - s_srv_stake_item_free((void *)l_stake); - } - HASH_ITER(hh, l_srv_stake->hardfork.sandbox, l_stake, l_tmp) { - HASH_DEL(l_srv_stake->hardfork.sandbox, l_stake); - s_srv_stake_item_free((void *)l_stake); - } - struct cache_item *l_cache_item = NULL, *l_cache_tmp = NULL; - HASH_ITER(hh, l_srv_stake->cache, l_cache_item, l_cache_tmp) { - HASH_DEL(l_srv_stake->cache, l_cache_item); - DAP_DELETE(l_cache_item); - } -} - void dap_chain_net_srv_stake_pos_delegate_deinit() { dap_chain_srv_delete((dap_chain_srv_uid_t) { .uint64 = DAP_CHAIN_NET_SRV_STAKE_POS_DELEGATE_ID }); @@ -494,27 +465,20 @@ static void s_stake_recalculate_weights(dap_chain_net_id_t a_net_id) while (s_weights_truncate(l_srv_stake, l_limit_min)); } -static void s_stake_key_delegate_sandbox(struct srv_stake *a_srv_stake, dap_chain_addr_t *a_signing_addr, dap_pkey_t *a_pkey) +static void s_stake_add_tx(dap_chain_net_t *a_net, dap_chain_net_srv_stake_item_t *a_stake) { - dap_return_if_pass(!a_srv_stake || !a_signing_addr || !a_pkey); - log_it(L_NOTICE, "Add key %s delegation in hardfork process", dap_hash_fast_to_str_static(&a_signing_addr->data.hash_fast)); - dap_chain_net_srv_stake_item_t *l_stake = NULL; - bool l_found = false; - HASH_FIND(hh, a_srv_stake->hardfork.sandbox, &a_signing_addr->data.hash_fast, sizeof(dap_hash_fast_t), l_stake); - if (!l_stake) - l_stake = DAP_NEW_Z_RET_IF_FAIL(dap_chain_net_srv_stake_item_t); - else - l_found = true; - if (dap_pkey_get_size(l_stake->pkey)) { - log_it(L_DEBUG, "Full pkey by hash %s was replaced", dap_hash_fast_to_str_static(&a_signing_addr->data.hash_fast)); - DAP_DELETE(l_stake->pkey); - } - l_stake->pkey = DAP_DUP_SIZE(a_pkey, dap_pkey_get_size(a_pkey)); - if (!l_found) { - l_stake->signing_addr = *a_signing_addr; - HASH_ADD(hh, a_srv_stake->hardfork.sandbox, signing_addr.data.hash_fast, sizeof(dap_hash_fast_t), l_stake); + dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_hash(a_net->pub.ledger, &a_stake->tx_hash); + if (!l_tx) + return; + dap_chain_tx_out_cond_t *l_cond = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, NULL); + if (l_cond && (l_cond->tsd_size == dap_chain_datum_tx_item_out_cond_create_srv_stake_get_tsd_size(true, dap_pkey_get_size(a_stake->pkey)))) { + dap_tsd_t *l_tsd = dap_tsd_find(l_cond->tsd, l_cond->tsd_size, DAP_CHAIN_TX_OUT_COND_TSD_ADDR); + a_stake->sovereign_addr = dap_tsd_get_scalar(l_tsd, dap_chain_addr_t); + l_tsd = dap_tsd_find(l_cond->tsd, l_cond->tsd_size, DAP_CHAIN_TX_OUT_COND_TSD_VALUE); + a_stake->sovereign_tax = dap_tsd_get_scalar(l_tsd, uint256_t); + if (compare256(a_stake->sovereign_tax, dap_chain_balance_coins_scan("1.0")) == 1) + a_stake->sovereign_tax = dap_chain_balance_coins_scan("1.0"); } - return; } void dap_chain_net_srv_stake_key_delegate(dap_chain_net_t *a_net, dap_chain_addr_t *a_signing_addr, dap_chain_datum_decree_t *a_decree, @@ -534,7 +498,8 @@ void dap_chain_net_srv_stake_key_delegate(dap_chain_net_t *a_net, dap_chain_addr l_stake = DAP_NEW_Z(dap_chain_net_srv_stake_item_t); else { l_found = true; - HASH_DELETE(ht, l_srv_stake->tx_itemlist, l_stake); + if (!l_srv_stake->hardfork.in_process) + HASH_DELETE(ht, l_srv_stake->tx_itemlist, l_stake); } l_stake->net = a_net; l_stake->node_addr = *a_node_addr; @@ -551,20 +516,16 @@ void dap_chain_net_srv_stake_key_delegate(dap_chain_net_t *a_net, dap_chain_addr } if (!l_found) HASH_ADD(hh, l_srv_stake->itemlist, signing_addr.data.hash_fast, sizeof(dap_hash_fast_t), l_stake); + if (l_srv_stake->hardfork.in_process) { + const char *l_value_str; dap_uint256_to_char(a_value, &l_value_str); + log_it(L_DEBUG, "Added key with fingerprint %s and locked value %s for node " NODE_ADDR_FP_STR, + dap_chain_hash_fast_to_str_static(&a_signing_addr->data.hash_fast), l_value_str, NODE_ADDR_FP_ARGS(a_node_addr)); + s_stake_recalculate_weights(a_signing_addr->net_id); + return; + } if (!dap_hash_fast_is_blank(&l_stake->tx_hash)) { HASH_ADD(ht, l_srv_stake->tx_itemlist, tx_hash, sizeof(dap_hash_fast_t), l_stake); - dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_hash(a_net->pub.ledger, &l_stake->tx_hash); - if (l_tx) { - dap_chain_tx_out_cond_t *l_cond = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, NULL); - if (l_cond && (l_cond->tsd_size == dap_chain_datum_tx_item_out_cond_create_srv_stake_get_tsd_size(true, dap_pkey_get_size(l_stake->pkey)))) { - dap_tsd_t *l_tsd = dap_tsd_find(l_cond->tsd, l_cond->tsd_size, DAP_CHAIN_TX_OUT_COND_TSD_ADDR); - l_stake->sovereign_addr = dap_tsd_get_scalar(l_tsd, dap_chain_addr_t); - l_tsd = dap_tsd_find(l_cond->tsd, l_cond->tsd_size, DAP_CHAIN_TX_OUT_COND_TSD_VALUE); - l_stake->sovereign_tax = dap_tsd_get_scalar(l_tsd, uint256_t); - if (compare256(l_stake->sovereign_tax, dap_chain_balance_coins_scan("1.0")) == 1) - l_stake->sovereign_tax = dap_chain_balance_coins_scan("1.0"); - } - } + s_stake_add_tx(a_net, l_stake); } dap_chain_esbocs_add_validator_to_clusters(a_net->pub.id, a_node_addr); const char *l_value_str; dap_uint256_to_char(a_value, &l_value_str); @@ -832,20 +793,43 @@ int dap_chain_net_srv_stake_load_cache(dap_chain_net_t *a_net) return 0; } -static int s_pos_delegate_purge(dap_chain_net_id_t a_net_id) +static int s_pos_delegate_purge(dap_chain_net_id_t a_net_id, void *a_service_internal) { - dap_ledger_t *l_ledger = dap_chain_net_by_id(a_net_id)->pub.ledger; + dap_chain_net_t *l_net = dap_chain_net_by_id(a_net_id); + if (!l_net) + return -1; + dap_ledger_t *l_ledger = l_net->pub.ledger; char *l_gdb_group = dap_ledger_get_gdb_group(l_ledger, DAP_CHAIN_NET_SRV_STAKE_POS_DELEGATE_GDB_GROUP); dap_global_db_erase_table(l_gdb_group, NULL, NULL); DAP_DELETE(l_gdb_group); - struct srv_stake *l_srv_stake = s_srv_stake_by_net_id(a_net_id); - s_pos_delegate_delete(l_srv_stake); + char *l_approved_group = s_get_approved_group(l_net); + dap_global_db_erase_table(l_approved_group, NULL, NULL); + DAP_DELETE(l_approved_group); + + struct srv_stake *l_srv_stake = (struct srv_stake *)a_service_internal; + dap_chain_net_srv_stake_item_t *l_stake = NULL, *l_tmp = NULL; + HASH_ITER(ht, l_srv_stake->tx_itemlist, l_stake, l_tmp) { + // Clang bug at this, l_stake should change at every loop cycle + HASH_DELETE(ht, l_srv_stake->tx_itemlist, l_stake); + } + HASH_ITER(hh, l_srv_stake->itemlist, l_stake, l_tmp) { + HASH_DEL(l_srv_stake->itemlist, l_stake); + s_srv_stake_item_free((void *)l_stake); + } + HASH_ITER(hh, l_srv_stake->hardfork.sandbox, l_stake, l_tmp) { + HASH_DEL(l_srv_stake->hardfork.sandbox, l_stake); + s_srv_stake_item_free((void *)l_stake); + } + struct cache_item *l_cache_item = NULL, *l_cache_tmp = NULL; + HASH_ITER(hh, l_srv_stake->cache, l_cache_item, l_cache_tmp) { + HASH_DEL(l_srv_stake->cache, l_cache_item); + DAP_DELETE(l_cache_item); + } memset(l_srv_stake, 0, sizeof(*l_srv_stake)); l_srv_stake->delegate_allowed_min = dap_chain_balance_coins_scan("1.0"); return 0; } - // Freeze staker's funds when delegating a key static dap_chain_datum_tx_t *s_stake_tx_create(dap_chain_net_t * a_net, dap_enc_key_t *a_key, uint256_t a_value, uint256_t a_fee, @@ -1158,7 +1142,8 @@ dap_chain_datum_decree_t *dap_chain_net_srv_stake_decree_approve(dap_chain_net_t return NULL; } - if(dap_chain_net_srv_stake_verify_key_and_node(&l_tx_out_cond->subtype.srv_stake_pos_delegate.signing_addr, &l_tx_out_cond->subtype.srv_stake_pos_delegate.signer_node_addr)){ + if(dap_chain_net_srv_stake_verify_key_and_node(&l_tx_out_cond->subtype.srv_stake_pos_delegate.signing_addr, + &l_tx_out_cond->subtype.srv_stake_pos_delegate.signer_node_addr)){ log_it(L_WARNING, "Key and node verification error"); return NULL; } @@ -4329,40 +4314,12 @@ int dap_chain_net_srv_stake_hardfork_data_import(dap_chain_net_id_t a_net_id, da log_it(L_ERROR, "Can't find hardfork decree by hash %s", dap_hash_fast_to_str_static(a_hardfork_decree_hash)); return -1; } - // temporary save poa pkeys - dap_list_t *l_current_list = NULL; - struct srv_stake *l_srv_stake = s_srv_stake_by_net_id(a_net_id); if (!l_srv_stake) return -2; - if (l_srv_stake->hardfork.in_process && l_srv_stake->hardfork.sandbox) { - log_it(L_ERROR, "Temp hardfork table already existed in net %"DAP_UINT64_FORMAT_U, a_net_id.uint64); - return -3; - } - dap_chain_net_srv_stake_item_t *l_stake, *l_tmp; - HASH_ITER(hh, l_srv_stake->itemlist, l_stake, l_tmp) { - if (dap_hash_fast_is_blank(&l_stake->tx_hash)) { - l_current_list = dap_list_append(l_current_list, l_stake); - HASH_DEL(l_srv_stake->itemlist, l_stake); - } - } - // clean prev table - if (!l_srv_stake->hardfork.in_process) - s_pos_delegate_purge(a_net_id); - - // restore poa keys - for ( dap_list_t* l_iter = dap_list_first(l_current_list); l_iter; l_iter = l_iter->next) { - l_stake = (dap_chain_net_srv_stake_item_t *)l_iter->data; - if (l_srv_stake->hardfork.in_process) { - s_stake_key_delegate_sandbox(l_srv_stake, &l_stake->signing_addr, l_stake->pkey); - } else { - dap_chain_net_srv_stake_key_delegate(l_net, &l_stake->signing_addr, NULL, l_stake->value, &l_stake->node_addr, l_stake->pkey); - } - } - dap_list_free_full(l_current_list, s_srv_stake_item_free); - l_current_list = dap_tsd_find_all(l_decree->data_n_signs, l_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HASH, sizeof(dap_hash_fast_t)); - for ( dap_list_t* l_iter = dap_list_first(l_current_list); l_iter; l_iter = l_iter->next) { + dap_list_t *l_current_list = dap_tsd_find_all(l_decree->data_n_signs, l_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HASH, sizeof(dap_hash_fast_t)); + for (dap_list_t *l_iter = dap_list_first(l_current_list); l_iter; l_iter = l_iter->next) { dap_chain_datum_decree_t *l_current_decree = dap_ledger_decree_get_by_hash(l_net, (dap_hash_fast_t *)((dap_tsd_t *)l_iter->data)->data, NULL); if (!l_decree) { log_it(L_ERROR, "Can't find delegate decree by hash %s", dap_hash_fast_to_str_static((dap_hash_fast_t *)((dap_tsd_t *)l_iter->data)->data)); @@ -4384,12 +4341,9 @@ int dap_chain_net_srv_stake_hardfork_data_import(dap_chain_net_id_t a_net_id, da dap_list_free_full(l_current_list, NULL); return -4; } - if (l_srv_stake->hardfork.in_process) { - s_stake_key_delegate_sandbox(l_srv_stake, &l_addr, dap_chain_datum_decree_get_pkey(l_current_decree)); - } else { - dap_chain_net_srv_stake_key_delegate(l_net, &l_addr, l_current_decree, l_value, &l_node_addr, dap_chain_datum_decree_get_pkey(l_current_decree)); + dap_chain_net_srv_stake_key_delegate(l_net, &l_addr, l_current_decree, l_value, &l_node_addr, dap_chain_datum_decree_get_pkey(l_current_decree)); + if (!l_srv_stake->hardfork.in_process) dap_chain_net_srv_stake_add_approving_decree_info(l_current_decree, l_net); - } } dap_list_free_full(l_current_list, NULL); return 0; @@ -4444,20 +4398,47 @@ int dap_chain_net_srv_stake_hardfork_data_verify(dap_chain_net_t *a_net, dap_has */ int dap_chain_net_srv_stake_switch_table(dap_chain_net_id_t a_net_id, bool a_to_sandbox) { + dap_chain_net_t *l_net = dap_chain_net_by_id(a_net_id); struct srv_stake *l_srv_stake = s_srv_stake_by_net_id(a_net_id); - if (!l_srv_stake) + if (!l_srv_stake || !l_net) return -1; if (l_srv_stake->hardfork.in_process == a_to_sandbox) { log_it(L_DEBUG, "Key delegate table already switched to %s table", a_to_sandbox ? "sandbox" : "main"); return -2; } - if (!a_to_sandbox) { // free temp table if switch to main - dap_chain_net_srv_stake_item_t *l_stake = NULL, *l_tmp = NULL; - HASH_ITER(hh, l_srv_stake->hardfork.sandbox, l_stake, l_tmp) { + if (l_srv_stake->hardfork.sandbox && a_to_sandbox) { + log_it(L_ERROR, "Temp hardfork table already existed in net %"DAP_UINT64_FORMAT_U, a_net_id.uint64); + return -3; + } + if (a_to_sandbox) { + // switch to sandbox + l_srv_stake->hardfork.sandbox = l_srv_stake->itemlist; + l_srv_stake->itemlist = NULL; + // restore poa keys + for (dap_chain_net_srv_stake_item_t *it = l_srv_stake->hardfork.sandbox; it; it = it->hh.next) + if (dap_hash_fast_is_blank(&it->tx_hash)) { + dap_chain_net_srv_stake_item_t *l_poa = DAP_DUP_RET_VAL_IF_FAIL(it, -4); + l_poa->pkey = DAP_DUP_SIZE_RET_VAL_IF_FAIL(it->pkey, dap_pkey_get_size(it->pkey), -4); + HASH_ADD(hh, l_srv_stake->itemlist, signing_addr.data.hash_fast, sizeof(dap_hash_fast_t), l_poa); + } + } else { // free temp table if switch to main + dap_chain_net_srv_stake_item_t *l_stake, *l_tmp; + HASH_ITER(hh, l_srv_stake->itemlist, l_stake, l_tmp) { HASH_DEL(l_srv_stake->itemlist, l_stake); - s_srv_stake_item_free((void *)l_stake); + s_srv_stake_item_free(l_stake); } + l_srv_stake->itemlist = l_srv_stake->hardfork.sandbox; + l_srv_stake->hardfork.sandbox = NULL; } l_srv_stake->hardfork.in_process = a_to_sandbox; return 0; } + +void dap_chain_net_srv_stake_hardfork_tx_update(dap_chain_net_t *a_net) + { + struct srv_stake *l_srv_stake = s_srv_stake_by_net_id(a_net->pub.id); + if (!l_srv_stake) + return log_it(L_ERROR, "Can't update tx list: no stake service found by net id %" DAP_UINT64_FORMAT_U, a_net->pub.id.uint64); + for (dap_chain_net_srv_stake_item_t *it = l_srv_stake->itemlist; it; it = it->hh.next) + s_stake_add_tx(a_net, it); + } diff --git a/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h b/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h index 3b8c7080e068031501b0f5aef90fc28b37e49bf6..129135e631499c30e905ff09289c5b6fb6320683 100644 --- a/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h +++ b/modules/service/stake/include/dap_chain_net_srv_stake_pos_delegate.h @@ -84,3 +84,4 @@ int dap_chain_net_srv_stake_hardfork_data_export(dap_chain_net_t *a_net, dap_lis int dap_chain_net_srv_stake_hardfork_data_import(dap_chain_net_id_t a_net_id, dap_hash_fast_t *a_hardfork_decree_hash); int dap_chain_net_srv_stake_hardfork_data_verify(dap_chain_net_t *a_net, dap_hash_fast_t *a_hardfork_decree_hash); int dap_chain_net_srv_stake_switch_table(dap_chain_net_id_t a_net_id, bool a_to_sandbox); +void dap_chain_net_srv_stake_hardfork_tx_update(dap_chain_net_t *a_net); diff --git a/modules/service/voting/dap_chain_net_srv_voting.c b/modules/service/voting/dap_chain_net_srv_voting.c index e4c4a55cc157dee21d9d0178e53fdf6951f473c6..3847e37142e3129ccb8e255c2c16c4655a882d7d 100644 --- a/modules/service/voting/dap_chain_net_srv_voting.c +++ b/modules/service/voting/dap_chain_net_srv_voting.c @@ -64,7 +64,8 @@ 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_callback_purge(dap_chain_net_id_t a_net_id, 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, void *a_service_internal); static int s_votings_restore(dap_chain_net_id_t a_net_id, byte_t *a_state, uint64_t a_state_size, uint32_t a_states_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); @@ -102,7 +103,11 @@ 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, .hardfork_prepare = s_votings_backup, .hardfork_load = s_votings_restore }; + dap_chain_static_srv_callbacks_t l_srv_callbacks = { .start = s_callback_start, + .purge = s_callback_purge, + .hardfork_prepare = s_votings_backup, + .hardfork_load = s_votings_restore + }; int ret = dap_chain_srv_add(l_uid, DAP_CHAIN_SRV_VOTING_LITERAL, &l_srv_callbacks); if (ret) { log_it(L_ERROR, "Can't register voting service"); @@ -132,7 +137,7 @@ static void *s_callback_start(dap_chain_net_id_t UNUSED_ARG a_net_id, dap_config return l_service_internal; } -static void s_callback_delete(void *a_service_internal) +static int s_callback_purge(dap_chain_net_id_t UNUSED_ARG a_net_id, void *a_service_internal) { struct srv_voting *l_service_internal = a_service_internal; struct voting *it = NULL, *tmp; @@ -141,7 +146,7 @@ static void s_callback_delete(void *a_service_internal) s_voting_clear(it); DAP_DELETE(it); } - DAP_DELETE(l_service_internal); + return 0; } static inline struct voting *s_votings_ht_get(dap_chain_net_id_t a_net_id) @@ -1407,13 +1412,13 @@ static size_t s_voting_serial_size_calc(struct voting *a_voting, size_t *a_votes return ret; } -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 byte_t *s_votings_backup(dap_chain_net_id_t a_net_id, uint64_t *a_state_size, uint32_t *a_state_count, void *a_service_internal) { 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); + struct voting *votings_ht = a_service_internal ? ((struct srv_voting *)a_service_internal)->ht : NULL; if (!votings_ht) { 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; diff --git a/modules/service/vpn/dap_chain_net_srv_vpn.c b/modules/service/vpn/dap_chain_net_srv_vpn.c index 75332bfc0549ac82dbe0ecd8f68024e0d42305d0..42be26474d86bdaa3eb00cfbf8ae1d00c0070924 100644 --- a/modules/service/vpn/dap_chain_net_srv_vpn.c +++ b/modules/service/vpn/dap_chain_net_srv_vpn.c @@ -862,11 +862,12 @@ static void *s_vpn_service_create(dap_chain_net_id_t a_net_id, dap_config_t *a_c return l_srv; } -static void s_vpn_service_delete(void *a_service) +static int s_vpn_service_delete(dap_chain_net_id_t a_net_id, void *a_service) { dap_chain_net_srv_t *l_srv = a_service; DAP_DELETE(l_srv->_pvt); dap_chain_net_srv_del(l_srv); + return 0; } @@ -905,7 +906,7 @@ int dap_chain_net_srv_vpn_init() return -4; } dap_chain_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_VPN_ID }; - dap_chain_static_srv_callbacks_t l_callbacks = { .start = s_vpn_service_create, .delete = s_vpn_service_delete }; + dap_chain_static_srv_callbacks_t l_callbacks = { .start = s_vpn_service_create, .purge = s_vpn_service_delete }; dap_chain_srv_add(l_uid, "VPN", &l_callbacks); dap_stream_ch_proc_add(DAP_CHAIN_NET_SRV_VPN_CH_ID, s_ch_vpn_new, s_ch_vpn_delete, s_ch_packet_in, diff --git a/modules/type/blocks/dap_chain_block.c b/modules/type/blocks/dap_chain_block.c index c02e3cb673ebb9b47ae099fbfa0df0e22fcf8f5f..0e6d2421450bdd6186c16e60ca1b36001f9992c1 100644 --- a/modules/type/blocks/dap_chain_block.c +++ b/modules/type/blocks/dap_chain_block.c @@ -81,9 +81,6 @@ dap_chain_block_t *dap_chain_block_new(dap_chain_hash_fast_t *a_prev_block, size l_block_size = dap_chain_block_meta_add(&l_block, l_block_size, DAP_CHAIN_BLOCK_META_NONCE, &l_nonce, sizeof(uint64_t)); } - /*if (l_block_size && a_block_reward) - l_block_size = dap_chain_block_meta_add(&l_block, l_block_size, DAP_CHAIN_BLOCK_META_REWARD, - a_block_reward, sizeof(uint256_t));*/ if (!l_block_size) { log_it(L_ERROR, "Can't add meta to block"); DAP_DEL_Z(l_block); diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c index 253fb58de7b3aa3824a457a686a5ccf47e65a0c1..6e034e231d906486a40d87f48fcbdadee6561473 100644 --- a/modules/type/blocks/dap_chain_cs_blocks.c +++ b/modules/type/blocks/dap_chain_cs_blocks.c @@ -23,7 +23,7 @@ #include <pthread.h> #include "dap_common.h" #include "dap_chain.h" -#include "dap_chain_cell.h" +#include "dap_chain_srv.h" #include "dap_chain_cs.h" #include "dap_chain_cs_blocks.h" #include "dap_chain_block.h" @@ -1542,7 +1542,6 @@ static int s_callback_cs_blocks_purge(dap_chain_t *a_chain) l_datum_index = NULL; } pthread_rwlock_unlock(&PVT(l_blocks)->datums_rwlock); - dap_chain_cell_close_all(a_chain); return 0; } @@ -1640,19 +1639,6 @@ static int s_delete_atom_datums(dap_chain_cs_blocks_t *a_blocks, dap_chain_block return l_ret; } -/** - * @brief s_add_atom_to_blocks - * @param a_blocks - * @param a_block_cache - * @return - */ -static void s_add_atom_to_blocks(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_cache_t *a_block_cache) -{ - - return; -} - - static bool s_select_longest_branch(dap_chain_cs_blocks_t * a_blocks, dap_chain_block_cache_t * a_bcache, uint64_t a_main_branch_length) { dap_chain_cs_blocks_t * l_blocks = a_blocks; @@ -1772,21 +1758,19 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da if ( !dap_chain_net_get_load_mode(l_net) ) { int l_err = dap_chain_atom_save(a_chain, l_block->hdr.cell_id, a_atom, a_atom_size, a_atom_new ? &l_block_hash : NULL, (char**)&l_block); if (l_err) { - dap_chain_net_srv_stake_switch_table(a_chain->net_id, false); log_it(L_ERROR, "Can't save atom to file, code %d", l_err); return ATOM_REJECT; } } #endif if (!( l_block_cache = dap_chain_block_cache_new(&l_block_hash, l_block, a_atom_size, PVT(l_blocks)->blocks_count + 1, !a_chain->is_mapped) )) { - dap_chain_net_srv_stake_switch_table(a_chain->net_id, false); log_it(L_ERROR, "Block %s is corrupted!", l_block_cache->block_hash_str); return dap_chain_net_get_load_mode(l_net) ? ATOM_CORRUPTED : ATOM_REJECT; } debug_if(s_debug_more, L_DEBUG, "... new block %s", l_block_cache->block_hash_str); pthread_rwlock_wrlock(& PVT(l_blocks)->rwlock); - if (PVT(l_blocks)->blocks){ + if (!l_block_cache->is_genesis) { dap_chain_block_cache_t *l_last_block = HASH_LAST(PVT(l_blocks)->blocks); if (l_last_block && dap_hash_fast_compare(&l_last_block->block_hash, &l_block_prev_hash)){ ++PVT(l_blocks)->blocks_count; @@ -1860,7 +1844,8 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da } } - } else { + } else { // Block is genesis + uint8_t *l_generation_meta = dap_chain_block_meta_get(l_block, a_atom_size, DAP_CHAIN_BLOCK_META_GENERATION); uint16_t l_generation = l_generation_meta ? *(uint16_t *)l_generation_meta : 0; if (l_generation && a_chain->generation < l_generation) { @@ -1869,6 +1854,12 @@ static dap_chain_atom_verify_res_t s_callback_atom_add(dap_chain_t * a_chain, da log_it(L_ERROR, "Can't find hardfork decree hash in candidate block meta"); return ATOM_REJECT; } + a_chain->generation++; + dap_ledger_anchor_purge(l_net->pub.ledger, a_chain->id); + dap_ledger_tx_purge(l_net->pub.ledger, false); + dap_chain_srv_purge_all(a_chain->net_id); + dap_chain_purge(a_chain); + l_net->pub.ledger->is_hardfork_state = true; if (dap_chain_net_srv_stake_hardfork_data_import(a_chain->net_id, l_hardfork_decree_hash)) { // True import log_it(L_ERROR, "Can't accept hardfork genesis block %s: error in hardfork data restoring", dap_hash_fast_to_str_static(a_atom_hash)); return ATOM_REJECT; @@ -2503,7 +2494,7 @@ static void s_datum_iter_fill(dap_chain_datum_iter_t *a_datum_iter, dap_chain_bl a_datum_iter->ret_code = a_datum_index->ret_code; a_datum_iter->action = a_datum_index->action; a_datum_iter->uid = a_datum_index->service_uid; - a_datum_iter->token_ticker = dap_strcmp(a_datum_index->token_ticker, "0") ? a_datum_index->token_ticker : NULL; + a_datum_iter->token_ticker = dap_strcmp(a_datum_index->token_ticker, "") ? a_datum_index->token_ticker : NULL; } else { a_datum_iter->cur = NULL; a_datum_iter->cur_hash = NULL; @@ -2612,7 +2603,9 @@ static size_t s_callback_add_datums(dap_chain_t *a_chain, dap_chain_datum_t **a_ } if (!l_blocks->block_new) { dap_chain_block_cache_t *l_bcache_last = HASH_LAST(l_blocks_pvt->blocks); - l_blocks->block_new = dap_chain_block_new(&l_bcache_last->block_hash, &l_blocks->block_new_size); + if (a_chain->hardfork_data && l_bcache_last->block->hdr.cell_id.uint64 != c_dap_chain_cell_id_hardfork.uint64) + l_bcache_last = NULL; // Workaround until separate cells storages will be realized + l_blocks->block_new = dap_chain_block_new(l_bcache_last ? &l_bcache_last->block_hash : NULL, &l_blocks->block_new_size); l_blocks->block_new->hdr.cell_id = a_chain->hardfork_data ? c_dap_chain_cell_id_hardfork : c_dap_chain_cell_id_null; l_blocks->block_new->hdr.chain_id.uint64 = l_blocks->chain->id.uint64; }