diff --git a/dap-sdk/net/core/dap_events.c b/dap-sdk/net/core/dap_events.c index fd786c671c1b1831f49cb734c6239ffa6f35185e..f29f7f3d8fde6dc2c51966100a673972b5739ccb 100644 --- a/dap-sdk/net/core/dap_events.c +++ b/dap-sdk/net/core/dap_events.c @@ -39,7 +39,7 @@ #include <sys/stat.h> #endif -#include <netdb.h> +//#include <netdb.h> #include <unistd.h> #include <fcntl.h> #include <errno.h> diff --git a/dap-sdk/net/core/include/dap_events_socket.h b/dap-sdk/net/core/include/dap_events_socket.h index 68020f1a339071b7269d987bb897aee2b45f6d7f..dae83d1d74efea7e56b64f3b4eb6fd78dbc5bac0 100644 --- a/dap-sdk/net/core/include/dap_events_socket.h +++ b/dap-sdk/net/core/include/dap_events_socket.h @@ -54,12 +54,12 @@ #define DAP_EVENTS_CAPS_PIPE_POSIX #endif -#if defined(DAP_EVENTS_CAPS_EPOLL) -#include <sys/epoll.h> -#define EPOLL_HANDLE int -#elif defined (DAP_EVENTS_CAPS_WEPOLL) +#if defined(DAP_EVENTS_CAPS_WEPOLL) #include "wepoll.h" #define EPOLL_HANDLE HANDLE +#elif defined (DAP_EVENTS_CAPS_EPOLL) +#include <sys/epoll.h> +#define EPOLL_HANDLE int #endif #define BIT( x ) ( 1 << x ) diff --git a/modules/chain/dap_chain_cs.c b/modules/chain/dap_chain_cs.c index cc88a25baf6e5909289d9c3fde67996ad1acdaf7..c7349da68ed0835a3380218488fc93cb1082045d 100644 --- a/modules/chain/dap_chain_cs.c +++ b/modules/chain/dap_chain_cs.c @@ -123,7 +123,7 @@ int dap_chain_cs_create(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) if ( l_item ) { log_it(L_NOTICE,"Consensus \"%s\" found, prepare to parse config file",l_item->name ); l_item->callback_init( a_chain, a_chain_cfg); - // TODO + DAP_CHAIN_PVT(a_chain)->cs_name = l_item->name; return 0; } else { log_it(L_ERROR,"Can't find consensus \"%s\"",dap_config_get_item_str( a_chain_cfg, "chain", "consensus")); diff --git a/modules/chain/dap_chain_ledger.c b/modules/chain/dap_chain_ledger.c index e0cf28cbf82400ac48ceb062dd45b6956c66352f..0f66f0343ac4482091d452ee3de40a29048f30c1 100644 --- a/modules/chain/dap_chain_ledger.c +++ b/modules/chain/dap_chain_ledger.c @@ -52,7 +52,6 @@ #include "dap_chain_datum_token.h" #include "dap_chain_mempool.h" #include "dap_chain_global_db.h" -#include "dap_chain_net.h" #include "dap_chain_ledger.h" #define LOG_TAG "dap_chain_ledger" @@ -69,18 +68,12 @@ static pthread_rwlock_t s_verificators_rwlock; #define MAX_OUT_ITEMS 10 typedef struct dap_chain_ledger_token_emission_item { dap_chain_hash_fast_t datum_token_emission_hash; - // while these are not needed - //dap_chain_hash_fast_t datum_tx_token_hash; - //dap_chain_tx_token_t * tx_token; - dap_chain_datum_token_emission_t *datum_token_emission; UT_hash_handle hh; } dap_chain_ledger_token_emission_item_t; typedef struct dap_chain_ledger_token_item { char ticker[DAP_CHAIN_TICKER_SIZE_MAX]; - dap_chain_hash_fast_t datum_token_hash; - uint8_t padding[6]; dap_chain_datum_token_t * datum_token; uint64_t total_supply; pthread_rwlock_t token_emissions_rwlock; @@ -88,17 +81,18 @@ typedef struct dap_chain_ledger_token_item { UT_hash_handle hh; } dap_chain_ledger_token_item_t; -// ledger cache item - one of unspendet outputs +// ledger cache item - one of unspent outputs typedef struct dap_chain_ledger_tx_item { dap_chain_hash_fast_t tx_hash_fast; dap_chain_datum_tx_t *tx; - time_t ts_created; - int n_outs; - int n_outs_used; - char token_tiker[10]; - // TODO dynamically allocates the memory in order not to limit the number of outputs in transaction - dap_chain_hash_fast_t tx_hash_spent_fast[MAX_OUT_ITEMS]; // spent outs list - uint8_t padding[6]; + struct { + time_t ts_created; + int n_outs; + int n_outs_used; + char token_tiker[10]; + // TODO dynamically allocates the memory in order not to limit the number of outputs in transaction + dap_chain_hash_fast_t tx_hash_spent_fast[MAX_OUT_ITEMS]; // spent outs list + } cache_data; UT_hash_handle hh; } dap_chain_ledger_tx_item_t; @@ -123,21 +117,24 @@ typedef struct dap_chain_ledger_tx_bound { dap_chain_ledger_tx_item_t *item_out; } dap_chain_ledger_tx_bound_t; -// Gotta use a regular null-terminated string instead, for uthash usability -/*typedef struct dap_ledger_wallet_balance_key{ - dap_chain_addr_t addr; - char ticker[DAP_CHAIN_TICKER_SIZE_MAX]; -} DAP_ALIGN_PACKED dap_ledger_wallet_balance_key_t; */ - // in-memory wallet balance typedef struct dap_ledger_wallet_balance { - //dap_ledger_wallet_balance_key_t key; char *key; char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX]; uint128_t balance; UT_hash_handle hh; } dap_ledger_wallet_balance_t; +typedef struct dap_ledger_cache_item { + dap_chain_hash_fast_t *hash; + bool found; +} dap_ledger_cache_item_t; + +typedef struct dap_ledger_cache_str_item { + char *key; + bool found; +} dap_ledger_cache_str_item_t; + // dap_ledget_t private section typedef struct dap_ledger_private { // List of ledger - unspent transactions cache @@ -163,6 +160,11 @@ typedef struct dap_ledger_private { bool check_cells_ds; bool check_token_emission; dap_chain_cell_id_t local_cell_id; + /* Cache section */ + dap_ledger_cache_item_t last_tx; + dap_ledger_cache_item_t last_thres_tx; + dap_ledger_cache_item_t last_emit; + dap_ledger_cache_str_item_t last_ticker; } dap_ledger_private_t; #define PVT(a) ( (dap_ledger_private_t* ) a->_internal ) @@ -282,13 +284,19 @@ int dap_chain_ledger_token_add(dap_ledger_t * a_ledger, dap_chain_datum_token_t l_token_item = DAP_NEW_Z(dap_chain_ledger_token_item_t); dap_snprintf(l_token_item->ticker,sizeof (l_token_item->ticker),"%s",a_token->ticker); pthread_rwlock_init(&l_token_item->token_emissions_rwlock,NULL); - l_token_item->datum_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, a_token_size); - memcpy(l_token_item->datum_token, a_token,a_token_size); - dap_hash_fast(a_token,a_token_size, &l_token_item->datum_token_hash); + HASH_ADD_STR(PVT(a_ledger)->tokens, ticker, l_token_item); + // Add it to cache + dap_chain_datum_token_t *l_token_cache = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, a_token_size); + memcpy(l_token_cache, a_token, a_token_size); + char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "tokens"); + if (!dap_chain_global_db_gr_set(dap_strdup(a_token->ticker), l_token_cache, a_token_size, l_gdb_group)) { + log_it(L_WARNING, "Ledger cache mismatch"); + DAP_DELETE(l_token_cache); + } + DAP_DELETE(l_gdb_group); - HASH_ADD_STR(PVT(a_ledger)->tokens, ticker, l_token_item) ; switch(a_token->type){ case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE: l_token_item->total_supply = a_token->header_private.total_supply; @@ -311,6 +319,15 @@ int dap_chain_ledger_token_add(dap_ledger_t * a_ledger, dap_chain_datum_token_t return 0; } +int dap_chain_ledger_token_load(dap_ledger_t *a_ledger, dap_chain_datum_token_t *a_token, size_t a_token_size) +{ + if (PVT(a_ledger)->last_ticker.found) { + return dap_chain_ledger_token_add(a_ledger, a_token, a_token_size); + } else if (!strncmp(PVT(a_ledger)->last_ticker.key, a_token->ticker, DAP_CHAIN_TICKER_SIZE_MAX)) { + PVT(a_ledger)->last_ticker.found = true; + } + return 0; +} /** * @brief s_treshold_emissions_proc * @param a_ledger @@ -332,21 +349,120 @@ static void s_treshold_txs_proc( dap_ledger_t * a_ledger) } +void dap_chain_ledger_load_cache(dap_ledger_t *a_ledger) +{ + dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger); + + char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "tokens"); + size_t l_objs_count = 0; + dap_global_db_obj_t *l_objs = dap_chain_global_db_gr_load(l_gdb_group, &l_objs_count); + for (size_t i = 0; i < l_objs_count; i++) { + dap_chain_ledger_token_item_t *l_token_item = DAP_NEW_Z(dap_chain_ledger_token_item_t); + strncpy(l_token_item->ticker, l_objs[i].key, sizeof(l_token_item->ticker)); + l_token_item->datum_token = DAP_NEW_Z_SIZE(dap_chain_datum_token_t, l_objs[i].value_len); + memcpy(l_token_item->datum_token, l_objs[i].value, l_objs[i].value_len); + pthread_rwlock_init(&l_token_item->token_emissions_rwlock, NULL); + if (l_token_item->datum_token->type == DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE) { + l_token_item->total_supply = l_token_item->datum_token->header_private.total_supply; + } + HASH_ADD_STR(PVT(a_ledger)->tokens, ticker, l_token_item); + if (i == l_objs_count - 1) { + l_ledger_pvt->last_ticker.key = l_token_item->ticker; + } + } + dap_chain_global_db_objs_delete(l_objs, l_objs_count); + DAP_DELETE(l_gdb_group); + if (l_objs_count == 0) { + l_ledger_pvt->last_ticker.found = true; + } + + l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "emissions"); + l_objs_count = 0; + l_objs = dap_chain_global_db_gr_load(l_gdb_group, &l_objs_count); + for (size_t i = 0; i < l_objs_count; i++) { + dap_chain_ledger_token_emission_item_t *l_emission_item = DAP_NEW_Z(dap_chain_ledger_token_emission_item_t); + dap_chain_str_to_hash_fast(l_objs[i].key, &l_emission_item->datum_token_emission_hash); + l_emission_item->datum_token_emission = DAP_NEW_Z_SIZE(dap_chain_datum_token_emission_t, l_objs[i].value_len); + memcpy(l_emission_item->datum_token_emission, l_objs[i].value, l_objs[i].value_len); + const char * c_token_ticker = l_emission_item->datum_token_emission->hdr.ticker; + dap_chain_ledger_token_item_t *l_token_item = NULL; + HASH_FIND_STR(l_ledger_pvt->tokens, c_token_ticker, l_token_item); + if (l_token_item) { + HASH_ADD(hh, l_token_item->token_emissions, datum_token_emission_hash, + sizeof(dap_chain_hash_fast_t), l_emission_item); + } else { + HASH_ADD(hh, l_ledger_pvt->treshold_emissions, datum_token_emission_hash, + sizeof(dap_chain_hash_fast_t), l_emission_item); + } + if (i == l_objs_count - 1) { + l_ledger_pvt->last_emit.hash = &l_emission_item->datum_token_emission_hash; + } + } + dap_chain_global_db_objs_delete(l_objs, l_objs_count); + DAP_DELETE(l_gdb_group); + if (l_objs_count == 0) { + l_ledger_pvt->last_emit.found = true; + } + + l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "txs"); + l_objs_count = 0; + l_objs = dap_chain_global_db_gr_load(l_gdb_group, &l_objs_count); + for (size_t i = 0; i < l_objs_count; i++) { + dap_chain_ledger_tx_item_t *l_tx_item = DAP_NEW_Z(dap_chain_ledger_tx_item_t); + dap_chain_str_to_hash_fast(l_objs[i].key, &l_tx_item->tx_hash_fast); + l_tx_item->tx = DAP_NEW_Z_SIZE(dap_chain_datum_tx_t, l_objs[i].value_len - sizeof(l_tx_item->cache_data)); + memcpy(l_tx_item->tx, l_objs[i].value + sizeof(l_tx_item->cache_data), l_objs[i].value_len - sizeof(l_tx_item->cache_data)); + memcpy(&l_tx_item->cache_data, l_objs[i].value, sizeof(l_tx_item->cache_data)); + HASH_ADD(hh, l_ledger_pvt->ledger_items, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_tx_item); + if (i == l_objs_count - 1) { + PVT(a_ledger)->last_tx.hash = &l_tx_item->tx_hash_fast; + } + } + dap_chain_global_db_objs_delete(l_objs, l_objs_count); + DAP_DELETE(l_gdb_group); + if (l_objs_count == 0) { + l_ledger_pvt->last_tx.found = true; + } + + //TODO add tx threshold cache if need + l_ledger_pvt->last_thres_tx.found = true; + + l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "balances"); + l_objs_count = 0; + l_objs = dap_chain_global_db_gr_load(l_gdb_group, &l_objs_count); + for (size_t i = 0; i < l_objs_count; i++) { + dap_ledger_wallet_balance_t *l_balance_item = DAP_NEW_Z(dap_ledger_wallet_balance_t); + l_balance_item->key = DAP_NEW_Z_SIZE(char, strlen(l_objs[i].key) + 1); + strcpy(l_balance_item->key, l_objs[i].key); + char *l_ptr = strchr(l_balance_item->key, ' '); + if (l_ptr++) { + strcpy(l_balance_item->token_ticker, l_ptr); + } + l_balance_item->balance = *(uint128_t *)l_objs[i].value; + HASH_ADD_KEYPTR(hh, l_ledger_pvt->balance_accounts, l_balance_item->key, + strlen(l_balance_item->key), l_balance_item); + } + dap_chain_global_db_objs_delete(l_objs, l_objs_count); + DAP_DELETE(l_gdb_group); +} + /** * @brief dap_chain_ledger_create * @param a_check_flags * @return dap_ledger_t */ -dap_ledger_t* dap_chain_ledger_create(uint16_t a_check_flags) +dap_ledger_t* dap_chain_ledger_create(uint16_t a_check_flags, char *a_net_name) { dap_ledger_t *l_ledger = dap_chain_ledger_handle_new(); + l_ledger->net_name = a_net_name; dap_ledger_private_t *l_ledger_priv = PVT(l_ledger); l_ledger_priv->check_flags = a_check_flags; l_ledger_priv->check_ds = a_check_flags & DAP_CHAIN_LEDGER_CHECK_LOCAL_DS; l_ledger_priv->check_cells_ds = a_check_flags & DAP_CHAIN_LEDGER_CHECK_CELLS_DS; l_ledger_priv->check_token_emission = a_check_flags & DAP_CHAIN_LEDGER_CHECK_TOKEN_EMISSION; - // load ledger from mempool - return l_ledger; //dap_chain_ledger_load(l_ledger, "kelvin-testnet", "plasma"); + // load ledger cache from GDB + dap_chain_ledger_load_cache(l_ledger); + return l_ledger; } int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger, const dap_chain_datum_token_emission_t *a_token_emission @@ -430,16 +546,23 @@ int dap_chain_ledger_token_emission_add(dap_ledger_t *a_ledger, memcpy(l_token_emission_item->datum_token_emission, a_token_emission, a_token_emission_size); memcpy(&l_token_emission_item->datum_token_emission_hash, l_token_emission_hash_ptr, sizeof(l_token_emission_hash)); - dap_chain_ledger_token_emission_item_t * l_token_emissions = l_token_item ? - l_token_item->token_emissions : l_ledger_priv->treshold_emissions; - HASH_ADD(hh, l_token_emissions , - datum_token_emission_hash, sizeof(l_token_emission_hash), - l_token_emission_item); - // save pointer to structure - if(l_token_item) - l_token_item->token_emissions = l_token_emissions; - else - l_ledger_priv->treshold_emissions = l_token_emissions; + if (l_token_item) { + HASH_ADD(hh, l_token_item->token_emissions, datum_token_emission_hash, + sizeof(l_token_emission_hash), l_token_emission_item); + } else { + HASH_ADD(hh, l_ledger_priv->treshold_emissions, datum_token_emission_hash, + sizeof(l_token_emission_hash), l_token_emission_item); + } + // Add it to cache + dap_chain_datum_token_emission_t *l_emission_cache = DAP_NEW_Z_SIZE(dap_chain_datum_token_emission_t, a_token_emission_size); + memcpy(l_emission_cache, a_token_emission, a_token_emission_size); + char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "emissions"); + if (!dap_chain_global_db_gr_set(dap_strdup(l_hash_str), l_emission_cache, a_token_emission_size, l_gdb_group)) { + log_it(L_WARNING, "Ledger cache mismatch"); + DAP_DELETE(l_emission_cache); + } + DAP_DELETE(l_gdb_group); + char * l_token_emission_address_str = dap_chain_addr_to_str( &(a_token_emission->hdr.address) ); log_it(L_NOTICE, "Added token emission datum to %s: type=%s value=%.1llf token=%s to_addr=%s ", @@ -466,6 +589,20 @@ int dap_chain_ledger_token_emission_add(dap_ledger_t *a_ledger, return ret; } +int dap_chain_ledger_token_emission_load(dap_ledger_t *a_ledger, const dap_chain_datum_token_emission_t *a_token_emission, size_t a_token_emission_size) +{ + if (PVT(a_ledger)->last_emit.found) { + return dap_chain_ledger_token_emission_add(a_ledger, a_token_emission, a_token_emission_size); + } else { + dap_chain_hash_fast_t l_token_emission_hash = {}; + dap_hash_fast(a_token_emission, a_token_emission_size, &l_token_emission_hash); + if (!memcmp(PVT(a_ledger)->last_emit.hash, &l_token_emission_hash, sizeof(dap_chain_hash_fast_t))) { + PVT(a_ledger)->last_emit.found = true; + } + } + return 0; +} + /** * @brief dap_chain_ledger_token_emission_find * @param a_token_ticker @@ -522,7 +659,7 @@ const char* dap_chain_ledger_tx_get_token_ticker_by_hash(dap_ledger_t *a_ledger, pthread_rwlock_rdlock(&l_ledger_priv->ledger_rwlock); HASH_FIND(hh, l_ledger_priv->ledger_items, a_tx_hash, sizeof ( *a_tx_hash), l_item ); pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock); - return l_item? l_item->token_tiker: NULL; + return l_item ? l_item->cache_data.token_tiker : NULL; } /** @@ -548,7 +685,7 @@ void dap_chain_ledger_addr_get_token_ticker_all(dap_ledger_t *a_ledger, dap_chai for(size_t i = 0; i < l_tickers_size; i++) { if (l_tickers[i]==NULL) break; - if(l_tickers[i] && strcmp(l_tickers[i], l_tx_item->token_tiker) == 0) { + if(l_tickers[i] && strcmp(l_tickers[i], l_tx_item->cache_data.token_tiker) == 0) { l_is_not_in_list = false; break; } @@ -558,7 +695,7 @@ void dap_chain_ledger_addr_get_token_ticker_all(dap_ledger_t *a_ledger, dap_chai l_tickers_size += (l_tickers_size / 2); l_tickers = DAP_REALLOC(l_tickers, l_tickers_size); } - l_tickers[l_tickers_pos] = dap_strdup(l_tx_item->token_tiker); + l_tickers[l_tickers_pos] = dap_strdup(l_tx_item->cache_data.token_tiker); l_tickers_pos++; } dap_chain_hash_fast_t* l_tx_hash = dap_chain_node_datum_tx_calc_hash(l_tx_item->tx); @@ -647,8 +784,8 @@ static bool dap_chain_ledger_item_is_used_out(dap_chain_ledger_tx_item_t *a_item } assert(a_idx_out < MAX_OUT_ITEMS); // if there are used 'out' items - if(a_item->n_outs_used > 0) { - if(!dap_hash_fast_is_blank(&(a_item->tx_hash_spent_fast[a_idx_out]))) + if(a_item->cache_data.n_outs_used > 0) { + if(!dap_hash_fast_is_blank(&(a_item->cache_data.tx_hash_spent_fast[a_idx_out]))) l_used_out = true; } return l_used_out; @@ -888,7 +1025,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t l_token = NULL; } if (!l_token || !*l_token) { - l_token = l_item_out->token_tiker; + l_token = l_item_out->cache_data.token_tiker; } if (!*l_token) { log_it(L_WARNING, "No token ticker found in previous transaction"); @@ -1057,6 +1194,19 @@ int dap_chain_ledger_tx_add_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t * return 0; } +int dap_chain_ledger_balance_cache_update(dap_ledger_t *a_ledger, dap_ledger_wallet_balance_t *a_balance) +{ + char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "balances"); + uint128_t *l_balance_value = DAP_NEW_Z(uint128_t); + *l_balance_value = a_balance->balance; + if (!dap_chain_global_db_gr_set(dap_strdup(a_balance->key), l_balance_value, sizeof(uint128_t), l_gdb_group)) { + log_it(L_WARNING, "Ledger cache mismatch"); + DAP_DELETE(l_balance_value); + return -1; + } + return 0; +} + /** * Add new transaction to the cache list * @@ -1113,8 +1263,8 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx) void *l_item_in = *(void **)&bound_item->in; dap_chain_tx_item_type_t l_type = *(uint8_t *)l_item_in; dap_chain_ledger_tx_item_t *l_prev_item_out = bound_item->item_out; - if (*l_prev_item_out->token_tiker) { - l_token_ticker = l_prev_item_out->token_tiker; + if (*l_prev_item_out->cache_data.token_tiker) { + l_token_ticker = l_prev_item_out->cache_data.token_tiker; } else { // Previous multichannel transaction l_token_ticker = bound_item->out.tx_prev_out_ext->token; } @@ -1140,26 +1290,28 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx) bound_item->out.tx_prev_out_ext->header.value; //log_it(L_DEBUG,"SPEND %lu from addr: %s", l_value, l_wallet_balance_key); wallet_balance->balance -= l_value; + // Update the cache + dap_chain_ledger_balance_cache_update(a_ledger, wallet_balance); } else { log_it(L_ERROR,"!!! Attempt to SPEND from some non-existent balance !!!: %s %s", l_addr_str, l_token_ticker); } DAP_DELETE(l_addr_str); DAP_DELETE(l_wallet_balance_key); /// Mark 'out' item in cache because it used - l_tx_prev_hash = &(l_prev_item_out->tx_hash_spent_fast[l_tx_in->header.tx_out_prev_idx]); + l_tx_prev_hash = &(l_prev_item_out->cache_data.tx_hash_spent_fast[l_tx_in->header.tx_out_prev_idx]); } else { // TX_ITEM_TYPE_IN_COND // all balance deducts performed with previous conditional transaction dap_chain_tx_in_cond_t *l_tx_in_cond = bound_item->in.tx_cur_in_cond; /// Mark 'out' item in cache because it used - l_tx_prev_hash = &(l_prev_item_out->tx_hash_spent_fast[l_tx_in_cond->header.tx_out_prev_idx]); + l_tx_prev_hash = &(l_prev_item_out->cache_data.tx_hash_spent_fast[l_tx_in_cond->header.tx_out_prev_idx]); } memcpy(l_tx_prev_hash, l_tx_hash, sizeof(dap_chain_hash_fast_t)); // add a used output - l_prev_item_out->n_outs_used++; + l_prev_item_out->cache_data.n_outs_used++; char * l_tx_prev_hash_str = dap_chain_hash_fast_to_str_new(l_tx_prev_hash); // delete previous transactions from cache because all out is used - if(l_prev_item_out->n_outs_used == l_prev_item_out->n_outs) { + if(l_prev_item_out->cache_data.n_outs_used == l_prev_item_out->cache_data.n_outs) { dap_chain_hash_fast_t l_tx_prev_hash_to_del = bound_item->tx_prev_hash_fast; // remove from memory ledger int res = dap_chain_ledger_tx_remove(a_ledger, &l_tx_prev_hash_to_del); @@ -1237,6 +1389,8 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx) //log_it(L_DEBUG, "Balance item is present in cache"); wallet_balance->balance += l_value; DAP_DELETE (l_wallet_balance_key); + // Update the cache + dap_chain_ledger_balance_cache_update(a_ledger, wallet_balance); } else { wallet_balance = DAP_NEW_Z(dap_ledger_wallet_balance_t); wallet_balance->key = l_wallet_balance_key; @@ -1245,6 +1399,8 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx) //log_it(L_DEBUG,"!!! Create new balance item: %s %s", l_addr_str, l_token_ticker); HASH_ADD_KEYPTR(hh, PVT(a_ledger)->balance_accounts, wallet_balance->key, strlen(l_wallet_balance_key), wallet_balance); + // Add it to cache + dap_chain_ledger_balance_cache_update(a_ledger, wallet_balance); } #ifdef __ANDROID__ log_it(L_INFO, "Updated balance +%.3Lf %s on addr %s", @@ -1272,15 +1428,15 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx) l_item_tmp = DAP_NEW_Z(dap_chain_ledger_tx_item_t); memcpy(&l_item_tmp->tx_hash_fast, l_tx_hash, sizeof(dap_chain_hash_fast_t)); l_item_tmp->tx = DAP_NEW_SIZE(dap_chain_datum_tx_t, dap_chain_datum_tx_get_size(a_tx)); - l_item_tmp->ts_created = (time_t) a_tx->header.ts_created; + l_item_tmp->cache_data.ts_created = (time_t) a_tx->header.ts_created; //calculate l_item_tmp->n_outs; // If debug mode dump the UTXO if ( dap_log_level_get() == L_DEBUG){ - l_item_tmp->n_outs = 0; - if( l_item_tmp->n_outs){ - dap_list_t *l_tist_tmp = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT, &l_item_tmp->n_outs); - for (size_t i =0; i < (size_t) l_item_tmp->n_outs; i++){ + l_item_tmp->cache_data.n_outs = 0; + if( l_item_tmp->cache_data.n_outs){ + dap_list_t *l_tist_tmp = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT, &l_item_tmp->cache_data.n_outs); + for (size_t i =0; i < (size_t) l_item_tmp->cache_data.n_outs; i++){ // TODO list conditional outputs dap_chain_tx_out_t * l_tx_out = l_tist_tmp->data; char * l_tx_out_addr_str = dap_chain_addr_to_str( &l_tx_out->addr ); @@ -1303,10 +1459,20 @@ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx) } } if (l_token_ticker && !l_multichannel) - strncpy(l_item_tmp->token_tiker, l_token_ticker, sizeof(l_item_tmp->token_tiker) - 1); - - memcpy(l_item_tmp->tx, a_tx, dap_chain_datum_tx_get_size(a_tx)); - HASH_ADD(hh, l_ledger_priv->ledger_items, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_item_tmp); // tx_hash_fast: name of key field + strncpy(l_item_tmp->cache_data.token_tiker, l_token_ticker, sizeof(l_item_tmp->cache_data.token_tiker) - 1); + size_t l_tx_size = dap_chain_datum_tx_get_size(a_tx); + memcpy(l_item_tmp->tx, a_tx, l_tx_size); + HASH_ADD(hh, l_ledger_priv->ledger_items, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_item_tmp); // tx_hash_fast: name of key field + // Add it to cache + uint8_t *l_tx_cache = DAP_NEW_Z_SIZE(uint8_t, l_tx_size + sizeof(l_item_tmp->cache_data)); + memcpy(l_tx_cache, &l_item_tmp->cache_data, sizeof(l_item_tmp->cache_data)); + memcpy(l_tx_cache + sizeof(l_item_tmp->cache_data), a_tx, l_tx_size); + char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "txs"); + if (!dap_chain_global_db_gr_set(dap_strdup(l_tx_hash_str), l_tx_cache, l_tx_size + sizeof(l_item_tmp->cache_data), l_gdb_group)) { + log_it(L_WARNING, "Ledger cache mismatch"); + DAP_DELETE(l_tx_cache); + } + DAP_DELETE(l_gdb_group); ret = 1; } FIN: @@ -1316,6 +1482,25 @@ FIN: return ret; } +int dap_chain_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx) +{ + if (PVT(a_ledger)->last_tx.found && PVT(a_ledger)->last_thres_tx.found) { + return dap_chain_ledger_tx_add(a_ledger, a_tx); + } else { + 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 (!PVT(a_ledger)->last_tx.found && + !memcmp(PVT(a_ledger)->last_tx.hash, &l_tx_hash, sizeof(dap_chain_hash_fast_t))) { + PVT(a_ledger)->last_tx.found = true; + } + if (!PVT(a_ledger)->last_thres_tx.found && + !memcmp(PVT(a_ledger)->last_thres_tx.hash, &l_tx_hash, sizeof(dap_chain_hash_fast_t))) { + PVT(a_ledger)->last_thres_tx.found = true; + } + } + return 1; +} + /** * Delete transaction from the cache * @@ -1332,18 +1517,20 @@ int dap_chain_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_ HASH_FIND(hh, l_ledger_priv->ledger_items, a_tx_hash, sizeof(dap_chain_hash_fast_t), l_item_tmp); if(l_item_tmp != NULL) { HASH_DEL(l_ledger_priv->ledger_items, l_item_tmp); + // delete transaction + DAP_DELETE(l_item_tmp->tx); + // del struct for hash + DAP_DELETE(l_item_tmp); + // Remove it from cache + char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "txs"); + dap_chain_global_db_gr_del(dap_chain_hash_fast_to_str_new(a_tx_hash), l_gdb_group); + DAP_DELETE(l_gdb_group); l_ret = 1; } else // hash not found in the cache l_ret = -2; pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock); - if(!l_ret) { - // delete transaction - DAP_DELETE(l_item_tmp->tx); - // del struct for hash - DAP_DELETE(l_item_tmp); - } return l_ret; } @@ -1353,16 +1540,82 @@ int dap_chain_ledger_tx_remove(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_ void dap_chain_ledger_purge(dap_ledger_t *a_ledger) { dap_ledger_private_t *l_ledger_priv = PVT(a_ledger); - dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp; + const int l_hash_str_size = DAP_CHAIN_HASH_FAST_SIZE * 2 + 2; + char l_hash_str[l_hash_str_size]; pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock); - HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp) - { - // delete transaction - DAP_DELETE(l_iter_current->tx); - // del struct for hash - HASH_DEL(l_ledger_priv->ledger_items, l_iter_current); + pthread_rwlock_wrlock(&l_ledger_priv->tokens_rwlock); + pthread_rwlock_wrlock(&l_ledger_priv->treshold_emissions_rwlock); + pthread_rwlock_wrlock(&l_ledger_priv->treshold_txs_rwlock); + + // delete transactions + dap_chain_ledger_tx_item_t *l_item_current, *l_item_tmp; + char *l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "txs"); + HASH_ITER(hh, l_ledger_priv->ledger_items , l_item_current, l_item_tmp) { + DAP_DELETE(l_item_current->tx); + HASH_DEL(l_ledger_priv->ledger_items, l_item_current); + dap_chain_hash_fast_to_str(&l_item_current->tx_hash_fast, l_hash_str, l_hash_str_size); + dap_chain_global_db_gr_del(l_hash_str, l_gdb_group); + DAP_DELETE(l_item_current); + } + DAP_DELETE(l_gdb_group); + + // delete threshold txs + l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "thres_txs"); + HASH_ITER(hh, l_ledger_priv->treshold_txs, l_item_current, l_item_tmp) { + HASH_DEL(l_ledger_priv->treshold_txs, l_item_current); + dap_chain_hash_fast_to_str(&l_item_current->tx_hash_fast, l_hash_str, l_hash_str_size); + dap_chain_global_db_gr_del(l_hash_str, l_gdb_group); + DAP_DELETE(l_item_current->tx); + DAP_DELETE(l_item_current); + } + DAP_DELETE(l_gdb_group); + + // delete balances + dap_ledger_wallet_balance_t *l_balance_current, *l_balance_tmp; + l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "balances"); + HASH_ITER(hh, l_ledger_priv->balance_accounts, l_balance_current, l_balance_tmp) { + HASH_DEL(l_ledger_priv->balance_accounts, l_balance_current); + dap_chain_global_db_gr_del(l_balance_current->key, l_gdb_group); + DAP_DELETE(l_balance_current->key); + DAP_DELETE(l_balance_current); } + DAP_DELETE(l_gdb_group); + + // delete threshold emissions + dap_chain_ledger_token_emission_item_t *l_emission_current, *l_emission_tmp; + char *l_emissions_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "emissions"); + HASH_ITER(hh, l_ledger_priv->treshold_emissions, l_emission_current, l_emission_tmp) { + HASH_DEL(l_ledger_priv->treshold_emissions, l_emission_current); + dap_chain_hash_fast_to_str(&l_emission_current->datum_token_emission_hash, l_hash_str, l_hash_str_size); + dap_chain_global_db_gr_del(l_hash_str, l_emissions_gdb_group); + DAP_DELETE(l_emission_current->datum_token_emission); + DAP_DELETE(l_emission_current); + } + + // delete tokens & its emissions + dap_chain_ledger_token_item_t *l_token_current, *l_token_tmp; + l_gdb_group = dap_chain_ledger_get_gdb_group(a_ledger, "tokens"); + HASH_ITER(hh, l_ledger_priv->tokens, l_token_current, l_token_tmp) { + HASH_DEL(l_ledger_priv->tokens, l_token_current); + HASH_ITER(hh, l_token_current->token_emissions, l_emission_current, l_emission_tmp) { + HASH_DEL(l_token_current->token_emissions, l_emission_current); + dap_chain_hash_fast_to_str(&l_emission_current->datum_token_emission_hash, l_hash_str, l_hash_str_size); + dap_chain_global_db_gr_del(l_hash_str, l_emissions_gdb_group); + DAP_DELETE(l_emission_current->datum_token_emission); + DAP_DELETE(l_emission_current); + } + dap_chain_global_db_gr_del(l_token_current->ticker, l_gdb_group); + DAP_DELETE(l_token_current->datum_token); + pthread_rwlock_destroy(&l_token_current->token_emissions_rwlock); + DAP_DELETE(l_token_current); + } + DAP_DELETE(l_gdb_group); + DAP_DELETE(l_emissions_gdb_group); + pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock); + pthread_rwlock_unlock(&l_ledger_priv->tokens_rwlock); + pthread_rwlock_unlock(&l_ledger_priv->treshold_emissions_rwlock); + pthread_rwlock_unlock(&l_ledger_priv->treshold_txs_rwlock); } /** @@ -1370,16 +1623,7 @@ void dap_chain_ledger_purge(dap_ledger_t *a_ledger) */ _dap_int128_t dap_chain_ledger_count(dap_ledger_t *a_ledger) { - _dap_int128_t l_ret = 0; - dap_ledger_private_t *l_ledger_priv = PVT(a_ledger); - dap_chain_ledger_tx_item_t *l_iter_current, *l_item_tmp; - pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock); - HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp) - { - l_ret++; - } - pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock); - return l_ret; + return HASH_COUNT(PVT(a_ledger)->ledger_items); } /** @@ -1397,17 +1641,17 @@ uint64_t dap_chain_ledger_count_from_to(dap_ledger_t * a_ledger, time_t a_ts_fro pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock); if ( a_ts_from && a_ts_to) { HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp){ - if ( l_iter_current->ts_created >= a_ts_from && l_iter_current->ts_created <= a_ts_to ) + if ( l_iter_current->cache_data.ts_created >= a_ts_from && l_iter_current->cache_data.ts_created <= a_ts_to ) l_ret++; } } else if ( a_ts_to ){ HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp){ - if ( l_iter_current->ts_created <= a_ts_to ) + if ( l_iter_current->cache_data.ts_created <= a_ts_to ) l_ret++; } } else if ( a_ts_from ){ HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp){ - if ( l_iter_current->ts_created >= a_ts_from ) + if ( l_iter_current->cache_data.ts_created >= a_ts_from ) l_ret++; } }else { @@ -1512,7 +1756,7 @@ uint64_t dap_chain_ledger_calc_balance_full(dap_ledger_t *a_ledger, const dap_ch if (l_type == TX_ITEM_TYPE_OUT) { const dap_chain_tx_out_t *l_tx_out = (const dap_chain_tx_out_t*) l_list_tmp->data; // Check for token name - if (!strcmp(a_token_ticker, l_iter_current->token_tiker)) + if (!strcmp(a_token_ticker, l_iter_current->cache_data.token_tiker)) { // if transaction has the out item with requested addr if (!memcmp(a_addr, &l_tx_out->addr, sizeof(dap_chain_addr_t))) { // if 'out' item not used & transaction is valid @@ -1563,7 +1807,8 @@ static dap_chain_ledger_tx_item_t* tx_item_find_by_addr(dap_ledger_t *a_ledger, HASH_ITER(hh, l_ledger_priv->ledger_items , l_iter_current, l_item_tmp) { // If a_token is setup we check if its not our token - miss it - if (a_token && *l_iter_current->token_tiker && dap_strcmp(l_iter_current->token_tiker, a_token)) + if (a_token && *l_iter_current->cache_data.token_tiker && + dap_strcmp(l_iter_current->cache_data.token_tiker, a_token)) continue; // Now work with it dap_chain_datum_tx_t *l_tx = l_iter_current->tx; @@ -1715,7 +1960,7 @@ dap_chain_datum_tx_t* dap_chain_ledger_tx_cache_find_out_cond(dap_ledger_t *a_le l_cur_tx = l_tx_tmp; memcpy(a_tx_first_hash, l_tx_hash_tmp, sizeof(dap_chain_hash_fast_t)); if (a_token_ticker) { - strcpy(a_token_ticker, l_iter_current->token_tiker); + strcpy(a_token_ticker, l_iter_current->cache_data.token_tiker); } break; } diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h index 86f4782d85f2e2720f72e56a7c5a305f2c0ee0b5..ed3f73afb2df178761798d6cee8a7485fe6d388a 100644 --- a/modules/chain/include/dap_chain.h +++ b/modules/chain/include/dap_chain.h @@ -117,6 +117,7 @@ typedef struct dap_chain{ dap_chain_callback_new_cfg_t callback_created; dap_chain_callback_t callback_delete; + dap_chain_callback_t callback_purge; dap_chain_callback_atom_t callback_atom_add; dap_chain_callback_atom_verify_t callback_atom_verify; diff --git a/modules/chain/include/dap_chain_ledger.h b/modules/chain/include/dap_chain_ledger.h index 29b7b7e9f0ecf06987174d0b66e1ca87b3370b82..14fd1a61bf110d9845f6a319136599aa97e70341 100644 --- a/modules/chain/include/dap_chain_ledger.h +++ b/modules/chain/include/dap_chain_ledger.h @@ -38,6 +38,7 @@ #include "dap_chain_datum_tx_items.h" typedef struct dap_ledger { + char *net_name; void *_internal; } dap_ledger_t; @@ -52,7 +53,7 @@ typedef bool (* dap_chain_ledger_verificator_callback_t)(dap_chain_tx_out_cond_t // Check the double spending in all cells #define DAP_CHAIN_LEDGER_CHECK_CELLS_DS 0x0100 -dap_ledger_t* dap_chain_ledger_create(uint16_t a_check_flags); +dap_ledger_t* dap_chain_ledger_create(uint16_t a_check_flags, char *a_net_name); // Remove dap_ledger_t structure void dap_chain_ledger_handle_free(dap_ledger_t *a_ledger); @@ -67,19 +68,28 @@ void dap_chain_ledger_set_local_cell_id(dap_ledger_t *a_ledger, dap_chain_cell_i * @param a_tx * @return */ -static inline dap_chain_hash_fast_t* dap_chain_node_datum_tx_calc_hash(dap_chain_datum_tx_t *a_tx) +DAP_STATIC_INLINE dap_chain_hash_fast_t* dap_chain_node_datum_tx_calc_hash(dap_chain_datum_tx_t *a_tx) { dap_chain_hash_fast_t *tx_hash = DAP_NEW_Z(dap_chain_hash_fast_t); dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), tx_hash); return tx_hash; } +DAP_STATIC_INLINE char *dap_chain_ledger_get_gdb_group(dap_ledger_t *a_ledger, const char *a_suffix) +{ + if (a_ledger) { + return dap_strdup_printf("local.ledger-cahce.%s.%s", a_ledger->net_name, a_suffix); + } + return NULL; +} + /** * Add new transaction to the cache * * return 1 OK, -1 error */ int dap_chain_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx); +int dap_chain_ledger_tx_load(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx); int dap_chain_ledger_tx_add_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx); @@ -97,6 +107,7 @@ int dap_chain_ledger_token_ticker_check(dap_ledger_t * a_ledger, const char *a_t */ int dap_chain_ledger_token_add(dap_ledger_t * a_ledger,dap_chain_datum_token_t *a_token, size_t a_token_size); +int dap_chain_ledger_token_load(dap_ledger_t * a_ledger,dap_chain_datum_token_t *a_token, size_t a_token_size); int dap_chain_ledger_token_decl_add_check(dap_ledger_t * a_ledger,dap_chain_datum_token_t *a_token); /** @@ -104,6 +115,8 @@ int dap_chain_ledger_token_decl_add_check(dap_ledger_t * a_ledger,dap_chain_datu */ int dap_chain_ledger_token_emission_add(dap_ledger_t *a_ledger, const dap_chain_datum_token_emission_t *a_token_emission, size_t a_token_emission_size); +int dap_chain_ledger_token_emission_load(dap_ledger_t *a_ledger, + const dap_chain_datum_token_emission_t *a_token_emission, size_t a_token_emission_size); // Check if it addable int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger, diff --git a/modules/chain/include/dap_chain_pvt.h b/modules/chain/include/dap_chain_pvt.h index d18e434a8f0300db0f245c688dc17e75f3f358c9..4af990d5fcdf6b2650e6ba1a44785a67400d26dd 100644 --- a/modules/chain/include/dap_chain_pvt.h +++ b/modules/chain/include/dap_chain_pvt.h @@ -41,6 +41,8 @@ typedef struct dap_chain_pvt { dap_chain_t * chain; char * file_storage_dir; + char * cs_name; + int celled; } dap_chain_pvt_t; #define DAP_CHAIN_PVT(a) ((dap_chain_pvt_t *) a->_pvt ) diff --git a/modules/channel/chain/dap_stream_ch_chain.c b/modules/channel/chain/dap_stream_ch_chain.c index 1d6eb6a2d6f28c2ec9e75f885f077a0e4285278b..b55fe1269d5d0b599635e903270801164775ba88 100644 --- a/modules/channel/chain/dap_stream_ch_chain.c +++ b/modules/channel/chain/dap_stream_ch_chain.c @@ -174,6 +174,9 @@ bool s_sync_chains_callback(dap_proc_thread_t *a_thread, void *a_arg) l_ch_chain->request_net_id, l_ch_chain->request_chain_id, l_ch_chain->request_cell_id, &l_request, sizeof(l_request)); l_ch_chain->state = CHAIN_STATE_IDLE; + if (l_ch_chain->callback_notify_packet_out) + l_ch_chain->callback_notify_packet_out(l_ch_chain, DAP_STREAM_CH_CHAIN_PKT_TYPE_SYNCED_CHAINS, + NULL, 0, l_ch_chain->callback_notify_arg); } DAP_DELETE(l_lasts); DAP_DELETE(l_iter); diff --git a/modules/consensus/none/dap_chain_cs_none.c b/modules/consensus/none/dap_chain_cs_none.c index f68ce988c17733f7bc2ef0354ae48308afc0ba96..42da69734162495bd016df1978b08dce4ad85f05 100644 --- a/modules/consensus/none/dap_chain_cs_none.c +++ b/modules/consensus/none/dap_chain_cs_none.c @@ -65,8 +65,6 @@ typedef struct dap_chain_gdb_private #define PVT(a) ( (a) ? (dap_chain_gdb_private_t* ) (a)->_internal : NULL) -static int dap_chain_gdb_ledger_load(dap_chain_gdb_t *a_gdb, dap_chain_net_t *a_net); - // Atomic element organization callbacks static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t, size_t); // Accept new event in gdb static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t, size_t); // Verify new event in gdb @@ -138,10 +136,16 @@ static void s_history_callback_notify(void * a_arg, const char a_op_code, const dap_chain_net_t *l_net = dap_chain_net_by_id( l_gdb->chain->net_id); log_it(L_DEBUG,"%s.%s: op_code='%c' group=\"%s\" key=\"%s\" value_size=%u",l_net->pub.name, l_gdb->chain->name, a_op_code, a_group, a_key, a_value_size); + dap_chain_node_mempool_autoproc_notify((void *)l_net, a_op_code, a_prefix, a_group, a_key, a_value, a_value_size); dap_chain_net_sync_gdb_broadcast((void *)l_net, a_op_code, a_prefix, a_group, a_key, a_value, a_value_size); } } +static void s_dap_chain_gdb_callback_purge(dap_chain_t *a_chain) +{ + PVT(DAP_CHAIN_GDB(a_chain))->is_load_mode = true; +} + /** * @brief dap_chain_gdb_new * @param a_chain @@ -176,10 +180,10 @@ int dap_chain_gdb_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) // load ledger l_gdb_priv->is_load_mode = true; - dap_chain_gdb_ledger_load(l_gdb, l_net); - l_gdb_priv->is_load_mode = false; + dap_chain_gdb_ledger_load(l_gdb_priv->group_datums, a_chain); a_chain->callback_delete = dap_chain_gdb_delete; + a_chain->callback_purge = s_dap_chain_gdb_callback_purge; // Atom element callbacks a_chain->callback_atom_add = s_chain_callback_atom_add; // Accept new element in chain @@ -258,24 +262,17 @@ const char* dap_chain_gdb_get_group(dap_chain_t * a_chain) * * return 0 if OK otherwise negative error code */ -static int dap_chain_gdb_ledger_load(dap_chain_gdb_t *a_gdb, dap_chain_net_t *a_net) +int dap_chain_gdb_ledger_load(char *a_gdb_group, dap_chain_t *a_chain) { - dap_chain_gdb_private_t *l_gdb_priv = PVT(a_gdb); - // protect from reloading - if(dap_chain_ledger_count( a_net->pub.ledger ) > 0) - return 0; - size_t l_data_size = 0; - - // Read the entire database into an array of size bytes - dap_global_db_obj_t *data = dap_chain_global_db_gr_load(l_gdb_priv->group_datums , &l_data_size); + dap_global_db_obj_t *data = dap_chain_global_db_gr_load(a_gdb_group, &l_data_size); // make list of datums for(size_t i = 0; i < l_data_size; i++) { - s_chain_callback_atom_add(a_gdb->chain,data[i].value, data[i].value_len); - + s_chain_callback_atom_add(a_chain, data[i].value, data[i].value_len); } dap_chain_global_db_objs_delete(data, l_data_size); + PVT(DAP_CHAIN_GDB(a_chain))->is_load_mode = false; return 0; } @@ -322,11 +319,11 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha switch (l_datum->header.type_id) { case DAP_CHAIN_DATUM_TOKEN_DECL:{ dap_chain_datum_token_t *l_token = (dap_chain_datum_token_t*) l_datum->data; - dap_chain_ledger_token_add(a_chain->ledger,l_token, l_datum->header.data_size); + dap_chain_ledger_token_load(a_chain->ledger,l_token, l_datum->header.data_size); }break; case DAP_CHAIN_DATUM_TOKEN_EMISSION: { dap_chain_datum_token_emission_t *l_token_emission = (dap_chain_datum_token_emission_t*) l_datum->data; - dap_chain_ledger_token_emission_add(a_chain->ledger, l_token_emission, l_datum->header.data_size); + dap_chain_ledger_token_emission_load(a_chain->ledger, l_token_emission, l_datum->header.data_size); }break; case DAP_CHAIN_DATUM_TX:{ dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*) l_datum->data; @@ -335,7 +332,7 @@ static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_cha //if(dap_chain_datum_tx_get_size(l_tx) == l_datum->header.data_size){ // don't save bad transactions to base - if(dap_chain_ledger_tx_add(a_chain->ledger, l_tx) != 1) + if(dap_chain_ledger_tx_load(a_chain->ledger, l_tx) != 1) return ATOM_REJECT; //}else // return -2; diff --git a/modules/consensus/none/include/dap_chain_cs_none.h b/modules/consensus/none/include/dap_chain_cs_none.h index e40ae2184e63b48f74f699755053ed77c5420eb5..adf5cd6f0082c2239fd221d6c976fc6e74d60f31 100644 --- a/modules/consensus/none/include/dap_chain_cs_none.h +++ b/modules/consensus/none/include/dap_chain_cs_none.h @@ -39,4 +39,4 @@ int dap_chain_gdb_init(void); int dap_chain_gdb_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg); void dap_chain_gdb_delete(dap_chain_t * a_chain); const char* dap_chain_gdb_get_group(dap_chain_t * a_chain); - +int dap_chain_gdb_ledger_load(char *a_gdb_group, dap_chain_t *a_chain); diff --git a/modules/net/CMakeLists.txt b/modules/net/CMakeLists.txt index e5d055725660d5a26b7aa656d5037c7616204d48..104d304db2ca5a35ca2cb8e215b77affb1e62b30 100644 --- a/modules/net/CMakeLists.txt +++ b/modules/net/CMakeLists.txt @@ -40,12 +40,12 @@ add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_NET_SRCS} ${DAP_CHAIN_NET_HEADERS if(WIN32) target_link_libraries(dap_chain_net dap_core dap_crypto dap_client dap_stream_ch_chain dap_stream_ch_chain_net dap_stream_ch_chain_net_srv dap_chain dap_chain_crypto dap_chain_wallet dap_chain_net_srv - dap_chain_mempool dap_chain_global_db dap_chain_net_srv_stake) + dap_chain_mempool dap_chain_global_db dap_chain_net_srv_stake dap_chain_cs_none) endif() if(UNIX) target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_client dap_stream_ch_chain dap_stream_ch_chain_net dap_stream_ch_chain_net_srv dap_chain - dap_chain_wallet dap_chain_net_srv dap_chain_mempool dap_chain_global_db dap_chain_net_srv_stake + dap_chain_wallet dap_chain_net_srv dap_chain_mempool dap_chain_global_db dap_chain_net_srv_stake dap_chain_cs_none resolv ) endif() diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index 586c36a59f959d3d6797e5a86edfa1384832c7de..7e6256f1bdab41c8de91d023ed6fad50bd28ba38 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -66,10 +66,12 @@ #include "dap_enc_http.h" #include "dap_chain_common.h" #include "dap_chain_net.h" +#include "dap_chain_pvt.h" #include "dap_chain_node_client.h" #include "dap_chain_node_cli.h" #include "dap_chain_node_cli_cmd.h" #include "dap_chain_ledger.h" +#include "dap_chain_cs_none.h" #include "dap_chain_global_db.h" #include "dap_chain_global_db_remote.h" @@ -865,7 +867,8 @@ int dap_chain_net_init() "\tPrint list of authority cetificates from GDB group\n" "net -net <chain net name> ca del -hash <cert hash> [-H hex|base58(default)]\n" "\tDelete certificate from list of authority cetificates in GDB group by it's hash\n" - ); + "net -net <chain net name> ledger reload\n" + "\tPurge the cache of chain net ledger and recalculate it from chain file\n" ); s_seed_mode = dap_config_get_item_bool_default(g_config,"general","seed_mode",false); dap_chain_global_db_add_history_group_prefix("global", GROUP_LOCAL_HISTORY); @@ -1004,12 +1007,14 @@ static int s_cli_net( int argc, char **argv, void *arg_func, char **a_str_reply) const char *l_get_str = NULL; const char *l_stats_str = NULL; const char *l_ca_str = NULL; + const char *l_ledger_str = NULL; dap_chain_node_cli_find_option_val(argv, arg_index, argc, "sync", &l_sync_str); dap_chain_node_cli_find_option_val(argv, arg_index, argc, "link", &l_links_str); dap_chain_node_cli_find_option_val(argv, arg_index, argc, "go", &l_go_str); dap_chain_node_cli_find_option_val(argv, arg_index, argc, "get", &l_get_str); dap_chain_node_cli_find_option_val(argv, arg_index, argc, "stats", &l_stats_str); dap_chain_node_cli_find_option_val(argv, arg_index, argc, "ca", &l_ca_str); + dap_chain_node_cli_find_option_val(argv, arg_index, argc, "ledger", &l_ledger_str); if ( l_stats_str ){ if ( strcmp(l_stats_str,"tx") == 0 ) { @@ -1245,6 +1250,19 @@ static int s_cli_net( int argc, char **argv, void *arg_func, char **a_str_reply) "Subcommand \"ca\" requires one of parameter: add, list, del\n"); ret = -5; } + } else if (l_ledger_str && !strcmp(l_ledger_str, "reload")) { + dap_chain_ledger_purge(l_net->pub.ledger); + dap_chain_t *l_chain; + DL_FOREACH(l_net->pub.chains, l_chain) { + if (l_chain->callback_purge) { + l_chain->callback_purge(l_chain); + } + if (!strcmp(DAP_CHAIN_PVT(l_chain)->cs_name, "none")) { + dap_chain_gdb_ledger_load((char *)dap_chain_gdb_get_group(l_chain), l_chain); + } else { + dap_chain_load_all(l_chain); + } + } } else { dap_chain_node_cli_set_reply_text(a_str_reply,"Command requires one of subcomand: sync, links\n"); ret = -1; @@ -1381,7 +1399,7 @@ int s_net_load(const char * a_net_name, uint16_t a_acl_idx) l_ledger_flags |= DAP_CHAIN_LEDGER_CHECK_LOCAL_DS; } // init LEDGER model - l_net->pub.ledger = dap_chain_ledger_create(l_ledger_flags); + l_net->pub.ledger = dap_chain_ledger_create(l_ledger_flags, l_net->pub.name); // Check if seed nodes are present in local db alias char **l_seed_aliases = dap_config_get_array_str( l_cfg , "general" ,"seed_nodes_aliases" ,&PVT(l_net)->seed_aliases_count); diff --git a/modules/net/srv/dap_chain_net_srv_order.c b/modules/net/srv/dap_chain_net_srv_order.c index 8aba700a30215b038b580b8d0ee49744bd6684e3..869461dc4f5340562c2a40ee97251d6fa451f224 100644 --- a/modules/net/srv/dap_chain_net_srv_order.c +++ b/modules/net/srv/dap_chain_net_srv_order.c @@ -524,17 +524,17 @@ static void s_srv_order_callback_notify(void *a_arg, const char a_op_code, const if (!strcmp(a_group, l_gdb_group_str)) { dap_chain_net_srv_order_t *l_order = (dap_chain_net_srv_order_t *)a_value; if (l_order->version == 1) { - dap_chain_global_db_gr_del((char *)a_key, a_group); + dap_chain_global_db_gr_del(dap_strdup(a_key), a_group); } else { dap_sign_t *l_sign = (dap_sign_t *)&l_order->ext[l_order->ext_size]; if (!dap_sign_verify(l_sign, l_order, sizeof(dap_chain_net_srv_order_t) + l_order->ext_size)) { - dap_chain_global_db_gr_del((char *)a_key, a_group); + dap_chain_global_db_gr_del(dap_strdup(a_key), a_group); DAP_DELETE(l_gdb_group_str); return; } dap_chain_hash_fast_t l_pkey_hash; if (!dap_sign_get_pkey_hash(l_sign, &l_pkey_hash)) { - dap_chain_global_db_gr_del((char *)a_key, a_group); + dap_chain_global_db_gr_del(dap_strdup(a_key), a_group); DAP_DELETE(l_gdb_group_str); return; } @@ -542,7 +542,7 @@ static void s_srv_order_callback_notify(void *a_arg, const char a_op_code, const dap_chain_addr_fill(&l_addr, l_sign->header.type, &l_pkey_hash, l_net->pub.id); uint64_t l_solvency = dap_chain_ledger_calc_balance(l_net->pub.ledger, &l_addr, l_order->price_ticker); if (l_solvency < l_order->price && !dap_chain_net_srv_stake_key_delegated(&l_addr)) { - dap_chain_global_db_gr_del((char *)a_key, a_group); + dap_chain_global_db_gr_del(dap_strdup(a_key), a_group); } } DAP_DELETE(l_gdb_group_str); diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c index b7bd5071492e047932395300fca186099c49d41c..6336a366903b8bb6b989257ab085598fd4846351 100644 --- a/modules/service/xchange/dap_chain_net_srv_xchange.c +++ b/modules/service/xchange/dap_chain_net_srv_xchange.c @@ -653,7 +653,6 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c } DAP_DELETE(l_order_hash_str); DAP_DELETE(l_price->wallet_str); - DAP_DELETE(l_price->key_ptr); DAP_DELETE(l_price); if (!l_str_reply->len) { dap_string_append(l_str_reply, "Price successfully removed"); @@ -715,7 +714,7 @@ static int s_cli_srv_xchange_price(int a_argc, char **a_argv, int a_arg_index, c return -14; } HASH_DEL(s_srv_xchange->pricelist, l_price); - dap_chain_global_db_gr_del(l_price->key_ptr, GROUP_LOCAL_XCHANGE); + dap_chain_global_db_gr_del(dap_strdup(l_price->key_ptr), GROUP_LOCAL_XCHANGE); bool l_ret = s_xchage_tx_invalidate(l_price, l_wallet); // may be changed to old price later dap_chain_wallet_close(l_wallet); if (!l_ret) { diff --git a/modules/type/dag/dap_chain_cs_dag.c b/modules/type/dag/dap_chain_cs_dag.c index 6385aacf84141e8111d2e39249a4a947de32bbd8..e9b1d4f5fad51d987e48a05dd68641763dd5f776 100644 --- a/modules/type/dag/dap_chain_cs_dag.c +++ b/modules/type/dag/dap_chain_cs_dag.c @@ -78,6 +78,8 @@ typedef struct dap_chain_cs_dag_pvt { #define PVT(a) ((dap_chain_cs_dag_pvt_t *) a->_pvt ) +static void s_dap_chain_cs_dag_purge(dap_chain_t *a_chain); + // Atomic element organization callbacks static dap_chain_atom_verify_res_t s_chain_callback_atom_add(dap_chain_t * a_chain, dap_chain_atom_ptr_t , size_t); // Accept new event in dag static dap_chain_atom_verify_res_t s_chain_callback_atom_verify(dap_chain_t * a_chain, dap_chain_atom_ptr_t , size_t); // Verify new event in dag @@ -168,6 +170,7 @@ int dap_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) pthread_rwlock_init(& PVT(l_dag)->events_rwlock,NULL); a_chain->callback_delete = dap_chain_cs_dag_delete; + a_chain->callback_purge = s_dap_chain_cs_dag_purge; // Atom element callbacks a_chain->callback_atom_add = s_chain_callback_atom_add ; // Accept new element in chain @@ -227,6 +230,34 @@ int dap_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) return 0; } +static void s_dap_chain_cs_dag_purge(dap_chain_t *a_chain) +{ + dap_chain_cs_dag_pvt_t *l_dag_pvt = PVT(DAP_CHAIN_CS_DAG(a_chain)); + pthread_rwlock_wrlock(&l_dag_pvt->events_rwlock); + dap_chain_cs_dag_event_item_t *l_event_current, *l_event_tmp; + HASH_ITER(hh, l_dag_pvt->events, l_event_current, l_event_tmp) { + HASH_DEL(l_dag_pvt->events, l_event_current); + DAP_DELETE(l_event_current); + } + HASH_ITER(hh, l_dag_pvt->events_lasts_unlinked, l_event_current, l_event_tmp) { + HASH_DEL(l_dag_pvt->events_lasts_unlinked, l_event_current); + DAP_DELETE(l_event_current); + } + HASH_ITER(hh, l_dag_pvt->events_treshold, l_event_current, l_event_tmp) { + HASH_DEL(l_dag_pvt->events_treshold, l_event_current); + DAP_DELETE(l_event_current); + } + HASH_ITER(hh, l_dag_pvt->events_treshold_conflicted, l_event_current, l_event_tmp) { + HASH_DEL(l_dag_pvt->events_treshold_conflicted, l_event_current); + DAP_DELETE(l_event_current); + } + HASH_ITER(hh, l_dag_pvt->tx_events, l_event_current, l_event_tmp) { + HASH_DEL(l_dag_pvt->tx_events, l_event_current); + DAP_DELETE(l_event_current); + } + pthread_rwlock_unlock(&l_dag_pvt->events_rwlock); +} + /** * @brief dap_chain_cs_dag_delete * @param a_dag @@ -234,6 +265,7 @@ int dap_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) */ void dap_chain_cs_dag_delete(dap_chain_t * a_chain) { + s_dap_chain_cs_dag_purge(a_chain); dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG ( a_chain ); pthread_rwlock_destroy(& PVT(l_dag)->events_rwlock); @@ -251,12 +283,12 @@ static int s_dap_chain_add_atom_to_ledger(dap_chain_cs_dag_t * a_dag, dap_ledger switch (l_datum->header.type_id) { case DAP_CHAIN_DATUM_TOKEN_DECL: { dap_chain_datum_token_t *l_token = (dap_chain_datum_token_t*) l_datum->data; - return dap_chain_ledger_token_add(a_ledger, l_token, l_datum->header.data_size); + return dap_chain_ledger_token_load(a_ledger, l_token, l_datum->header.data_size); } break; case DAP_CHAIN_DATUM_TOKEN_EMISSION: { dap_chain_datum_token_emission_t *l_token_emission = (dap_chain_datum_token_emission_t*) l_datum->data; - return dap_chain_ledger_token_emission_add(a_ledger, l_token_emission, l_datum->header.data_size); + return dap_chain_ledger_token_emission_load(a_ledger, l_token_emission, l_datum->header.data_size); } break; case DAP_CHAIN_DATUM_TX: { @@ -270,7 +302,7 @@ static int s_dap_chain_add_atom_to_ledger(dap_chain_cs_dag_t * a_dag, dap_ledger HASH_ADD(hh,PVT(a_dag)->tx_events,hash,sizeof (l_tx_event->hash),l_tx_event); // don't save bad transactions to base - if(dap_chain_ledger_tx_add(a_ledger, l_tx) != 1) { + if(dap_chain_ledger_tx_load(a_ledger, l_tx) != 1) { return -1; } }