Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • cellframe/cellframe-sdk
  • MIKA83/cellframe-sdk
2 results
Show changes
Commits on Source (37)
Showing
with 712 additions and 574 deletions
......@@ -11,7 +11,7 @@ set(DAPSDK_MODULES "")
if(NOT DEFINED CELLFRAME_MODULES)
include (cmake/OS_Detection.cmake)
set(CELLFRAME_MODULES "core chains mining network srv cs-dag-poa cs-block-poa cs-dag-pos cs-block-pos cs-block-ton cs-none srv-app srv-app-db srv-datum srv-stake-pos-delegate srv-stake-lock srv-xchange")
set(CELLFRAME_MODULES "core chains mining network srv cs-dag-poa cs-block-poa cs-dag-pos cs-block-pos cs-esbocs cs-none srv-app srv-app-db srv-datum srv-stake-pos-delegate srv-stake-lock srv-xchange")
if(LINUX OR DARWIN)
set(CELLFRAME_MODULES "${CELLFRAME_MODULES} srv-vpn")
......@@ -144,8 +144,8 @@ if (CELLFRAME_MODULES MATCHES "cs-dag-pos")
endif()
# Blocks based consensus(es)
if (CELLFRAME_MODULES MATCHES "cs-block-" )
set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_cs_dag)
if (CELLFRAME_MODULES MATCHES "cs-block-" OR CELLFRAME_MODULES MATCHES "cs-esbocs")
set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_cs_blocks)
endif()
# PoA consensus for blocks
......@@ -161,9 +161,9 @@ if (CELLFRAME_MODULES MATCHES "cs-block-pos")
endif()
# TON consensus for blocks
if (CELLFRAME_MODULES MATCHES "cs-block-ton")
message("[+] Module 'cs-block-ton'")
set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_cs_block_ton)
if (CELLFRAME_MODULES MATCHES "cs-esbocs")
message("[+] Module 'cs-esbocs'")
set(CELLFRAME_LIBS ${CELLFRAME_LIBS} dap_chain_cs_esbocs)
endif()
# PoW consensus for blocks
......
Subproject commit db02d76ec8415fd426bc401eafa92c776712eb45
Subproject commit 2fa175608533db70a74d61ab1ed57edd85a01607
......@@ -67,8 +67,8 @@ if (CELLFRAME_MODULES MATCHES "cs-block-pos")
endif()
# Block TON
if (CELLFRAME_MODULES MATCHES "cs-block-ton")
add_subdirectory(consensus/block-ton)
if (CELLFRAME_MODULES MATCHES "cs-esbocs")
add_subdirectory(consensus/esbocs)
endif()
# Block PoW
......
......@@ -261,6 +261,8 @@ static dap_chain_type_t s_chain_type_from_str(const char *a_type_str)
if(!dap_strcmp(a_type_str, "signer")) {
return CHAIN_TYPE_SIGNER;
}
if (!dap_strcmp(a_type_str, "decree"))
return CHAIN_TYPE_DECREE;
return CHAIN_TYPE_LAST;
}
......@@ -287,6 +289,8 @@ static uint16_t s_datum_type_from_str(const char *a_type_str)
if (!dap_strcmp(a_type_str, "signer")) {
return DAP_CHAIN_DATUM_SIGNER;
}
if (!dap_strcmp(a_type_str, "decree"))
return DAP_CHAIN_DATUM_DECREE;
return DAP_CHAIN_DATUM_CUSTOM;
}
......@@ -407,19 +411,13 @@ dap_chain_t * dap_chain_load_from_cfg(dap_ledger_t* a_ledger, const char * a_cha
}
l_chain = dap_chain_create(a_ledger,a_chain_net_name,l_chain_name, a_chain_net_id,l_chain_id);
if ( dap_chain_cs_create(l_chain, l_cfg) == 0 )
{
if ( dap_chain_cs_create(l_chain, l_cfg) == 0 ) {
log_it (L_NOTICE, "Consensus initialized for chain id 0x%016"DAP_UINT64_FORMAT_x, l_chain_id.uint64);
if ( dap_config_get_item_path_default(l_cfg , "files","storage_dir",NULL ) )
{
DAP_CHAIN_PVT(l_chain)->file_storage_dir = dap_strdup( dap_config_get_item_path( l_cfg , "files","storage_dir" ) );
if (dap_chain_load_all(l_chain) == 0)
log_it (L_NOTICE, "Loaded chain files");
else {
dap_chain_save_all( l_chain );
log_it (L_NOTICE, "Initialized chain files");
}
} else
log_it (L_INFO, "Not set file storage path, will not stored in files");
......@@ -460,7 +458,7 @@ dap_chain_t * dap_chain_load_from_cfg(dap_ledger_t* a_ledger, const char * a_cha
}
// add datum types
if (l_datum_types && l_datum_types_count > 0)
if (l_datum_types && l_datum_types_count > 0)
{
l_chain->datum_types = DAP_NEW_SIZE(dap_chain_type_t, l_datum_types_count * sizeof(dap_chain_type_t)); // TODO: pls check counter for recognized types before memory allocation!
l_count_recognized = 0;
......@@ -576,10 +574,13 @@ int dap_chain_load_all(dap_chain_t *l_chain)
int l_ret = 0;
if (!l_chain)
return -2;
if(!dap_dir_test(DAP_CHAIN_PVT (l_chain)->file_storage_dir)) {
dap_mkdir_with_parents(DAP_CHAIN_PVT (l_chain)->file_storage_dir);
char *l_storage_dir = DAP_CHAIN_PVT(l_chain)->file_storage_dir;
if (!l_storage_dir)
return 0;
if (!dap_dir_test(l_storage_dir)) {
dap_mkdir_with_parents(l_storage_dir);
}
DIR * l_dir = opendir(DAP_CHAIN_PVT(l_chain)->file_storage_dir);
DIR *l_dir = opendir(l_storage_dir);
if (!l_dir) {
log_it(L_ERROR, "Cannot open directory %s", DAP_CHAIN_PVT (l_chain)->file_storage_dir);
return -3;
......
......@@ -55,7 +55,7 @@
#include "dap_config.h"
#include "dap_cert.h"
#include "dap_timerfd.h"
#include "dap_chain_datum_tx_token.h"
#include "dap_chain_datum_tx_in_ems.h"
#include "dap_chain_datum_token.h"
#include "dap_chain_mempool.h"
#include "dap_global_db.h"
......@@ -84,7 +84,7 @@ static pthread_rwlock_t s_verificators_rwlock;
typedef struct dap_chain_ledger_stake_lock_item {
dap_chain_hash_fast_t tx_for_stake_lock_hash;
dap_chain_hash_fast_t tx_used_out;
// const char datum_token_emission_hash[DAP_CHAIN_HASH_FAST_STR_SIZE];
uint256_t ems_value;
UT_hash_handle hh;
} dap_chain_ledger_stake_lock_item_t;
......@@ -93,6 +93,7 @@ typedef struct dap_chain_ledger_token_emission_item {
dap_chain_datum_token_emission_t *datum_token_emission;
size_t datum_token_emission_size;
dap_chain_hash_fast_t tx_used_out;
dap_nanotime_t ts_added;
UT_hash_handle hh;
} dap_chain_ledger_token_emission_item_t;
......@@ -141,14 +142,15 @@ typedef struct dap_chain_ledger_token_item {
typedef struct dap_chain_ledger_tx_item {
dap_chain_hash_fast_t tx_hash_fast;
dap_chain_datum_tx_t *tx;
dap_nanotime_t ts_added;
struct {
dap_time_t ts_created;
uint32_t n_outs;
uint32_t n_outs_used;
char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX];
char padding[6];
byte_t padding[6];
byte_t multichannel;
char pad[15];
byte_t pad[15];
// 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
} DAP_ALIGN_PACKED cache_data;
......@@ -178,7 +180,8 @@ typedef struct dap_chain_ledger_tx_bound {
union {
dap_chain_tx_in_t *tx_cur_in;
dap_chain_tx_in_cond_t *tx_cur_in_cond;
} in;
dap_chain_tx_in_ems_t *tx_cur_in_ems;
} in;
union {
dap_chain_tx_out_old_t *tx_prev_out;
// 256
......@@ -257,6 +260,9 @@ typedef struct dap_ledger_private {
struct timespec tps_current_time;
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_ledger_private_t;
#define PVT(a) ( (dap_ledger_private_t* ) a->_internal )
......@@ -265,6 +271,8 @@ static dap_chain_ledger_tx_item_t* tx_item_find_by_addr(dap_ledger_t *a_ledger,
const dap_chain_addr_t *a_addr, const char * a_token, dap_chain_hash_fast_t *a_tx_first_hash);
static void s_threshold_emissions_proc( dap_ledger_t * a_ledger);
static void s_threshold_txs_proc( dap_ledger_t * a_ledger);
static void s_threshold_txs_free(dap_ledger_t *a_ledger);
static void s_threshold_emission_free(dap_ledger_t *a_ledger);
static int s_token_tsd_parse(dap_ledger_t * a_ledger, dap_chain_ledger_token_item_t *a_token_item , dap_chain_datum_token_t * a_token, size_t a_token_size);
static int s_ledger_permissions_check(dap_chain_ledger_token_item_t * a_token_item, uint16_t a_permission_id, const void * a_data,size_t a_data_size );
static bool s_ledger_tps_callback(void *a_arg);
......@@ -281,6 +289,7 @@ static inline int s_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_e
static size_t s_threshold_emissions_max = 1000;
static size_t s_threshold_txs_max = 10000;
static bool s_debug_more = false;
static size_t s_threshold_free_timer_tick = 900000; // 900000 ms = 15 minutes.
struct json_object *wallet_info_json_collect(dap_ledger_t *a_ledger, dap_ledger_wallet_balance_t* a_bal);
......@@ -329,6 +338,10 @@ 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,
(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,
(dap_timer_callback_t) s_threshold_emission_free, l_ledger);
return l_ledger;
}
......@@ -626,8 +639,8 @@ char * dap_ledger_token_tx_item_list(dap_ledger_t * a_ledger, dap_chain_addr_t *
}
if (dap_hash_fast_is_blank(l_tx_prev_hash)) {
l_base_tx = true;
dap_chain_tx_token_t *l_token = (dap_chain_tx_token_t *)dap_chain_datum_tx_item_get(
l_tx, NULL, TX_ITEM_TYPE_TOKEN, NULL);
dap_chain_tx_in_ems_t *l_token = (dap_chain_tx_in_ems_t *)dap_chain_datum_tx_item_get(
l_tx, NULL, TX_ITEM_TYPE_IN_EMS, NULL);
if (l_token)
l_src_token = l_token->header.ticker;
break;
......@@ -1578,12 +1591,13 @@ dap_string_t *dap_chain_ledger_balance_info(dap_ledger_t *a_ledger)
dap_list_t *dap_chain_ledger_token_info(dap_ledger_t *a_ledger)
{
dap_list_t *l_ret_list = NULL;
dap_string_t *l_str_tmp = dap_string_new("");
dap_string_t *l_str_tmp;// = dap_string_new("");
dap_chain_ledger_token_item_t *l_token_item, *l_tmp_item;
pthread_rwlock_rdlock(&PVT(a_ledger)->tokens_rwlock);
HASH_ITER(hh, PVT(a_ledger)->tokens, l_token_item, l_tmp_item) {
l_str_tmp = dap_string_new("");
const char *l_type_str;
//const char *l_flags_str = s_flag_str_from_code(l_token_item->datum_token->header_private_decl.flags);;
const char *l_flags_str = s_flag_str_from_code(l_token_item->datum_token->header_private_decl.flags);;
switch (l_token_item->type) {
case DAP_CHAIN_DATUM_TOKEN_TYPE_SIMPLE: // 256
case DAP_CHAIN_DATUM_TOKEN_TYPE_OLD_SIMPLE:
......@@ -1700,7 +1714,6 @@ static void s_threshold_txs_proc( dap_ledger_t *a_ledger)
if (l_res != DAP_CHAIN_CS_VERIFY_CODE_TX_NO_EMISSION &&
l_res != DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS) {
HASH_DEL(l_ledger_pvt->threshold_txs, l_tx_item);
if (l_res != 1)
DAP_DELETE(l_tx_item->tx);
DAP_DELETE(l_tx_item);
l_success = true;
......@@ -1710,6 +1723,52 @@ static void s_threshold_txs_proc( dap_ledger_t *a_ledger)
pthread_rwlock_unlock(&l_ledger_pvt->threshold_txs_rwlock);
}
/**
* @breif s_treshold_txs_free
* @param a_ledger
*/
static void s_threshold_txs_free(dap_ledger_t *a_ledger){
log_it(L_DEBUG, "Start free threshold txs");
dap_ledger_private_t *l_pvt = PVT(a_ledger);
dap_chain_ledger_tx_item_t *l_current = NULL, *l_tmp = NULL;
dap_nanotime_t l_time_cut_off = dap_nanotime_now() - dap_nanotime_from_sec(7200); //7200 sec = 2 hours.
pthread_rwlock_wrlock(&l_pvt->threshold_txs_rwlock);
HASH_ITER(hh, l_pvt->threshold_txs, l_current, l_tmp) {
if (l_current->ts_added < l_time_cut_off) {
HASH_DEL(l_pvt->threshold_txs, l_current);
char *l_hash_tx = dap_chain_hash_fast_to_str_new(&l_current->tx_hash_fast);
DAP_DELETE(l_current->tx);
DAP_DELETE(l_current);
log_it(L_NOTICE, "Removed transaction %s form threshold ledger", l_hash_tx);
DAP_DELETE(l_hash_tx);
}
}
pthread_rwlock_unlock(&l_pvt->threshold_txs_rwlock);
}
/**
* @breif s_treshold_emission_free
* @param a_ledger
*/
static void s_threshold_emission_free(dap_ledger_t *a_ledger){
log_it(L_DEBUG, "Start free threshold emission");
dap_ledger_private_t *l_pvt = PVT(a_ledger);
dap_chain_ledger_token_emission_item_t *l_current = NULL, *l_tmp = NULL;
dap_nanotime_t l_time_cut_off = dap_nanotime_now() - dap_nanotime_from_sec(7200); //7200 sec = 2 hours.
pthread_rwlock_wrlock(&l_pvt->threshold_emissions_rwlock);
HASH_ITER(hh, l_pvt->threshold_emissions, l_current, l_tmp) {
if (l_current->ts_added < l_time_cut_off) {
char *l_hash_token = dap_chain_hash_fast_to_str_new(&l_current->datum_token_emission_hash);
HASH_DEL(l_pvt->threshold_emissions, l_current);
DAP_DELETE(l_current->datum_token_emission);
log_it(L_NOTICE, "Removed token emission %s form threshold ledger", l_hash_token);
DAP_DELETE(l_hash_token);
}
}
pthread_rwlock_unlock(&l_pvt->threshold_emissions_rwlock);
}
/**
* @brief s_load_cache_gdb_loaded_balances_callback
* @param a_global_db_context
......@@ -1808,6 +1867,7 @@ static void s_load_cache_gdb_loaded_txs_callback(dap_global_db_context_t *a_glob
l_tx_item->tx = DAP_NEW_Z_SIZE(dap_chain_datum_tx_t, a_values[i].value_len - sizeof(l_tx_item->cache_data));
memcpy(&l_tx_item->cache_data, a_values[i].value, sizeof(l_tx_item->cache_data));
memcpy(l_tx_item->tx, a_values[i].value + sizeof(l_tx_item->cache_data), a_values[i].value_len - sizeof(l_tx_item->cache_data));
l_tx_item->ts_added = dap_nanotime_now();
HASH_ADD_INORDER(hh, l_ledger_pvt->ledger_items, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_tx_item, s_sort_ledger_tx_item);
}
......@@ -2008,6 +2068,9 @@ dap_ledger_t* dap_chain_ledger_create(uint16_t a_check_flags, char *a_net_name)
int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_t a_token_emission_size)
{
if (!a_token_emission || !a_token_emission_size)
return -100;
int l_ret = 0;
dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
......@@ -2021,7 +2084,7 @@ int dap_chain_ledger_token_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_
if (!l_token_item) {
log_it(L_WARNING, "Ledger_token_emission_add_check. Token ticker %s was not found", c_token_ticker);
return -5;
return DAP_CHAIN_CS_VERIFY_CODE_TX_NO_TOKEN; // old return -5
}
// check if such emission is already present in table
......@@ -2236,16 +2299,36 @@ static int s_token_emission_add_unsafe(dap_ledger_t *a_ledger, byte_t *a_token_e
static inline int s_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_t a_token_emission_size,
dap_hash_fast_t *a_emission_hash, bool a_from_threshold, bool a_safe_call)
{
dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
dap_chain_ledger_token_emission_item_t * l_token_emission_item = NULL;
int l_ret = dap_chain_ledger_token_emission_add_check(a_ledger, a_token_emission, a_token_emission_size);
if (l_ret)
if (l_ret) {
if (l_ret == DAP_CHAIN_CS_VERIFY_CODE_TX_NO_TOKEN) {
if (HASH_COUNT(l_ledger_priv->threshold_emissions) < s_threshold_emissions_max) {
l_token_emission_item = DAP_NEW_Z(dap_chain_ledger_token_emission_item_t);
l_token_emission_item->datum_token_emission = DAP_DUP_SIZE(a_token_emission, a_token_emission_size);
l_token_emission_item->datum_token_emission_size = a_token_emission_size;
dap_hash_fast_t l_emi_hash = {0};
dap_hash_fast(a_token_emission, a_token_emission_size, &l_emi_hash);
pthread_rwlock_wrlock(&l_ledger_priv->threshold_emissions_rwlock);
l_token_emission_item->datum_token_emission_hash = l_emi_hash;
l_token_emission_item->ts_added = dap_nanotime_now();
HASH_ADD(hh, l_ledger_priv->threshold_emissions, datum_token_emission_hash,
sizeof(*a_emission_hash), l_token_emission_item);
pthread_rwlock_unlock(&l_ledger_priv->threshold_emissions_rwlock);
} else {
if(s_debug_more)
log_it(L_WARNING,"threshold for emissions is overfulled (%zu max), dropping down new data, added nothing",
s_threshold_emissions_max);
}
}
return l_ret;
dap_ledger_private_t *l_ledger_priv = PVT(a_ledger);
}
const char * c_token_ticker = ((dap_chain_datum_token_emission_t *)a_token_emission)->hdr.ticker;
dap_chain_ledger_token_item_t * l_token_item = NULL;
pthread_rwlock_rdlock(&l_ledger_priv->tokens_rwlock);
HASH_FIND_STR(l_ledger_priv->tokens, c_token_ticker, l_token_item);
pthread_rwlock_unlock(&l_ledger_priv->tokens_rwlock);
dap_chain_ledger_token_emission_item_t * l_token_emission_item = NULL;
if (!l_token_item && a_from_threshold)
return DAP_CHAIN_CS_VERIFY_CODE_TX_NO_TOKEN;
......@@ -2270,8 +2353,12 @@ static inline int s_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_e
|| (l_token_item->type == DAP_CHAIN_DATUM_TOKEN_TYPE_PRIVATE_UPDATE)
|| (l_token_item->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_DECL)
|| (l_token_item->type == DAP_CHAIN_DATUM_TOKEN_TYPE_NATIVE_UPDATE)) {
if (!s_chain_ledger_token_tsd_check(l_token_item, (dap_chain_datum_token_emission_t *)a_token_emission))
return -114;
if (!s_chain_ledger_token_tsd_check(l_token_item, (dap_chain_datum_token_emission_t *)a_token_emission)) {
DAP_DELETE(l_token_emission_item->datum_token_emission);
DAP_DELETE(l_token_emission_item);
DAP_DELETE(l_hash_str);
return -114;
}
}
//Update value in ledger memory object
if (!IS_ZERO_256(l_token_item->total_supply)) {
......@@ -2288,6 +2375,9 @@ static inline int s_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_e
l_balance, l_value);
DAP_DELETE(l_balance);
DAP_DELETE(l_value);
DAP_DELETE(l_token_emission_item->datum_token_emission);
DAP_DELETE(l_token_emission_item);
DAP_DELETE(l_hash_str);
return -4;
}
if (PVT(a_ledger)->cached)
......@@ -2313,7 +2403,12 @@ static inline int s_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_e
s_threshold_txs_proc(a_ledger);
} else if (HASH_COUNT(l_ledger_priv->threshold_emissions) < s_threshold_emissions_max) {
l_token_emission_item->datum_token_emission = DAP_DUP_SIZE(a_token_emission, a_token_emission_size);
l_token_emission_item->datum_token_emission_size = a_token_emission_size;
if(a_safe_call) pthread_rwlock_wrlock(&l_ledger_priv->threshold_emissions_rwlock);
l_token_emission_item->ts_added = dap_nanotime_now();
dap_chain_hash_fast_t l_emi_hash = {0};
dap_hash_fast(a_token_emission, a_token_emission_size, &l_emi_hash);
l_token_emission_item->datum_token_emission_hash = l_emi_hash;
HASH_ADD(hh, l_ledger_priv->threshold_emissions, datum_token_emission_hash,
sizeof(*a_emission_hash), l_token_emission_item);
if(a_safe_call) pthread_rwlock_unlock(&l_ledger_priv->threshold_emissions_rwlock);
......@@ -2327,6 +2422,7 @@ static inline int s_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_e
DAP_DELETE(l_token_emission_address_str);
}
} else {
DAP_DELETE(l_token_emission_item->datum_token_emission);
DAP_DELETE(l_token_emission_item);
if(s_debug_more)
log_it(L_WARNING,"threshold for emissions is overfulled (%zu max), dropping down new data, added nothing",
......@@ -2336,7 +2432,7 @@ static inline int s_token_emission_add(dap_ledger_t *a_ledger, byte_t *a_token_e
} else {
if (l_token_item) {
if(s_debug_more) {
if ( ((dap_chain_datum_token_emission_t *)a_token_emission)->hdr.version == 1 ) { // && ((dap_chain_datum_token_emission_t *)a_token_emission)->hdr.type_256 ) // 256
if ( ((dap_chain_datum_token_emission_t *)a_token_emission)->hdr.version == 2 ) {
char *l_balance = dap_chain_balance_print(((dap_chain_datum_token_emission_t *)a_token_emission)->hdr.value_256);
log_it(L_ERROR, "Duplicate token emission datum of %s %s ( %s )", l_balance, c_token_ticker, l_hash_str);
DAP_DELETE(l_balance);
......@@ -2906,43 +3002,54 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
bound_item = DAP_NEW_Z(dap_chain_ledger_tx_bound_t);
dap_chain_tx_in_t *l_tx_in = NULL;
dap_chain_addr_t l_tx_in_from={0};
dap_chain_tx_in_cond_t *l_tx_in_cond;
dap_chain_tx_in_cond_t *l_tx_in_cond = NULL;
dap_chain_tx_in_ems_t * l_tx_in_ems = NULL;
dap_chain_hash_fast_t l_tx_prev_hash={0};
uint8_t l_cond_type = *(uint8_t *)l_list_tmp->data;
// one of the previous transaction
if (l_cond_type == TX_ITEM_TYPE_IN) {
switch (l_cond_type) {
case TX_ITEM_TYPE_IN:
l_tx_in = (dap_chain_tx_in_t *)l_list_tmp->data;
l_tx_prev_hash = l_tx_in->header.tx_prev_hash;
bound_item->in.tx_cur_in = l_tx_in;
} else { // TX_ITEM_TYPE_IN_COND
break;
case TX_ITEM_TYPE_IN_COND:
l_tx_in_cond = (dap_chain_tx_in_cond_t *)l_list_tmp->data;
l_tx_prev_hash = l_tx_in_cond->header.tx_prev_hash;
bound_item->in.tx_cur_in_cond = l_tx_in_cond;
break;
case TX_ITEM_TYPE_IN_EMS:
l_tx_in_ems = (dap_chain_tx_in_ems_t *)l_list_tmp->data;
l_tx_prev_hash =l_tx_in_ems->header.token_emission_hash;
bound_item->in.tx_cur_in_ems = l_tx_in_ems;
break;
default:
break;
}
bound_item->tx_prev_hash = l_tx_prev_hash;
bool l_is_blank = dap_hash_fast_is_blank(&l_tx_prev_hash);
bool l_is_ems = (l_cond_type ==TX_ITEM_TYPE_IN_EMS) ? 1 : 0;
char l_tx_prev_hash_str[70]={[0]='\0'};
if (l_is_blank){
if (l_is_ems){
debug_if(s_debug_more && !a_from_threshold, L_DEBUG, "Tx check: blank prev hash");
dap_snprintf(l_tx_prev_hash_str,sizeof( l_tx_prev_hash_str),"BLANK");
}else{
dap_chain_hash_fast_to_str(&l_tx_prev_hash,l_tx_prev_hash_str,sizeof(l_tx_prev_hash_str));
}
if (l_is_blank) { // It's the first TX
// if at least one blank hash is present, then all the hashes should be blank
if (l_list_tmp_num > 1) {
l_err_num = -3;
log_it(L_WARNING, "Only one IN item allowed for base TX");
break;
}
dap_chain_tx_token_t *l_tx_token = (dap_chain_tx_token_t *)dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_TOKEN, NULL);
uint256_t l_value;
void *l_tx_prev_out = NULL;
dap_chain_datum_tx_t *l_tx_prev = NULL;
bool is_emission = false;
if (l_is_ems) { // It's the emission TX
dap_chain_tx_in_ems_t *l_tx_token = (dap_chain_tx_in_ems_t *)dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_IN_EMS, NULL);
if (!l_tx_token) {
log_it(L_WARNING, "tx token item is mandatory fot base TX");
log_it(L_WARNING, "tx token item is mandatory for base TX");
l_err_num = -4;
break;
}
//bool is_emission = false;
l_token = l_tx_token->header.ticker;
l_emission_hash = &l_tx_token->header.token_emission_hash;
dap_chain_ledger_token_emission_item_t *l_emission_item = s_emission_item_find(a_ledger, l_token, l_emission_hash);
......@@ -2971,9 +3078,9 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
break;
}
// int item_count = 0;
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);//TODO: ADD CHECK COUNT TX
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_EXT, 0);//TODO: ADD CHECK COUNT TX
if (!l_tx_out) {
debug_if(s_debug_more, L_WARNING, "Can't find OUT item for base TX with tx_token [%s]", l_tx_token->header.ticker);
debug_if(true, L_WARNING, "Can't find OUT item for base TX with tx_token [%s]", l_tx_token->header.ticker);
l_err_num = -24;
break;
}
......@@ -3020,11 +3127,11 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
if (!IS_ZERO_256(l_token_item->total_supply) &&
compare256(l_token_item->current_supply, l_tx_out->header.value) < 0) {
char *l_balance = dap_chain_balance_print(l_token_item->current_supply);
char *l_value = dap_chain_balance_print(l_tx_out->header.value);
char *l_value_ch = dap_chain_balance_print(l_tx_out->header.value);
log_it(L_WARNING, "Token current supply %s lower, than emission value = %s",
l_balance, l_value);
l_balance, l_value_ch);
DAP_DEL_Z(l_balance);
DAP_DEL_Z(l_value);
DAP_DEL_Z(l_value_ch);
l_err_num = -30;
break;
}
......@@ -3055,89 +3162,65 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
debug_if(s_debug_more, L_NOTICE, "Check emission passed for tx_token [%s]", l_tx_token->header.ticker);
bound_item->tx_prev = l_tx_stake_lock;
bound_item->stake_lock_item = stake_lock_emission;
l_list_bound_items = dap_list_append(l_list_bound_items, bound_item);
break;
bound_item->stake_lock_item->ems_value = l_value_expected;
//l_list_bound_items = dap_list_append(l_list_bound_items, bound_item);
is_emission = true;
} else {
debug_if(s_debug_more, L_WARNING, "tx_token [%s] not valid for stake_lock transaction", l_token);
l_err_num = -31;
break;
}
}
if (!l_emission_item) {
debug_if(s_debug_more && !a_from_threshold, L_WARNING, "Emission for tx_token [%s] wasn't found", l_tx_token->header.ticker);
l_err_num = DAP_CHAIN_CS_VERIFY_CODE_TX_NO_EMISSION;
break;
}
if (!dap_hash_fast_is_blank(&l_emission_item->tx_used_out)) {
debug_if(s_debug_more, L_WARNING, "Emission for tx_token [%s] is already used", l_tx_token->header.ticker);
l_err_num = -22;
break;
}
dap_chain_datum_token_emission_t * l_token_emission = l_emission_item->datum_token_emission;
int l_outs_count;
dap_list_t *l_list_out = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT, &l_outs_count);
dap_chain_tx_out_t *l_out = l_list_out ? (dap_chain_tx_out_t *)l_list_out->data : NULL;
dap_list_free(l_list_out);
if (l_outs_count != 1) {
l_err_num = -23;
log_it(L_WARNING, "Only one OUT item allowed for base TX");
break;
}
if (!EQUAL_256(l_token_emission->hdr.value_256, l_out->header.value)) {
l_err_num = -10;
log_it(L_WARNING, "Output value of base TX must be equal emission value");
else
if(l_emission_item)
{
if (!dap_hash_fast_is_blank(&l_emission_item->tx_used_out)) {
debug_if(s_debug_more, L_WARNING, "Emission for tx_token [%s] is already used", l_tx_token->header.ticker);
l_err_num = -22;
break;
}
bound_item->item_emission = l_emission_item;
}//end else emission
}
else //It's not the emission TX
{
// Get previous transaction in the cache by hash
dap_chain_ledger_tx_item_t *l_item_out = NULL;
l_tx_prev = s_find_datum_tx_by_hash(a_ledger, &l_tx_prev_hash, &l_item_out);
if (!l_tx_prev) { // Unchained transaction
debug_if(s_debug_more && !a_from_threshold, L_DEBUG, "No previous transaction was found for hash %s", l_tx_prev_hash_str);
l_err_num = DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS;
break;
}
if (memcmp(&l_token_emission->hdr.address, &l_out->addr, sizeof(dap_chain_addr_t))) {
l_err_num = -24;
log_it(L_WARNING, "Output addr of base TX must be equal emission addr");
bound_item->item_out = l_item_out;
l_token = l_item_out->cache_data.token_ticker;
debug_if(s_debug_more && !a_from_threshold, L_INFO, "Previous transaction was found for hash %s",l_tx_prev_hash_str);
bound_item->tx_prev = l_tx_prev;
// 2. Check if out in previous transaction has spent
int l_idx = (l_cond_type == TX_ITEM_TYPE_IN) ? l_tx_in->header.tx_out_prev_idx : l_tx_in_cond->header.tx_out_prev_idx;
if (dap_chain_ledger_item_is_used_out(l_item_out, l_idx)) {
l_err_num = -6;
break;
}
// Match the signature of the emission with the transaction
/*if(!s_tx_match_sign(l_token_emission, a_tx)) {
log_it(L_WARNING, "Base TX is not signed by the same certificate as the emission");
l_err_num = -25;
break;
}*/ // Base TX can be unsigned so temporary disabled
bound_item->item_emission = l_emission_item;
l_list_bound_items = dap_list_append(l_list_bound_items, bound_item);
break;
}
// Get previous transaction in the cache by hash
dap_chain_ledger_tx_item_t *l_item_out = NULL;
dap_chain_datum_tx_t *l_tx_prev = s_find_datum_tx_by_hash(a_ledger, &l_tx_prev_hash, &l_item_out);
if (!l_tx_prev) { // Unchained transaction
debug_if(s_debug_more && !a_from_threshold, L_DEBUG, "No previous transaction was found for hash %s", l_tx_prev_hash_str);
l_err_num = DAP_CHAIN_CS_VERIFY_CODE_TX_NO_PREVIOUS;
break;
}
bound_item->item_out = l_item_out;
l_token = l_item_out->cache_data.token_ticker;
debug_if(s_debug_more && !a_from_threshold, L_INFO, "Previous transaction was found for hash %s",l_tx_prev_hash_str);
bound_item->tx_prev = l_tx_prev;
// 2. Check if out in previous transaction has spent
int l_idx = (l_cond_type == TX_ITEM_TYPE_IN) ? l_tx_in->header.tx_out_prev_idx : l_tx_in_cond->header.tx_out_prev_idx;
if (dap_chain_ledger_item_is_used_out(l_item_out, l_idx)) {
l_err_num = -6;
break;
}
uint256_t l_value;
// Get one 'out' item in previous transaction bound with current 'in' item
void *l_tx_prev_out = dap_chain_datum_tx_item_get_nth(l_tx_prev, TX_ITEM_TYPE_OUT_ALL, l_idx);
if(!l_tx_prev_out) {
l_err_num = -8;
break;
}
// 3. Compare out in previous transaction with currently used out
for (dap_list_t *it = l_list_bound_items; it; it = it->next) {
dap_chain_ledger_tx_bound_t *l_bound_tmp = it->data;
if (l_tx_prev_out == l_bound_tmp->out.tx_prev_out) {
debug_if(s_debug_more, L_ERROR, "Previous transaction output already used in current tx");
l_err_num = -7;
// Get one 'out' item in previous transaction bound with current 'in' item
l_tx_prev_out = dap_chain_datum_tx_item_get_nth(l_tx_prev, TX_ITEM_TYPE_OUT_ALL, l_idx);
if(!l_tx_prev_out) {
l_err_num = -8;
break;
}
// 3. Compare out in previous transaction with currently used out
for (dap_list_t *it = l_list_bound_items; it; it = it->next) {
dap_chain_ledger_tx_bound_t *l_bound_tmp = it->data;
if (l_tx_prev_out == l_bound_tmp->out.tx_prev_out) {
debug_if(s_debug_more, L_ERROR, "Previous transaction output already used in current tx");
l_err_num = -7;
break;
}
}
}
if (l_err_num)
break;
......@@ -3186,7 +3269,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
l_err_num = -9;
break;
}
} else { // TX_ITEM_TYPE_IN_COND
} else if(l_cond_type == TX_ITEM_TYPE_IN_COND) { // TX_ITEM_TYPE_IN_COND
if(*(uint8_t *)l_tx_prev_out != TX_ITEM_TYPE_OUT_COND) {
l_err_num = -8;
break;
......@@ -3236,6 +3319,17 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
bound_item->out.tx_prev_out_cond_256 = l_tx_prev_out_cond;
l_value = l_tx_prev_out_cond->header.value;
}
else if(l_cond_type == TX_ITEM_TYPE_IN_EMS){
if(is_emission){
l_token = bound_item->in.tx_cur_in_ems->header.ticker;
l_value = bound_item->stake_lock_item->ems_value;
is_emission = false;
}
else{
l_token = bound_item->item_emission->datum_token_emission->hdr.ticker;
l_value = bound_item->item_emission->datum_token_emission->hdr.value_256;
}
}
if (! l_token || !*l_token ) {
log_it(L_WARNING, "No token ticker found in previous transaction");
l_err_num = -15;
......@@ -3329,7 +3423,7 @@ int dap_chain_ledger_tx_cache_check(dap_ledger_t *a_ledger, dap_chain_datum_tx_t
uint256_t l_value = {}, l_fee_value = {}, l_fee_sum = {};
dap_chain_addr_t l_fee_addr = {};
#ifndef DAP_CHAIN_LEDGER_TEST
bool l_fee_check = dap_chain_net_tx_get_fee(PVT(a_ledger)->net->pub.id, &l_fee_value, &l_fee_addr);
bool l_fee_check = dap_chain_net_tx_get_fee(PVT(a_ledger)->net->pub.id, NULL, &l_fee_value, &l_fee_addr);
#else
bool l_fee_check = false;
#endif
......@@ -3650,6 +3744,7 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d
l_item_tmp = DAP_NEW_Z(dap_chain_ledger_tx_item_t);
l_item_tmp->tx_hash_fast = *a_tx_hash;
l_item_tmp->tx = DAP_DUP_SIZE(a_tx, dap_chain_datum_tx_get_size(a_tx));
l_item_tmp->ts_added = dap_nanotime_now();
HASH_ADD_BYHASHVALUE(hh, l_ledger_priv->threshold_txs, tx_hash_fast, sizeof(dap_chain_hash_fast_t), l_hash_value, l_item_tmp);
if(s_debug_more)
log_it (L_DEBUG, "Tx %s added to threshold", l_tx_hash_str);
......@@ -3681,57 +3776,59 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d
dap_chain_ledger_tx_bound_t *bound_item = l_list_tmp->data;
void *l_item_in = *(void **)&bound_item->in;
dap_chain_tx_item_type_t l_type = *(uint8_t *)l_item_in;
if (l_type == TX_ITEM_TYPE_IN) {
dap_chain_tx_in_t *l_tx_in = bound_item->in.tx_cur_in;
if (dap_hash_fast_is_blank(&l_tx_in->header.tx_prev_hash)) { // It's the emission behind
// Find token ticker for emission
dap_chain_tx_token_t * l_tx_token = (dap_chain_tx_token_t *) dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_TOKEN, NULL);
if (l_tx_token)
l_main_token_ticker = l_tx_token->header.ticker;
else {
log_it(L_ERROR, "No token item with blank prev tx hash");
if (l_type == TX_ITEM_TYPE_IN_EMS) {
// It's the emission behind
// Find token ticker for emission
dap_chain_tx_in_ems_t * l_tx_token = (dap_chain_tx_in_ems_t *) dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_IN_EMS, NULL);
if (l_tx_token)
l_main_token_ticker = l_tx_token->header.ticker;
else {
log_it(L_ERROR, "No token item with blank prev tx hash");
break;
}
if (bound_item->tx_prev) { // It's the stake lock emission
dap_chain_ledger_token_item_t *l_token_item = NULL;
pthread_rwlock_rdlock(&l_ledger_priv->tokens_rwlock);
HASH_FIND_STR(l_ledger_priv->tokens, l_main_token_ticker, l_token_item);
pthread_rwlock_unlock(&l_ledger_priv->tokens_rwlock);
if (!l_token_item){
log_it(L_ERROR, "No token item found for token %s", l_main_token_ticker);
break;
}
if (bound_item->tx_prev) { // It's the stake lock emission
dap_chain_ledger_token_item_t *l_token_item = NULL;
pthread_rwlock_rdlock(&l_ledger_priv->tokens_rwlock);
HASH_FIND_STR(l_ledger_priv->tokens, l_main_token_ticker, l_token_item);
pthread_rwlock_unlock(&l_ledger_priv->tokens_rwlock);
if (!l_token_item){
log_it(L_ERROR, "No token item found for token %s", l_main_token_ticker);
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);
SUBTRACT_256_256(l_token_item->current_supply, l_tx_out->header.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);
if (PVT(a_ledger)->cached)
s_ledger_token_cache_update(a_ledger, l_token_item);
}
bound_item->stake_lock_item->tx_used_out = *a_tx_hash;
if (PVT(a_ledger)->cached)
// Mirror it in cache
s_ledger_stake_lock_cache_update(a_ledger, bound_item->stake_lock_item);
} else { // It's the general emission
// Mark it as used with base tx hash
bound_item->item_emission->tx_used_out = *a_tx_hash;
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);
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);
if (PVT(a_ledger)->cached)
// Mirror it in cache
s_ledger_emission_cache_update(a_ledger, bound_item->item_emission);
s_ledger_token_cache_update(a_ledger, l_token_item);
}
l_list_tmp = dap_list_next(l_list_tmp);
i--; // Do not calc this output with tx used items
l_outs_used--;
continue;
bound_item->stake_lock_item->tx_used_out = *a_tx_hash;
if (PVT(a_ledger)->cached)
// Mirror it in cache
s_ledger_stake_lock_cache_update(a_ledger, bound_item->stake_lock_item);
} else { // It's the general emission
// Mark it as used with base tx hash
bound_item->item_emission->tx_used_out = *a_tx_hash;
if (PVT(a_ledger)->cached)
// Mirror it in cache
s_ledger_emission_cache_update(a_ledger, bound_item->item_emission);
}
l_list_tmp = dap_list_next(l_list_tmp);
i--; // Do not calc this output with tx used items
l_outs_used--;
continue;
}
dap_chain_ledger_tx_item_t *l_prev_item_out = bound_item->item_out;
l_cur_token_ticker = l_prev_item_out->cache_data.token_ticker;
if (!l_main_token_ticker)
l_main_token_ticker = l_cur_token_ticker;
int l_tx_prev_out_used_idx;
int l_tx_prev_out_used_idx = 0;
if (l_type == TX_ITEM_TYPE_IN) {
dap_chain_tx_in_t *l_tx_in = bound_item->in.tx_cur_in;
dap_ledger_wallet_balance_t *wallet_balance = NULL;
......@@ -3779,7 +3876,7 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d
DAP_DELETE(l_wallet_balance_key);
/// Mark 'out' item in cache because it used
l_tx_prev_out_used_idx = l_tx_in->header.tx_out_prev_idx;
} else { // TX_ITEM_TYPE_IN_COND
} 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
......@@ -3798,6 +3895,7 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d
if (l_verificator && l_verificator->callback_added)
l_verificator->callback_added(a_ledger, a_tx, l_cond);
}
// add a used output
l_prev_item_out->cache_data.tx_hash_spent_fast[l_tx_prev_out_used_idx] = *a_tx_hash;
l_prev_item_out->cache_data.n_outs_used++;
......@@ -3849,6 +3947,7 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d
l_list_tmp = dap_list_next(l_list_tmp);
}
//Update balance : raise
bool l_multichannel = false;
for (dap_list_t *l_tx_out = l_list_tx_out; l_tx_out; l_tx_out = dap_list_next(l_tx_out)) {
......@@ -3953,6 +4052,7 @@ static inline int s_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, d
debug_if(s_debug_more, L_ERROR, "No token ticker in previous txs");
l_tx_item->cache_data.multichannel = l_multichannel;
if(a_safe_call) pthread_rwlock_wrlock(&l_ledger_priv->ledger_rwlock);
l_tx_item->ts_added = dap_nanotime_now();
HASH_ADD_INORDER(hh, l_ledger_priv->ledger_items, tx_hash_fast, sizeof(dap_chain_hash_fast_t),
l_tx_item, s_sort_ledger_tx_item); // tx_hash_fast: name of key field
if(a_safe_call) pthread_rwlock_unlock(&l_ledger_priv->ledger_rwlock);
......@@ -4426,7 +4526,6 @@ uint256_t dap_chain_ledger_calc_balance_full(dap_ledger_t *a_ledger, const dap_c
return balance;
}
/**
* Get the transaction in the cache by the addr in out item
*
......
......@@ -32,6 +32,7 @@
#include "dap_chain_common.h"
#include "dap_chain_datum.h"
#include "dap_chain_datum_tx.h"
#include "dap_cert.h"
typedef struct dap_chain dap_chain_t;
......@@ -45,15 +46,14 @@ typedef const void * dap_chain_atom_ptr_t;
// Atomic element iterator
typedef struct dap_chain_atom_iter{
dap_chain_t * chain;
dap_chain_t *chain;
dap_chain_atom_ptr_t cur;
dap_chain_hash_fast_t *cur_hash;
dap_chain_cell_id_t cell_id;
bool with_treshold;
bool found_in_treshold;
size_t cur_size;
void * cur_item;
void * _inheritor;
void *cur_item;
} dap_chain_atom_iter_t;
......@@ -89,12 +89,13 @@ typedef dap_chain_atom_ptr_t * (*dap_chain_callback_atom_iter_get_atoms_t)(dap_c
typedef size_t (*dap_chain_callback_add_datums_t)(dap_chain_t * , dap_chain_datum_t **, size_t );
typedef dap_chain_atom_ptr_t (*dap_chain_callback_atom_iter_get_next_t)(dap_chain_atom_iter_t * ,size_t*);
typedef void (*dap_chain_callback_atom_iter_delete_t)(dap_chain_atom_iter_t * );
typedef void (*dap_chain_callback_atom_iter_delete_t)(dap_chain_atom_iter_t *);
typedef void (*dap_chain_callback_notify_t)(void * a_arg, dap_chain_t *a_chain, dap_chain_cell_id_t a_id, void* a_atom, size_t a_atom_size); //change in chain happened
typedef size_t(*dap_chain_callback_get_count)(dap_chain_t *a_chain);
typedef dap_list_t *(*dap_chain_callback_get_list)(dap_chain_t *a_chain, size_t a_count, size_t a_page, bool a_reverse);
typedef dap_list_t *(*dap_chain_callback_get_poa_certs)(dap_chain_t *a_chain, size_t *a_auth_certs_count, uint16_t *count_verify);
typedef enum dap_chain_type
{
......@@ -104,7 +105,8 @@ typedef enum dap_chain_type
CHAIN_TYPE_TX,
CHAIN_TYPE_CA,
CHAIN_TYPE_SIGNER,
CHAIN_TYPE_LAST
CHAIN_TYPE_LAST,
CHAIN_TYPE_DECREE
} dap_chain_type_t;
typedef struct dap_chain {
......@@ -169,6 +171,8 @@ typedef struct dap_chain {
dap_chain_callback_get_count callback_count_atom;
dap_chain_callback_get_list callback_get_atoms;
dap_chain_callback_get_poa_certs callback_get_poa_certs;
dap_list_t * atom_notifiers;
// dap_chain_callback_notify_t callback_notify;
// void *callback_notify_arg;
......
......@@ -33,7 +33,7 @@
#include "dap_chain_common.h"
#include "dap_chain_datum_token.h"
#include "dap_chain_datum_tx.h"
#include "dap_chain_datum_tx_token.h"
#include "dap_chain_datum_tx_in_ems.h"
#include "dap_chain_datum_tx_items.h"
typedef struct dap_ledger {
......
......@@ -4,6 +4,7 @@
#include "dap_chain_wallet.h"
#include "dap_math_ops.h"
static const uint64_t s_fee = 2;
static const uint64_t s_total_supply = 500;
static const uint64_t s_standard_value_tx = 500;
static const char* s_token_ticker = "TestCoins";
......@@ -45,24 +46,26 @@ dap_chain_datum_tx_t *dap_chain_ledger_test_create_datum_base_tx(
dap_chain_hash_fast_t *l_emi_hash,
dap_chain_addr_t a_addr_to,
dap_cert_t *a_cert) {
uint256_t l_value_fee = dap_chain_uint256_from(s_fee);
uint256_t l_value_need = a_emi->hdr.value_256;
dap_chain_datum_tx_t *l_tx = DAP_NEW_Z_SIZE(dap_chain_datum_tx_t, sizeof(dap_chain_datum_tx_t));
l_tx->header.ts_created = time(NULL);
dap_chain_hash_fast_t l_tx_prev_hash = { 0 };
dap_chain_tx_token_t *l_token = DAP_NEW_Z(dap_chain_tx_token_t);
l_token->header.type = TX_ITEM_TYPE_TOKEN;
l_token->header.token_emission_chain_id.uint64 = 0;
l_token->header.token_emission_hash = *l_emi_hash;
strcpy(l_token->header.ticker, a_emi->hdr.ticker);
dap_chain_tx_in_t *l_in = dap_chain_datum_tx_item_in_create(&l_tx_prev_hash, 0);
dap_chain_tx_out_t *l_out = dap_chain_datum_tx_item_out_create(&a_addr_to, a_emi->hdr.value_256);
dap_chain_datum_tx_add_item(&l_tx, (const uint8_t*) l_token);
dap_chain_datum_tx_add_item(&l_tx, (const uint8_t*) l_in);
dap_chain_tx_in_ems_t *l_in_ems = DAP_NEW_Z(dap_chain_tx_in_ems_t);
l_in_ems->header.type = TX_ITEM_TYPE_IN_EMS;
l_in_ems->header.token_emission_chain_id.uint64 = 0;
l_in_ems->header.token_emission_hash = *l_emi_hash;
strcpy(l_in_ems->header.ticker, a_emi->hdr.ticker);
SUBTRACT_256_256(l_value_need, l_value_fee, &l_value_need);
dap_chain_tx_out_t *l_out = dap_chain_datum_tx_item_out_create(&a_addr_to, l_value_need);
dap_chain_tx_out_cond_t *l_tx_out_fee = dap_chain_datum_tx_item_out_cond_create_fee(l_value_fee);
dap_chain_datum_tx_add_item(&l_tx, (const uint8_t*) l_in_ems);
dap_chain_datum_tx_add_item(&l_tx, (const uint8_t*) l_out);
dap_chain_datum_tx_add_item(&l_tx, (const uint8_t*) l_tx_out_fee);
dap_chain_datum_tx_add_sign_item(&l_tx, a_cert->enc_key);
DAP_DEL_Z(l_token);
DAP_DEL_Z(l_in);
DAP_DEL_Z(l_in_ems);
DAP_DEL_Z(l_out);
DAP_DEL_Z(l_tx_out_fee);
return l_tx;
}
......@@ -87,7 +90,7 @@ void dap_chain_ledger_test_double_spending(
dap_chain_addr_t l_addr_first = {0};
dap_chain_addr_fill_from_key(&l_addr_first, l_first_cert->enc_key, a_net_id);
dap_chain_datum_tx_t *l_first_tx = dap_chain_ledger_test_create_tx(a_from_key, a_prev_hash,
&l_addr_first, dap_chain_uint256_from(s_standard_value_tx));
&l_addr_first, dap_chain_uint256_from(s_standard_value_tx - s_fee));
dap_assert_PIF(l_first_tx, "Can't creating base transaction.");
dap_chain_hash_fast_t l_first_tx_hash = {0};
dap_hash_fast(l_first_tx, dap_chain_datum_tx_get_size(l_first_tx), &l_first_tx_hash);
......@@ -95,7 +98,7 @@ void dap_chain_ledger_test_double_spending(
uint256_t l_balance = dap_chain_ledger_calc_balance(a_ledger, &l_addr_first, s_token_ticker);
// Second tx
dap_chain_datum_tx_t *l_second_tx = dap_chain_ledger_test_create_tx(a_from_key, a_prev_hash,
&l_addr_first, dap_chain_uint256_from(s_standard_value_tx));
&l_addr_first, dap_chain_uint256_from(s_standard_value_tx - s_fee));
dap_chain_hash_fast_t l_second_tx_hash = {0};
dap_hash_fast(l_second_tx, dap_chain_datum_tx_get_size(l_second_tx), &l_second_tx_hash);
dap_assert_PIF(dap_chain_ledger_tx_add(a_ledger, l_second_tx, &l_second_tx_hash, false) != 1, "Added second transaction on ledger");
......@@ -232,12 +235,12 @@ void dap_chain_ledger_test_write_back_list(dap_ledger_t *a_ledger, dap_cert_t *a
"Can't added base tx in white address");
dap_hash_fast_t l_tx_addr4_hash = {0};
dap_chain_datum_tx_t *l_tx_to_addr4 = dap_chain_ledger_test_create_tx(l_addr_1->enc_key, &l_btx_addr1_hash,
l_addr_4->addr, dap_chain_uint256_from(s_total_supply));
l_addr_4->addr, dap_chain_uint256_from(s_total_supply-s_fee));
dap_hash_fast(l_tx_to_addr4, dap_chain_datum_tx_get_size(l_tx_to_addr4), &l_tx_addr4_hash);
dap_assert_PIF(dap_chain_ledger_tx_add(a_ledger, l_tx_to_addr4, &l_tx_addr4_hash, false) == 1,
"Can't added transaction to address from white list in ledger");
dap_chain_datum_tx_t *l_tx_to_addr3 = dap_chain_ledger_test_create_tx(l_addr_4->enc_key, &l_tx_addr4_hash,
l_addr_3->addr, dap_chain_uint256_from(s_total_supply));
l_addr_3->addr, dap_chain_uint256_from(s_total_supply-s_fee));
dap_hash_fast_t l_tx_addr3_hash = {0};
dap_hash_fast(l_tx_to_addr3, dap_chain_datum_tx_get_size(l_tx_to_addr3), &l_tx_addr3_hash);
int res_add_tx = dap_chain_ledger_tx_add(a_ledger, l_tx_to_addr3, &l_tx_addr3_hash, false);
......@@ -376,6 +379,7 @@ void dap_chain_ledger_test_run(void){
l_check_added_decl_token = dap_chain_ledger_token_decl_add_check(l_ledger, l_token_decl, l_token_decl_size);
dap_assert_PIF(l_check_added_decl_token == 0, "Checking whether it is possible to add a token declaration to ledger.");
dap_assert_PIF(!dap_chain_ledger_token_add(l_ledger, l_token_decl, l_token_decl_size), "Adding token declaration to ledger.");
// Create emission
dap_chain_addr_t l_addr = {0};
dap_chain_addr_fill_from_key(&l_addr, l_cert->enc_key, l_iddn);
......@@ -394,7 +398,9 @@ void dap_chain_ledger_test_run(void){
dap_hash_fast(l_base_tx, dap_chain_datum_tx_get_size(l_base_tx), &l_hash_btx);
dap_assert_PIF(dap_chain_ledger_tx_add(l_ledger, l_base_tx, &l_hash_btx, false) == 1, "Added base tx in ledger.");
uint256_t l_balance_example = dap_chain_uint256_from(s_standard_value_tx);
uint256_t l_balance = dap_chain_ledger_calc_balance(l_ledger, &l_addr, s_token_ticker);
uint256_t l_balance = dap_chain_ledger_calc_balance(l_ledger, &l_addr, s_token_ticker);
uint256_t l_fee = dap_chain_uint256_from(s_fee);
SUM_256_256(l_balance,l_fee,&l_balance);
dap_assert_PIF(!compare256(l_balance, l_balance_example), "Checking the availability of the necessary balance "
"on the wallet after the first transaction.");
dap_pass_msg("Validation of the declaration of the tocen, creation of an emission and a basic transaction using this in the ledger.");
......@@ -409,8 +415,9 @@ void dap_chain_ledger_test_run(void){
dap_pass_msg("Checking for a failure to add a second base transaction for the same issue to the ledger.");
} else {
dap_fail("Checking for a failure to add a second base transaction for the same issue to the ledger.");
}
}
dap_chain_ledger_test_double_spending(l_ledger, &l_hash_btx, l_cert->enc_key, l_iddn);
dap_chain_ledger_test_excess_supply(l_ledger, l_cert, &l_addr);
dap_chain_ledger_test_write_back_list(l_ledger, l_cert, l_iddn);
//dap_chain_ledger_test_write_back_list(l_ledger, l_cert, l_iddn);
}
......@@ -370,8 +370,8 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
typedef dap_stream_ch_chain_net_srv_pkt_test_t pkt_test_t;
pkt_test_t *l_request = (pkt_test_t*)l_ch_pkt->data;
size_t l_request_size = l_request->data_size + sizeof(pkt_test_t);
if (l_ch_pkt->hdr.size != l_request_size) {
log_it(L_WARNING, "Wrong request size %u, must be %zu [pkt seq %"DAP_UINT64_FORMAT_U"]", l_ch_pkt->hdr.size, l_request_size, l_ch_pkt->hdr.seq_id);
if (l_ch_pkt->hdr.data_size != l_request_size) {
log_it(L_WARNING, "Wrong request size %u, must be %zu [pkt seq %"DAP_UINT64_FORMAT_U"]", l_ch_pkt->hdr.data_size, l_request_size, l_ch_pkt->hdr.seq_id);
l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_WRONG_SIZE;
dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof(l_err));
break;
......@@ -406,29 +406,29 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
} break; /* DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_CHECK_REQUEST */
case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_REQUEST: {
if (l_ch_pkt->hdr.size < sizeof(dap_stream_ch_chain_net_srv_pkt_request_hdr_t) ){
if (l_ch_pkt->hdr.data_size < sizeof(dap_stream_ch_chain_net_srv_pkt_request_hdr_t) ){
log_it( L_WARNING, "Wrong request size, less than minimum");
break;
}
dap_chain_net_srv_grace_t *l_grace = DAP_NEW_Z(dap_chain_net_srv_grace_t);
// Parse the request
l_grace->request = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_request_t, l_ch_pkt->hdr.size);
memcpy(l_grace->request, l_ch_pkt->data, l_ch_pkt->hdr.size);
l_grace->request = DAP_NEW_Z_SIZE(dap_stream_ch_chain_net_srv_pkt_request_t, l_ch_pkt->hdr.data_size);
memcpy(l_grace->request, l_ch_pkt->data, l_ch_pkt->hdr.data_size);
l_ch_chain_net_srv->srv_uid.uint64 = l_grace->request->hdr.srv_uid.uint64;
l_grace->request_size = l_ch_pkt->hdr.size;
l_grace->request_size = l_ch_pkt->hdr.data_size;
l_grace->ch_uuid = a_ch->uuid;
l_grace->stream_worker = a_ch->stream_worker;
s_grace_period_control(l_grace);
} break; /* DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_REQUEST */
case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_RESPONSE: {
if (l_ch_pkt->hdr.size < sizeof(dap_chain_receipt_info_t)) {
log_it(L_ERROR, "Wrong sign response size, %u when expected at least %zu with smth", l_ch_pkt->hdr.size,
if (l_ch_pkt->hdr.data_size < sizeof(dap_chain_receipt_info_t)) {
log_it(L_ERROR, "Wrong sign response size, %u when expected at least %zu with smth", l_ch_pkt->hdr.data_size,
sizeof(dap_chain_receipt_info_t));
break;
}
dap_chain_datum_tx_receipt_t * l_receipt = (dap_chain_datum_tx_receipt_t *) l_ch_pkt->data;
size_t l_receipt_size = l_ch_pkt->hdr.size;
size_t l_receipt_size = l_ch_pkt->hdr.data_size;
dap_chain_net_srv_usage_t * l_usage= NULL, *l_tmp= NULL;
bool l_is_found = false;
pthread_mutex_lock(& l_srv_session->parent->mutex ); // TODO rework it with packet usage_id
......@@ -593,13 +593,13 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
} break;
case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_DATA: {
if (l_ch_pkt->hdr.size < sizeof(dap_stream_ch_chain_net_srv_pkt_data_hdr_t) ){
if (l_ch_pkt->hdr.data_size < sizeof(dap_stream_ch_chain_net_srv_pkt_data_hdr_t) ){
log_it( L_WARNING, "Wrong request size, less than minimum");
break;
}
typedef dap_stream_ch_chain_net_srv_pkt_data_t pkt_t;
pkt_t * l_pkt =(pkt_t *) l_ch_pkt->data;
size_t l_pkt_size = l_ch_pkt->hdr.size - sizeof(pkt_t);
size_t l_pkt_size = l_ch_pkt->hdr.data_size - sizeof(pkt_t);
dap_chain_net_srv_t * l_srv = dap_chain_net_srv_get( l_pkt->hdr.srv_uid);
dap_chain_net_srv_usage_t * l_usage = dap_chain_net_srv_usage_find_unsafe( l_srv_session, l_pkt->hdr.usage_id );
// If service not found
......@@ -625,12 +625,12 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg)
} break;
case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR:{
if ( l_ch_pkt->hdr.size == sizeof (dap_stream_ch_chain_net_srv_pkt_error_t) ){
if ( l_ch_pkt->hdr.data_size == sizeof (dap_stream_ch_chain_net_srv_pkt_error_t) ){
dap_stream_ch_chain_net_srv_pkt_error_t * l_err = (dap_stream_ch_chain_net_srv_pkt_error_t *) l_ch_pkt->data;
log_it( L_NOTICE, "Remote responsed with error code 0x%08X", l_err->code );
// TODO code for service client mode
}else{
log_it(L_ERROR, "Wrong error response size, %u when expected %zu", l_ch_pkt->hdr.size,
log_it(L_ERROR, "Wrong error response size, %u when expected %zu", l_ch_pkt->hdr.data_size,
sizeof ( dap_stream_ch_chain_net_srv_pkt_error_t) );
}
} break;
......
......@@ -170,7 +170,6 @@ void s_stream_ch_new(dap_stream_ch_t* a_ch, void* a_arg)
void s_stream_ch_delete(dap_stream_ch_t* a_ch, void* a_arg)
{
(void) a_arg;
//printf("* del session=%d\n", a_ch->stream->session->id);
dap_stream_ch_chain_net_t * l_ch_chain_net = DAP_STREAM_CH_CHAIN_NET(a_ch);
if(l_ch_chain_net) {
pthread_mutex_lock(&l_ch_chain_net->mutex);
......@@ -227,9 +226,8 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
l_ch_chain_net_pkt->hdr.net_id, l_err_str, strlen(l_err_str) + 1);
dap_stream_ch_set_ready_to_write_unsafe(a_ch, true);
}
//size_t l_ch_chain_net_pkt_data_size = (size_t) l_ch_pkt->hdr.size - sizeof (l_ch_chain_net_pkt->hdr);
if (!l_error && l_ch_chain_net_pkt) {
size_t l_ch_chain_net_pkt_data_size = l_ch_pkt->hdr.size - sizeof(dap_stream_ch_chain_net_pkt_hdr_t);
size_t l_ch_chain_net_pkt_data_size = l_ch_pkt->hdr.data_size - sizeof(dap_stream_ch_chain_net_pkt_hdr_t);
switch (l_ch_pkt->hdr.type) {
case DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_DBG: {
dap_stream_ch_chain_net_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_PING,
......
......@@ -6,7 +6,7 @@ file(GLOB DAP_STREAM_CH_CHAIN_VOTING_HDRS include/*.h)
add_library(${PROJECT_NAME} STATIC ${DAP_STREAM_CH_CHAIN_VOTING_SRCS} ${DAP_STREAM_CH_CHAIN_VOTING_HDRS})
target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_stream dap_stream_ch dap_stream_ch_chain dap_chain_net)
target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_stream dap_stream_ch dap_chain_net)
target_include_directories(${PROJECT_NAME} INTERFACE .)
......
......@@ -8,86 +8,46 @@
#include "dap_stream_ch_chain_voting.h"
#include "dap_chain_net.h"
#include "dap_client_pvt.h"
#include "dap_proc_queue.h"
#include "dap_chain_node_cli.h"
#define LOG_TAG "dap_stream_ch_chain_voting"
typedef struct voting_pkt_in_callback{
struct voting_pkt_in_callback {
void * arg;
voting_ch_callback_t packet_in_callback;
} voting_pkt_in_callback_t;
typedef struct voting_pkt_addr {
dap_chain_node_addr_t node_addr;
dap_stream_ch_chain_voting_pkt_t *voting_pkt;
} voting_pkt_addr_t;
dap_chain_voting_ch_callback_t packet_in_callback;
};
typedef struct voting_pkt_items {
pthread_rwlock_t rwlock_out;
pthread_rwlock_t rwlock_in;
dap_list_t * pkts_out; // voting_pkt_addr_t
dap_list_t * pkts_in; // dap_stream_ch_chain_voting_pkt_t
} voting_pkt_items_t;
typedef struct voting_node_client_list {
struct voting_node_client_list {
dap_chain_node_addr_t node_addr; // HT key
dap_chain_node_info_t *node_info;
dap_chain_node_client_t *node_client;
dap_events_socket_uuid_t uuid;
dap_chain_node_addr_t node_addr;
UT_hash_handle hh;
} voting_node_client_list_t;
static size_t s_pkt_in_callback_count = 0;
static voting_pkt_in_callback_t s_pkt_in_callback[256]={{0}};
static voting_pkt_items_t *s_pkt_items = NULL;
static voting_node_client_list_t *s_node_client_list = NULL;
static void s_callback_send_all_loopback(uint64_t a_node_addr);
static void s_callback_send_all_unsafe(dap_client_t *a_client, void *a_arg);
static void s_callback_send_all_unsafe(dap_client_t *a_client, void *a_arg);
static void s_stream_ch_new(dap_stream_ch_t* a_ch, void* a_arg);
static void s_stream_ch_delete(dap_stream_ch_t* a_ch, void* a_arg);
};
static void s_packet_in_callback_handler(void * a_arg);
static void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg);
static void s_stream_ch_packet_out(dap_stream_ch_t* a_ch, void* a_arg);
static struct voting_node_client_list *s_node_client_list = NULL;
static dap_interval_timer_t *s_packet_in_callback_timer = NULL;
static bool s_is_inited = false;
static size_t s_pkt_in_callback_count = 0;
static struct voting_pkt_in_callback s_pkt_in_callback[16] = {};
//static int s_cli_voting(int argc, char ** argv, char **a_str_reply);
static void s_stream_ch_new(dap_stream_ch_t *a_ch, void *a_arg);
static void s_stream_ch_delete(dap_stream_ch_t *a_ch, void *a_arg);
static void s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg);
int dap_stream_ch_chain_voting_init() {
int dap_stream_ch_chain_voting_init()
{
log_it(L_NOTICE, "Chains voting channel initialized");
if (s_is_inited) {
return 0;
}
if (!s_pkt_items) {
s_pkt_items = DAP_NEW_Z(voting_pkt_items_t);
s_pkt_items->pkts_out = NULL;
s_pkt_items->pkts_in = NULL;
pthread_rwlock_init(&s_pkt_items->rwlock_out, NULL);
pthread_rwlock_init(&s_pkt_items->rwlock_in, NULL);
}
dap_stream_ch_proc_add(dap_stream_ch_chain_voting_get_id(),
s_stream_ch_new,
s_stream_ch_delete,
s_stream_ch_packet_in,
s_stream_ch_packet_out);
NULL);
if (!s_packet_in_callback_timer) {
s_packet_in_callback_timer = dap_interval_timer_create(1000, s_packet_in_callback_handler, NULL);
}
s_is_inited = true;
// s_packet_in_callback_handler();
return 0;
}
void dap_stream_ch_chain_voting_in_callback_add(void* a_arg, voting_ch_callback_t packet_in_callback)
void dap_stream_ch_chain_voting_in_callback_add(void* a_arg, dap_chain_voting_ch_callback_t packet_in_callback)
{
size_t i = s_pkt_in_callback_count;
s_pkt_in_callback[i].arg = a_arg;
......@@ -95,263 +55,122 @@ void dap_stream_ch_chain_voting_in_callback_add(void* a_arg, voting_ch_callback_
s_pkt_in_callback_count++;
}
void dap_stream_ch_chain_voting_message_write(dap_chain_net_t * a_net, dap_list_t *a_sendto_nodes,
dap_chain_hash_fast_t * a_data_hash,
const void * a_data, size_t a_data_size)
static bool s_callback_pkt_in_call_all(UNUSED_ARG dap_proc_thread_t *a_thread, void *a_arg)
{
dap_stream_ch_chain_voting_pkt_t * l_voting_pkt;
size_t l_voting_pkt_size = sizeof(l_voting_pkt->hdr) + a_data_size;
l_voting_pkt = DAP_NEW_SIZE(dap_stream_ch_chain_voting_pkt_t, l_voting_pkt_size );
l_voting_pkt->hdr.data_size = a_data_size;
memcpy( &l_voting_pkt->hdr.data_hash, a_data_hash, sizeof(dap_chain_hash_fast_t));
l_voting_pkt->hdr.pkt_type = DAP_STREAM_CH_CHAIN_VOTING_PKT_TYPE_TEST;
l_voting_pkt->hdr.version = 1;
l_voting_pkt->hdr.net_id.uint64 = a_net->pub.id.uint64;
if (a_data_size && a_data) {
memcpy( l_voting_pkt->data, a_data, a_data_size);
dap_stream_ch_chain_voting_pkt_t *l_voting_pkt = a_arg;
for (size_t i = 0; i < s_pkt_in_callback_count; i++) {
struct voting_pkt_in_callback *l_callback = s_pkt_in_callback + i;
if (l_callback->packet_in_callback) {
l_callback->packet_in_callback(l_callback->arg, &l_voting_pkt->hdr.sender_node_addr,
&l_voting_pkt->hdr.data_hash, l_voting_pkt->data, l_voting_pkt->hdr.data_size);
}
}
voting_pkt_addr_t * l_pkt_addr = DAP_NEW_Z(voting_pkt_addr_t);
l_pkt_addr->node_addr.uint64 = 0;
l_pkt_addr->voting_pkt = l_voting_pkt;
pthread_rwlock_wrlock(&s_pkt_items->rwlock_out);
s_pkt_items->pkts_out = dap_list_append(s_pkt_items->pkts_out, l_pkt_addr);
pthread_rwlock_unlock(&s_pkt_items->rwlock_out);
dap_stream_ch_chain_voting_pkt_broadcast(a_net, a_sendto_nodes);
return true;
}
static void s_callback_send_all_unsafe_on_worker(dap_worker_t *a_worker, void *a_arg)
void dap_stream_ch_chain_voting_message_write(dap_chain_net_t *a_net, dap_chain_node_addr_t *a_remote_node_addr,
dap_stream_ch_chain_voting_pkt_t *a_voting_pkt)
{
UNUSED(a_worker);
s_callback_send_all_unsafe((dap_client_t *)a_arg, NULL);
}
void dap_stream_ch_chain_voting_pkt_broadcast(dap_chain_net_t *a_net, dap_list_t *a_sendto_nodes)
{
bool l_send_loop = false;
dap_list_t *l_nodes_list_temp = dap_list_first(a_sendto_nodes);
while(l_nodes_list_temp) {
dap_list_t *l_nodes_list = l_nodes_list_temp;
l_nodes_list_temp = l_nodes_list_temp->next;
dap_chain_node_addr_t *l_remote_node_addr = (dap_chain_node_addr_t *)l_nodes_list->data;
voting_node_client_list_t *l_node_item = NULL;
if ( l_remote_node_addr->uint64 != dap_chain_net_get_cur_addr_int(a_net) ) {
HASH_FIND(hh, s_node_client_list, l_remote_node_addr, sizeof(dap_chain_node_addr_t), l_node_item);
if (l_node_item) {
dap_chain_node_client_t *l_usable = dap_chain_node_client_find(l_node_item->uuid);
if (l_usable && !dap_client_get_stream(l_usable->client)) {
dap_chain_node_client_close(l_node_item->uuid);
l_usable = NULL;
}
if (!l_usable) {
char l_channels[] = {dap_stream_ch_chain_voting_get_id(),0};
l_node_item->node_client = dap_chain_node_client_connect_channels(a_net, l_node_item->node_info, l_channels);
l_node_item->uuid = l_node_item->node_client->uuid;
}
} else {
size_t node_info_size = 0;
char *l_key = dap_chain_node_addr_to_hash_str(l_remote_node_addr);
dap_chain_node_info_t *l_node_info =
(dap_chain_node_info_t *)dap_global_db_get_sync(a_net->pub.gdb_nodes, l_key,
&node_info_size, NULL, NULL);
DAP_DELETE(l_key);
if (!l_node_info) {
continue;
}
char l_channels[] = {dap_stream_ch_chain_voting_get_id(),0};
dap_chain_node_client_t *l_node_client = dap_chain_node_client_connect_channels(a_net, l_node_info, l_channels);
if (!l_node_client) {
continue;
}
voting_node_client_list_t *l_node_client_item = DAP_NEW_Z(voting_node_client_list_t);
l_node_client_item->node_addr = *l_remote_node_addr;
l_node_client_item->node_info = l_node_info;
l_node_client_item->node_client = l_node_client;
l_node_client_item->uuid = l_node_client->uuid;
HASH_ADD(hh, s_node_client_list, node_addr, sizeof(dap_chain_node_addr_t), l_node_client_item);
l_node_item = l_node_client_item;
size_t l_voting_pkt_size = sizeof(*a_voting_pkt) + a_voting_pkt->hdr.data_size;
struct voting_node_client_list *l_node_client_item = NULL;
if (a_remote_node_addr->uint64 != dap_chain_net_get_cur_addr_int(a_net)) {
HASH_FIND(hh, s_node_client_list, a_remote_node_addr, sizeof(dap_chain_node_addr_t), l_node_client_item);
if (!l_node_client_item) {
size_t node_info_size = 0;
char *l_key = dap_chain_node_addr_to_hash_str(a_remote_node_addr);
dap_chain_node_info_t *l_node_info =
(dap_chain_node_info_t *)dap_global_db_get_sync(a_net->pub.gdb_nodes, l_key,
&node_info_size, NULL, NULL);
DAP_DELETE(l_key);
if (!l_node_info) {
log_it(L_WARNING, "Can't find validator's addr "NODE_ADDR_FP_STR" in database", NODE_ADDR_FP_ARGS(a_remote_node_addr));
return;
}
if ( !l_node_item || !l_node_item->node_client ) {
continue;
char l_channels[] = {dap_stream_ch_chain_voting_get_id(),0};
dap_chain_node_client_t *l_node_client = dap_chain_node_client_connect_channels(a_net, l_node_info, l_channels);
if (!l_node_client || !l_node_client->client) {
log_it(L_ERROR, "Can't connect to remote node "NODE_ADDR_FP_STR, NODE_ADDR_FP_ARGS(a_remote_node_addr));
return;
}
dap_client_pvt_t * l_client_pvt = dap_client_pvt_find(l_node_item->node_client->client->pvt_uuid);
if (NULL == l_client_pvt) {
continue;
}
pthread_rwlock_wrlock(&s_pkt_items->rwlock_out);
dap_list_t* l_pkts_list_temp = s_pkt_items->pkts_out;
while(l_pkts_list_temp) {
dap_list_t *l_pkts_list = l_pkts_list_temp;
l_pkts_list_temp = l_pkts_list_temp->next;
voting_pkt_addr_t * l_pkt_addr = (voting_pkt_addr_t *)l_pkts_list->data;
if (!l_pkt_addr->node_addr.uint64) {
voting_pkt_addr_t * l_pkt_addr_new = DAP_NEW(voting_pkt_addr_t);
l_pkt_addr_new->node_addr.uint64 = l_remote_node_addr->uint64;
l_pkt_addr_new->voting_pkt = DAP_DUP_SIZE(l_pkt_addr->voting_pkt,
l_pkt_addr->voting_pkt->hdr.data_size+sizeof(dap_stream_ch_chain_voting_pkt_hdr_t));
l_pkt_addr_new->voting_pkt->hdr.sender_node_addr.uint64 = dap_chain_net_get_cur_addr_int(a_net);
l_pkt_addr_new->voting_pkt->hdr.recipient_node_addr.uint64 = l_remote_node_addr->uint64;
s_pkt_items->pkts_out = dap_list_append(s_pkt_items->pkts_out, l_pkt_addr_new);
}
}
pthread_rwlock_unlock(&s_pkt_items->rwlock_out);
l_node_client->client->connect_on_demand = true;
if (dap_client_get_stage(l_node_item->node_client->client) != STAGE_STREAM_STREAMING)
dap_client_go_stage(l_node_item->node_client->client, STAGE_STREAM_STREAMING, s_callback_send_all_unsafe);
else {
dap_stream_t *l_stream = dap_client_get_stream(l_node_item->node_client->client);
dap_worker_exec_callback_on(l_stream->stream_worker->worker, s_callback_send_all_unsafe_on_worker,
l_node_item->node_client->client);
}
} else
l_send_loop = true;
}
s_callback_send_all_loopback(l_send_loop ? dap_chain_net_get_cur_addr_int(a_net) : 0);
}
static void s_callback_send_all_loopback(uint64_t a_node_addr)
{
pthread_rwlock_wrlock(&s_pkt_items->rwlock_out);
dap_list_t* l_pkts_list = s_pkt_items->pkts_out;
while (l_pkts_list) {
dap_list_t *l_pkts_list_next = l_pkts_list->next;
voting_pkt_addr_t *l_pkt_addr = (voting_pkt_addr_t *)l_pkts_list->data;
if (l_pkt_addr->node_addr.uint64 == 0) {
if (a_node_addr) {
l_pkt_addr->voting_pkt->hdr.sender_node_addr.uint64 =
l_pkt_addr->voting_pkt->hdr.recipient_node_addr.uint64 =
a_node_addr;
pthread_rwlock_wrlock(&s_pkt_items->rwlock_in);
s_pkt_items->pkts_in = dap_list_append(s_pkt_items->pkts_in, l_pkt_addr->voting_pkt);
pthread_rwlock_unlock(&s_pkt_items->rwlock_in);
} else
DAP_DELETE(l_pkt_addr->voting_pkt);
DAP_DELETE(l_pkt_addr);
s_pkt_items->pkts_out = dap_list_delete_link(s_pkt_items->pkts_out, l_pkts_list);
l_node_client_item = DAP_NEW_Z(struct voting_node_client_list);
l_node_client_item->node_addr = *a_remote_node_addr;
l_node_client_item->node_info = l_node_info;
l_node_client_item->node_client = l_node_client;
HASH_ADD(hh, s_node_client_list, node_addr, sizeof(dap_chain_node_addr_t), l_node_client_item);
}
l_pkts_list = l_pkts_list_next;
}
pthread_rwlock_unlock(&s_pkt_items->rwlock_out);
}
static void s_callback_send_all_unsafe(dap_client_t *a_client, void *a_arg)
{
UNUSED(a_arg);
pthread_rwlock_wrlock(&s_pkt_items->rwlock_out);
dap_chain_node_client_t *l_node_client = DAP_CHAIN_NODE_CLIENT(a_client);
if (l_node_client) {
dap_stream_ch_t * l_ch = dap_client_get_stream_ch_unsafe(a_client, dap_stream_ch_chain_voting_get_id() );
if (l_ch) {
dap_list_t* l_pkts_list = s_pkt_items->pkts_out;
while(l_pkts_list) {
dap_list_t *l_pkts_list_next = l_pkts_list->next;
voting_pkt_addr_t *l_pkt_addr = (voting_pkt_addr_t *)l_pkts_list->data;
dap_stream_ch_chain_voting_pkt_t * l_voting_pkt = l_pkt_addr->voting_pkt;
size_t l_voting_pkt_size = sizeof(l_voting_pkt->hdr) + l_voting_pkt->hdr.data_size;
if ( l_pkt_addr->node_addr.uint64 == l_node_client->remote_node_addr.uint64 ) {
if (l_ch) {
dap_stream_ch_pkt_write_unsafe(l_ch,
l_voting_pkt->hdr.pkt_type, l_voting_pkt, l_voting_pkt_size);
log_it(L_DEBUG, "Sent pkt size %zu to addr "NODE_ADDR_FP_STR, l_voting_pkt_size,
NODE_ADDR_FP_ARGS_S(l_node_client->remote_node_addr));
}
DAP_DELETE(l_voting_pkt);
DAP_DELETE(l_pkt_addr);
s_pkt_items->pkts_out = dap_list_delete_link(s_pkt_items->pkts_out, l_pkts_list);
}
l_pkts_list = l_pkts_list_next;
}
if (!l_node_client_item->node_client) {
log_it(L_ERROR, "NULL node_client in item of voting channel");
return;
}
}
pthread_rwlock_unlock(&s_pkt_items->rwlock_out);
dap_chain_node_client_write_mt(l_node_client_item->node_client, dap_stream_ch_chain_voting_get_id(),
DAP_STREAM_CH_CHAIN_VOTING_PKT_TYPE_DATA, a_voting_pkt,
l_voting_pkt_size);
} else
dap_proc_queue_add_callback(dap_events_worker_get_auto(), s_callback_pkt_in_call_all,
DAP_DUP_SIZE(a_voting_pkt, l_voting_pkt_size));
}
void dap_stream_ch_chain_voting_deinit() {
voting_node_client_list_t *l_node_info_item=NULL, *l_node_info_tmp=NULL;
struct voting_node_client_list *l_node_info_item, *l_node_info_tmp;
HASH_ITER(hh, s_node_client_list, l_node_info_item, l_node_info_tmp) {
// Clang bug at this, l_node_info_item should change at every loop cycle
HASH_DEL(s_node_client_list, l_node_info_item);
DAP_DELETE(l_node_info_item->node_client);
dap_chain_node_client_close_mt(l_node_info_item->node_client);
DAP_DELETE(l_node_info_item);
}
}
static void s_stream_ch_new(dap_stream_ch_t* a_ch, void* a_arg) {
static void s_stream_ch_new(dap_stream_ch_t *a_ch, void *a_arg) {
UNUSED(a_arg);
a_ch->internal = DAP_NEW_Z(dap_stream_ch_chain_voting_t);
dap_stream_ch_chain_voting_t * l_ch_chain_voting = DAP_STREAM_CH_CHAIN_VOTING(a_ch);
l_ch_chain_voting->ch = a_ch;
dap_stream_ch_chain_voting_t *l_ch_chain_voting = DAP_STREAM_CH_CHAIN_VOTING(a_ch);
l_ch_chain_voting->_inheritor = a_ch;
}
static void s_stream_ch_delete(dap_stream_ch_t* a_ch, void* a_arg)
static void s_stream_ch_delete(dap_stream_ch_t *a_ch, UNUSED_ARG void *a_arg)
{
DAP_DEL_Z(a_ch->internal);
}
static void s_packet_in_callback_handler(void *a_arg)
static void s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg)
{
UNUSED(a_arg);
pthread_rwlock_wrlock(&s_pkt_items->rwlock_in);
if (s_pkt_items->pkts_in) {
dap_list_t* l_list_pkts = dap_list_copy(s_pkt_items->pkts_in);
dap_list_free(s_pkt_items->pkts_in);
s_pkt_items->pkts_in = NULL;
pthread_rwlock_unlock(&s_pkt_items->rwlock_in);
while(l_list_pkts) {
dap_stream_ch_chain_voting_pkt_t * l_voting_pkt = (dap_stream_ch_chain_voting_pkt_t *)l_list_pkts->data;
for (size_t i=0; i<s_pkt_in_callback_count; i++) {
voting_pkt_in_callback_t * l_callback = s_pkt_in_callback+i;
if (l_callback->packet_in_callback) {
l_callback->packet_in_callback(l_callback->arg, &l_voting_pkt->hdr.sender_node_addr,
&l_voting_pkt->hdr.data_hash, l_voting_pkt->data, l_voting_pkt->hdr.data_size);
}
}
DAP_DELETE(l_voting_pkt);
l_list_pkts = l_list_pkts->next;
}
dap_list_free(l_list_pkts);
} else {
pthread_rwlock_unlock(&s_pkt_items->rwlock_in);
}
}
static void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
{
dap_stream_ch_pkt_t * l_ch_pkt = (dap_stream_ch_pkt_t *) a_arg;
dap_stream_ch_pkt_t *l_ch_pkt = (dap_stream_ch_pkt_t *) a_arg;
if (!l_ch_pkt)
return;
pthread_rwlock_wrlock(&s_pkt_items->rwlock_in);
size_t l_voting_pkt_size = l_ch_pkt->hdr.size;
size_t l_voting_pkt_size = l_ch_pkt->hdr.data_size;
if (!l_voting_pkt_size || l_voting_pkt_size > UINT16_MAX)
return;
dap_stream_ch_chain_voting_pkt_t *l_voting_pkt = DAP_DUP_SIZE(&l_ch_pkt->data, l_voting_pkt_size);
s_pkt_items->pkts_in = dap_list_append(s_pkt_items->pkts_in, l_voting_pkt);
pthread_rwlock_unlock(&s_pkt_items->rwlock_in);
}
static void s_stream_ch_packet_out(dap_stream_ch_t* a_ch, void* a_arg) {
UNUSED(a_arg);
dap_stream_ch_chain_voting_pkt_t *l_voting_pkt = (dap_stream_ch_chain_voting_pkt_t *)l_ch_pkt->data;
dap_proc_queue_add_callback(a_ch->stream_worker->worker, s_callback_pkt_in_call_all,
DAP_DUP_SIZE(l_voting_pkt, l_voting_pkt_size));
dap_stream_ch_chain_voting_t *l_ch_chain_voting = DAP_STREAM_CH_CHAIN_VOTING(a_ch);
if (l_ch_chain_voting->callback_notify)
l_ch_chain_voting->callback_notify(l_ch_chain_voting, l_ch_pkt->hdr.type, l_voting_pkt,
l_voting_pkt->hdr.data_size, l_ch_chain_voting->callback_notify_arg);
}
dap_stream_ch_chain_voting_pkt_t *dap_stream_ch_chain_voting_pkt_new(uint64_t a_net_id, const void *a_data, size_t a_data_size)
{
dap_stream_ch_chain_voting_pkt_t *l_voting_pkt = DAP_NEW_Z_SIZE(dap_stream_ch_chain_voting_pkt_t,
sizeof(dap_stream_ch_chain_voting_pkt_t) + a_data_size);
l_voting_pkt->hdr.data_size = a_data_size;
l_voting_pkt->hdr.version = 1;
l_voting_pkt->hdr.net_id.uint64 = a_net_id;
dap_hash_fast(a_data, a_data_size, &l_voting_pkt->hdr.data_hash);
if (a_data_size && a_data)
memcpy(l_voting_pkt->data, a_data, a_data_size);
return l_voting_pkt;
}
size_t dap_stream_ch_chain_voting_pkt_write_unsafe(dap_stream_ch_t *a_ch, uint8_t a_type, uint64_t a_net_id,
const void * a_data, size_t a_data_size)
{
dap_stream_ch_chain_voting_pkt_t * l_chain_pkt;
size_t l_chain_pkt_size = sizeof (l_chain_pkt->hdr) + a_data_size;
l_chain_pkt = DAP_NEW_Z_SIZE(dap_stream_ch_chain_voting_pkt_t, l_chain_pkt_size );
l_chain_pkt->hdr.data_size = a_data_size;
l_chain_pkt->hdr.pkt_type = a_type;
l_chain_pkt->hdr.version = 1;
l_chain_pkt->hdr.net_id.uint64 = a_net_id;
if (a_data_size && a_data)
memcpy( &l_chain_pkt->data, a_data, a_data_size);
size_t l_ret = dap_stream_ch_pkt_write_unsafe(a_ch, a_type , l_chain_pkt, l_chain_pkt_size);
DAP_DELETE(l_chain_pkt);
dap_stream_ch_chain_voting_pkt_t *l_voting_pkt = dap_stream_ch_chain_voting_pkt_new(a_net_id, a_data, a_data_size);
size_t l_ret = dap_stream_ch_pkt_write_unsafe(a_ch, a_type, l_voting_pkt, sizeof(l_voting_pkt) + a_data_size);
DAP_DELETE(l_voting_pkt);
return l_ret;
}
......@@ -10,40 +10,19 @@
// #include "dap_stream_ch_chain_pkt.h"
#include "uthash.h"
#define DAP_STREAM_CH_CHAIN_VOTING_PKT_TYPE_TEST 0x01
#define DAP_STREAM_CH_CHAIN_VOTING_PKT_TYPE_TEST_RES 0x02
typedef void (*voting_ch_callback_t) (void*,dap_chain_node_addr_t*,dap_chain_hash_fast_t*,uint8_t*,size_t);
// typedef struct dap_stream_ch_chain_pkt_hdr{
// union{
// struct{
// uint8_t version;
// uint8_t padding[7];
// } DAP_ALIGN_PACKED;
// uint64_t ext_id;
// }DAP_ALIGN_PACKED;
// dap_chain_net_id_t net_id;
// dap_chain_id_t chain_id;
// dap_chain_cell_id_t cell_id;
// } DAP_ALIGN_PACKED dap_stream_ch_chain_pkt_hdr_t;
#define DAP_STREAM_CH_CHAIN_VOTING_PKT_TYPE_DATA 0x01
#define DAP_STREAM_CH_CHAIN_VOTING_PKT_TYPE_TEST 0x02
typedef void (*dap_chain_voting_ch_callback_t)(void *a_arg, dap_chain_node_addr_t *a_addr, dap_chain_hash_fast_t *a_data_hash, uint8_t *a_data, size_t a_data_size);
typedef struct dap_stream_ch_chain_voting_pkt_hdr {
uint8_t pkt_type;
union{
struct{
uint8_t version;
uint8_t padding[7];
} DAP_ALIGN_PACKED;
uint64_t ext_id;
}DAP_ALIGN_PACKED;
size_t data_size;
uint8_t version;
uint8_t padding[7];
uint64_t data_size;
dap_chain_hash_fast_t data_hash;
dap_chain_net_id_t net_id;
dap_chain_node_addr_t sender_node_addr;
dap_chain_node_addr_t recipient_node_addr;
// dap_chain_id_t chain_id;
// dap_chain_cell_id_t cell_id;
dap_chain_node_addr_t receiver_node_addr;
} DAP_ALIGN_PACKED dap_stream_ch_chain_voting_pkt_hdr_t;
typedef struct dap_stream_ch_chain_voting_pkt {
......@@ -53,24 +32,12 @@ typedef struct dap_stream_ch_chain_voting_pkt {
typedef struct dap_stream_ch_chain_voting dap_stream_ch_chain_voting_t;
typedef void (*dap_stream_ch_chain_voting_callback_packet_t)(dap_stream_ch_chain_voting_t*, uint8_t a_pkt_type,
typedef void (*dap_stream_ch_chain_voting_callback_packet_t)(dap_stream_ch_chain_voting_t *a_ch_voting, uint8_t a_pkt_type,
dap_stream_ch_chain_voting_pkt_t *a_pkt, size_t a_pkt_data_size,
void * a_arg);
typedef struct dap_stream_ch_chain_voting {
//void *_inheritor;
dap_stream_ch_t * ch;
//dap_stream_ch_chain_state_t state;
dap_chain_node_client_t * node_client; // Node client associated with stream
// request section
//dap_stream_ch_chain_sync_request_t request;
//dap_stream_ch_chain_pkt_hdr_t request_hdr;
//dap_list_t *request_db_iter;
//bool was_active;
//dap_stream_ch_chain_voting_callback_packet_t callback_notify_packet_out;
void *_inheritor; // parent stream ch
dap_stream_ch_chain_voting_callback_packet_t callback_notify;
void *callback_notify_arg;
} dap_stream_ch_chain_voting_t;
......@@ -79,16 +46,12 @@ typedef struct dap_stream_ch_chain_voting {
inline static uint8_t dap_stream_ch_chain_voting_get_id(void) { return (uint8_t) 'V'; }
void dap_stream_ch_chain_voting_in_callback_add(void* a_arg, voting_ch_callback_t packet_in_callback);
void dap_stream_ch_chain_voting_in_callback_add(void* a_arg, dap_chain_voting_ch_callback_t packet_in_callback);
void dap_stream_ch_chain_voting_message_write(dap_chain_net_t * a_net, dap_list_t *a_sendto_nodes,
dap_chain_hash_fast_t * a_data_hash,
const void * a_data, size_t a_data_size);
void dap_stream_ch_chain_voting_pkt_broadcast(dap_chain_net_t * a_net, dap_list_t *a_sendto_nodes);
void dap_stream_ch_chain_voting_message_write(dap_chain_net_t * a_net, dap_chain_node_addr_t *a_remote_node_addr,
dap_stream_ch_chain_voting_pkt_t *a_voting_pkt);
// size_t dap_stream_ch_chain_voting_pkt_write_mt(dap_stream_worker_t *a_worker, dap_stream_ch_uuid_t a_ch_uuid,
// uint8_t a_type,uint64_t a_net_id,
// const void * a_data, size_t a_data_size);
dap_stream_ch_chain_voting_pkt_t *dap_stream_ch_chain_voting_pkt_new(uint64_t a_net_id, const void *a_data, size_t a_data_size);
size_t dap_stream_ch_chain_voting_pkt_write_unsafe(dap_stream_ch_t *a_ch, uint8_t a_type, uint64_t a_net_id,
const void * a_data, size_t a_data_size);
......
......@@ -545,6 +545,7 @@ static bool s_sync_in_chains_callback(dap_proc_thread_t *a_thread, void *a_arg)
dap_chain_hash_fast_t l_atom_hash = {};
if (l_pkt_item->pkt_data_size == 0 || !l_pkt_item->pkt_data) {
log_it(L_CRITICAL, "In proc thread got CHAINS stream ch packet with zero data");
DAP_DEL_Z(l_pkt_item->pkt_data);
DAP_DELETE(l_sync_request);
return true;
}
......@@ -970,14 +971,14 @@ static bool s_chain_timer_callback(void *a_arg)
s_stream_ch_packet_out(l_ch, NULL);
// Sending dumb packet with nothing to inform remote thats we're just skiping atoms of GDB's, nothing freezed
if (l_ch_chain->state == CHAIN_STATE_SYNC_CHAINS && l_ch_chain->sent_breaks >= 3 * DAP_SYNC_TICKS_PER_SECOND) {
debug_if(s_debug_more, L_INFO, "Send one chain TSD packet");
dap_stream_ch_chain_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_CHAINS_TSD,
l_ch_chain->request_hdr.net_id.uint64, l_ch_chain->request_hdr.chain_id.uint64,
l_ch_chain->request_hdr.cell_id.uint64, NULL, 0);
l_ch_chain->sent_breaks = 0;
}
if (l_ch_chain->state == CHAIN_STATE_SYNC_GLOBAL_DB && l_ch_chain->sent_breaks >= 3 * DAP_SYNC_TICKS_PER_SECOND) {
if (s_debug_more)
log_it(L_INFO, "Send one global_db TSD packet (rest=%zu/%zu items)",
debug_if(s_debug_more, L_INFO, "Send one global_db TSD packet (rest=%zu/%zu items)",
dap_db_log_list_get_count_rest(l_ch_chain->request_db_log),
dap_db_log_list_get_count(l_ch_chain->request_db_log));
dap_stream_ch_chain_pkt_write_unsafe(l_ch, DAP_STREAM_CH_CHAIN_PKT_TYPE_UPDATE_GLOBAL_DB_TSD,
......@@ -1022,12 +1023,12 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg)
log_it(L_ERROR, "No chain packet in channel packet, returning");
return;
}
if (l_ch_pkt->hdr.size < sizeof (l_chain_pkt->hdr)){
log_it(L_ERROR, "Corrupted packet: too small size %u, smaller then header size %zu", l_ch_pkt->hdr.size,
if (l_ch_pkt->hdr.data_size < sizeof (l_chain_pkt->hdr)){
log_it(L_ERROR, "Corrupted packet: too small size %u, smaller then header size %zu", l_ch_pkt->hdr.data_size,
sizeof(l_chain_pkt->hdr));
return;
}
size_t l_chain_pkt_data_size = l_ch_pkt->hdr.size-sizeof (l_chain_pkt->hdr);
size_t l_chain_pkt_data_size = l_ch_pkt->hdr.data_size - sizeof(l_chain_pkt->hdr);
dap_chain_net_t *l_net = dap_chain_net_by_id(l_chain_pkt->hdr.net_id);
if (!l_net) {
if (l_ch_pkt->hdr.type == DAP_STREAM_CH_CHAIN_PKT_TYPE_ERROR) {
......@@ -1655,10 +1656,12 @@ static void s_stream_ch_io_complete(dap_events_socket_t *a_es, void *a_arg, int
if (a_errno)
return;
dap_stream_t *l_stream = NULL;
dap_client_pvt_t *l_client_pvt = DAP_ESOCKET_CLIENT_PVT(a_es);
if (l_client_pvt && dap_client_pvt_find(l_client_pvt->uuid) == l_client_pvt)
if (!a_es->server) {
dap_client_t *l_client = DAP_ESOCKET_CLIENT(a_es);
assert(l_client);
dap_client_pvt_t *l_client_pvt = DAP_CLIENT_PVT(l_client);
l_stream = l_client_pvt->stream;
else {
} else {
dap_http_client_t *l_http_client = DAP_HTTP_CLIENT(a_es);
if (l_http_client)
l_stream = DAP_STREAM(l_http_client);
......
......@@ -38,6 +38,7 @@
#define LOG_TAG "dap_chain_common"
const dap_chain_net_srv_uid_t c_dap_chain_net_srv_uid_null = {0};
const dap_chain_cell_id_t c_dap_chain_cell_id_null = {0};
/*
* Forward declarations
......@@ -173,19 +174,30 @@ dap_chain_net_srv_uid_t dap_chain_net_srv_uid_from_str( const char * a_net_srv_u
* @param a_net_id
* @return
*/
void dap_chain_addr_fill_from_key(dap_chain_addr_t *a_addr, dap_enc_key_t *a_key, dap_chain_net_id_t a_net_id) {
int dap_chain_addr_fill_from_key(dap_chain_addr_t *a_addr, dap_enc_key_t *a_key, dap_chain_net_id_t a_net_id)
{
dap_sign_type_t l_type = dap_sign_type_from_key_type(a_key->type);
size_t l_pub_key_data_size;
uint8_t *l_pub_key_data = dap_enc_key_serealize_pub_key(a_key, &l_pub_key_data_size);
if (!l_pub_key_data) {
log_it(L_ERROR,"Can't fill address from key, its empty");
return;
return -1;
}
dap_chain_hash_fast_t l_hash_public_key;
// serialized key -> key hash
dap_hash_fast(l_pub_key_data, l_pub_key_data_size, &l_hash_public_key);
dap_chain_addr_fill(a_addr, l_type, &l_hash_public_key, a_net_id);
DAP_DELETE(l_pub_key_data);
return 0;
}
int dap_chain_addr_fill_from_sign(dap_chain_addr_t *a_addr, dap_sign_t *a_sign, dap_chain_net_id_t a_net_id)
{
dap_hash_fast_t l_sign_pkey_hash;
if (!dap_sign_get_pkey_hash(a_sign, &l_sign_pkey_hash))
return -1;
dap_chain_addr_fill(a_addr, a_sign->header.type, &l_sign_pkey_hash, a_net_id);
return 0;
}
/**
......@@ -226,6 +238,8 @@ int dap_chain_addr_check_sum(const dap_chain_addr_t *a_addr)
return -1;
}
uint64_t dap_chain_uint128_to(uint128_t a_from)
{
#ifdef DAP_GLOBAL_IS_INT128
......
......@@ -29,6 +29,7 @@
#include "dap_chain_datum_tx.h"
#include "dap_chain_datum_token.h"
#include "dap_chain_datum_tx_items.h"
#include "dap_chain_datum_decree.h"
#include "dap_chain_datum_hashtree_roots.h"
#include "dap_enc_base58.h"
......@@ -275,40 +276,40 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum,
DAP_DELETE(l_coins_str);
DAP_DELETE(l_addr_str);
} break;
case TX_ITEM_TYPE_TOKEN: {
l_hash_tmp = &((dap_chain_tx_token_t*)item)->header.token_emission_hash;
case TX_ITEM_TYPE_IN_EMS: {
l_hash_tmp = &((dap_chain_tx_in_ems_t*)item)->header.token_emission_hash;
if (!dap_strcmp(a_hash_out_type, "hex"))
l_hash_str = dap_chain_hash_fast_to_str_new(l_hash_tmp);
else
l_hash_str = dap_enc_base58_encode_hash_to_str(l_hash_tmp);
dap_string_append_printf(a_str_out, "\t TOKEN:\n"
dap_string_append_printf(a_str_out, "\t IN_EMS:\n"
"\t\t ticker: %s \n"
"\t\t token_emission_hash: %s\n"
"\t\t token_emission_chain_id: 0x%016"DAP_UINT64_FORMAT_x"\n",
((dap_chain_tx_token_t*)item)->header.ticker,
((dap_chain_tx_in_ems_t*)item)->header.ticker,
l_hash_str,
((dap_chain_tx_token_t*)item)->header.token_emission_chain_id.uint64);
((dap_chain_tx_in_ems_t*)item)->header.token_emission_chain_id.uint64);
DAP_DELETE(l_hash_str);
} break;
case TX_ITEM_TYPE_TOKEN_EXT: {
l_hash_tmp = &((dap_chain_tx_token_ext_t*)item)->header.ext_tx_hash;
case TX_ITEM_TYPE_IN_EMS_EXT: {
l_hash_tmp = &((dap_chain_tx_in_ems_ext_t*)item)->header.ext_tx_hash;
if (!dap_strcmp(a_hash_out_type, "hex"))
l_hash_str = dap_chain_hash_fast_to_str_new(l_hash_tmp);
else
l_hash_str = dap_enc_base58_encode_hash_to_str(l_hash_tmp);
dap_string_append_printf(a_str_out, "\t TOKEN EXT:\n"
dap_string_append_printf(a_str_out, "\t IN_EMS EXT:\n"
"\t\t Version: %u\n"
"\t\t Ticker: %s\n"
"\t\t Ext chain id: 0x%016"DAP_UINT64_FORMAT_x"\n"
"\t\t Ext net id: 0x%016"DAP_UINT64_FORMAT_x"\n"
"\t\t Ext tx hash: %s\n"
"\t\t Ext tx out idx: %u\n",
((dap_chain_tx_token_ext_t*)item)->header.version,
((dap_chain_tx_token_ext_t*)item)->header.ticker,
((dap_chain_tx_token_ext_t*)item)->header.ext_chain_id.uint64,
((dap_chain_tx_token_ext_t*)item)->header.ext_net_id.uint64,
((dap_chain_tx_in_ems_ext_t*)item)->header.version,
((dap_chain_tx_in_ems_ext_t*)item)->header.ticker,
((dap_chain_tx_in_ems_ext_t*)item)->header.ext_chain_id.uint64,
((dap_chain_tx_in_ems_ext_t*)item)->header.ext_net_id.uint64,
l_hash_str,
((dap_chain_tx_token_ext_t*)item)->header.ext_tx_out_idx);
((dap_chain_tx_in_ems_ext_t*)item)->header.ext_tx_out_idx);
DAP_DELETE(l_hash_str);
} break;
case TX_ITEM_TYPE_SIG: {
......@@ -544,6 +545,7 @@ void dap_chain_datum_dump(dap_string_t *a_str_out, dap_chain_datum_t *a_datum, c
if(l_token_size < sizeof(dap_chain_datum_token_t)){
dap_string_append_printf(a_str_out,"==Datum has incorrect size. Only %zu, while at least %zu is expected\n",
l_token_size, sizeof(dap_chain_datum_token_t));
DAP_DEL_Z(l_token);
return;
}
dap_string_append_printf(a_str_out,"=== Datum Token Declaration ===\n");
......@@ -625,6 +627,7 @@ void dap_chain_datum_dump(dap_string_t *a_str_out, dap_chain_datum_t *a_datum, c
default:
dap_string_append(a_str_out,"type: UNKNOWN\n");
}
DAP_DELETE(l_token);
} break;
case DAP_CHAIN_DATUM_TOKEN_EMISSION: {
size_t l_emisssion_size = a_datum->header.data_size;
......@@ -693,6 +696,50 @@ void dap_chain_datum_dump(dap_string_t *a_str_out, dap_chain_datum_t *a_datum, c
dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)a_datum->data;
dap_chain_datum_dump_tx(l_tx, NULL, a_str_out, a_hash_out_type, &l_datum_hash);
} break;
}
case DAP_CHAIN_DATUM_DECREE:{
dap_chain_datum_decree_t *l_decree = (dap_chain_datum_decree_t *)a_datum->data;
size_t l_decree_size = sizeof(dap_chain_datum_decree_t) + l_decree->header.data_size + l_decree->header.signs_size;
dap_string_append_printf(a_str_out,"=== Datum decree ===\n");
dap_string_append_printf(a_str_out, "hash: %s\n", l_hash_str);
dap_string_append_printf(a_str_out, "size: %zd\n", l_decree_size);
char *l_type_str = "";
switch(l_decree->header.type)
{
case DAP_CHAIN_DATUM_DECREE_TYPE_COMMON:
l_type_str = "DECREE_TYPE_COMMON";
break;
case DAP_CHAIN_DATUM_DECREE_TYPE_SERVICE:
l_type_str = "DECREE_TYPE_SERVICE";
break;
default:
l_type_str = "DECREE_TYPE_UNKNOWN";
}
dap_string_append_printf(a_str_out, "type: %s\n", l_type_str);
char *l_subtype_str = "";
switch(l_decree->header.type)
{
case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_FEE:
l_subtype_str = "DECREE_COMMON_SUBTYPE_FEE";
break;
case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_OWNERS:
l_subtype_str = "DECREE_COMMON_SUBTYPE_OWNERS";
break;
case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_OWNERS_MIN:
l_subtype_str = "DECREE_COMMON_SUBTYPE_OWNERS_MIN";
break;
case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_TON_SIGNERS_MIN:
l_subtype_str = "DECREE_COMMON_SUBTYPE_TON_SIGNERS_MIN";
break;
default:
l_subtype_str = "DECREE_TYPE_UNKNOWN";
}
dap_string_append_printf(a_str_out, "subtype: %s\n", l_subtype_str);
dap_chain_datum_decree_certs_dump(a_str_out, l_decree->data_n_signs + l_decree->header.data_size, l_decree->header.signs_size, a_hash_out_type);
} break;
}
DAP_DELETE(l_hash_str);
}
/*
* Authors:
* Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
* Frolov Daniil <daniil.frolov@demlabs.net>
* DeM Labs Inc. https://demlabs.net
* Copyright (c) 2020, All rights reserved.
......@@ -19,3 +19,157 @@
You should have received a copy of the GNU General Public License
along with any CellFrame SDK based project. If not, see <http://www.gnu.org/licenses/>.
*/
#include <memory.h>
#include <assert.h>
#include "dap_tsd.h"
#include "dap_sign.h"
#include "dap_common.h"
#include "dap_chain_datum_decree.h"
#include "dap_enc_base58.h"
#define LOG_TAG "dap_chain_datum_decree"
dap_sign_t *dap_chain_datum_decree_get_signs(dap_chain_datum_decree_t *a_decree, size_t* a_signs_size)
{
if (!a_decree)
return NULL;
dap_sign_t *l_signs_section = (dap_sign_t *)((byte_t*)a_decree->data_n_signs + a_decree->header.data_size);
*a_signs_size = a_decree->header.signs_size;
return l_signs_section;
}
int dap_chain_datum_decree_get_fee(dap_chain_datum_decree_t *a_decree, uint256_t *a_fee_value)
{
size_t l_tsd_offset = 0, tsd_data_size = a_decree->header.data_size;
if(!a_decree || !a_fee_value){
log_it(L_WARNING,"Wrong arguments");
return -1;
}
while(l_tsd_offset < tsd_data_size){
dap_tsd_t *l_tsd = (dap_tsd_t*)a_decree->data_n_signs + l_tsd_offset;
size_t l_tsd_size = l_tsd->size + sizeof(dap_tsd_t);
if(l_tsd_size > tsd_data_size){
log_it(L_WARNING,"TSD size is greater than all data size. It's possible corrupt data.");
return -1;
}
if (l_tsd->type == DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE){
if(l_tsd->size > sizeof(uint256_t)){
log_it(L_WARNING,"Wrong fee tsd data size.");
return -1;
}
*a_fee_value = dap_tsd_get_scalar(l_tsd, uint256_t);
return 0;
}
l_tsd_offset += l_tsd_size;
}
return 1;
}
dap_list_t *dap_chain_datum_decree_get_owners(dap_chain_datum_decree_t *a_decree, uint256_t *a_owners_num)
{
size_t l_tsd_offset = 0, tsd_data_size = a_decree->header.data_size;
uint64_t l_owners_num = 0;
dap_list_t *l_key_list = NULL;
if(!a_decree || !a_owners_num){
log_it(L_WARNING,"Wrong arguments");
return NULL;
}
while(l_tsd_offset < tsd_data_size){
dap_tsd_t *l_tsd = (dap_tsd_t*)((byte_t*)a_decree->data_n_signs + l_tsd_offset);
size_t l_tsd_size = dap_tsd_size(l_tsd);
if(l_tsd_size > tsd_data_size){
log_it(L_WARNING,"TSD size is greater than all data size. It's possible corrupt data.");
if (l_key_list)
dap_list_free_full(l_key_list, NULL);
return NULL;
}
if (l_tsd->type == DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER){
dap_pkey_t *l_owner_pkey = DAP_NEW_Z_SIZE(dap_pkey_t, l_tsd->size);
if (!l_owner_pkey){
log_it(L_WARNING,"Memory allocate failed.");
dap_list_free_full(l_key_list, NULL);
return NULL;
}
memcpy(l_owner_pkey, l_tsd->data, l_tsd->size);
l_key_list = dap_list_append(l_key_list, l_owner_pkey);
l_owners_num++;
}
l_tsd_offset += l_tsd_size;
}
*a_owners_num = GET_256_FROM_64(l_owners_num);
return l_key_list;
}
int dap_chain_datum_decree_get_min_owners(dap_chain_datum_decree_t *a_decree, uint256_t *a_min_owners_num)
{
size_t l_tsd_offset = 0, tsd_data_size = a_decree->header.data_size;
if(!a_decree || !a_min_owners_num){
log_it(L_WARNING,"Wrong arguments");
return -1;
}
while(l_tsd_offset < tsd_data_size){
dap_tsd_t *l_tsd = (dap_tsd_t*)a_decree->data_n_signs + l_tsd_offset;
size_t l_tsd_size = dap_tsd_size(l_tsd);
if(l_tsd_size > tsd_data_size){
log_it(L_WARNING,"TSD size is greater than all data size. It's possible corrupt data.");
return -1;
}
if (l_tsd->type == DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER){
if(l_tsd->size > sizeof(uint256_t)){
log_it(L_WARNING,"Wrong fee tsd data size.");
return -1;
}
*a_min_owners_num = dap_tsd_get_scalar(l_tsd, uint256_t);
return 0;
}
l_tsd_offset += l_tsd_size;
}
return 1;
}
void dap_chain_datum_decree_certs_dump(dap_string_t * a_str_out, byte_t * a_signs, size_t a_certs_size, const char *a_hash_out_type)
{
dap_string_append_printf(a_str_out, "signatures: ");
if (!a_certs_size) {
dap_string_append_printf(a_str_out, "<NONE>\n");
return;
}
dap_string_append_printf(a_str_out, "\n");
size_t l_offset = 0;
for (int i = 1; l_offset < (a_certs_size); i++) {
dap_sign_t *l_sign = (dap_sign_t *) (a_signs + l_offset);
l_offset += dap_sign_get_size(l_sign);
if (l_sign->header.sign_size == 0) {
dap_string_append_printf(a_str_out, "<CORRUPTED - 0 size signature>\n");
continue;
}
dap_chain_hash_fast_t l_pkey_hash = {0};
if (dap_sign_get_pkey_hash(l_sign, &l_pkey_hash) == false) {
dap_string_append_printf(a_str_out, "<CORRUPTED - can't calc hash>\n");
continue;
}
char *l_hash_str = NULL;
if(!dap_strcmp(a_hash_out_type, "hex"))
l_hash_str = dap_chain_hash_fast_to_str_new(&l_pkey_hash);
else
l_hash_str = dap_enc_base58_encode_hash_to_str(&l_pkey_hash);
dap_string_append_printf(a_str_out, "%d) %s, %s, %u bytes\n", i, l_hash_str,
dap_sign_type_to_str(l_sign->header.type), l_sign->header.sign_size);
DAP_DEL_Z(l_hash_str);
}
}
......@@ -161,6 +161,7 @@ void dap_chain_datum_token_certs_dump(dap_string_t * a_str_out, byte_t * a_data_
dap_string_append_printf(a_str_out, "%d) %s, %s, %u bytes\n", i, l_hash_str,
dap_sign_type_to_str(l_sign->header.type), l_sign->header.sign_size);
DAP_DEL_Z(l_hash_str);
}
}
......
......@@ -92,10 +92,10 @@ static size_t dap_chain_tx_sig_get_size(const dap_chain_tx_sig_t *a_item)
return size;
}
static size_t dap_chain_tx_token_get_size(const dap_chain_tx_token_t *a_item)
static size_t dap_chain_tx_token_get_size(const dap_chain_tx_in_ems_t *a_item)
{
(void) a_item;
size_t size = sizeof(dap_chain_tx_token_t);
size_t size = sizeof(dap_chain_tx_in_ems_t);
return size;
}
......@@ -129,7 +129,7 @@ dap_chain_tx_item_type_t dap_chain_datum_tx_item_str_to_type(const char *a_datum
else if(!dap_strcmp(a_datum_name, "sign"))
return TX_ITEM_TYPE_SIG;
else if(!dap_strcmp(a_datum_name, "token"))
return TX_ITEM_TYPE_TOKEN;
return TX_ITEM_TYPE_IN_EMS;
else if(!dap_strcmp(a_datum_name, "in_cond"))
return TX_ITEM_TYPE_IN_COND;
else if(!dap_strcmp(a_datum_name, "out_cond"))
......@@ -213,8 +213,8 @@ size_t dap_chain_datum_item_tx_get_size(const void *a_item)
case TX_ITEM_TYPE_SIG: // Transaction signatures
size = dap_chain_tx_sig_get_size((const dap_chain_tx_sig_t*) a_item);
break;
case TX_ITEM_TYPE_TOKEN: // token item
size = dap_chain_tx_token_get_size((const dap_chain_tx_token_t*) a_item);
case TX_ITEM_TYPE_IN_EMS: // token item
size = dap_chain_tx_token_get_size((const dap_chain_tx_in_ems_t*) a_item);
break;
case TX_ITEM_TYPE_TSD:
size = dap_chain_tx_tsd_get_size((const dap_chain_tx_tsd_t*)a_item);
......@@ -230,12 +230,12 @@ size_t dap_chain_datum_item_tx_get_size(const void *a_item)
*
* return item, NULL Error
*/
dap_chain_tx_token_t *dap_chain_datum_tx_item_token_create(dap_chain_id_t a_id, dap_chain_hash_fast_t *a_datum_token_hash, const char *a_ticker)
dap_chain_tx_in_ems_t *dap_chain_datum_tx_item_token_create(dap_chain_id_t a_id, dap_chain_hash_fast_t *a_datum_token_hash, const char *a_ticker)
{
if(!a_ticker)
return NULL;
dap_chain_tx_token_t *l_item = DAP_NEW_Z(dap_chain_tx_token_t);
l_item->header.type = TX_ITEM_TYPE_TOKEN;
dap_chain_tx_in_ems_t *l_item = DAP_NEW_Z(dap_chain_tx_in_ems_t);
l_item->header.type = TX_ITEM_TYPE_IN_EMS;
l_item->header.token_emission_chain_id.uint64 = a_id.uint64;
l_item->header.token_emission_hash = *a_datum_token_hash;;
strncpy(l_item->header.ticker, a_ticker, sizeof(l_item->header.ticker) - 1);
......@@ -497,7 +497,9 @@ uint8_t* dap_chain_datum_tx_item_get( dap_chain_datum_tx_t *a_tx, int *a_item_id
(a_type == TX_ITEM_TYPE_OUT_ALL && l_type == TX_ITEM_TYPE_OUT_COND) ||
(a_type == TX_ITEM_TYPE_OUT_ALL && l_type == TX_ITEM_TYPE_OUT_EXT) ||
(a_type == TX_ITEM_TYPE_IN_ALL && l_type == TX_ITEM_TYPE_IN) ||
(a_type == TX_ITEM_TYPE_IN_ALL && l_type == TX_ITEM_TYPE_IN_COND)) {
(a_type == TX_ITEM_TYPE_IN_ALL && l_type == TX_ITEM_TYPE_IN_COND) ||
(a_type == TX_ITEM_TYPE_IN_ALL && l_type == TX_ITEM_TYPE_IN_EMS) ||
(a_type == TX_ITEM_TYPE_IN_ALL && l_type == TX_ITEM_TYPE_IN_EMS_EXT)) {
if(a_item_idx)
*a_item_idx = l_item_idx;
if(a_item_out_size)
......
......@@ -109,6 +109,32 @@ dap_sign_t* dap_chain_datum_tx_receipt_sign_get(dap_chain_datum_tx_receipt_t * l
return l_sign;
}
uint32_t dap_chain_datum_tx_receipt_type_get(dap_chain_datum_tx_receipt_t * l_receipt)
{
if (!l_receipt)
return -1;
return l_receipt->receipt_info.units_type.enm;
}
uint64_t dap_chain_datum_tx_receipt_srv_uid_get(dap_chain_datum_tx_receipt_t * l_receipt)
{
if (!l_receipt)
return -1;
return l_receipt->receipt_info.srv_uid.uint64;
}
uint64_t dap_chain_datum_tx_receipt_units_get(dap_chain_datum_tx_receipt_t * l_receipt)
{
if (!l_receipt)
return -1;
return l_receipt->receipt_info.units;
}
uint256_t dap_chain_datum_tx_receipt_value_get(dap_chain_datum_tx_receipt_t * l_receipt)
{
uint256_t res = {};
if (!l_receipt)
return res;
return l_receipt->receipt_info.value_datoshi;
}
/**
* @brief dap_chain_datum_tx_receipt_signs_count
* @param a_receipt
......