diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c index 0e9f43596f0190c440db11be93dae3333b85e75c..75784cb6580b268121ccd17927c7636d2de96d77 100644 --- a/modules/chain/dap_chain_ledger.c +++ b/modules/chain/dap_chain_ledger.c @@ -65,7 +65,6 @@ #include "json-c/json_object.h" #include "dap_notify_srv.h" #include "dap_chain_net_tx.h" -#include "dap_chain_net_srv.h" #define LOG_TAG "dap_chain_ledger" @@ -254,6 +253,7 @@ typedef struct dap_ledger_private { bool load_mode; bool cached; + dap_chain_ledger_cache_tx_check_callback_t cache_tx_check_callback; // TPS section dap_timerfd_t *tps_timer; struct timespec tps_start_time; @@ -261,8 +261,8 @@ typedef struct dap_ledger_private { struct timespec tps_end_time; size_t tps_count; // Threshold fee - dap_timerfd_t *threshold_txs_fee_timer; - dap_timerfd_t *threshold_emissions_fee_timer; + dap_timerfd_t *threshold_txs_free_timer; + dap_timerfd_t *threshold_emissions_free_timer; } dap_ledger_private_t; #define PVT(a) ( (dap_ledger_private_t* ) a->_internal ) @@ -338,9 +338,9 @@ static dap_ledger_t * dap_chain_ledger_handle_new(void) pthread_rwlock_init(&l_ledger_pvt->threshold_emissions_rwlock , NULL); pthread_rwlock_init(&l_ledger_pvt->balance_accounts_rwlock , NULL); pthread_rwlock_init(&l_ledger_pvt->stake_lock_rwlock, NULL); - l_ledger_pvt->threshold_txs_fee_timer = dap_interval_timer_create(s_threshold_free_timer_tick, + l_ledger_pvt->threshold_txs_free_timer = dap_interval_timer_create(s_threshold_free_timer_tick, (dap_timer_callback_t)s_threshold_txs_free, l_ledger); - l_ledger_pvt->threshold_emissions_fee_timer = dap_interval_timer_create(s_threshold_free_timer_tick, + l_ledger_pvt->threshold_emissions_free_timer = dap_interval_timer_create(s_threshold_free_timer_tick, (dap_timer_callback_t) s_threshold_emission_free, l_ledger); return l_ledger; } @@ -3797,12 +3797,8 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d break; } if (!IS_ZERO_256(l_token_item->total_supply)) { - dap_chain_tx_out_t *l_tx_out = (dap_chain_tx_out_t*)dap_chain_datum_tx_item_get(a_tx, 0, TX_ITEM_TYPE_OUT, 0); -// dap_chain_tx_out_ext_t *l_tx_out_ext = (dap_chain_tx_out_ext_t*)dap_chain_datum_tx_item_get(a_tx, 0, TX_ITEM_TYPE_OUT_EXT, 0); -// uint256_t tmp = l_tx_out ? l_tx_out->header.value : l_tx_out_ext->header.value; - uint256_t l_value_tmp = bound_item->stake_lock_item->ems_value; - //SUBTRACT_256_256(l_token_item->current_supply, l_tx_out->header.value, &l_token_item->current_supply); - SUBTRACT_256_256(l_token_item->current_supply, l_value_tmp, &l_token_item->current_supply); + SUBTRACT_256_256(l_token_item->current_supply, bound_item->stake_lock_item->ems_value, + &l_token_item->current_supply); char *l_balance = dap_chain_balance_print(l_token_item->current_supply); log_it(L_DEBUG, "New current supply %s for token %s", l_balance, l_token_item->ticker); DAP_DEL_Z(l_balance); @@ -4116,8 +4112,10 @@ int dap_chain_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_hash_fast_t l_tx_hash; dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), &l_tx_hash); if (a_tx_hash) - memcpy(a_tx_hash, &l_tx_hash, sizeof(l_tx_hash)); + *a_tx_hash = l_tx_hash; if (PVT(a_ledger)->load_mode) { + if (PVT(a_ledger)->cache_tx_check_callback) + PVT(a_ledger)->cache_tx_check_callback(&l_tx_hash); dap_chain_ledger_tx_item_t *l_tx_item; unsigned l_hash_value; HASH_VALUE(&l_tx_hash, sizeof(dap_chain_hash_fast_t), l_hash_value); @@ -4173,7 +4171,6 @@ int dap_chain_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_ if (!l_item_used) { // Add it to spent items l_item_used = DAP_NEW_Z(dap_chain_ledger_tx_spent_item_t); l_item_used->tx_hash_fast = *a_tx_hash; - int l_len = strnlen(l_item_tmp->cache_data.token_ticker, DAP_CHAIN_TICKER_SIZE_MAX); l_item_used->cache_data.spent_time = a_spent_time; strncpy(l_item_used->cache_data.token_ticker, l_item_tmp->cache_data.token_ticker, DAP_CHAIN_TICKER_SIZE_MAX); int l_out_num = -1; @@ -5025,3 +5022,13 @@ void dap_chain_ledger_tx_add_notify(dap_ledger_t *a_ledger, dap_chain_ledger_tx_ l_notifier->arg = a_arg; a_ledger->tx_add_notifiers = dap_list_append(a_ledger->tx_add_notifiers, l_notifier); } + +bool dap_chain_ledger_cache_enabled(dap_ledger_t *a_ledger) +{ + return PVT(a_ledger)->cached; +} + +void dap_chain_ledger_set_cache_tx_check_callback(dap_ledger_t *a_ledger, dap_chain_ledger_cache_tx_check_callback_t a_callback) +{ + PVT(a_ledger)->cache_tx_check_callback = a_callback; +} diff --git a/modules/chain/include/dap_chain_ledger.h b/modules/chain/include/dap_chain_ledger.h index 2e368825ba698f1cf7656f988d514def902a8598..665fa340d82900f19b3d1c81c3cef70bf157fd0a 100644 --- a/modules/chain/include/dap_chain_ledger.h +++ b/modules/chain/include/dap_chain_ledger.h @@ -46,7 +46,7 @@ typedef bool (* dap_chain_ledger_verificator_callback_t)(dap_ledger_t * a_ledger dap_chain_datum_tx_t *a_tx_in, bool a_owner); typedef void (*dap_chain_ledger_verificator_callback_out_t)(dap_ledger_t* a_ledger, dap_chain_datum_tx_t* a_tx, dap_chain_tx_out_cond_t* a_cond); typedef void (* dap_chain_ledger_tx_add_notify_t)(void *a_arg, dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx); - +typedef bool (*dap_chain_ledger_cache_tx_check_callback_t)(dap_hash_fast_t *a_tx_hash); typedef struct dap_chain_net dap_chain_net_t; // Checks the emission of the token, usualy on zero chain @@ -260,3 +260,6 @@ dap_list_t * dap_chain_ledger_get_txs(dap_ledger_t *a_ledger, size_t a_count, si //bool dap_chain_ledger_fee_verificator(dap_ledger_t* a_ledger, dap_chain_tx_out_cond_t* a_cond, dap_chain_datum_tx_t* a_tx, bool a_owner); void dap_chain_ledger_tx_add_notify(dap_ledger_t *a_ledger, dap_chain_ledger_tx_add_notify_t a_callback, void *a_arg); + +bool dap_chain_ledger_cache_enabled(dap_ledger_t *a_ledger); +void dap_chain_ledger_set_cache_tx_check_callback(dap_ledger_t *a_ledger, dap_chain_ledger_cache_tx_check_callback_t a_callback); diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index 8f5ee1712f2127f815de35bc5c68683e90e55052..024ef53ba54004773e4ab791b622fc6e80ddca39 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -1167,7 +1167,7 @@ static bool s_net_states_proc(dap_proc_thread_t *a_thread, void *a_arg) switch (l_net_pvt->state) { // State OFFLINE where we don't do anything case NET_STATE_OFFLINE: { - // delete all links + // delete all links struct net_link *l_link, *l_link_tmp; HASH_ITER(hh, l_net_pvt->net_links, l_link, l_link_tmp) { HASH_DEL(l_net_pvt->net_links, l_link); @@ -1528,6 +1528,7 @@ const char* dap_chain_net_get_type(dap_chain_t *l_chain) static void s_chain_net_ledger_cache_reload(dap_chain_net_t *l_net) { dap_chain_ledger_purge(l_net->pub.ledger, false); + dap_chain_net_srv_stake_cache_purge(l_net); dap_chain_t *l_chain = NULL; DL_FOREACH(l_net->pub.chains, l_chain) { if (l_chain->callback_purge) @@ -1847,7 +1848,7 @@ static int s_cli_net(int argc, char **argv, char **a_str_reply) if ( strcmp(l_links_str,"list") == 0 ) { size_t i =0; dap_chain_net_pvt_t * l_net_pvt = PVT(l_net); - pthread_rwlock_rdlock(&l_net_pvt->uplinks_lock); + pthread_rwlock_rdlock(&l_net_pvt->uplinks_lock); size_t l_links_count = HASH_COUNT(l_net_pvt->net_links); dap_string_t *l_reply = dap_string_new(""); dap_string_append_printf(l_reply,"Links %zu:\n", l_links_count); @@ -2207,6 +2208,8 @@ int s_net_load(const char * a_net_name, uint16_t a_acl_idx) HASH_ADD(hh,s_net_items_ids,net_id,sizeof ( l_net_item2->net_id),l_net_item2); pthread_rwlock_unlock(&s_net_ids_rwlock); + + // LEDGER model uint16_t l_ledger_flags = 0; switch ( PVT( l_net )->node_role.enums ) { @@ -2475,10 +2478,7 @@ int s_net_load(const char * a_net_name, uint16_t a_acl_idx) else{ log_it(L_WARNING, "Not present our own address %s in database", (l_node_alias_str) ? l_node_alias_str: ""); } - - - } - + } char * l_chains_path = dap_strdup_printf("%s/network/%s", dap_config_path(), l_net->pub.name); DIR * l_chains_dir = opendir(l_chains_path); @@ -2512,10 +2512,12 @@ int s_net_load(const char * a_net_name, uint16_t a_acl_idx) } closedir(l_chains_dir); + dap_chain_net_srv_stake_load_cache(l_net); // reload ledger cache at once if (s_chain_net_reload_ledger_cache_once(l_net)) { log_it(L_WARNING,"Start one time ledger cache reloading"); dap_chain_ledger_purge(l_net->pub.ledger, false); + dap_chain_net_srv_stake_cache_purge(l_net); } // sort list with chains names by priority @@ -2751,7 +2753,7 @@ dap_chain_net_t * dap_chain_net_by_id( dap_chain_net_id_t a_id) pthread_rwlock_rdlock(&s_net_ids_rwlock); HASH_FIND(hh,s_net_items_ids,&a_id,sizeof (a_id), l_net_item ); pthread_rwlock_unlock(&s_net_ids_rwlock); - return l_net_item ? l_net_item->chain_net : NULL; + return l_net_item ? l_net_item->chain_net : NULL; } /** @@ -3384,7 +3386,6 @@ int dap_chain_datum_add(dap_chain_t *a_chain, dap_chain_datum_t *a_datum, size_t return 0; } - bool dap_chain_net_get_load_mode(dap_chain_net_t * a_net) { return PVT(a_net)->load_mode; diff --git a/modules/service/stake_pos_delegate/dap_chain_net_srv_stake_pos_delegate.c b/modules/service/stake_pos_delegate/dap_chain_net_srv_stake_pos_delegate.c index 01989bfe192af0ae0f5b5a2af08b8165ff558f50..29f6163b7867165d4cf6aa8c87ad5ae26c6008f5 100644 --- a/modules/service/stake_pos_delegate/dap_chain_net_srv_stake_pos_delegate.c +++ b/modules/service/stake_pos_delegate/dap_chain_net_srv_stake_pos_delegate.c @@ -24,6 +24,7 @@ #include <math.h> #include "dap_chain_node_cli.h" +#include "dap_config.h" #include "dap_string.h" #include "dap_list.h" #include "dap_enc_base58.h" @@ -37,20 +38,17 @@ #define LOG_TAG "dap_chain_net_srv_stake" +#define DAP_CHAIN_NET_SRV_STAKE_POS_DELEGATE_GDB_GROUP "delegate_keys" + static int s_cli_srv_stake(int a_argc, char **a_argv, char **a_str_reply); static bool s_stake_verificator_callback(dap_ledger_t * a_ledger,dap_hash_fast_t *a_tx_out_hash, dap_chain_tx_out_cond_t *a_cond, dap_chain_datum_tx_t *a_tx_in, bool a_owner); static void s_stake_updater_callback(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_cond); +static void s_cache_data(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_addr_t *a_signing_addr); + static dap_chain_net_srv_stake_t *s_srv_stake = NULL; -typedef struct dap_chain_net_srv_stake_cache_data -{ - uint256_t value; - dap_chain_addr_t signing_addr; - dap_chain_hash_fast_t tx_hash; - dap_chain_node_addr_t node_addr; -} DAP_ALIGN_PACKED dap_chain_net_srv_stake_cache_data_t; /** * @brief dap_stream_ch_vpn_init Init actions for VPN stream channel @@ -95,12 +93,18 @@ int dap_chain_net_srv_stake_pos_delegate_init() void dap_chain_net_srv_stake_pos_delegate_deinit() { - dap_chain_net_srv_stake_item_t *l_stake = NULL, *l_tmp; + dap_chain_net_srv_stake_item_t *l_stake, *l_tmp; HASH_ITER(hh, s_srv_stake->itemlist, l_stake, l_tmp) { // Clang bug at this, l_stake should change at every loop cycle HASH_DEL(s_srv_stake->itemlist, l_stake); DAP_DELETE(l_stake); } + dap_chain_net_srv_stake_cache_item_t *l_cache_item, *l_cache_tmp; + HASH_ITER(hh, s_srv_stake->cache, l_cache_item, l_cache_tmp) { + // Clang bug at this, l_stake should change at every loop cycle + HASH_DEL(s_srv_stake->cache, l_cache_item); + DAP_DELETE(l_cache_item); + } DAP_DEL_Z(s_srv_stake); } @@ -114,12 +118,14 @@ static bool s_stake_verificator_callback(dap_ledger_t UNUSED_ARG *a_ledger, dap_ return true; } -static void s_stake_updater_callback(dap_ledger_t UNUSED_ARG *a_ledger, dap_chain_datum_tx_t UNUSED_ARG *a_tx, dap_chain_tx_out_cond_t *a_cond) +static void s_stake_updater_callback(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_cond) { assert(s_srv_stake); if (!a_cond) return; - dap_chain_net_srv_stake_key_invalidate(&a_cond->subtype.srv_stake_pos_delegate.signing_addr); + dap_chain_addr_t *l_signing_addr = &a_cond->subtype.srv_stake_pos_delegate.signing_addr; + dap_chain_net_srv_stake_key_invalidate(l_signing_addr); + s_cache_data(a_ledger, a_tx, l_signing_addr); } static bool s_srv_stake_is_poa_cert(dap_chain_net_t *a_net, dap_enc_key_t *a_key) @@ -200,6 +206,57 @@ dap_list_t *dap_chain_net_srv_stake_get_validators() return l_ret; } +static bool s_stake_cache_check_tx(dap_hash_fast_t *a_tx_hash) +{ + dap_chain_net_srv_stake_cache_item_t *l_stake; + HASH_FIND(hh, s_srv_stake->cache, a_tx_hash, sizeof(*a_tx_hash), l_stake); + if (l_stake) { + dap_chain_net_srv_stake_key_invalidate(&l_stake->signing_addr); + return true; + } + return false; +} + +int dap_chain_net_srv_stake_load_cache(dap_chain_net_t *a_net) +{ + dap_ledger_t *l_ledger = a_net->pub.ledger; + if (!dap_chain_ledger_cache_enabled(l_ledger)) + return 0; + char *l_gdb_group = dap_chain_ledger_get_gdb_group(l_ledger, DAP_CHAIN_NET_SRV_STAKE_POS_DELEGATE_GDB_GROUP); + size_t l_objs_count = 0; + dap_store_obj_t *l_store_obj = dap_global_db_get_all_raw_sync(l_gdb_group, 0, &l_objs_count); + if (!l_objs_count || !l_store_obj) { + log_it(L_ATT, "Stake cache data not found"); + return -1; + } + for (size_t i = 0; i < l_objs_count; i++){ + dap_chain_net_srv_stake_cache_data_t *l_cache_data = + (dap_chain_net_srv_stake_cache_data_t *)l_store_obj[i].value; + dap_chain_net_srv_stake_cache_item_t *l_cache = DAP_NEW_Z(dap_chain_net_srv_stake_cache_item_t); + l_cache->signing_addr = l_cache_data->signing_addr; + l_cache->tx_hash = l_cache_data->tx_hash; + HASH_ADD(hh, s_srv_stake->cache, tx_hash, sizeof(dap_hash_fast_t), l_cache); + } + dap_store_obj_free(l_store_obj, l_objs_count); + dap_chain_ledger_set_cache_tx_check_callback(l_ledger, s_stake_cache_check_tx); + return 0; +} + +void dap_chain_net_srv_stake_cache_purge(dap_chain_net_t *a_net) +{ + dap_ledger_t *l_ledger = a_net->pub.ledger; + char *l_gdb_group = dap_chain_ledger_get_gdb_group(l_ledger, DAP_CHAIN_NET_SRV_STAKE_POS_DELEGATE_GDB_GROUP); + dap_global_db_del(l_gdb_group, NULL, NULL, NULL); + DAP_DELETE(l_gdb_group); + dap_chain_net_srv_stake_cache_item_t *l_cache_item, *l_cache_tmp; + HASH_ITER(hh, s_srv_stake->cache, l_cache_item, l_cache_tmp) { + // Clang bug at this, l_stake should change at every loop cycle + HASH_DEL(s_srv_stake->cache, l_cache_item); + DAP_DELETE(l_cache_item); + } +} + + // 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_chain_wallet_t *a_wallet, uint256_t a_value, uint256_t a_fee, @@ -433,20 +490,6 @@ static dap_chain_datum_decree_t *s_stake_decree_approve(dap_chain_net_t *a_net, return NULL; } - //TODO: form decree for key delegating - /* Used sections - a_stake_tx_hash - l_tx_out_cond->header.value, - l_tx_out_cond->subtype.srv_stake_pos_delegate.signing_addr, - l_tx_out_cond->subtype.srv_stake_pos_delegate.signer_node_addr - - // add 'sign' items - if(dap_chain_datum_tx_add_sign_item(&l_tx, a_cert->enc_key) != 1) { - dap_chain_datum_tx_delete(l_tx); - log_it( L_ERROR, "Can't add sign output"); - return NULL; - } */ - return l_decree; } @@ -630,16 +673,6 @@ static dap_chain_datum_decree_t *s_stake_decree_invalidate(dap_chain_net_t *a_ne return NULL; } - /* Used sections - - l_tx_out_cond->subtype.srv_stake_pos_delegate.signing_addr, - - // add 'sign' items - if(dap_chain_datum_tx_add_sign_item(&l_tx, a_key) != 1) { - dap_chain_datum_tx_delete(l_tx); - log_it( L_ERROR, "Can't add sign output"); - return NULL; - } */ return l_decree; } @@ -1417,7 +1450,8 @@ static int s_cli_srv_stake(int a_argc, char **a_argv, char **a_str_reply) return 0; } -void dap_chain_net_srv_stake_get_fee_validators(dap_chain_net_t *a_net, dap_string_t *a_string_ret){ +void dap_chain_net_srv_stake_get_fee_validators(dap_chain_net_t *a_net, dap_string_t *a_string_ret) +{ if (!a_net || !a_string_ret) return; char * l_gdb_group_str = dap_chain_net_srv_order_get_gdb_group(a_net); @@ -1474,3 +1508,16 @@ void dap_chain_net_srv_stake_get_fee_validators(dap_chain_net_t *a_net, dap_stri DAP_DELETE(l_average_coins); } +static void s_cache_data(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_addr_t *a_signing_addr) +{ + if (!dap_chain_ledger_cache_enabled(a_ledger)) + return; + dap_chain_net_srv_stake_cache_data_t l_cache_data; + dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), &l_cache_data.tx_hash); + l_cache_data.signing_addr = *a_signing_addr; + char *l_data_key = dap_chain_hash_fast_to_str_new(&l_cache_data.tx_hash); + char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, DAP_CHAIN_NET_SRV_STAKE_POS_DELEGATE_GDB_GROUP); + if (dap_global_db_set(l_gdb_group, l_data_key, &l_cache_data, sizeof(l_cache_data), true, NULL, NULL)) + log_it(L_WARNING, "Stake service cache mismatch"); + DAP_DELETE(l_data_key); +} diff --git a/modules/service/stake_pos_delegate/include/dap_chain_net_srv_stake_pos_delegate.h b/modules/service/stake_pos_delegate/include/dap_chain_net_srv_stake_pos_delegate.h index e8173fd1ed843267c85371d75a1ed86fead09c75..2f940c6e074ddfa5bc332a882f6318dc751a15f8 100644 --- a/modules/service/stake_pos_delegate/include/dap_chain_net_srv_stake_pos_delegate.h +++ b/modules/service/stake_pos_delegate/include/dap_chain_net_srv_stake_pos_delegate.h @@ -40,9 +40,22 @@ typedef struct dap_chain_net_srv_stake_item { UT_hash_handle hh; } dap_chain_net_srv_stake_item_t; + +typedef struct dap_chain_net_srv_stake_cache_data { + dap_chain_hash_fast_t tx_hash; + dap_chain_addr_t signing_addr; +} DAP_ALIGN_PACKED dap_chain_net_srv_stake_cache_data_t; + +typedef struct dap_chain_net_srv_stake_cache_item { + dap_chain_hash_fast_t tx_hash; + dap_chain_addr_t signing_addr; + UT_hash_handle hh; +} dap_chain_net_srv_stake_cache_item_t; + typedef struct dap_chain_net_srv_stake { uint256_t delegate_allowed_min; dap_chain_net_srv_stake_item_t *itemlist; + dap_chain_net_srv_stake_cache_item_t *cache; } dap_chain_net_srv_stake_t; int dap_chain_net_srv_stake_pos_delegate_init(); @@ -58,3 +71,6 @@ bool dap_chain_net_srv_stake_key_delegated(dap_chain_addr_t *a_addr); dap_list_t *dap_chain_net_srv_stake_get_validators(); void dap_chain_net_srv_stake_get_fee_validators(dap_chain_net_t *a_net, dap_string_t *a_string); + +int dap_chain_net_srv_stake_load_cache(dap_chain_net_t *a_net); +void dap_chain_net_srv_stake_cache_purge(dap_chain_net_t *a_net);