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 (3)
Showing
with 1913 additions and 396 deletions
Subproject commit caa3b8fe001e5459c7656bd9a96e15cd6fb074a6 Subproject commit 9db9d52588ceaae60bc7b57ca96888fdf03bb128
...@@ -86,6 +86,7 @@ void dap_chain_deinit(void) ...@@ -86,6 +86,7 @@ void dap_chain_deinit(void)
dap_chain_item_t * l_item = NULL, *l_tmp = NULL; dap_chain_item_t * l_item = NULL, *l_tmp = NULL;
HASH_ITER(hh, s_chain_items, l_item, l_tmp) { HASH_ITER(hh, s_chain_items, l_item, l_tmp) {
dap_chain_delete(l_item->chain); dap_chain_delete(l_item->chain);
DAP_DELETE(l_item);
} }
} }
...@@ -142,7 +143,7 @@ dap_chain_t *dap_chain_create(const char *a_chain_net_name, const char *a_chain_ ...@@ -142,7 +143,7 @@ dap_chain_t *dap_chain_create(const char *a_chain_net_name, const char *a_chain_
* delete dap chain object * delete dap chain object
* @param a_chain dap_chain_t object * @param a_chain dap_chain_t object
*/ */
void dap_chain_delete(dap_chain_t * a_chain) void dap_chain_delete(dap_chain_t *a_chain)
{ {
dap_chain_item_t * l_item = NULL; dap_chain_item_t * l_item = NULL;
dap_chain_item_id_t l_chain_item_id = { dap_chain_item_id_t l_chain_item_id = {
...@@ -161,15 +162,17 @@ void dap_chain_delete(dap_chain_t * a_chain) ...@@ -161,15 +162,17 @@ void dap_chain_delete(dap_chain_t * a_chain)
} }
pthread_rwlock_unlock(&s_chain_items_rwlock); pthread_rwlock_unlock(&s_chain_items_rwlock);
dap_list_free_full(a_chain->atom_notifiers, NULL); dap_list_free_full(a_chain->atom_notifiers, NULL);
dap_config_close(a_chain->config);
if (a_chain->callback_delete) if (a_chain->callback_delete)
a_chain->callback_delete(a_chain); a_chain->callback_delete(a_chain);
dap_config_close(a_chain->config);
if (DAP_CHAIN_PVT(a_chain)) { if (DAP_CHAIN_PVT(a_chain)) {
DAP_DEL_MULTY(DAP_CHAIN_PVT(a_chain)->file_storage_dir, DAP_CHAIN_PVT(a_chain)); DAP_DEL_MULTY(DAP_CHAIN_PVT(a_chain)->file_storage_dir, DAP_CHAIN_PVT(a_chain));
} }
DAP_DEL_MULTY(a_chain->name, a_chain->net_name, a_chain->datum_types, a_chain->autoproc_datum_types, a_chain->authorized_nodes_addrs, a_chain->_inheritor, a_chain); DAP_DEL_MULTY(a_chain->name, a_chain->net_name, a_chain->datum_types, a_chain->autoproc_datum_types,
a_chain->authorized_nodes_addrs, a_chain->_inheritor);
pthread_rwlock_destroy(&a_chain->rwlock); pthread_rwlock_destroy(&a_chain->rwlock);
pthread_rwlock_destroy(&a_chain->cell_rwlock); pthread_rwlock_destroy(&a_chain->cell_rwlock);
DAP_DELETE(a_chain);
} }
/** /**
...@@ -634,6 +637,66 @@ void dap_chain_add_callback_notify(dap_chain_t *a_chain, dap_chain_callback_noti ...@@ -634,6 +637,66 @@ void dap_chain_add_callback_notify(dap_chain_t *a_chain, dap_chain_callback_noti
} }
/**
* @brief Add a callback to monitor adding new atom into index
* @param a_chain
* @param a_callback
* @param a_arg
*/
void dap_chain_add_callback_datum_index_notify(dap_chain_t *a_chain, dap_chain_callback_datum_notify_t a_callback, dap_proc_thread_t *a_thread, void *a_callback_arg)
{
if(!a_chain){
log_it(L_ERROR, "NULL chain passed to dap_chain_add_callback_notify()");
return;
}
if(!a_callback){
log_it(L_ERROR, "NULL callback passed to dap_chain_add_callback_notify()");
return;
}
dap_chain_datum_notifier_t * l_notifier = DAP_NEW_Z(dap_chain_datum_notifier_t);
if (l_notifier == NULL){
log_it(L_ERROR, "Can't allocate memory for notifier in dap_chain_add_callback_notify()");
return;
}
l_notifier->callback = a_callback;
l_notifier->proc_thread = a_thread;
l_notifier->arg = a_callback_arg;
pthread_rwlock_wrlock(&a_chain->rwlock);
a_chain->datum_notifiers = dap_list_append(a_chain->datum_notifiers, l_notifier);
pthread_rwlock_unlock(&a_chain->rwlock);
}
/**
* @brief Add a callback to monitor adding new atom into index
* @param a_chain
* @param a_callback
* @param a_arg
*/
void dap_chain_add_callback_datum_removed_from_index_notify(dap_chain_t *a_chain, dap_chain_callback_datum_removed_notify_t a_callback, dap_proc_thread_t *a_thread, void *a_callback_arg)
{
if(!a_chain){
log_it(L_ERROR, "NULL chain passed to dap_chain_add_callback_notify()");
return;
}
if(!a_callback){
log_it(L_ERROR, "NULL callback passed to dap_chain_add_callback_notify()");
return;
}
dap_chain_datum_removed_notifier_t * l_notifier = DAP_NEW_Z(dap_chain_datum_removed_notifier_t);
if (l_notifier == NULL){
log_it(L_ERROR, "Can't allocate memory for notifier in dap_chain_add_callback_notify()");
return;
}
l_notifier->callback = a_callback;
l_notifier->proc_thread = a_thread;
l_notifier->arg = a_callback_arg;
pthread_rwlock_wrlock(&a_chain->rwlock);
a_chain->datum_removed_notifiers = dap_list_append(a_chain->datum_removed_notifiers, l_notifier);
pthread_rwlock_unlock(&a_chain->rwlock);
}
/** /**
* @brief Add a callback to monitor blocks received enough confirmations * @brief Add a callback to monitor blocks received enough confirmations
* @param a_chain * @param a_chain
...@@ -694,6 +757,28 @@ struct chain_thread_notifier { ...@@ -694,6 +757,28 @@ struct chain_thread_notifier {
size_t atom_size; size_t atom_size;
}; };
struct chain_thread_datum_notifier {
dap_chain_callback_datum_notify_t callback;
void *callback_arg;
dap_chain_t *chain;
dap_chain_cell_id_t cell_id;
dap_hash_fast_t hash;
void *datum;
uint32_t action;
dap_chain_net_srv_uid_t uid;
size_t datum_size;
int ret_code;
};
struct chain_thread_datum_removed_notifier {
dap_chain_callback_datum_removed_notify_t callback;
void *callback_arg;
dap_chain_t *chain;
dap_chain_cell_id_t cell_id;
dap_hash_fast_t hash;
int ret_code;
};
static bool s_notify_atom_on_thread(void *a_arg) static bool s_notify_atom_on_thread(void *a_arg)
{ {
struct chain_thread_notifier *l_arg = a_arg; struct chain_thread_notifier *l_arg = a_arg;
...@@ -705,6 +790,27 @@ static bool s_notify_atom_on_thread(void *a_arg) ...@@ -705,6 +790,27 @@ static bool s_notify_atom_on_thread(void *a_arg)
return false; return false;
} }
static bool s_notify_datum_on_thread(void *a_arg)
{
struct chain_thread_datum_notifier *l_arg = a_arg;
assert(l_arg->datum && l_arg->callback);
l_arg->callback(l_arg->callback_arg, &l_arg->hash, l_arg->datum, l_arg->datum_size, l_arg->ret_code, l_arg->action, l_arg->uid);
if ( !l_arg->chain->is_mapped )
DAP_DELETE(l_arg->datum);
DAP_DELETE(l_arg);
return false;
}
static bool s_notify_datum_removed_on_thread(void *a_arg)
{
struct chain_thread_datum_removed_notifier *l_arg = a_arg;
assert(l_arg->callback);
l_arg->callback(l_arg->callback_arg, &l_arg->hash);
DAP_DELETE(l_arg);
return false;
}
ssize_t dap_chain_atom_save(dap_chain_cell_t *a_chain_cell, const uint8_t *a_atom, size_t a_atom_size, dap_hash_fast_t *a_new_atom_hash) ssize_t dap_chain_atom_save(dap_chain_cell_t *a_chain_cell, const uint8_t *a_atom, size_t a_atom_size, dap_hash_fast_t *a_new_atom_hash)
{ {
dap_return_val_if_fail(a_chain_cell && a_chain_cell->chain, -1); dap_return_val_if_fail(a_chain_cell && a_chain_cell->chain, -1);
...@@ -791,6 +897,57 @@ void dap_chain_atom_notify(dap_chain_cell_t *a_chain_cell, dap_hash_fast_t *a_ha ...@@ -791,6 +897,57 @@ void dap_chain_atom_notify(dap_chain_cell_t *a_chain_cell, dap_hash_fast_t *a_ha
} }
} }
void dap_chain_datum_notify(dap_chain_cell_t *a_chain_cell, dap_hash_fast_t *a_hash, const uint8_t *a_datum, size_t a_datum_size, int a_ret_code, uint32_t a_action, dap_chain_net_srv_uid_t a_uid) {
#ifdef DAP_CHAIN_BLOCKS_TEST
return;
#endif
if ( !a_chain_cell->chain->datum_notifiers )
return;
dap_list_t *l_iter;
DL_FOREACH(a_chain_cell->chain->datum_notifiers, l_iter) {
dap_chain_datum_notifier_t *l_notifier = (dap_chain_datum_notifier_t*)l_iter->data;
struct chain_thread_datum_notifier *l_arg = DAP_NEW_Z(struct chain_thread_datum_notifier);
if (!l_arg) {
log_it(L_CRITICAL, "%s", c_error_memory_alloc);
continue;
}
*l_arg = (struct chain_thread_datum_notifier) {
.callback = l_notifier->callback, .callback_arg = l_notifier->arg,
.chain = a_chain_cell->chain, .cell_id = a_chain_cell->id,
.hash = *a_hash,
.datum = a_chain_cell->chain->is_mapped ? (byte_t*)a_datum : DAP_DUP_SIZE(a_datum, a_datum_size),
.datum_size = a_datum_size,
.ret_code = a_ret_code,
.action = a_action,
.uid = a_uid};
dap_proc_thread_callback_add_pri(l_notifier->proc_thread, s_notify_datum_on_thread, l_arg, DAP_QUEUE_MSG_PRIORITY_LOW);
}
}
void dap_chain_datum_removed_notify(dap_chain_cell_t *a_chain_cell, dap_hash_fast_t *a_hash) {
#ifdef DAP_CHAIN_BLOCKS_TEST
return;
#endif
if ( !a_chain_cell->chain->datum_removed_notifiers )
return;
dap_list_t *l_iter;
DL_FOREACH(a_chain_cell->chain->datum_removed_notifiers, l_iter) {
dap_chain_datum_removed_notifier_t *l_notifier = (dap_chain_datum_removed_notifier_t*)l_iter->data;
struct chain_thread_datum_removed_notifier *l_arg = DAP_NEW_Z(struct chain_thread_datum_removed_notifier);
if (!l_arg) {
log_it(L_CRITICAL, "%s", c_error_memory_alloc);
continue;
}
*l_arg = (struct chain_thread_datum_removed_notifier) {
.callback = l_notifier->callback, .callback_arg = l_notifier->arg,
.chain = a_chain_cell->chain, .cell_id = a_chain_cell->id,
.hash = *a_hash};
dap_proc_thread_callback_add_pri(l_notifier->proc_thread, s_notify_datum_removed_on_thread, l_arg, DAP_QUEUE_MSG_PRIORITY_LOW);
}
}
void dap_chain_atom_add_from_threshold(dap_chain_t *a_chain) { void dap_chain_atom_add_from_threshold(dap_chain_t *a_chain) {
if ( !a_chain->callback_atom_add_from_treshold ) if ( !a_chain->callback_atom_add_from_treshold )
return; return;
...@@ -822,5 +979,4 @@ const char *dap_chain_type_to_str(const dap_chain_type_t a_default_chain_type) { ...@@ -822,5 +979,4 @@ const char *dap_chain_type_to_str(const dap_chain_type_t a_default_chain_type) {
return "anchor"; return "anchor";
default: break; default: break;
} }
return "invalid";
} }
...@@ -33,6 +33,7 @@ typedef struct dap_chain_callback_new_cfg_item ...@@ -33,6 +33,7 @@ typedef struct dap_chain_callback_new_cfg_item
{ {
char name[32]; char name[32];
dap_chain_callback_new_cfg_t callback_init; dap_chain_callback_new_cfg_t callback_init;
dap_chain_callback_t callback_start;
UT_hash_handle hh; UT_hash_handle hh;
} dap_chain_callback_new_cfg_item_t; } dap_chain_callback_new_cfg_item_t;
...@@ -61,7 +62,7 @@ void dap_chain_cs_deinit(void) ...@@ -61,7 +62,7 @@ void dap_chain_cs_deinit(void)
* @param a_cs_str consensus name * @param a_cs_str consensus name
* @param a_callback_init callback function * @param a_callback_init callback function
*/ */
void dap_chain_cs_type_add (const char * a_cs_str, dap_chain_callback_new_cfg_t a_callback_init) void dap_chain_cs_type_add (const char * a_cs_str, dap_chain_callback_new_cfg_t a_callback_init, dap_chain_callback_t a_callback_start)
{ {
dap_chain_callback_new_cfg_item_t *l_item = DAP_NEW_Z ( dap_chain_callback_new_cfg_item_t ); dap_chain_callback_new_cfg_item_t *l_item = DAP_NEW_Z ( dap_chain_callback_new_cfg_item_t );
if ( !l_item ) { if ( !l_item ) {
...@@ -71,6 +72,7 @@ void dap_chain_cs_type_add (const char * a_cs_str, dap_chain_callback_new_cfg_t ...@@ -71,6 +72,7 @@ void dap_chain_cs_type_add (const char * a_cs_str, dap_chain_callback_new_cfg_t
strncpy(l_item->name, a_cs_str, sizeof (l_item->name) - 1); strncpy(l_item->name, a_cs_str, sizeof (l_item->name) - 1);
l_item->name[sizeof (l_item->name) - 1] = '\0'; l_item->name[sizeof (l_item->name) - 1] = '\0';
l_item->callback_init = a_callback_init; l_item->callback_init = a_callback_init;
l_item->callback_start = a_callback_start;
HASH_ADD_STR( s_class_callbacks, name, l_item); HASH_ADD_STR( s_class_callbacks, name, l_item);
} }
...@@ -89,6 +91,19 @@ int dap_chain_cs_type_create(const char *a_type, dap_chain_t * a_chain, dap_conf ...@@ -89,6 +91,19 @@ int dap_chain_cs_type_create(const char *a_type, dap_chain_t * a_chain, dap_conf
return -1; return -1;
} }
/**
* @brief dap_chain_class_create
* @param a_chain
* @return
*/
void dap_chain_cs_type_start(const char *a_type, dap_chain_t *a_chain)
{
dap_chain_callback_new_cfg_item_t *l_item = NULL;
HASH_FIND_STR(s_class_callbacks, a_type, l_item);
if (l_item && l_item->callback_start)
l_item->callback_start(a_chain);
}
/** /**
* @brief dap_chain_cs_add * @brief dap_chain_cs_add
...@@ -96,7 +111,7 @@ int dap_chain_cs_type_create(const char *a_type, dap_chain_t * a_chain, dap_conf ...@@ -96,7 +111,7 @@ int dap_chain_cs_type_create(const char *a_type, dap_chain_t * a_chain, dap_conf
* @param a_cs_str * @param a_cs_str
* @param a_callback_init * @param a_callback_init
*/ */
void dap_chain_cs_add (const char * a_cs_str, dap_chain_callback_new_cfg_t a_callback_init) void dap_chain_cs_add (const char * a_cs_str, dap_chain_callback_new_cfg_t a_callback_init)
{ {
dap_chain_callback_new_cfg_item_t *l_item = DAP_NEW_Z ( dap_chain_callback_new_cfg_item_t ); dap_chain_callback_new_cfg_item_t *l_item = DAP_NEW_Z ( dap_chain_callback_new_cfg_item_t );
if ( !l_item ) { if ( !l_item ) {
......
...@@ -49,7 +49,7 @@ typedef const void * dap_chain_atom_ptr_t; ...@@ -49,7 +49,7 @@ typedef const void * dap_chain_atom_ptr_t;
typedef struct dap_chain_atom_iter { typedef struct dap_chain_atom_iter {
dap_chain_t *chain; dap_chain_t *chain;
dap_chain_cell_id_t cell_id; dap_chain_cell_id_t cell_id;
void *cur_item; void *cur_item;
dap_chain_atom_ptr_t cur; dap_chain_atom_ptr_t cur;
size_t cur_size; size_t cur_size;
dap_chain_hash_fast_t *cur_hash; dap_chain_hash_fast_t *cur_hash;
...@@ -126,6 +126,9 @@ typedef dap_chain_atom_ptr_t * (*dap_chain_callback_atom_iter_get_atoms_t)(dap_c ...@@ -126,6 +126,9 @@ 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 size_t (*dap_chain_callback_add_datums_t)(dap_chain_t * , dap_chain_datum_t **, size_t );
typedef void (*dap_chain_callback_notify_t)(void *a_arg, dap_chain_t *a_chain, dap_chain_cell_id_t a_id, dap_chain_hash_fast_t *a_atom_hash, void *a_atom, size_t a_atom_size); //change in chain happened typedef void (*dap_chain_callback_notify_t)(void *a_arg, dap_chain_t *a_chain, dap_chain_cell_id_t a_id, dap_chain_hash_fast_t *a_atom_hash, void *a_atom, size_t a_atom_size); //change in chain happened
typedef void (*dap_chain_callback_datum_notify_t)(void *a_arg, dap_chain_hash_fast_t *a_datum_hash, void *a_datum,
size_t a_datum_size, int a_ret_code, uint32_t a_action, dap_chain_net_srv_uid_t a_uid); //change in chain happened
typedef void (*dap_chain_callback_datum_removed_notify_t)(void *a_arg, dap_chain_hash_fast_t *a_datum_hash); //change in chain happened
typedef uint64_t (*dap_chain_callback_get_count)(dap_chain_t *a_chain); typedef uint64_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_list)(dap_chain_t *a_chain, size_t a_count, size_t a_page, bool a_reverse);
...@@ -234,6 +237,8 @@ typedef struct dap_chain { ...@@ -234,6 +237,8 @@ typedef struct dap_chain {
dap_chain_datum_callback_iter_delete_t callback_datum_iter_delete; dap_chain_datum_callback_iter_delete_t callback_datum_iter_delete;
dap_list_t *atom_notifiers; dap_list_t *atom_notifiers;
dap_list_t *datum_notifiers;
dap_list_t *datum_removed_notifiers;
dap_list_t *atom_confirmed_notifiers; dap_list_t *atom_confirmed_notifiers;
...@@ -251,6 +256,17 @@ typedef struct dap_chain_atom_notifier { ...@@ -251,6 +256,17 @@ typedef struct dap_chain_atom_notifier {
void *arg; void *arg;
} dap_chain_atom_notifier_t; } dap_chain_atom_notifier_t;
typedef struct dap_chain_datum_notifier {
dap_chain_callback_datum_notify_t callback;
dap_proc_thread_t *proc_thread;
void *arg;
} dap_chain_datum_notifier_t;
typedef struct dap_chain_datum_removed_notifier {
dap_chain_callback_datum_removed_notify_t callback;
dap_proc_thread_t *proc_thread;
void *arg;
} dap_chain_datum_removed_notifier_t;
typedef struct dap_chain_atom_confirmed_notifier { typedef struct dap_chain_atom_confirmed_notifier {
uint64_t block_notify_cnt; uint64_t block_notify_cnt;
dap_chain_callback_notify_t callback; dap_chain_callback_notify_t callback;
...@@ -292,8 +308,12 @@ dap_chain_t *dap_chain_load_from_cfg(const char *a_chain_net_name, dap_chain_net ...@@ -292,8 +308,12 @@ dap_chain_t *dap_chain_load_from_cfg(const char *a_chain_net_name, dap_chain_net
void dap_chain_delete(dap_chain_t * a_chain); void dap_chain_delete(dap_chain_t * a_chain);
void dap_chain_add_callback_notify(dap_chain_t *a_chain, dap_chain_callback_notify_t a_callback, dap_proc_thread_t *a_thread, void *a_arg); void dap_chain_add_callback_notify(dap_chain_t *a_chain, dap_chain_callback_notify_t a_callback, dap_proc_thread_t *a_thread, void *a_arg);
void dap_chain_add_callback_datum_index_notify(dap_chain_t *a_chain, dap_chain_callback_datum_notify_t a_callback, dap_proc_thread_t *a_thread, void *a_callback_arg);
void dap_chain_add_callback_datum_removed_from_index_notify(dap_chain_t *a_chain, dap_chain_callback_datum_removed_notify_t a_callback, dap_proc_thread_t *a_thread, void *a_callback_arg);
void dap_chain_atom_confirmed_notify_add(dap_chain_t *a_chain, dap_chain_callback_notify_t a_callback, void *a_arg, uint64_t a_conf_cnt); void dap_chain_atom_confirmed_notify_add(dap_chain_t *a_chain, dap_chain_callback_notify_t a_callback, void *a_arg, uint64_t a_conf_cnt);
void dap_chain_atom_notify(dap_chain_cell_t *a_chain_cell, dap_hash_fast_t *a_hash, const uint8_t *a_atom, size_t a_atom_size); void dap_chain_atom_notify(dap_chain_cell_t *a_chain_cell, dap_hash_fast_t *a_hash, const uint8_t *a_atom, size_t a_atom_size);
void dap_chain_datum_notify(dap_chain_cell_t *a_chain_cell, dap_hash_fast_t *a_hash, const uint8_t *a_datum, size_t a_datum_size, int a_ret_code, uint32_t a_action, dap_chain_net_srv_uid_t a_uid);
void dap_chain_datum_removed_notify(dap_chain_cell_t *a_chain_cell, dap_hash_fast_t *a_hash);
void dap_chain_atom_add_from_threshold(dap_chain_t *a_chain); void dap_chain_atom_add_from_threshold(dap_chain_t *a_chain);
dap_chain_atom_ptr_t dap_chain_get_atom_by_hash(dap_chain_t * a_chain, dap_chain_hash_fast_t * a_atom_hash, size_t * a_atom_size); dap_chain_atom_ptr_t dap_chain_get_atom_by_hash(dap_chain_t * a_chain, dap_chain_hash_fast_t * a_atom_hash, size_t * a_atom_size);
bool dap_chain_get_atom_last_hash_num(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_atom_hash, uint64_t *a_atom_num); bool dap_chain_get_atom_last_hash_num(dap_chain_t *a_chain, dap_chain_cell_id_t a_cell_id, dap_hash_fast_t *a_atom_hash, uint64_t *a_atom_num);
......
...@@ -36,8 +36,9 @@ typedef struct dap_chain_cs{ ...@@ -36,8 +36,9 @@ typedef struct dap_chain_cs{
int dap_chain_cs_init(void); int dap_chain_cs_init(void);
void dap_chain_cs_deinit(void); void dap_chain_cs_deinit(void);
void dap_chain_cs_add (const char * a_cs_str, dap_chain_callback_new_cfg_t a_callback_init); void dap_chain_cs_add (const char *a_cs_str, dap_chain_callback_new_cfg_t a_callback_init);
int dap_chain_cs_create(dap_chain_t * a_chain, dap_config_t * a_chain_cfg); int dap_chain_cs_create(dap_chain_t *a_chain, dap_config_t *a_chain_cfg);
void dap_chain_cs_type_add (const char * a_cs_str, dap_chain_callback_new_cfg_t a_callback_init); void dap_chain_cs_type_add (const char *a_cs_str, dap_chain_callback_new_cfg_t a_callback_init, dap_chain_callback_t a_callback_start);
int dap_chain_cs_type_create(const char *a_type, dap_chain_t * a_chain, dap_config_t * a_chain_cfg); int dap_chain_cs_type_create(const char *a_type, dap_chain_t *a_chain, dap_config_t *a_chain_cfg);
void dap_chain_cs_type_start(const char *a_type, dap_chain_t *a_chain);
\ No newline at end of file
...@@ -420,7 +420,7 @@ static int s_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) ...@@ -420,7 +420,7 @@ static int s_callback_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
dap_cert_t *l_cert = dap_cert_generate_mem_with_seed("testCert", DAP_ENC_KEY_TYPE_SIG_PICNIC, l_seed_ph, l_seed_ph_size); dap_cert_t *l_cert = dap_cert_generate_mem_with_seed("testCert", DAP_ENC_KEY_TYPE_SIG_PICNIC, l_seed_ph, l_seed_ph_size);
l_poa_pvt->auth_certs[0] = l_cert; l_poa_pvt->auth_certs[0] = l_cert;
#endif #endif
dap_chain_cs_type_start("dag", a_chain);
return 0; return 0;
} }
......
...@@ -66,6 +66,7 @@ ...@@ -66,6 +66,7 @@
#include "dap_chain_net_srv.h" #include "dap_chain_net_srv.h"
#include "dap_chain_cs_blocks.h" #include "dap_chain_cs_blocks.h"
#include "dap_chain_net_srv_stake_pos_delegate.h" #include "dap_chain_net_srv_stake_pos_delegate.h"
#include "dap_chain_wallet_cache.h"
#include "dap_chain_mempool_rpc.h" #include "dap_chain_mempool_rpc.h"
...@@ -162,15 +163,18 @@ char *dap_chain_mempool_tx_create(dap_chain_t * a_chain, dap_enc_key_t *a_key_fr ...@@ -162,15 +163,18 @@ char *dap_chain_mempool_tx_create(dap_chain_t * a_chain, dap_enc_key_t *a_key_fr
if (l_single_channel) if (l_single_channel)
SUM_256_256(l_value_need, l_total_fee, &l_value_need); SUM_256_256(l_value_need, l_total_fee, &l_value_need);
else if (!IS_ZERO_256(l_total_fee)) { else if (!IS_ZERO_256(l_total_fee)) {
l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker, if (dap_chain_wallet_cache_tx_find_outs_with_val(l_ledger->net, l_native_ticker, a_addr_from, &l_list_fee_out, l_total_fee, &l_fee_transfer) == -101)
l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker,
a_addr_from, l_total_fee, &l_fee_transfer); a_addr_from, l_total_fee, &l_fee_transfer);
if (!l_list_fee_out) { if (!l_list_fee_out) {
log_it(L_WARNING, "Not enough funds to pay fee"); log_it(L_WARNING, "Not enough funds to pay fee");
return NULL; return NULL;
} }
} }
dap_list_t *l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, a_token_ticker, dap_list_t *l_list_used_out = NULL;
a_addr_from, l_value_need, &l_value_transfer); if (dap_chain_wallet_cache_tx_find_outs_with_val(l_ledger->net, a_token_ticker, a_addr_from, &l_list_used_out, l_value_need, &l_value_transfer) == -101)
l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, a_token_ticker,
a_addr_from, l_value_need, &l_value_transfer);
if (!l_list_used_out) { if (!l_list_used_out) {
log_it(L_WARNING, "Not enough funds to transfer"); log_it(L_WARNING, "Not enough funds to transfer");
return NULL; return NULL;
...@@ -587,8 +591,10 @@ int dap_chain_mempool_tx_create_massive( dap_chain_t * a_chain, dap_enc_key_t *a ...@@ -587,8 +591,10 @@ int dap_chain_mempool_tx_create_massive( dap_chain_t * a_chain, dap_enc_key_t *a
const char *l_balance; dap_uint256_to_char(l_value_need, &l_balance); const char *l_balance; dap_uint256_to_char(l_value_need, &l_balance);
log_it(L_DEBUG, "Create %"DAP_UINT64_FORMAT_U" transactions, summary %s", a_tx_num, l_balance); log_it(L_DEBUG, "Create %"DAP_UINT64_FORMAT_U" transactions, summary %s", a_tx_num, l_balance);
dap_ledger_t *l_ledger = dap_chain_net_by_id(a_chain->net_id)->pub.ledger; dap_ledger_t *l_ledger = dap_chain_net_by_id(a_chain->net_id)->pub.ledger;
dap_list_t *l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, a_token_ticker, dap_list_t *l_list_used_out = NULL;
a_addr_from, l_value_need, &l_value_transfer); if (dap_chain_wallet_cache_tx_find_outs_with_val(l_ledger->net, a_token_ticker, a_addr_from, &l_list_used_out, l_value_need, &l_value_transfer) == -101)
l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, a_token_ticker,
a_addr_from, l_value_need, &l_value_transfer);
if (!l_list_used_out) { if (!l_list_used_out) {
log_it(L_WARNING,"Not enough funds to transfer"); log_it(L_WARNING,"Not enough funds to transfer");
DAP_DELETE(l_objs); DAP_DELETE(l_objs);
...@@ -927,8 +933,10 @@ char *dap_chain_mempool_tx_create_cond(dap_chain_net_t *a_net, ...@@ -927,8 +933,10 @@ char *dap_chain_mempool_tx_create_cond(dap_chain_net_t *a_net,
dap_chain_addr_t l_addr_from; dap_chain_addr_t l_addr_from;
dap_chain_addr_fill_from_key(&l_addr_from, a_key_from, a_net->pub.id); dap_chain_addr_fill_from_key(&l_addr_from, a_key_from, a_net->pub.id);
// list of transaction with 'out' items // list of transaction with 'out' items
dap_list_t *l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, a_token_ticker, dap_list_t *l_list_used_out = NULL;
&l_addr_from, l_value_need, &l_value_transfer); if (dap_chain_wallet_cache_tx_find_outs_with_val(l_ledger->net, a_token_ticker, &l_addr_from, &l_list_used_out, l_value_need, &l_value_transfer) == -101)
l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, a_token_ticker,
&l_addr_from, l_value_need, &l_value_transfer);
if(!l_list_used_out) { if(!l_list_used_out) {
log_it( L_ERROR, "Nothing to transfer (not enough funds)"); log_it( L_ERROR, "Nothing to transfer (not enough funds)");
return NULL; return NULL;
...@@ -1054,7 +1062,9 @@ char *dap_chain_mempool_base_tx_create(dap_chain_t *a_chain, dap_chain_hash_fast ...@@ -1054,7 +1062,9 @@ char *dap_chain_mempool_base_tx_create(dap_chain_t *a_chain, dap_chain_hash_fast
} }
dap_ledger_t *l_ledger = dap_chain_net_by_id(a_chain->net_id)->pub.ledger; dap_ledger_t *l_ledger = dap_chain_net_by_id(a_chain->net_id)->pub.ledger;
// list of transaction with 'out' items // list of transaction with 'out' items
dap_list_t *l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker, dap_list_t *l_list_used_out = NULL;
if (dap_chain_wallet_cache_tx_find_outs_with_val(l_ledger->net, l_native_ticker, &l_addr_from_fee, &l_list_used_out, l_total_fee, &l_value_transfer) == -101)
l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker,
&l_addr_from_fee, l_total_fee, &l_value_transfer); &l_addr_from_fee, l_total_fee, &l_value_transfer);
if (!l_list_used_out) { if (!l_list_used_out) {
log_it(L_WARNING,"Not enough funds to transfer"); log_it(L_WARNING,"Not enough funds to transfer");
......
...@@ -1791,6 +1791,15 @@ void dap_chain_net_delete(dap_chain_net_t *a_net) ...@@ -1791,6 +1791,15 @@ void dap_chain_net_delete(dap_chain_net_t *a_net)
dap_ledger_purge(a_net->pub.ledger, true); dap_ledger_purge(a_net->pub.ledger, true);
dap_ledger_handle_free(a_net->pub.ledger); dap_ledger_handle_free(a_net->pub.ledger);
} }
if (a_net->pub.chains) {
dap_chain_t
*l_cur = NULL,
*l_tmp = NULL;
DL_FOREACH_SAFE(a_net->pub.chains, l_cur, l_tmp) {
DL_DELETE(a_net->pub.chains, l_cur);
dap_chain_delete(l_cur);
}
}
HASH_DEL(s_nets_by_name, a_net); HASH_DEL(s_nets_by_name, a_net);
HASH_DELETE(hh2, s_nets_by_id, a_net); HASH_DELETE(hh2, s_nets_by_id, a_net);
DAP_DELETE(a_net); DAP_DELETE(a_net);
...@@ -1952,6 +1961,9 @@ int s_net_init(const char *a_net_name, const char *a_path, uint16_t a_acl_idx) ...@@ -1952,6 +1961,9 @@ int s_net_init(const char *a_net_name, const char *a_path, uint16_t a_acl_idx)
} }
} else { } else {
HASH_DEL(l_all_chain_configs, l_chain_config); HASH_DEL(l_all_chain_configs, l_chain_config);
dap_config_close(l_chain_config);
dap_chain_net_delete(l_net);
return -5;
} }
} }
HASH_CLEAR(hh, l_all_chain_configs); HASH_CLEAR(hh, l_all_chain_configs);
......
...@@ -248,6 +248,9 @@ static dap_chain_net_links_t *s_get_node_addrs(dap_chain_net_t *a_net, uint16_t ...@@ -248,6 +248,9 @@ static dap_chain_net_links_t *s_get_node_addrs(dap_chain_net_t *a_net, uint16_t
if (a_external_call) { if (a_external_call) {
l_nodes_count = dap_min(l_nodes_count, s_max_links_response_count); l_nodes_count = dap_min(l_nodes_count, s_max_links_response_count);
} }
if (!l_nodes_count) {
return NULL;
}
// memory alloc // memory alloc
dap_chain_net_links_t *l_ret = DAP_NEW_Z_SIZE(dap_chain_net_links_t, sizeof(dap_chain_net_links_t) + l_nodes_count * sizeof(dap_link_info_t)); dap_chain_net_links_t *l_ret = DAP_NEW_Z_SIZE(dap_chain_net_links_t, sizeof(dap_chain_net_links_t) + l_nodes_count * sizeof(dap_link_info_t));
if (!l_ret) { if (!l_ret) {
...@@ -285,6 +288,9 @@ static dap_chain_net_links_t *s_get_node_addrs_old(dap_chain_net_t *a_net, uint1 ...@@ -285,6 +288,9 @@ static dap_chain_net_links_t *s_get_node_addrs_old(dap_chain_net_t *a_net, uint1
l_nodes_count = dap_min(l_nodes_count, a_links_need); l_nodes_count = dap_min(l_nodes_count, a_links_need);
} }
l_nodes_count = dap_min(l_nodes_count, s_max_links_response_count); l_nodes_count = dap_min(l_nodes_count, s_max_links_response_count);
if (!l_nodes_count) {
return NULL;
}
// memory alloc // memory alloc
dap_chain_net_links_t *l_ret = DAP_NEW_Z_SIZE(dap_chain_net_links_t, sizeof(dap_chain_net_links_t) + l_nodes_count * sizeof(dap_chain_node_info_old_t)); dap_chain_net_links_t *l_ret = DAP_NEW_Z_SIZE(dap_chain_net_links_t, sizeof(dap_chain_net_links_t) + l_nodes_count * sizeof(dap_chain_node_info_old_t));
if (!l_ret) { if (!l_ret) {
...@@ -410,8 +416,8 @@ void dap_chain_net_balancer_http_issue_link(dap_http_simple_t *a_http_simple, vo ...@@ -410,8 +416,8 @@ void dap_chain_net_balancer_http_issue_link(dap_http_simple_t *a_http_simple, vo
log_it(L_DEBUG, "HTTP balancer parser retrieve netname %s", l_net_str); log_it(L_DEBUG, "HTTP balancer parser retrieve netname %s", l_net_str);
dap_chain_net_links_t *l_link_full_node_list = s_balancer_issue_link(l_net_str, l_links_need, l_protocol_version, l_ignored_str); dap_chain_net_links_t *l_link_full_node_list = s_balancer_issue_link(l_net_str, l_links_need, l_protocol_version, l_ignored_str);
if (!l_link_full_node_list) { if (!l_link_full_node_list) {
log_it(L_WARNING, "Can't issue link for network %s, no acceptable links found", l_net_str); log_it(L_DEBUG, "Can't issue link for network %s, no acceptable links found", l_net_str);
*l_return_code = Http_Status_NotFound; *l_return_code = Http_Status_NoContent;
return; return;
} }
*l_return_code = Http_Status_OK; *l_return_code = Http_Status_OK;
...@@ -541,10 +547,10 @@ dap_string_t *dap_chain_net_balancer_get_node_str(dap_chain_net_t *a_net) ...@@ -541,10 +547,10 @@ dap_string_t *dap_chain_net_balancer_get_node_str(dap_chain_net_t *a_net)
dap_return_val_if_pass(!a_net, NULL); dap_return_val_if_pass(!a_net, NULL);
// func work // func work
dap_chain_net_links_t *l_links_info_list = s_get_node_addrs(a_net, 0, NULL, false); // TODO dap_chain_net_links_t *l_links_info_list = s_get_node_addrs(a_net, 0, NULL, false); // TODO
dap_string_t *l_ret = dap_string_new(l_links_info_list ? dap_string_t *l_ret = dap_string_new(
"-----------------------------------------------------------------\n" "-----------------------------------------------------------------\n"
"|\t\tNode addr\t|\tHost addr\t\t|\n" "|\t\tNode addr\t|\tHost addr\t\t|\n"
"--Send in balancer http response---------------------------------\n" : "Empty\n"); "--Send in balancer http response---------------------------------\n");
uint64_t l_node_num = l_links_info_list ? l_links_info_list->count_node : 0; uint64_t l_node_num = l_links_info_list ? l_links_info_list->count_node : 0;
for (uint64_t i = 0; i < l_node_num; ++i) { for (uint64_t i = 0; i < l_node_num; ++i) {
dap_link_info_t *l_link_info = (dap_link_info_t *)l_links_info_list->nodes_info + i; dap_link_info_t *l_link_info = (dap_link_info_t *)l_links_info_list->nodes_info + i;
......
...@@ -99,6 +99,7 @@ ...@@ -99,6 +99,7 @@
#include "dap_json_rpc_errors.h" #include "dap_json_rpc_errors.h"
#include "dap_http_ban_list_client.h" #include "dap_http_ban_list_client.h"
#include "dap_chain_datum_tx_voting.h" #include "dap_chain_datum_tx_voting.h"
#include "dap_chain_wallet_cache.h"
#include "dap_json_rpc.h" #include "dap_json_rpc.h"
#include "dap_json_rpc_request.h" #include "dap_json_rpc_request.h"
#include "dap_client_pvt.h" #include "dap_client_pvt.h"
...@@ -6561,8 +6562,9 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply) ...@@ -6561,8 +6562,9 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply)
if (!dap_strcmp(l_native_token, l_main_token)) { if (!dap_strcmp(l_native_token, l_main_token)) {
SUM_256_256(l_value_need_check, l_value_need, &l_value_need_check); SUM_256_256(l_value_need_check, l_value_need, &l_value_need_check);
SUM_256_256(l_value_need_check, l_value_need_fee, &l_value_need_check); SUM_256_256(l_value_need_check, l_value_need_fee, &l_value_need_check);
l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_net->pub.ledger, l_json_item_token, if (dap_chain_wallet_cache_tx_find_outs_with_val(l_net, l_json_item_token, l_addr_from, &l_list_used_out, l_value_need_check, &l_value_transfer) == -101)
l_addr_from, l_value_need_check, &l_value_transfer); l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_net->pub.ledger, l_json_item_token,
l_addr_from, l_value_need_check, &l_value_transfer);
if(!l_list_used_out) { if(!l_list_used_out) {
log_it(L_WARNING, "Not enough funds in previous tx to transfer"); log_it(L_WARNING, "Not enough funds in previous tx to transfer");
json_object *l_jobj_err = json_object_new_string("Can't create in transaction. Not enough funds in previous tx " json_object *l_jobj_err = json_object_new_string("Can't create in transaction. Not enough funds in previous tx "
...@@ -6574,7 +6576,8 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply) ...@@ -6574,7 +6576,8 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply)
} }
} else { } else {
//CHECK value need //CHECK value need
l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_net->pub.ledger, l_json_item_token, if (dap_chain_wallet_cache_tx_find_outs_with_val(l_net, l_json_item_token, l_addr_from, &l_list_used_out, l_value_need, &l_value_transfer) == -101)
l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_net->pub.ledger, l_json_item_token,
l_addr_from, l_value_need, &l_value_transfer); l_addr_from, l_value_need, &l_value_transfer);
if(!l_list_used_out) { if(!l_list_used_out) {
log_it(L_WARNING, "Not enough funds in previous tx to transfer"); log_it(L_WARNING, "Not enough funds in previous tx to transfer");
...@@ -6586,7 +6589,8 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply) ...@@ -6586,7 +6589,8 @@ int com_tx_create_json(int a_argc, char ** a_argv, void **a_json_arr_reply)
continue; continue;
} }
//CHECK value fee //CHECK value fee
l_list_used_out_fee = dap_ledger_get_list_tx_outs_with_val(l_net->pub.ledger, l_native_token, if (dap_chain_wallet_cache_tx_find_outs_with_val(l_net, l_native_token, l_addr_from, &l_list_used_out_fee, l_value_need_fee, &l_value_transfer_fee) == -101)
l_list_used_out_fee = dap_ledger_get_list_tx_outs_with_val(l_net->pub.ledger, l_native_token,
l_addr_from, l_value_need_fee, &l_value_transfer_fee); l_addr_from, l_value_need_fee, &l_value_transfer_fee);
if(!l_list_used_out_fee) { if(!l_list_used_out_fee) {
log_it(L_WARNING, "Not enough funds in previous tx to transfer"); log_it(L_WARNING, "Not enough funds in previous tx to transfer");
......
This diff is collapsed.
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#include "dap_chain_net_srv_stake_lock.h" #include "dap_chain_net_srv_stake_lock.h"
#include "dap_chain_net_tx.h" #include "dap_chain_net_tx.h"
#include "dap_chain_wallet.h" #include "dap_chain_wallet.h"
#include "dap_chain_wallet_cache.h"
#include "dap_chain_mempool.h" #include "dap_chain_mempool.h"
#include "dap_chain_net_srv.h" #include "dap_chain_net_srv.h"
#include "dap_cli_server.h" #include "dap_cli_server.h"
...@@ -1142,7 +1143,8 @@ static dap_chain_datum_t *s_stake_lock_datum_create(dap_chain_net_t *a_net, dap_ ...@@ -1142,7 +1143,8 @@ static dap_chain_datum_t *s_stake_lock_datum_create(dap_chain_net_t *a_net, dap_
if (l_main_native) if (l_main_native)
SUM_256_256(l_value_need, l_total_fee, &l_value_need); SUM_256_256(l_value_need, l_total_fee, &l_value_need);
else if (!IS_ZERO_256(l_total_fee)) { else if (!IS_ZERO_256(l_total_fee)) {
l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(a_net->pub.ledger, l_native_ticker, if (dap_chain_wallet_cache_tx_find_outs_with_val(a_net, l_native_ticker, &l_addr, &l_list_fee_out, l_total_fee, &l_fee_transfer) == -101)
l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(a_net->pub.ledger, l_native_ticker,
&l_addr, l_total_fee, &l_fee_transfer); &l_addr, l_total_fee, &l_fee_transfer);
if (!l_list_fee_out) { if (!l_list_fee_out) {
log_it(L_WARNING, "Not enough funds to pay fee"); log_it(L_WARNING, "Not enough funds to pay fee");
...@@ -1150,8 +1152,10 @@ static dap_chain_datum_t *s_stake_lock_datum_create(dap_chain_net_t *a_net, dap_ ...@@ -1150,8 +1152,10 @@ static dap_chain_datum_t *s_stake_lock_datum_create(dap_chain_net_t *a_net, dap_
} }
} }
// list of transaction with 'out' items // list of transaction with 'out' items
dap_list_t *l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, a_main_ticker, dap_list_t *l_list_used_out = NULL;
&l_addr, l_value_need, &l_value_transfer); if (dap_chain_wallet_cache_tx_find_outs_with_val(l_ledger->net, a_main_ticker, &l_addr, &l_list_used_out, l_value_need, &l_value_transfer) == -101)
l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, a_main_ticker,
&l_addr, l_value_need, &l_value_transfer);
if(!l_list_used_out) { if(!l_list_used_out) {
log_it( L_ERROR, "Nothing to transfer (not enough funds)"); log_it( L_ERROR, "Nothing to transfer (not enough funds)");
return NULL; return NULL;
...@@ -1285,7 +1289,8 @@ dap_chain_datum_t *s_stake_unlock_datum_create(dap_chain_net_t *a_net, dap_enc_k ...@@ -1285,7 +1289,8 @@ dap_chain_datum_t *s_stake_unlock_datum_create(dap_chain_net_t *a_net, dap_enc_k
SUM_256_256(l_net_fee, a_value_fee, &l_total_fee); SUM_256_256(l_net_fee, a_value_fee, &l_total_fee);
if (!IS_ZERO_256(l_total_fee)) { if (!IS_ZERO_256(l_total_fee)) {
if (!l_main_native) { if (!l_main_native) {
l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(a_net->pub.ledger, l_native_ticker, if (dap_chain_wallet_cache_tx_find_outs_with_val(a_net, l_native_ticker, &l_addr, &l_list_fee_out, l_total_fee, &l_fee_transfer) == -101)
l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(a_net->pub.ledger, l_native_ticker,
&l_addr, l_total_fee, &l_fee_transfer); &l_addr, l_total_fee, &l_fee_transfer);
if (!l_list_fee_out) { if (!l_list_fee_out) {
log_it(L_WARNING, "Not enough funds to pay fee"); log_it(L_WARNING, "Not enough funds to pay fee");
...@@ -1297,7 +1302,8 @@ dap_chain_datum_t *s_stake_unlock_datum_create(dap_chain_net_t *a_net, dap_enc_k ...@@ -1297,7 +1302,8 @@ dap_chain_datum_t *s_stake_unlock_datum_create(dap_chain_net_t *a_net, dap_enc_k
} }
} }
if (!IS_ZERO_256(a_delegated_value)) { if (!IS_ZERO_256(a_delegated_value)) {
l_list_used_out = dap_ledger_get_list_tx_outs_with_val(a_net->pub.ledger, a_delegated_ticker_str, if (dap_chain_wallet_cache_tx_find_outs_with_val(a_net, a_delegated_ticker_str, &l_addr, &l_list_used_out, a_delegated_value, &l_value_transfer) == -101)
l_list_used_out = dap_ledger_get_list_tx_outs_with_val(a_net->pub.ledger, a_delegated_ticker_str,
&l_addr, a_delegated_value, &l_value_transfer); &l_addr, a_delegated_value, &l_value_transfer);
if(!l_list_used_out) { if(!l_list_used_out) {
log_it( L_ERROR, "Nothing to transfer (not enough delegated tokens)"); log_it( L_ERROR, "Nothing to transfer (not enough delegated tokens)");
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <math.h> #include <math.h>
#include "dap_chain_wallet.h" #include "dap_chain_wallet.h"
#include "dap_chain_wallet_cache.h"
#include "dap_config.h" #include "dap_config.h"
#include "dap_string.h" #include "dap_string.h"
#include "dap_list.h" #include "dap_list.h"
...@@ -737,7 +738,10 @@ static dap_chain_datum_tx_t *s_stake_tx_create(dap_chain_net_t * a_net, dap_enc_ ...@@ -737,7 +738,10 @@ static dap_chain_datum_tx_t *s_stake_tx_create(dap_chain_net_t * a_net, dap_enc_
bool l_net_fee_used = dap_chain_net_tx_get_fee(a_net->pub.id, &l_net_fee, &l_net_fee_addr); bool l_net_fee_used = dap_chain_net_tx_get_fee(a_net->pub.id, &l_net_fee, &l_net_fee_addr);
if (l_net_fee_used) if (l_net_fee_used)
SUM_256_256(l_fee_total, l_net_fee, &l_fee_total); SUM_256_256(l_fee_total, l_net_fee, &l_fee_total);
dap_list_t *l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker,
dap_list_t *l_list_fee_out = NULL;
if (dap_chain_wallet_cache_tx_find_outs_with_val(a_net, l_native_ticker, &l_owner_addr, &l_list_fee_out, l_fee_total, &l_fee_transfer) == -101)
l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker,
&l_owner_addr, l_fee_total, &l_fee_transfer); &l_owner_addr, l_fee_total, &l_fee_transfer);
if (!l_list_fee_out) { if (!l_list_fee_out) {
log_it(L_WARNING, "Nothing to pay for fee (not enough funds)"); log_it(L_WARNING, "Nothing to pay for fee (not enough funds)");
...@@ -748,7 +752,9 @@ static dap_chain_datum_tx_t *s_stake_tx_create(dap_chain_net_t * a_net, dap_enc_ ...@@ -748,7 +752,9 @@ static dap_chain_datum_tx_t *s_stake_tx_create(dap_chain_net_t * a_net, dap_enc_
dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create();
if (!a_prev_tx) { if (!a_prev_tx) {
dap_list_t *l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_delegated_ticker, dap_list_t *l_list_used_out = NULL ;
if (dap_chain_wallet_cache_tx_find_outs_with_val(a_net, l_delegated_ticker, &l_owner_addr, &l_list_used_out, a_value, &l_value_transfer) == -101)
l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_delegated_ticker,
&l_owner_addr, a_value, &l_value_transfer); &l_owner_addr, a_value, &l_value_transfer);
if (!l_list_used_out) { if (!l_list_used_out) {
log_it(L_WARNING, "Nothing to pay for delegate (not enough funds)"); log_it(L_WARNING, "Nothing to pay for delegate (not enough funds)");
...@@ -856,7 +862,9 @@ static dap_chain_datum_tx_t *s_stake_tx_update(dap_chain_net_t *a_net, dap_hash_ ...@@ -856,7 +862,9 @@ static dap_chain_datum_tx_t *s_stake_tx_update(dap_chain_net_t *a_net, dap_hash_
bool l_net_fee_used = dap_chain_net_tx_get_fee(a_net->pub.id, &l_net_fee, &l_net_fee_addr); bool l_net_fee_used = dap_chain_net_tx_get_fee(a_net->pub.id, &l_net_fee, &l_net_fee_addr);
if (l_net_fee_used) if (l_net_fee_used)
SUM_256_256(l_fee_total, l_net_fee, &l_fee_total); SUM_256_256(l_fee_total, l_net_fee, &l_fee_total);
dap_list_t *l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker, dap_list_t *l_list_fee_out = NULL;
if (dap_chain_wallet_cache_tx_find_outs_with_val(a_net, l_native_ticker, &l_owner_addr, &l_list_fee_out, l_fee_total, &l_fee_transfer) == -101)
l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker,
&l_owner_addr, l_fee_total, &l_fee_transfer); &l_owner_addr, l_fee_total, &l_fee_transfer);
if (!l_list_fee_out) { if (!l_list_fee_out) {
log_it(L_WARNING, "Nothing to pay for fee (not enough funds)"); log_it(L_WARNING, "Nothing to pay for fee (not enough funds)");
...@@ -895,7 +903,9 @@ static dap_chain_datum_tx_t *s_stake_tx_update(dap_chain_net_t *a_net, dap_hash_ ...@@ -895,7 +903,9 @@ static dap_chain_datum_tx_t *s_stake_tx_update(dap_chain_net_t *a_net, dap_hash_
if (l_increasing) { if (l_increasing) {
uint256_t l_refund_value = {}; uint256_t l_refund_value = {};
SUBTRACT_256_256(a_new_value, l_value_prev, &l_refund_value); SUBTRACT_256_256(a_new_value, l_value_prev, &l_refund_value);
dap_list_t *l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_delegated_ticker, dap_list_t *l_list_used_out = NULL;
if (dap_chain_wallet_cache_tx_find_outs_with_val(a_net, l_delegated_ticker, &l_owner_addr, &l_list_used_out, l_refund_value, &l_value_transfer) == -101)
l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_delegated_ticker,
&l_owner_addr, l_refund_value, &l_value_transfer); &l_owner_addr, l_refund_value, &l_value_transfer);
if (!l_list_used_out) { if (!l_list_used_out) {
log_it(L_WARNING, "Nothing to pay for delegate (not enough funds)"); log_it(L_WARNING, "Nothing to pay for delegate (not enough funds)");
...@@ -1212,7 +1222,9 @@ static dap_chain_datum_tx_t *s_stake_tx_invalidate(dap_chain_net_t *a_net, dap_h ...@@ -1212,7 +1222,9 @@ static dap_chain_datum_tx_t *s_stake_tx_invalidate(dap_chain_net_t *a_net, dap_h
bool l_net_fee_used = dap_chain_net_tx_get_fee(a_net->pub.id, &l_net_fee, &l_net_fee_addr); bool l_net_fee_used = dap_chain_net_tx_get_fee(a_net->pub.id, &l_net_fee, &l_net_fee_addr);
if (l_net_fee_used) if (l_net_fee_used)
SUM_256_256(l_fee_total, l_net_fee, &l_fee_total); SUM_256_256(l_fee_total, l_net_fee, &l_fee_total);
dap_list_t *l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker, dap_list_t *l_list_fee_out = NULL;
if (dap_chain_wallet_cache_tx_find_outs_with_val(a_net, l_native_ticker, &l_owner_addr, &l_list_fee_out, l_fee_total, &l_fee_transfer) == -101)
l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker,
&l_owner_addr, l_fee_total, &l_fee_transfer); &l_owner_addr, l_fee_total, &l_fee_transfer);
if (!l_list_fee_out) { if (!l_list_fee_out) {
log_it(L_WARNING, "Nothing to pay for fee (not enough funds)"); log_it(L_WARNING, "Nothing to pay for fee (not enough funds)");
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
#include "uthash.h" #include "uthash.h"
#include "utlist.h" #include "utlist.h"
#include "dap_cli_server.h" #include "dap_cli_server.h"
#include "dap_chain_wallet_cache.h"
#define LOG_TAG "chain_net_voting" #define LOG_TAG "chain_net_voting"
...@@ -1266,7 +1267,9 @@ int dap_chain_net_vote_create(const char *a_question, dap_list_t *a_options, dap ...@@ -1266,7 +1267,9 @@ int dap_chain_net_vote_create(const char *a_question, dap_list_t *a_options, dap
SUM_256_256(l_net_fee, a_fee, &l_total_fee); SUM_256_256(l_net_fee, a_fee, &l_total_fee);
dap_ledger_t* l_ledger = a_net->pub.ledger; dap_ledger_t* l_ledger = a_net->pub.ledger;
dap_list_t *l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker, dap_list_t *l_list_used_out = NULL;
if (dap_chain_wallet_cache_tx_find_outs_with_val(a_net, l_native_ticker, l_addr_from, &l_list_used_out, l_total_fee, &l_value_transfer) == -101)
l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker,
l_addr_from, l_total_fee, &l_value_transfer); l_addr_from, l_total_fee, &l_value_transfer);
if (!l_list_used_out) { if (!l_list_used_out) {
return DAP_CHAIN_NET_VOTE_CREATE_NOT_ENOUGH_FUNDS_TO_TRANSFER; return DAP_CHAIN_NET_VOTE_CREATE_NOT_ENOUGH_FUNDS_TO_TRANSFER;
......
...@@ -46,6 +46,7 @@ ...@@ -46,6 +46,7 @@
#include "dap_chain_net_srv_xchange.h" #include "dap_chain_net_srv_xchange.h"
#include "uthash.h" #include "uthash.h"
#include "dap_cli_server.h" #include "dap_cli_server.h"
#include "dap_chain_wallet_cache.h"
#define LOG_TAG "dap_chain_net_srv_xchange" #define LOG_TAG "dap_chain_net_srv_xchange"
...@@ -478,7 +479,8 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_request(dap_chain_net_srv_xchan ...@@ -478,7 +479,8 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_request(dap_chain_net_srv_xchan
if (l_single_channel) if (l_single_channel)
SUM_256_256(l_value_need, l_total_fee, &l_value_need); SUM_256_256(l_value_need, l_total_fee, &l_value_need);
else { else {
l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker, if (dap_chain_wallet_cache_tx_find_outs_with_val(l_ledger->net, l_native_ticker, &l_seller_addr, &l_list_fee_out, l_total_fee, &l_fee_transfer) == -101)
l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker,
&l_seller_addr, l_total_fee, &l_fee_transfer); &l_seller_addr, l_total_fee, &l_fee_transfer);
if (!l_list_fee_out) { if (!l_list_fee_out) {
log_it(L_WARNING, "Not enough funds to pay fee"); log_it(L_WARNING, "Not enough funds to pay fee");
...@@ -486,7 +488,9 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_request(dap_chain_net_srv_xchan ...@@ -486,7 +488,9 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_request(dap_chain_net_srv_xchan
} }
} }
// list of transaction with 'out' items to sell // list of transaction with 'out' items to sell
dap_list_t *l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, a_price->token_sell, dap_list_t *l_list_used_out = NULL;
if (dap_chain_wallet_cache_tx_find_outs_with_val(l_ledger->net, a_price->token_sell, &l_seller_addr, &l_list_used_out, l_value_need, &l_value_transfer) == -101)
l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, a_price->token_sell,
&l_seller_addr, l_value_need, &l_value_transfer); &l_seller_addr, l_value_need, &l_value_transfer);
if(!l_list_used_out) { if(!l_list_used_out) {
log_it(L_WARNING, "Nothing to change from %s (not enough funds in %s (%s))", log_it(L_WARNING, "Nothing to change from %s (not enough funds in %s (%s))",
...@@ -634,7 +638,9 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha ...@@ -634,7 +638,9 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha
DAP_DELETE(l_wallet_addr); DAP_DELETE(l_wallet_addr);
// list of transaction with 'out' items to sell // list of transaction with 'out' items to sell
dap_list_t *l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, a_price->token_buy, dap_list_t *l_list_used_out = NULL;
if (dap_chain_wallet_cache_tx_find_outs_with_val(l_ledger->net, a_price->token_buy, &l_buyer_addr, &l_list_used_out, l_value_need, &l_value_transfer) == -101)
l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, a_price->token_buy,
&l_buyer_addr, l_value_need, &l_value_transfer); &l_buyer_addr, l_value_need, &l_value_transfer);
if (!l_list_used_out) { if (!l_list_used_out) {
log_it(L_WARNING, "Nothing to change from %s (not enough funds in %s (%s))", log_it(L_WARNING, "Nothing to change from %s (not enough funds in %s (%s))",
...@@ -647,8 +653,9 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha ...@@ -647,8 +653,9 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha
if (l_buy_with_native) if (l_buy_with_native)
SUM_256_256(l_value_need, l_total_fee, &l_value_need); SUM_256_256(l_value_need, l_total_fee, &l_value_need);
else { else {
l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker, if (dap_chain_wallet_cache_tx_find_outs_with_val(l_ledger->net, l_native_ticker, &l_buyer_addr, &l_list_fee_out, l_total_fee, &l_fee_transfer) == -101)
&l_buyer_addr, l_total_fee, &l_fee_transfer); l_list_fee_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker,
&l_buyer_addr, l_total_fee, &l_fee_transfer);
if (!l_list_fee_out) { if (!l_list_fee_out) {
dap_list_free_full(l_list_used_out, NULL); dap_list_free_full(l_list_used_out, NULL);
log_it(L_WARNING, "Not enough funds to pay fee"); log_it(L_WARNING, "Not enough funds to pay fee");
...@@ -1050,7 +1057,9 @@ static char* s_xchange_tx_invalidate(dap_chain_net_srv_xchange_price_t *a_price, ...@@ -1050,7 +1057,9 @@ static char* s_xchange_tx_invalidate(dap_chain_net_srv_xchange_price_t *a_price,
if (!l_single_channel) { if (!l_single_channel) {
uint256_t l_transfer_fee = {}, l_fee_back = {}; uint256_t l_transfer_fee = {}, l_fee_back = {};
// list of transaction with 'out' items to get net fee // list of transaction with 'out' items to get net fee
dap_list_t *l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker, dap_list_t *l_list_used_out = NULL;
if (dap_chain_wallet_cache_tx_find_outs_with_val(l_ledger->net, l_native_ticker, &l_seller_addr, &l_list_used_out, l_total_fee, &l_transfer_fee) == -101)
l_list_used_out = dap_ledger_get_list_tx_outs_with_val(l_ledger, l_native_ticker,
&l_seller_addr, l_total_fee, &l_transfer_fee); &l_seller_addr, l_total_fee, &l_transfer_fee);
if (!l_list_used_out) { if (!l_list_used_out) {
dap_chain_datum_tx_delete(l_tx); dap_chain_datum_tx_delete(l_tx);
......
...@@ -180,7 +180,7 @@ static bool s_debug_more = false; ...@@ -180,7 +180,7 @@ static bool s_debug_more = false;
int dap_chain_cs_blocks_init() int dap_chain_cs_blocks_init()
{ {
dap_chain_block_init(); dap_chain_block_init();
dap_chain_cs_type_add("blocks", s_chain_cs_blocks_new); dap_chain_cs_type_add("blocks", s_chain_cs_blocks_new, NULL);
s_seed_mode = dap_config_get_item_bool_default(g_config,"general","seed_mode",false); s_seed_mode = dap_config_get_item_bool_default(g_config,"general","seed_mode",false);
s_debug_more = dap_config_get_item_bool_default(g_config, "blocks", "debug_more", false); s_debug_more = dap_config_get_item_bool_default(g_config, "blocks", "debug_more", false);
dap_cli_server_cmd_add ("block", s_cli_blocks, "Create and explore blockchains", dap_cli_server_cmd_add ("block", s_cli_blocks, "Create and explore blockchains",
...@@ -1528,27 +1528,30 @@ static int s_add_atom_datums(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_ca ...@@ -1528,27 +1528,30 @@ static int s_add_atom_datums(dap_chain_cs_blocks_t *a_blocks, dap_chain_block_ca
dap_ledger_datum_iter_data_t l_datum_index_data = { .token_ticker = "0", .action = DAP_CHAIN_TX_TAG_ACTION_UNKNOWN , .uid.uint64 = 0 }; dap_ledger_datum_iter_data_t l_datum_index_data = { .token_ticker = "0", .action = DAP_CHAIN_TX_TAG_ACTION_UNKNOWN , .uid.uint64 = 0 };
int l_res = dap_chain_datum_add(a_blocks->chain, l_datum, l_datum_size, l_datum_hash, &l_datum_index_data); int l_res = dap_chain_datum_add(a_blocks->chain, l_datum, l_datum_size, l_datum_hash, &l_datum_index_data);
l_ret++; if (l_datum->header.type_id != DAP_CHAIN_DATUM_TX || l_res != DAP_LEDGER_CHECK_ALREADY_CACHED){ // If this is any datum other than a already cached transaction
if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX) l_ret++;
PVT(a_blocks)->tx_count++; if (l_datum->header.type_id == DAP_CHAIN_DATUM_TX)
// Save datum hash -> block_hash link in hash table PVT(a_blocks)->tx_count++;
dap_chain_block_datum_index_t *l_datum_index = DAP_NEW_Z(dap_chain_block_datum_index_t); // Save datum hash -> block_hash link in hash table
if (!l_datum_index) { dap_chain_block_datum_index_t *l_datum_index = DAP_NEW_Z(dap_chain_block_datum_index_t);
log_it(L_CRITICAL, "%s", c_error_memory_alloc); if (!l_datum_index) {
return 1; log_it(L_CRITICAL, "%s", c_error_memory_alloc);
return 1;
}
l_datum_index->ts_added = time(NULL);
l_datum_index->block_cache = a_block_cache;
l_datum_index->datum_hash = *l_datum_hash;
l_datum_index->ret_code = l_res;
l_datum_index->datum_index = i;
l_datum_index->action = l_datum_index_data.action;
l_datum_index->service_uid = l_datum_index_data.uid;
dap_strncpy(l_datum_index->token_ticker, l_datum_index_data.token_ticker, DAP_CHAIN_TICKER_SIZE_MAX);
pthread_rwlock_wrlock(&PVT(a_blocks)->datums_rwlock);
HASH_ADD(hh, PVT(a_blocks)->datum_index, datum_hash, sizeof(*l_datum_hash), l_datum_index);
pthread_rwlock_unlock(&PVT(a_blocks)->datums_rwlock);
dap_chain_cell_t *l_cell = dap_chain_cell_find_by_id(a_blocks->chain, a_blocks->chain->active_cell_id);
dap_chain_datum_notify(l_cell, l_datum_hash, (byte_t*)l_datum, l_datum_size, l_res, l_datum_index_data.action, l_datum_index_data.uid);
} }
l_datum_index->ts_added = time(NULL);
l_datum_index->block_cache = a_block_cache;
l_datum_index->datum_hash = *l_datum_hash;
l_datum_index->ret_code = l_res;
l_datum_index->datum_index = i;
l_datum_index->action = l_datum_index_data.action;
l_datum_index->service_uid = l_datum_index_data.uid;
dap_strncpy(l_datum_index->token_ticker, l_datum_index_data.token_ticker, DAP_CHAIN_TICKER_SIZE_MAX);
pthread_rwlock_wrlock(&PVT(a_blocks)->datums_rwlock);
HASH_ADD(hh, PVT(a_blocks)->datum_index, datum_hash, sizeof(*l_datum_hash), l_datum_index);
pthread_rwlock_unlock(&PVT(a_blocks)->datums_rwlock);
} }
debug_if(s_debug_more, L_DEBUG, "Block %s checked, %s", a_block_cache->block_hash_str, debug_if(s_debug_more, L_DEBUG, "Block %s checked, %s", a_block_cache->block_hash_str,
l_ret == (int)a_block_cache->datum_count ? "all correct" : "there are rejected datums"); l_ret == (int)a_block_cache->datum_count ? "all correct" : "there are rejected datums");
...@@ -1579,6 +1582,9 @@ static int s_delete_atom_datums(dap_chain_cs_blocks_t *a_blocks, dap_chain_block ...@@ -1579,6 +1582,9 @@ static int s_delete_atom_datums(dap_chain_cs_blocks_t *a_blocks, dap_chain_block
dap_chain_datum_remove(a_blocks->chain, l_datum, l_datum_size, l_datum_hash); dap_chain_datum_remove(a_blocks->chain, l_datum, l_datum_size, l_datum_hash);
l_ret++; l_ret++;
HASH_DEL(PVT(a_blocks)->datum_index, l_datum_index); HASH_DEL(PVT(a_blocks)->datum_index, l_datum_index);
// notify datum removed
dap_chain_cell_t *l_cell = dap_chain_cell_find_by_id(a_blocks->chain, a_blocks->chain->active_cell_id);
dap_chain_datum_removed_notify(l_cell, l_datum_hash);
} }
} }
debug_if(s_debug_more, L_DEBUG, "Block %s checked, %s", a_block_cache->block_hash_str, debug_if(s_debug_more, L_DEBUG, "Block %s checked, %s", a_block_cache->block_hash_str,
......
...@@ -84,13 +84,14 @@ typedef struct dap_chain_cs_dag_pvt { ...@@ -84,13 +84,14 @@ typedef struct dap_chain_cs_dag_pvt {
dap_chain_cs_dag_event_item_t * events_treshold_conflicted; dap_chain_cs_dag_event_item_t * events_treshold_conflicted;
dap_chain_cs_dag_event_item_t * events_lasts_unlinked; dap_chain_cs_dag_event_item_t * events_lasts_unlinked;
dap_chain_cs_dag_blocked_t *removed_events_from_treshold; dap_chain_cs_dag_blocked_t *removed_events_from_treshold;
dap_interval_timer_t treshold_fee_timer; dap_interval_timer_t treshold_free_timer;
uint64_t tx_count; uint64_t tx_count;
} dap_chain_cs_dag_pvt_t; } dap_chain_cs_dag_pvt_t;
#define PVT(a) ((dap_chain_cs_dag_pvt_t *) a->_pvt ) #define PVT(a) ((dap_chain_cs_dag_pvt_t *) a->_pvt )
static int s_chain_cs_dag_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg); static int s_chain_cs_dag_new(dap_chain_t *a_chain, dap_config_t *a_chain_cfg);
static void s_chain_cs_dag_start(dap_chain_t *a_chain);
static void s_chain_cs_dag_delete(dap_chain_t *a_chain); static void s_chain_cs_dag_delete(dap_chain_t *a_chain);
static void s_dap_chain_cs_dag_purge(dap_chain_t *a_chain); static void s_dap_chain_cs_dag_purge(dap_chain_t *a_chain);
static void s_threshold_free(dap_chain_cs_dag_t *a_dag); static void s_threshold_free(dap_chain_cs_dag_t *a_dag);
...@@ -147,7 +148,7 @@ static bool s_seed_mode = false, s_debug_more = false, s_threshold_enabled = fal ...@@ -147,7 +148,7 @@ static bool s_seed_mode = false, s_debug_more = false, s_threshold_enabled = fal
int dap_chain_cs_dag_init() int dap_chain_cs_dag_init()
{ {
srand((unsigned int) time(NULL)); srand((unsigned int) time(NULL));
dap_chain_cs_type_add( "dag", s_chain_cs_dag_new ); dap_chain_cs_type_add( "dag", s_chain_cs_dag_new, s_chain_cs_dag_start);
s_seed_mode = dap_config_get_item_bool_default(g_config, "general", "seed_mode", false); s_seed_mode = dap_config_get_item_bool_default(g_config, "general", "seed_mode", false);
s_debug_more = dap_config_get_item_bool_default(g_config, "dag", "debug_more", false); s_debug_more = dap_config_get_item_bool_default(g_config, "dag", "debug_more", false);
s_threshold_enabled = dap_config_get_item_bool_default(g_config, "dag", "threshold_enabled",false); s_threshold_enabled = dap_config_get_item_bool_default(g_config, "dag", "threshold_enabled",false);
...@@ -190,7 +191,7 @@ void dap_chain_cs_dag_deinit(void) ...@@ -190,7 +191,7 @@ void dap_chain_cs_dag_deinit(void)
*/ */
static int s_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) static int s_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
{ {
dap_chain_cs_dag_t * l_dag = DAP_NEW_Z(dap_chain_cs_dag_t); dap_chain_cs_dag_t *l_dag = DAP_NEW_Z(dap_chain_cs_dag_t);
if (!l_dag){ if (!l_dag){
log_it(L_CRITICAL, "%s", c_error_memory_alloc); log_it(L_CRITICAL, "%s", c_error_memory_alloc);
return -1; return -1;
...@@ -288,13 +289,22 @@ static int s_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg) ...@@ -288,13 +289,22 @@ static int s_chain_cs_dag_new(dap_chain_t * a_chain, dap_config_t * a_chain_cfg)
l_dag->gdb_group_events_round_new = dap_strdup_printf(l_dag->is_celled ? "dag-%s-%s-%016llx-round.new" : "dag-%s-%s-round.new", l_dag->gdb_group_events_round_new = dap_strdup_printf(l_dag->is_celled ? "dag-%s-%s-%016llx-round.new" : "dag-%s-%s-round.new",
"Snet", a_chain->name, 0LLU); "Snet", a_chain->name, 0LLU);
#endif #endif
PVT(l_dag)->treshold_fee_timer = dap_interval_timer_create(900000, (dap_timer_callback_t)s_threshold_free, l_dag);
log_it (L_NOTICE, "DAG chain initialized (%s)", l_dag->is_single_line ? "single line" : "multichain"); log_it (L_NOTICE, "DAG chain initialized (%s)", l_dag->is_single_line ? "single line" : "multichain");
return 0; return 0;
} }
/**
* @brief s_chain_cs_dag_start
* @param a_chain
*/
static void s_chain_cs_dag_start(dap_chain_t *a_chain)
{
dap_return_if_pass(!a_chain || !a_chain->_inheritor);
dap_chain_cs_dag_t *l_dag = a_chain->_inheritor;
dap_return_if_pass(!PVT(l_dag));
PVT(l_dag)->treshold_free_timer = dap_interval_timer_create(900000, (dap_timer_callback_t)s_threshold_free, l_dag);
}
static void s_threshold_free(dap_chain_cs_dag_t *a_dag) static void s_threshold_free(dap_chain_cs_dag_t *a_dag)
{ {
dap_chain_cs_dag_pvt_t *l_pvt = PVT(a_dag); dap_chain_cs_dag_pvt_t *l_pvt = PVT(a_dag);
...@@ -378,8 +388,11 @@ static void s_dap_chain_cs_dag_purge(dap_chain_t *a_chain) ...@@ -378,8 +388,11 @@ static void s_dap_chain_cs_dag_purge(dap_chain_t *a_chain)
*/ */
static void s_chain_cs_dag_delete(dap_chain_t * a_chain) static void s_chain_cs_dag_delete(dap_chain_t * a_chain)
{ {
dap_return_if_pass(!a_chain || !a_chain->_inheritor);
dap_chain_cs_dag_t *l_dag = DAP_CHAIN_CS_DAG ( a_chain );
dap_return_if_pass(!PVT(l_dag));
dap_interval_timer_delete(PVT(l_dag)->treshold_free_timer);
s_dap_chain_cs_dag_purge(a_chain); s_dap_chain_cs_dag_purge(a_chain);
dap_chain_cs_dag_t * l_dag = DAP_CHAIN_CS_DAG ( a_chain );
pthread_mutex_destroy(& PVT(l_dag)->events_mutex); pthread_mutex_destroy(& PVT(l_dag)->events_mutex);
if(l_dag->callback_delete ) if(l_dag->callback_delete )
l_dag->callback_delete(l_dag); l_dag->callback_delete(l_dag);
......
...@@ -72,6 +72,11 @@ ...@@ -72,6 +72,11 @@
#define LOG_TAG "dap_chain_wallet" #define LOG_TAG "dap_chain_wallet"
typedef struct dap_chain_wallet_notificator {
dap_chain_wallet_opened_callback_t callback;
void *arg;
} dap_chain_wallet_notificator_t;
#ifndef DAP_OS_WINDOWS /* An argument for open()/create() */ #ifndef DAP_OS_WINDOWS /* An argument for open()/create() */
static const mode_t s_fileprot = ( S_IREAD | S_IWRITE) | (S_IREAD >> 3) | (S_IREAD >> 6) ; static const mode_t s_fileprot = ( S_IREAD | S_IWRITE) | (S_IREAD >> 3) | (S_IREAD >> 6) ;
#endif #endif
...@@ -79,6 +84,8 @@ static char const s_wallet_ext [] = ".dwallet", *s_wallets_path = NULL; ...@@ -79,6 +84,8 @@ static char const s_wallet_ext [] = ".dwallet", *s_wallets_path = NULL;
static pthread_rwlock_t s_wallet_n_pass_lock = PTHREAD_RWLOCK_INITIALIZER; /* Coordinate access to the hash-table */ static pthread_rwlock_t s_wallet_n_pass_lock = PTHREAD_RWLOCK_INITIALIZER; /* Coordinate access to the hash-table */
static dap_chain_wallet_n_pass_t *s_wallet_n_pass; /* A hash table to keep passwords for wallets */ static dap_chain_wallet_n_pass_t *s_wallet_n_pass; /* A hash table to keep passwords for wallets */
static dap_list_t *s_wallet_open_notificators = NULL;
static dap_list_t *s_wallet_created_notificators = NULL;
struct wallet_addr_cache { struct wallet_addr_cache {
char name[DAP_WALLET$SZ_NAME + 1]; char name[DAP_WALLET$SZ_NAME + 1];
...@@ -437,6 +444,18 @@ dap_chain_wallet_internal_t *l_wallet_internal = NULL; ...@@ -437,6 +444,18 @@ dap_chain_wallet_internal_t *l_wallet_internal = NULL;
} }
l_wallet->_internal = l_wallet_internal; l_wallet->_internal = l_wallet_internal;
if ( !dap_chain_wallet_save(l_wallet, a_pass) ) {
log_it(L_INFO, "Wallet %s has been created (%s)", a_wallet_name, l_wallet_internal->file_name);
for (dap_list_t *l_tmp = s_wallet_created_notificators; l_tmp; l_tmp=l_tmp->next){
dap_chain_wallet_notificator_t *l_notificator = (dap_chain_wallet_notificator_t*)l_tmp->data;
if (l_notificator->callback)
l_notificator->callback(l_wallet, l_notificator->arg);
}
return l_wallet;
}
return dap_chain_wallet_save(l_wallet, a_pass) return dap_chain_wallet_save(l_wallet, a_pass)
? ( log_it(L_ERROR,"Can't save the new wallet (%s) to disk, errno=%d", l_wallet_internal->file_name, errno), ? ( log_it(L_ERROR,"Can't save the new wallet (%s) to disk, errno=%d", l_wallet_internal->file_name, errno),
dap_chain_wallet_close(l_wallet), dap_chain_wallet_close(l_wallet),
...@@ -988,6 +1007,12 @@ uint32_t l_csum = CRC32C_INIT, l_csum2 = CRC32C_INIT; ...@@ -988,6 +1007,12 @@ uint32_t l_csum = CRC32C_INIT, l_csum2 = CRC32C_INIT;
s_wallet_addr_cache_add(l_addr, l_wallet->name); s_wallet_addr_cache_add(l_addr, l_wallet->name);
DAP_DELETE(l_addr); DAP_DELETE(l_addr);
} }
for (dap_list_t *l_tmp = s_wallet_open_notificators; l_tmp; l_tmp=l_tmp->next){
dap_chain_wallet_notificator_t *l_notificator = (dap_chain_wallet_notificator_t*)l_tmp->data;
if (l_notificator->callback)
l_notificator->callback(l_wallet, l_notificator->arg);
}
} }
return l_wallet; return l_wallet;
...@@ -1070,6 +1095,33 @@ const char* dap_chain_wallet_check_sign(dap_chain_wallet_t *a_wallet) { ...@@ -1070,6 +1095,33 @@ const char* dap_chain_wallet_check_sign(dap_chain_wallet_t *a_wallet) {
return ""; return "";
} }
int dap_chain_wallet_add_wallet_opened_notify(dap_chain_wallet_opened_callback_t a_callback, void *a_arg)
{
if (!a_callback)
return -100;
dap_chain_wallet_notificator_t *l_notificator = DAP_NEW_Z(dap_chain_wallet_notificator_t);
l_notificator->callback = a_callback;
l_notificator->arg = a_arg;
s_wallet_open_notificators = dap_list_append(s_wallet_open_notificators, l_notificator);
return 0;
}
int dap_chain_wallet_add_wallet_created_notify(dap_chain_wallet_opened_callback_t a_callback, void *a_arg)
{
if (!a_callback)
return -100;
dap_chain_wallet_notificator_t *l_notificator = DAP_NEW_Z(dap_chain_wallet_notificator_t);
l_notificator->callback = a_callback;
l_notificator->arg = a_arg;
s_wallet_created_notificators = dap_list_append(s_wallet_created_notificators, l_notificator);
return 0;
}
json_object *dap_chain_wallet_info_to_json(const char *a_name, const char *a_path) { json_object *dap_chain_wallet_info_to_json(const char *a_name, const char *a_path) {
unsigned int res = 0; unsigned int res = 0;
dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(a_name, a_path, &res); dap_chain_wallet_t *l_wallet = dap_chain_wallet_open(a_name, a_path, &res);
......
/*
* Authors:
* Frolov Daniil <daniil.frolov@demlabs.com>
* DeM Labs Inc. https://demlabs.net
* DeM Labs Open source community https://github.com/demlabsinc
* Copyright (c) 2017-2018
* All rights reserved.
This file is part of DAP (Distributed Applications Platform) the open source project
DAP (Distributed Applications Platform) is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
DAP is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with any DAP based project. If not, see <http://www.gnu.org/licenses/>.
MODIFICATION HISTORY:
27-APR-2021 RRL Added password protected wallet support
*/
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <dirent.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <pthread.h>
#include "dap_chain_wallet_cache.h"
#include "dap_chain_wallet.h"
#include "dap_chain.h"
#include "dap_common.h"
#define LOG_TAG "dap_chain_wallet_cache"
typedef enum dap_s_wallets_cache_type{
DAP_WALLET_CACHE_TYPE_DISABLED = 0,
DAP_WALLET_CACHE_TYPE_LOCAL,
DAP_WALLET_CACHE_TYPE_ALL
} dap_s_wallets_cache_type_t;
typedef struct dap_wallet_tx_cache_input{
dap_chain_hash_fast_t tx_prev_hash;
uint32_t tx_out_prev_idx;
uint256_t value;
} dap_wallet_tx_cache_input_t;
typedef struct dap_wallet_tx_cache_output{
void* tx_out;
uint32_t tx_out_idx;
} dap_wallet_tx_cache_output_t;
typedef struct dap_wallet_tx_cache {
dap_hash_fast_t tx_hash;
dap_chain_datum_tx_t *tx;
char token_ticker[DAP_CHAIN_TICKER_SIZE_MAX];
bool multichannel;
int ret_code;
dap_chain_net_srv_uid_t tag;
dap_chain_tx_tag_action_type_t action;
dap_list_t *tx_wallet_inputs;
dap_list_t *tx_wallet_outputs;
UT_hash_handle hh;
} dap_wallet_tx_cache_t;
typedef struct dap_s_wallets_cache {
dap_chain_addr_t wallet_addr;
dap_wallet_tx_cache_t *wallet_txs;
UT_hash_handle hh;
} dap_wallet_cache_t;
typedef struct dap_atom_notify_arg {
dap_chain_t *chain;
dap_chain_net_t *net;
} dap_atom_notify_arg_t;
static dap_s_wallets_cache_type_t s_wallets_cache_type = DAP_WALLET_CACHE_TYPE_ALL;
static dap_wallet_cache_t *s_wallets_cache = NULL;
static pthread_rwlock_t s_wallet_cache_rwlock;
static int s_save_tx_into_wallet_cache(dap_chain_t *a_chain, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, int a_ret_code, char* a_main_token_ticker,
dap_chain_net_srv_uid_t a_srv_uid, dap_chain_tx_tag_action_type_t a_action);
static int s_save_tx_cache_for_addr(dap_chain_t *a_chain, dap_chain_addr_t *a_addr, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, int a_ret_code, char* a_main_token_ticker,
dap_chain_net_srv_uid_t a_srv_uid, dap_chain_tx_tag_action_type_t a_action);
static int s_save_cache_for_addr_in_net(dap_chain_net_t *a_net, dap_chain_addr_t *a_addr);
static void s_callback_datum_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_hash, void *a_datum,
size_t a_datum_size, int a_ret_code, uint32_t a_action,
dap_chain_net_srv_uid_t a_uid);
static void s_callback_datum_removed_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_hash);
static void s_wallet_opened_callback(dap_chain_wallet_t *a_wallet, void *a_arg);
static char * s_wallet_cache_type_to_str(dap_s_wallets_cache_type_t a_type)
{
switch (a_type){
case DAP_WALLET_CACHE_TYPE_DISABLED:
return "DISABLED";
case DAP_WALLET_CACHE_TYPE_LOCAL:
return "LOCAL";
case DAP_WALLET_CACHE_TYPE_ALL:
return "ALL";
default:
return "UNKNOWN";
}
}
int dap_chain_wallet_cache_init()
{
char *l_walet_cache_type_str = dap_config_get_item_str(g_config, "wallets","wallets_cache");
if (l_walet_cache_type_str){
if (!dap_strcmp(l_walet_cache_type_str, "disable")){
s_wallets_cache_type = DAP_WALLET_CACHE_TYPE_DISABLED;
} else if (!dap_strcmp(l_walet_cache_type_str, "local")){
s_wallets_cache_type = DAP_WALLET_CACHE_TYPE_LOCAL;
} else if (!dap_strcmp(l_walet_cache_type_str, "all")){
s_wallets_cache_type = DAP_WALLET_CACHE_TYPE_ALL;
} else {
log_it( L_WARNING, "Unknown cache type in config. Remain default: %s", s_wallet_cache_type_to_str(s_wallets_cache_type));
}
}
if (s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_DISABLED){
log_it( L_WARNING, "Wallet cache is disabled.");
return 0;
}
log_it(L_INFO, "Wallet cache type: %s", s_wallet_cache_type_to_str(s_wallets_cache_type));
pthread_rwlock_init(&s_wallet_cache_rwlock, NULL);
// Add notify callback for all chain with transactions in all nets
for(dap_chain_net_t *l_net = dap_chain_net_iter_start(); l_net; l_net=dap_chain_net_iter_next(l_net)){
// Find chain with transactions
dap_chain_t *l_chain = l_net->pub.chains;
while (l_chain){
for(int i = 0; i < l_chain->datum_types_count; i++) {
if(l_chain->datum_types[i] == CHAIN_TYPE_TX){
dap_atom_notify_arg_t *l_arg = DAP_NEW_Z(dap_atom_notify_arg_t);
l_arg->chain = l_chain;
l_arg->net = l_net;
dap_chain_datum_iter_t *l_iter = l_chain->callback_datum_iter_create(l_chain);
for (dap_chain_datum_t *l_datum = l_chain->callback_datum_iter_get_first(l_iter);
l_datum;
l_datum = l_chain->callback_datum_iter_get_next(l_iter)){
s_callback_datum_notify(l_arg, l_iter->cur_hash, l_datum, l_iter->cur_size, l_iter->ret_code, l_iter->action, l_iter->uid);
}
l_chain->callback_datum_iter_delete(l_iter);
dap_chain_add_callback_datum_index_notify(l_chain, s_callback_datum_notify, NULL, l_arg);
dap_chain_add_callback_datum_removed_from_index_notify(l_chain, s_callback_datum_removed_notify, NULL, l_arg);
}
}
l_chain=l_chain->next;
}
}
if (s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_LOCAL){
dap_chain_wallet_add_wallet_opened_notify(s_wallet_opened_callback, NULL);
dap_chain_wallet_add_wallet_created_notify(s_wallet_opened_callback, NULL);
}
return 0;
}
int dap_chain_wallet_cache_deinit()
{
return 0;
}
int dap_chain_wallet_cache_tx_find(dap_chain_addr_t *a_addr, char *a_token, dap_chain_datum_tx_t **a_datum, dap_hash_fast_t *a_tx_hash_curr, int* a_ret_code)
{
dap_wallet_cache_t *l_wallet_item = NULL;
pthread_rwlock_rdlock(&s_wallet_cache_rwlock);
HASH_FIND(hh, s_wallets_cache, a_addr, sizeof(dap_chain_addr_t), l_wallet_item);
if (!l_wallet_item){
log_it(L_ERROR, "Can't find wallet with address %s", dap_chain_addr_to_str_static(a_addr));
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
return -101;
}
dap_wallet_tx_cache_t *l_current_wallet_tx = NULL;
if (!dap_hash_fast_is_blank(a_tx_hash_curr)) {
// find start transaction
HASH_FIND(hh, l_wallet_item->wallet_txs, a_tx_hash_curr, sizeof(dap_chain_hash_fast_t), l_current_wallet_tx);
if (!l_current_wallet_tx){
log_it(L_ERROR, "Can't find tx %s for address %s", dap_hash_fast_to_str_static(a_tx_hash_curr), dap_chain_addr_to_str_static(a_addr));
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
return 0;
}
if (!l_current_wallet_tx->hh.next){
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
return 0;
}
// start searching from the next hash after a_tx_first_hash
l_current_wallet_tx = l_current_wallet_tx->hh.next;
} else {
// find wallet
l_current_wallet_tx = l_wallet_item->wallet_txs;
}
// Go iterate wallet txs
dap_wallet_tx_cache_t *l_current_wallet_tx_iter = NULL, *l_tmp = NULL;
HASH_ITER(hh, l_current_wallet_tx, l_current_wallet_tx_iter, l_tmp) {
if (l_current_wallet_tx_iter->ret_code != DAP_LEDGER_CHECK_OK)
continue;
bool skip = false;
if (a_token){
skip = true;
if (*l_current_wallet_tx_iter->token_ticker &&
!dap_strcmp(l_current_wallet_tx_iter->token_ticker, a_token))
{
skip = false;
} else if (l_current_wallet_tx_iter->multichannel){
for (dap_list_t *l_temp = l_current_wallet_tx_iter->tx_wallet_outputs; l_temp; l_temp=l_temp->next){
dap_wallet_tx_cache_output_t *l_cur_out_cache = (dap_wallet_tx_cache_output_t*)l_temp->data;
if ((*(dap_chain_tx_item_type_t*)l_cur_out_cache->tx_out == TX_ITEM_TYPE_OUT_EXT) && !dap_strcmp(a_token, ((dap_chain_tx_out_ext_t*)l_cur_out_cache->tx_out)->token)){
skip = false;
break;
}
}
}
}
if (skip)
continue;
// Now work with it
*a_tx_hash_curr = l_current_wallet_tx_iter->tx_hash;
if (a_datum)
*a_datum = l_current_wallet_tx_iter->tx;
if(a_ret_code)
*a_ret_code = l_current_wallet_tx_iter->ret_code;
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
return 0;
}
if (a_tx_hash_curr)
memset(a_tx_hash_curr, 0, sizeof(*a_tx_hash_curr));
if (a_datum)
*a_datum = NULL;
if(a_ret_code)
*a_ret_code = 0;
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
return 0;
}
int dap_chain_wallet_cache_tx_find_in_history(dap_chain_addr_t *a_addr, char **a_token, int* a_ret_code, dap_chain_tx_tag_action_type_t *a_action,
dap_chain_net_srv_uid_t *a_uid, dap_chain_datum_tx_t **a_datum, dap_hash_fast_t *a_tx_hash_curr)
{
dap_wallet_cache_t *l_wallet_item = NULL;
if (!a_tx_hash_curr)
return -100;
pthread_rwlock_rdlock(&s_wallet_cache_rwlock);
HASH_FIND(hh, s_wallets_cache, a_addr, sizeof(dap_chain_addr_t), l_wallet_item);
if (!l_wallet_item){
log_it(L_ERROR, "Can't find wallet with address %s", dap_chain_addr_to_str_static(a_addr));
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
return -101;
}
dap_wallet_tx_cache_t *l_current_wallet_tx = NULL;
if (!dap_hash_fast_is_blank(a_tx_hash_curr)) {
// find start transaction
HASH_FIND(hh, l_wallet_item->wallet_txs, a_tx_hash_curr, sizeof(dap_chain_hash_fast_t), l_current_wallet_tx);
if (l_current_wallet_tx && l_current_wallet_tx->hh.next){
// start searching from the next hash after a_tx_first_hash
l_current_wallet_tx = l_current_wallet_tx->hh.next;
} else
l_current_wallet_tx = NULL;
} else {
// find wallet
l_current_wallet_tx = l_wallet_item->wallet_txs;
}
// Go iterate wallet txs
if (l_current_wallet_tx){
// Now work with it
*a_tx_hash_curr = l_current_wallet_tx->tx_hash;
if (a_datum)
*a_datum = l_current_wallet_tx->tx;
if(a_ret_code)
*a_ret_code = l_current_wallet_tx->ret_code;
if(a_action)
*a_action = l_current_wallet_tx->action;
if(a_uid)
*a_uid = l_current_wallet_tx->tag;
if (a_token)
*a_token = l_current_wallet_tx->token_ticker;
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
return 0;
}
if (a_tx_hash_curr)
memset(a_tx_hash_curr, 0, sizeof(*a_tx_hash_curr));
if (a_datum)
*a_datum = NULL;
if(a_ret_code)
*a_ret_code = 0;
if(a_action)
*a_action = DAP_CHAIN_TX_TAG_ACTION_UNKNOWN;
if (a_uid)
memset(a_uid, 0, sizeof(*a_uid));
if (a_token)
*a_token = NULL;
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
return 0;
}
int dap_chain_wallet_cache_tx_find_outs_with_val(dap_chain_net_t *a_net, const char *a_token_ticker, const dap_chain_addr_t *a_addr,
dap_list_t **a_outs_list, uint256_t a_value_need, uint256_t *a_value_transfer)
{
dap_list_t *l_list_used_out = NULL; // list of transaction with 'out' items
uint256_t l_value_transfer = { };
dap_chain_datum_tx_t *l_tx;
if (!a_token_ticker){
log_it(L_ERROR, "Token ticker is not specified.");
return -100;
}
if(!a_addr || dap_chain_addr_is_blank(a_addr)){
log_it(L_ERROR, "Wallet addr is not specified.");
return -100;
}
if (IS_ZERO_256(a_value_need)){
log_it(L_ERROR, "Needed value is zero.");
return -100;
}
if (a_outs_list == NULL){
log_it(L_ERROR, "a_outs_list is NULL");
return -100;
}
dap_wallet_cache_t *l_wallet_item = NULL;
pthread_rwlock_rdlock(&s_wallet_cache_rwlock);
HASH_FIND(hh, s_wallets_cache, a_addr, sizeof(dap_chain_addr_t), l_wallet_item);
if (!l_wallet_item){
log_it(L_ERROR, "Can't find wallet with address %s", dap_chain_addr_to_str_static(a_addr));
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
return -101;
}
dap_wallet_tx_cache_t *l_current_wallet_tx = l_wallet_item->wallet_txs;
// Go iterate wallet txs
dap_wallet_tx_cache_t *l_current_wallet_tx_iter = NULL, *l_tmp = NULL;
HASH_ITER(hh, l_current_wallet_tx, l_current_wallet_tx_iter, l_tmp) {
if (l_current_wallet_tx_iter->ret_code != DAP_LEDGER_CHECK_OK)
continue;
if (*l_current_wallet_tx_iter->token_ticker &&
dap_strcmp(l_current_wallet_tx_iter->token_ticker, a_token_ticker) &&
!l_current_wallet_tx_iter->multichannel)
continue;
else if (*l_current_wallet_tx_iter->token_ticker && dap_strcmp(l_current_wallet_tx_iter->token_ticker, a_token_ticker) &&
l_current_wallet_tx_iter->multichannel){
bool skip = true;
for (dap_list_t *l_temp = l_current_wallet_tx_iter->tx_wallet_outputs; l_temp; l_temp=l_temp->next){
dap_wallet_tx_cache_output_t *l_out_cur = (dap_wallet_tx_cache_output_t*)l_temp->data;
dap_chain_tx_item_type_t l_type = *(dap_chain_tx_item_type_t*)l_out_cur->tx_out;
uint256_t l_value = { };
switch (l_type) {
case TX_ITEM_TYPE_OUT_EXT: {
dap_chain_tx_out_ext_t *l_out_ext = (dap_chain_tx_out_ext_t*)l_out_cur->tx_out;
if (dap_strcmp(l_out_ext->token, a_token_ticker))
continue;
if (IS_ZERO_256(l_out_ext->header.value) )
continue;
l_value = l_out_ext->header.value;
} break;
default:
continue;
}
// Check whether used 'out' items
if ( !dap_ledger_tx_hash_is_used_out_item (a_net->pub.ledger, &l_current_wallet_tx_iter->tx_hash, l_out_cur->tx_out_idx, NULL) ) {
dap_chain_tx_used_out_item_t *l_item = DAP_NEW_Z(dap_chain_tx_used_out_item_t);
*l_item = (dap_chain_tx_used_out_item_t) { l_current_wallet_tx_iter->tx_hash, (uint32_t)l_out_cur->tx_out_idx, l_value };
l_list_used_out = dap_list_append(l_list_used_out, l_item);
SUM_256_256(l_value_transfer, l_item->value, &l_value_transfer);
// already accumulated the required value, finish the search for 'out' items
if ( compare256(l_value_transfer, a_value_need) >= 0 ) {
break;
}
}
}
} else {
bool skip = true;
for (dap_list_t *l_temp = l_current_wallet_tx_iter->tx_wallet_outputs; l_temp; l_temp=l_temp->next){
dap_wallet_tx_cache_output_t *l_out_cur = (dap_wallet_tx_cache_output_t*)l_temp->data;
dap_chain_tx_item_type_t l_type = *(dap_chain_tx_item_type_t*)l_out_cur->tx_out;
uint256_t l_value = { };
switch (l_type) {
case TX_ITEM_TYPE_OUT_OLD: {
dap_chain_tx_out_old_t *l_out = (dap_chain_tx_out_old_t*)l_out_cur->tx_out;
if (!l_out->header.value)
continue;
l_value = GET_256_FROM_64(l_out->header.value);
} break;
case TX_ITEM_TYPE_OUT: {
dap_chain_tx_out_t *l_out = (dap_chain_tx_out_t*)l_out_cur->tx_out;
if (IS_ZERO_256(l_out->header.value) )
continue;
l_value = l_out->header.value;
} break;
case TX_ITEM_TYPE_OUT_EXT: {
// TODO: check ticker
dap_chain_tx_out_ext_t *l_out_ext = (dap_chain_tx_out_ext_t*)l_out_cur->tx_out;
if (dap_strcmp(l_out_ext->token, a_token_ticker))
continue;
if (IS_ZERO_256(l_out_ext->header.value) )
continue;
l_value = l_out_ext->header.value;
} break;
default:
continue;
}
// Check whether used 'out' items
if ( !dap_ledger_tx_hash_is_used_out_item (a_net->pub.ledger, &l_current_wallet_tx_iter->tx_hash, l_out_cur->tx_out_idx, NULL) ) {
dap_chain_tx_used_out_item_t *l_item = DAP_NEW_Z(dap_chain_tx_used_out_item_t);
*l_item = (dap_chain_tx_used_out_item_t) { l_current_wallet_tx_iter->tx_hash, (uint32_t)l_out_cur->tx_out_idx, l_value };
l_list_used_out = dap_list_append(l_list_used_out, l_item);
SUM_256_256(l_value_transfer, l_item->value, &l_value_transfer);
// already accumulated the required value, finish the search for 'out' items
if ( compare256(l_value_transfer, a_value_need) >= 0 ) {
break;
}
}
}
}
if ( compare256(l_value_transfer, a_value_need) >= 0 ) {
break;
}
}
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
if (compare256(l_value_transfer, a_value_need) >= 0 && l_list_used_out){
*a_outs_list = l_list_used_out;
if (a_value_transfer)
*a_value_transfer = l_value_transfer;
} else {
*a_outs_list = NULL;
dap_list_free(l_list_used_out);
if (a_value_transfer)
*a_value_transfer = uint256_0;
}
return 0;
}
static int s_save_tx_into_wallet_cache(dap_chain_t *a_chain, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, int a_ret_code, char* a_main_token_ticker,
dap_chain_net_srv_uid_t a_srv_uid, dap_chain_tx_tag_action_type_t a_action)
{
int l_ret_val = 0;
int l_items_cnt = 0;
dap_list_t *l_out_list = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT_ALL, &l_items_cnt);
bool l_multichannel = false;
int l_out_idx = 0;
for (dap_list_t *it=l_out_list; it; it=it->next, l_out_idx++){
uint8_t l_out_type = *(uint8_t *)it->data;
dap_chain_addr_t l_addr = {};
switch(l_out_type){
case TX_ITEM_TYPE_OUT_OLD: {
l_addr = ((dap_chain_tx_out_old_t*)it->data)->addr;
} break;
case TX_ITEM_TYPE_OUT: {
l_addr = ((dap_chain_tx_out_t*)it->data)->addr;
} break;
case TX_ITEM_TYPE_OUT_EXT: {
l_addr = ((dap_chain_tx_out_ext_t*)it->data)->addr;
l_multichannel = true;
} break;
default:
continue;
}
if(!dap_chain_addr_is_blank(&l_addr) && ((s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_LOCAL &&
dap_chain_wallet_addr_cache_get_name(&l_addr) != NULL) || s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_ALL)){
pthread_rwlock_wrlock(&s_wallet_cache_rwlock);
dap_wallet_cache_t *l_wallet_item = NULL;
HASH_FIND(hh, s_wallets_cache, &l_addr, sizeof(dap_chain_addr_t), l_wallet_item);
if (!l_wallet_item){
l_wallet_item = DAP_NEW_Z(dap_wallet_cache_t);
memcpy (&l_wallet_item->wallet_addr, &l_addr, sizeof(dap_chain_addr_t));
HASH_ADD(hh, s_wallets_cache, wallet_addr, sizeof(dap_chain_addr_t), l_wallet_item);
}
dap_wallet_tx_cache_t *l_wallet_tx_item = NULL;
HASH_FIND(hh, l_wallet_item->wallet_txs, a_tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
if (!l_wallet_tx_item){
l_wallet_tx_item = DAP_NEW_Z(dap_wallet_tx_cache_t);
l_wallet_tx_item->tx_hash = *a_tx_hash;
l_wallet_tx_item->tx = a_tx;
if (a_main_token_ticker)
dap_strncpy(l_wallet_tx_item->token_ticker, a_main_token_ticker, DAP_CHAIN_TICKER_SIZE_MAX);
l_wallet_tx_item->ret_code = a_ret_code;
l_wallet_tx_item->tag = a_srv_uid;
l_wallet_tx_item->action = a_action;
HASH_ADD(hh, l_wallet_item->wallet_txs, tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
}
l_wallet_tx_item->multichannel = l_multichannel;
dap_wallet_tx_cache_output_t *l_out = DAP_NEW_Z(dap_wallet_tx_cache_output_t);
l_out->tx_out = it->data;
l_out->tx_out_idx = l_out_idx;
l_wallet_tx_item->tx_wallet_outputs = dap_list_append(l_wallet_tx_item->tx_wallet_outputs, l_out);
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
}
}
dap_list_t *l_in_list = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_IN_ALL, &l_items_cnt);
for (dap_list_t *it=l_in_list; it; it=it->next ){
uint8_t l_cond_type = *(uint8_t *)it->data;
uint256_t l_value = {};
dap_chain_addr_t l_addr_from = {};
if(l_cond_type == TX_ITEM_TYPE_IN){
dap_hash_fast_t l_prev_tx_hash = ((dap_chain_tx_in_t*)it->data)->header.tx_prev_hash;
int l_prev_idx = ((dap_chain_tx_in_t*)it->data)->header.tx_out_prev_idx;
if (dap_hash_fast_is_blank(&l_prev_tx_hash))
continue;
dap_chain_datum_tx_t *l_tx_prev = (dap_chain_datum_tx_t *)(a_chain->callback_datum_find_by_hash(a_chain, &l_prev_tx_hash, NULL, NULL)->data);
if (!l_tx_prev)
continue;
uint8_t* l_prev_item = dap_chain_datum_tx_item_get_nth(l_tx_prev, TX_ITEM_TYPE_OUT, l_prev_idx);
if (!l_prev_item)
continue;
uint8_t l_out_type = *(uint8_t *)l_prev_item;
switch(l_out_type){
case TX_ITEM_TYPE_OUT_OLD: {
l_value = GET_256_FROM_64(((dap_chain_tx_out_old_t*)l_prev_item)->header.value);
l_addr_from = ((dap_chain_tx_out_old_t*)l_prev_item)->addr;
} break;
case TX_ITEM_TYPE_OUT:
case TX_ITEM_TYPE_OUT_EXT: {
l_value = ((dap_chain_tx_out_ext_t*)l_prev_item)->header.value;
l_addr_from = ((dap_chain_tx_out_ext_t*)l_prev_item)->addr;
} break;
default:
continue;
}
if(!dap_chain_addr_is_blank(&l_addr_from) && ((s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_LOCAL &&
dap_chain_wallet_addr_cache_get_name(&l_addr_from) != NULL) || s_wallets_cache_type == DAP_WALLET_CACHE_TYPE_ALL)){
pthread_rwlock_wrlock(&s_wallet_cache_rwlock);
dap_wallet_cache_t *l_wallet_item = NULL;
HASH_FIND(hh, s_wallets_cache, &l_addr_from, sizeof(dap_chain_addr_t), l_wallet_item);
if (!l_wallet_item){
l_wallet_item = DAP_NEW_Z(dap_wallet_cache_t);
memcpy (&l_wallet_item->wallet_addr, &l_addr_from, sizeof(dap_chain_addr_t));
HASH_ADD(hh, s_wallets_cache, wallet_addr, sizeof(dap_chain_addr_t), l_wallet_item);
}
dap_wallet_tx_cache_t *l_wallet_tx_item = NULL;
HASH_FIND(hh, l_wallet_item->wallet_txs, a_tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
if (!l_wallet_tx_item){
l_wallet_tx_item = DAP_NEW_Z(dap_wallet_tx_cache_t);
l_wallet_tx_item->tx_hash = *a_tx_hash;
l_wallet_tx_item->tx = a_tx;
if(a_main_token_ticker)
dap_strncpy(l_wallet_tx_item->token_ticker, a_main_token_ticker, DAP_CHAIN_TICKER_SIZE_MAX);
l_wallet_tx_item->multichannel = l_multichannel;
l_wallet_tx_item->ret_code = a_ret_code;
l_wallet_tx_item->tag = a_srv_uid;
l_wallet_tx_item->action = a_action;
HASH_ADD(hh, l_wallet_item->wallet_txs, tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
}
dap_wallet_tx_cache_input_t *l_tx_in = DAP_NEW_Z(dap_wallet_tx_cache_input_t);
l_tx_in->tx_prev_hash = l_prev_tx_hash;
l_tx_in->tx_out_prev_idx = l_prev_idx;
l_tx_in->value = l_value;
l_wallet_tx_item->tx_wallet_inputs = dap_list_append(l_wallet_tx_item->tx_wallet_inputs, l_tx_in);
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
}
}
}
if (l_out_list)
dap_list_free(l_out_list);
if (l_in_list)
dap_list_free(l_in_list);
return l_ret_val;
}
static int s_save_cache_for_addr_in_net(dap_chain_net_t *a_net, dap_chain_addr_t *a_addr)
{
// Find chain with transactions
dap_hash_fast_t l_curr_tx_hash = {0};
if (dap_chain_wallet_cache_tx_find_in_history(a_addr, NULL, NULL, NULL, NULL, NULL, &l_curr_tx_hash) == 0)
return 0;
dap_chain_t *l_chain = a_net->pub.chains;
while (l_chain){
for(int i = 0; i < l_chain->datum_types_count; i++) {
if(l_chain->datum_types[i] == CHAIN_TYPE_TX){
dap_chain_datum_iter_t *l_iter = l_chain->callback_datum_iter_create(l_chain);
for (dap_chain_datum_t *l_datum = l_chain->callback_datum_iter_get_first(l_iter);
l_datum;
l_datum = l_chain->callback_datum_iter_get_next(l_iter)){
s_save_tx_cache_for_addr(l_chain, a_addr, (dap_chain_datum_tx_t*)l_datum->data, l_iter->cur_hash, l_iter->ret_code, l_iter->token_ticker, l_iter->uid, l_iter->action);
}
break;
}
}
l_chain=l_chain->next;
}
return 0;
}
static void s_callback_datum_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_hash, void *a_datum,
size_t a_datum_size, int a_ret_code, uint32_t a_action,
dap_chain_net_srv_uid_t a_uid)
{
dap_atom_notify_arg_t *l_arg = (dap_atom_notify_arg_t*)a_arg;
dap_chain_datum_t *l_datum = (dap_chain_datum_t*)a_datum;
if (!l_datum || l_datum->header.type_id != DAP_CHAIN_DATUM_TX)
return;
dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t*)l_datum->data;
const char* l_main_token_ticker = NULL;
l_main_token_ticker = dap_ledger_tx_get_token_ticker_by_hash(l_arg->net->pub.ledger, a_datum_hash);
s_save_tx_into_wallet_cache(l_arg->chain, l_tx, a_datum_hash, a_ret_code, (char*)l_main_token_ticker, a_uid, a_action);
}
static void s_wallet_opened_callback(dap_chain_wallet_t *a_wallet, void *a_arg)
{
for(dap_chain_net_t *l_net = dap_chain_net_iter_start(); l_net; l_net=dap_chain_net_iter_next(l_net)){
// get wallet addr in current net
dap_chain_addr_t *l_addr = dap_chain_wallet_get_addr(a_wallet, l_net->pub.id);
s_save_cache_for_addr_in_net(l_net, l_addr);
}
}
static int s_save_tx_cache_for_addr(dap_chain_t *a_chain, dap_chain_addr_t *a_addr, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, int a_ret_code, char* a_main_token_ticker,
dap_chain_net_srv_uid_t a_srv_uid, dap_chain_tx_tag_action_type_t a_action)
{
int l_ret_val = 0;
int l_items_cnt = 0;
dap_list_t *l_out_list = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT_ALL, &l_items_cnt);
bool l_multichannel = false;
int l_out_idx = 0;
for (dap_list_t *it=l_out_list; it; it=it->next, l_out_idx++){
uint8_t l_out_type = *(uint8_t *)it->data;
dap_chain_addr_t l_addr = {};
switch(l_out_type){
case TX_ITEM_TYPE_OUT_OLD: {
l_addr = ((dap_chain_tx_out_old_t*)it->data)->addr;
} break;
case TX_ITEM_TYPE_OUT: {
l_addr = ((dap_chain_tx_out_t*)it->data)->addr;
} break;
case TX_ITEM_TYPE_OUT_EXT: {
l_addr = ((dap_chain_tx_out_ext_t*)it->data)->addr;
l_multichannel = true;
} break;
default:
continue;
}
if(!dap_chain_addr_is_blank(&l_addr) && dap_chain_addr_compare(&l_addr, a_addr)){
pthread_rwlock_wrlock(&s_wallet_cache_rwlock);
dap_wallet_cache_t *l_wallet_item = NULL;
HASH_FIND(hh, s_wallets_cache, &l_addr, sizeof(dap_chain_addr_t), l_wallet_item);
if (!l_wallet_item){
l_wallet_item = DAP_NEW_Z(dap_wallet_cache_t);
memcpy (&l_wallet_item->wallet_addr, &l_addr, sizeof(dap_chain_addr_t));
HASH_ADD(hh, s_wallets_cache, wallet_addr, sizeof(dap_chain_addr_t), l_wallet_item);
}
dap_wallet_tx_cache_t *l_wallet_tx_item = NULL;
HASH_FIND(hh, l_wallet_item->wallet_txs, a_tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
if (!l_wallet_tx_item){
l_wallet_tx_item = DAP_NEW_Z(dap_wallet_tx_cache_t);
l_wallet_tx_item->tx_hash = *a_tx_hash;
l_wallet_tx_item->tx = a_tx;
if (a_main_token_ticker)
dap_strncpy(l_wallet_tx_item->token_ticker, a_main_token_ticker, DAP_CHAIN_TICKER_SIZE_MAX);
l_wallet_tx_item->ret_code = a_ret_code;
l_wallet_tx_item->tag = a_srv_uid;
l_wallet_tx_item->action = a_action;
HASH_ADD(hh, l_wallet_item->wallet_txs, tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
}
l_wallet_tx_item->multichannel = l_multichannel;
dap_wallet_tx_cache_output_t *l_out = DAP_NEW_Z(dap_wallet_tx_cache_output_t);
l_out->tx_out = it->data;
l_out->tx_out_idx = l_out_idx;
l_wallet_tx_item->tx_wallet_outputs = dap_list_append(l_wallet_tx_item->tx_wallet_outputs, l_out);
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
}
}
dap_list_t *l_in_list = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_IN_ALL, &l_items_cnt);
for (dap_list_t *it=l_out_list; it; it=it->next ){
uint8_t l_cond_type = *(uint8_t *)it->data;
uint256_t l_value = {};
dap_chain_addr_t l_addr_from = {};
if(l_cond_type == TX_ITEM_TYPE_IN){
dap_hash_fast_t l_prev_tx_hash = ((dap_chain_tx_in_t*)it->data)->header.tx_prev_hash;
int l_prev_idx = ((dap_chain_tx_in_t*)it->data)->header.tx_out_prev_idx;
if (dap_hash_fast_is_blank(&l_prev_tx_hash))
continue;
dap_chain_datum_tx_t *l_tx_prev = (dap_chain_datum_tx_t *)(a_chain->callback_datum_find_by_hash(a_chain, &l_prev_tx_hash, NULL, NULL)->data);
if (!l_tx_prev)
continue;
uint8_t* l_prev_item = dap_chain_datum_tx_item_get_nth(l_tx_prev, TX_ITEM_TYPE_OUT, l_prev_idx);
if (!l_prev_item)
continue;
uint8_t l_out_type = *(uint8_t *)it->data;
switch(l_out_type){
case TX_ITEM_TYPE_OUT_OLD: {
l_value = GET_256_FROM_64(((dap_chain_tx_out_old_t*)it->data)->header.value);
l_addr_from = ((dap_chain_tx_out_old_t*)it->data)->addr;
} break;
case TX_ITEM_TYPE_OUT:
case TX_ITEM_TYPE_OUT_EXT: {
l_value = ((dap_chain_tx_out_ext_t*)it->data)->header.value;
l_addr_from = ((dap_chain_tx_out_ext_t*)it->data)->addr;
} break;
default:
continue;
}
if(!dap_chain_addr_is_blank(&l_addr_from) && dap_chain_addr_compare(&l_addr_from, a_addr)){
pthread_rwlock_wrlock(&s_wallet_cache_rwlock);
dap_wallet_cache_t *l_wallet_item = NULL;
HASH_FIND(hh, s_wallets_cache, &l_addr_from, sizeof(dap_chain_addr_t), l_wallet_item);
if (!l_wallet_item){
l_wallet_item = DAP_NEW_Z(dap_wallet_cache_t);
memcpy (&l_wallet_item->wallet_addr, &l_addr_from, sizeof(dap_chain_addr_t));
HASH_ADD(hh, s_wallets_cache, wallet_addr, sizeof(dap_chain_addr_t), l_wallet_item);
}
dap_wallet_tx_cache_t *l_wallet_tx_item = NULL;
HASH_FIND(hh, l_wallet_item->wallet_txs, a_tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
if (!l_wallet_tx_item){
l_wallet_tx_item = DAP_NEW_Z(dap_wallet_tx_cache_t);
l_wallet_tx_item->tx_hash = *a_tx_hash;
l_wallet_tx_item->tx = a_tx;
if(a_main_token_ticker)
dap_strncpy(l_wallet_tx_item->token_ticker, a_main_token_ticker, DAP_CHAIN_TICKER_SIZE_MAX);
l_wallet_tx_item->multichannel = l_multichannel;
l_wallet_tx_item->ret_code = a_ret_code;
l_wallet_tx_item->tag = a_srv_uid;
l_wallet_tx_item->action = a_action;
HASH_ADD(hh, l_wallet_item->wallet_txs, tx_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
}
dap_wallet_tx_cache_input_t *l_tx_in = DAP_NEW_Z(dap_wallet_tx_cache_input_t);
l_tx_in->tx_prev_hash = l_prev_tx_hash;
l_tx_in->tx_out_prev_idx = l_prev_idx;
l_tx_in->value = l_value;
l_wallet_tx_item->tx_wallet_inputs = dap_list_append(l_wallet_tx_item->tx_wallet_inputs, l_tx_in);
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
}
}
}
if (l_out_list)
dap_list_free(l_out_list);
if (l_in_list)
dap_list_free(l_in_list);
return l_ret_val;
}
static void s_callback_datum_removed_notify(void *a_arg, dap_chain_hash_fast_t *a_datum_hash)
{
if (!a_datum_hash)
return;
pthread_rwlock_wrlock(&s_wallet_cache_rwlock);
dap_wallet_cache_t *l_wallet_item = NULL, *l_tmp;
HASH_ITER(hh, s_wallets_cache, l_wallet_item, l_tmp){
dap_wallet_tx_cache_t *l_wallet_tx_item = NULL;
HASH_FIND(hh, l_wallet_item->wallet_txs, a_datum_hash, sizeof(dap_hash_fast_t), l_wallet_tx_item);
if (l_wallet_tx_item){
HASH_DEL(l_wallet_item->wallet_txs, l_wallet_tx_item);
dap_list_free_full(l_wallet_tx_item->tx_wallet_inputs, NULL);
dap_list_free_full(l_wallet_tx_item->tx_wallet_outputs, NULL);
DAP_DEL_Z(l_wallet_tx_item);
}
if (!l_wallet_item->wallet_txs){
HASH_DEL(s_wallets_cache, l_wallet_item);
DAP_DEL_Z(l_wallet_item);
}
}
pthread_rwlock_unlock(&s_wallet_cache_rwlock);
}
\ No newline at end of file
...@@ -45,6 +45,7 @@ typedef struct dap_chain_wallet{ ...@@ -45,6 +45,7 @@ typedef struct dap_chain_wallet{
void *_inheritor; void *_inheritor;
} dap_chain_wallet_t; } dap_chain_wallet_t;
typedef void (*dap_chain_wallet_opened_callback_t)(dap_chain_wallet_t *a_wallet, void *a_arg);
int dap_chain_wallet_init(); int dap_chain_wallet_init();
void dap_chain_wallet_deinit(void); void dap_chain_wallet_deinit(void);
...@@ -88,6 +89,7 @@ int dap_chain_wallet_activate (const char *a_name, ssize_t a_name_len, const c ...@@ -88,6 +89,7 @@ int dap_chain_wallet_activate (const char *a_name, ssize_t a_name_len, const c
int dap_chain_wallet_deactivate (const char *a_name, ssize_t a_name_len); int dap_chain_wallet_deactivate (const char *a_name, ssize_t a_name_len);
const char* dap_chain_wallet_check_sign(dap_chain_wallet_t *a_wallet); const char* dap_chain_wallet_check_sign(dap_chain_wallet_t *a_wallet);
const char *dap_chain_wallet_addr_cache_get_name(dap_chain_addr_t *a_addr); const char *dap_chain_wallet_addr_cache_get_name(dap_chain_addr_t *a_addr);
json_object *dap_chain_wallet_info_to_json(const char *a_name, const char *a_path); json_object *dap_chain_wallet_info_to_json(const char *a_name, const char *a_path);
\ No newline at end of file int dap_chain_wallet_add_wallet_opened_notify(dap_chain_wallet_opened_callback_t a_callback, void *a_arg);
int dap_chain_wallet_add_wallet_created_notify(dap_chain_wallet_opened_callback_t a_callback, void *a_arg);