diff --git a/dap-sdk b/dap-sdk index 026c0def2a5685885e9577586f6b5b93b042f896..1587a436ec9231ac3bb485e74cc5ec2a7534efd5 160000 --- a/dap-sdk +++ b/dap-sdk @@ -1 +1 @@ -Subproject commit 026c0def2a5685885e9577586f6b5b93b042f896 +Subproject commit 1587a436ec9231ac3bb485e74cc5ec2a7534efd5 diff --git a/modules/chain/dap_chain_ch.c b/modules/chain/dap_chain_ch.c index 65b2f1e43fad588092b751e4c1845f1d017ea05f..9af3f8ad1d8a2801ef83dd69c464c34daffa1b0f 100644 --- a/modules/chain/dap_chain_ch.c +++ b/modules/chain/dap_chain_ch.c @@ -143,7 +143,7 @@ static uint32_t s_sync_packets_per_thread_call = 10; static uint32_t s_sync_ack_window_size = 512; // atoms // Legacy -static uint_fast16_t s_update_pack_size = 100; // Number of hashes packed into the one packet +static const uint_fast16_t s_update_pack_size = 100; // Number of hashes packed into the one packet #ifdef DAP_SYS_DEBUG @@ -653,7 +653,7 @@ static bool s_sync_in_chains_callback(void *a_arg) break; } if (l_ack_send && l_args->ack_req) { - uint64_t l_ack_num = (l_chain_pkt->hdr.num_hi << 16) | l_chain_pkt->hdr.num_lo; + uint64_t l_ack_num = ((uint32_t)l_chain_pkt->hdr.num_hi << 16) | l_chain_pkt->hdr.num_lo; dap_chain_ch_pkt_t *l_pkt = dap_chain_ch_pkt_new(l_chain_pkt->hdr.net_id, l_chain_pkt->hdr.chain_id, l_chain_pkt->hdr.cell_id, &l_ack_num, sizeof(uint64_t), DAP_CHAIN_CH_PKT_VERSION_CURRENT); dap_stream_ch_pkt_send_by_addr(&l_args->addr, DAP_CHAIN_CH_ID, DAP_CHAIN_CH_PKT_TYPE_CHAIN_ACK, l_pkt, dap_chain_ch_pkt_get_size(l_pkt)); @@ -745,7 +745,7 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) } break; case DAP_CHAIN_CH_PKT_TYPE_CHAIN: { - if (!l_chain_pkt_data_size) { + if (!l_chain_pkt_data_size || l_chain_pkt_data_size > sizeof(dap_chain_ch_pkt_t) + DAP_CHAIN_ATOM_MAX_SIZE) { log_it(L_WARNING, "Incorrect data size %zu in packet %s", l_chain_pkt_data_size, dap_chain_ch_pkt_type_to_str(l_ch_pkt->hdr.type)); dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id, @@ -1101,7 +1101,7 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) // Response with gdb element hashes and sizes case DAP_CHAIN_CH_PKT_TYPE_UPDATE_GLOBAL_DB: { - if (l_chain_pkt_data_size % sizeof(dap_chain_ch_update_element_t)) { + if (l_chain_pkt_data_size % sizeof(dap_chain_ch_update_element_t) || l_chain_pkt_data_size > UINT16_MAX) { log_it(L_WARNING, "Incorrect data size %zu in packet %s", l_chain_pkt_data_size, dap_chain_ch_pkt_type_to_str(l_ch_pkt->hdr.type)); dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id, @@ -1214,7 +1214,8 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) case DAP_CHAIN_CH_PKT_TYPE_GLOBAL_DB: { dap_global_db_pkt_old_t *l_pkt = (dap_global_db_pkt_old_t *)l_chain_pkt->data; if (l_chain_pkt_data_size < sizeof(dap_global_db_pkt_old_t) || - l_chain_pkt_data_size != sizeof(*l_pkt) + l_pkt->data_size) { + (uint64_t)sizeof(*l_pkt) + l_pkt->data_size < l_pkt->data_size || + l_chain_pkt_data_size != (uint64_t)sizeof(*l_pkt) + l_pkt->data_size) { log_it(L_WARNING, "Incorrect data size %zu in packet %s", l_chain_pkt_data_size, dap_chain_ch_pkt_type_to_str(l_ch_pkt->hdr.type)); dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id, @@ -1353,7 +1354,7 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) // Response with atom hashes and sizes case DAP_CHAIN_CH_PKT_TYPE_UPDATE_CHAINS: { - if (l_chain_pkt_data_size > sizeof(dap_chain_ch_update_element_t) * s_update_pack_size) { + if (l_chain_pkt_data_size % sizeof(dap_chain_ch_update_element_t) || l_chain_pkt_data_size > UINT16_MAX) { log_it(L_WARNING, "Incorrect data size %zu in packet %s", l_chain_pkt_data_size, dap_chain_ch_pkt_type_to_str(l_ch_pkt->hdr.type)); dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id, @@ -1470,7 +1471,7 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t* a_ch, void* a_arg) } break; case DAP_CHAIN_CH_PKT_TYPE_CHAIN_OLD: { - if (!l_chain_pkt_data_size) { + if (!l_chain_pkt_data_size || l_chain_pkt_data_size > sizeof(dap_chain_ch_pkt_t) + DAP_CHAIN_ATOM_MAX_SIZE) { log_it(L_WARNING, "Incorrect data size %zu in packet %s", l_chain_pkt_data_size, dap_chain_ch_pkt_type_to_str(l_ch_pkt->hdr.type)); dap_stream_ch_write_error_unsafe(a_ch, l_chain_pkt->hdr.net_id, diff --git a/modules/chain/include/dap_chain.h b/modules/chain/include/dap_chain.h index ffefac6b4a44721b8015f8014f655b42e1577e2c..869ab65076249aaa437c4bf0be095493eb286365 100644 --- a/modules/chain/include/dap_chain.h +++ b/modules/chain/include/dap_chain.h @@ -30,6 +30,12 @@ #include "dap_chain_common.h" #include "dap_chain_datum.h" +#ifdef DAP_TPS_TEST +#define DAP_CHAIN_ATOM_MAX_SIZE (100 * 1024 * 1024) +#else +#define DAP_CHAIN_ATOM_MAX_SIZE (256 * 1024) // 256 KB +#endif + typedef struct dap_chain dap_chain_t; typedef struct dap_chain_cell dap_chain_cell_t; diff --git a/modules/chain/include/dap_chain_tx.h b/modules/chain/include/dap_chain_tx.h index 3bb0eb0ded723f70dd2571e2ab3abcff98a0c8d1..50b05aaeba48c696d6840d5ac0f41b10d0c826fa 100644 --- a/modules/chain/include/dap_chain_tx.h +++ b/modules/chain/include/dap_chain_tx.h @@ -45,10 +45,10 @@ typedef struct dap_chain_tx dap_chain_datum_token_t *token; // Inputs - dap_chain_datum_tx_item_t * in; + byte_t * in; dap_chain_tx_in_cond_t * in_cond; // Outputs - dap_chain_datum_tx_item_t * out; + byte_t * out; dap_chain_tx_out_cond_t * out_cond; // Previous diff --git a/modules/chain/tests/dap_chain_ledger_tests.c b/modules/chain/tests/dap_chain_ledger_tests.c index ac6ec1a215dfd49513b18386a5a47bc71ffa9100..2dd5bfa8320b2d4464b8b748d2efc2ec0901852c 100644 --- a/modules/chain/tests/dap_chain_ledger_tests.c +++ b/modules/chain/tests/dap_chain_ledger_tests.c @@ -107,7 +107,7 @@ dap_chain_datum_tx_t *dap_ledger_test_create_tx_full(dap_enc_key_t *a_key_from, dap_chain_addr_fill_from_key(&l_addr, a_key_from, a_ledger->net->pub.id); dap_chain_datum_tx_t *l_tx_prev = dap_ledger_tx_find_by_hash(a_ledger, a_hash_prev); int l_out_idx = 0; - dap_chain_tx_out_t *l_tx_prev_out = (dap_chain_tx_out_t *)dap_chain_datum_tx_item_get(l_tx_prev, &l_out_idx, TX_ITEM_TYPE_OUT, NULL); + dap_chain_tx_out_t *l_tx_prev_out = (dap_chain_tx_out_t *)dap_chain_datum_tx_item_get(l_tx_prev, &l_out_idx, NULL, TX_ITEM_TYPE_OUT, NULL); dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); dap_chain_tx_in_t *l_in = dap_chain_datum_tx_item_in_create(a_hash_prev, 0); dap_chain_tx_out_t *l_out = dap_chain_datum_tx_item_out_create(a_addr_to, a_value); @@ -129,7 +129,7 @@ dap_chain_datum_tx_t *dap_ledger_test_create_tx_cond(dap_enc_key_t *a_key_from, dap_chain_addr_fill_from_key(&l_addr, a_key_from, a_ledger->net->pub.id); dap_chain_datum_tx_t *l_tx_prev = dap_ledger_tx_find_by_hash(a_ledger, a_hash_prev); int l_out_idx = 0; - dap_chain_tx_out_t *l_tx_prev_out = (dap_chain_tx_out_t *)dap_chain_datum_tx_item_get(l_tx_prev, &l_out_idx, TX_ITEM_TYPE_OUT, NULL); + dap_chain_tx_out_t *l_tx_prev_out = (dap_chain_tx_out_t *)dap_chain_datum_tx_item_get(l_tx_prev, &l_out_idx, NULL, TX_ITEM_TYPE_OUT, NULL); dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); dap_chain_tx_in_t *l_in = dap_chain_datum_tx_item_in_create(a_hash_prev, 0); dap_chain_net_srv_uid_t l_srv_uid = {.uint64 = 1}; @@ -157,7 +157,7 @@ dap_chain_datum_tx_t *dap_ledger_test_create_spend_tx_cond(dap_enc_key_t *a_key_ dap_chain_datum_tx_t *l_tx_prev = dap_ledger_tx_find_by_hash(a_ledger, a_hash_prev); // get previous cond out int l_out_idx = 0; - dap_chain_tx_out_cond_t *l_tx_prev_out = (dap_chain_tx_out_cond_t *)dap_chain_datum_tx_item_get(l_tx_prev, &l_out_idx, TX_ITEM_TYPE_OUT_COND, NULL); + dap_chain_tx_out_cond_t *l_tx_prev_out = (dap_chain_tx_out_cond_t *)dap_chain_datum_tx_item_get(l_tx_prev, &l_out_idx, NULL, TX_ITEM_TYPE_OUT_COND, NULL); dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); dap_chain_tx_in_cond_t *l_in_cond = dap_chain_datum_tx_item_in_cond_create(a_hash_prev, 1, 0); @@ -199,7 +199,7 @@ dap_chain_datum_tx_t *dap_ledger_test_create_return_from_tx_cond(dap_chain_hash_ dap_chain_datum_tx_t *l_tx_prev = dap_ledger_tx_find_by_hash(a_ledger, a_hash_prev); // get previous cond out int l_out_idx = 1; - dap_chain_tx_out_cond_t *l_tx_prev_out = (dap_chain_tx_out_cond_t *)dap_chain_datum_tx_item_get(l_tx_prev, &l_out_idx, TX_ITEM_TYPE_OUT_COND, NULL); + dap_chain_tx_out_cond_t *l_tx_prev_out = (dap_chain_tx_out_cond_t *)dap_chain_datum_tx_item_get(l_tx_prev, &l_out_idx, NULL, TX_ITEM_TYPE_OUT_COND, NULL); dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); dap_chain_tx_in_cond_t *l_in_cond = dap_chain_datum_tx_item_in_cond_create(a_hash_prev, 1, 0); @@ -222,7 +222,7 @@ dap_chain_datum_tx_t *dap_ledger_test_create_stake_tx_cond(dap_enc_key_t *a_key_ dap_chain_datum_tx_t *l_tx_prev = dap_ledger_tx_find_by_hash(a_ledger, a_hash_prev); // get previous cond out int l_out_idx = 0; - dap_chain_tx_out_t *l_tx_prev_out = (dap_chain_tx_out_t *)dap_chain_datum_tx_item_get(l_tx_prev, &l_out_idx, TX_ITEM_TYPE_OUT, NULL); + dap_chain_tx_out_t *l_tx_prev_out = (dap_chain_tx_out_t *)dap_chain_datum_tx_item_get(l_tx_prev, &l_out_idx, NULL, TX_ITEM_TYPE_OUT, NULL); dap_chain_addr_t l_addr_to = {0}; dap_chain_addr_fill_from_key(&l_addr_to, a_key_from, a_ledger->net->pub.id); @@ -275,7 +275,7 @@ dap_chain_datum_tx_t *dap_ledger_test_create_unstake_tx_cond(dap_enc_key_t *a_ke return NULL; l_out_idx = 4; - dap_chain_tx_out_ext_t *l_tx_prev_out_ext = (dap_chain_tx_out_ext_t *)dap_chain_datum_tx_item_get(l_tx_prev, &l_out_idx, TX_ITEM_TYPE_OUT_EXT, NULL); + dap_chain_tx_out_ext_t *l_tx_prev_out_ext = (dap_chain_tx_out_ext_t *)dap_chain_datum_tx_item_get(l_tx_prev, &l_out_idx, NULL, TX_ITEM_TYPE_OUT_EXT, NULL); dap_chain_addr_t l_addr_to = {0}; dap_chain_addr_fill_from_key(&l_addr_to, a_key_from, a_ledger->net->pub.id); diff --git a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c index 75f0adec6b4031258261ed0c9d10c4c0cd1282bb..5dcf39ce43476b5d7cfbb044f9d09d58f87b382d 100644 --- a/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c +++ b/modules/channel/chain-net-srv/dap_stream_ch_chain_net_srv.c @@ -769,7 +769,7 @@ static bool s_grace_period_start(dap_chain_net_srv_grace_t *a_grace) if ( !l_price ) { log_it( L_WARNING, "Request can't be processed because no acceptable price in pricelist for token %s in network %s", l_ticker, l_net->pub.name ); - l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; + l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; s_grace_error(a_grace, l_err); return false; } @@ -1265,6 +1265,12 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg) return false; } pkt_test_t *l_request = (pkt_test_t*)l_ch_pkt->data; + if (l_request->data_size_recv > DAP_CHAIN_NET_SRV_CH_REQUEST_SIZE_MAX || l_request->data_size > DAP_CHAIN_NET_SRV_CH_REQUEST_SIZE_MAX) { + log_it(L_WARNING, "Too large payload %zu [pkt seq %"DAP_UINT64_FORMAT_U"]", l_request->data_size_recv, l_ch_pkt->hdr.seq_id); + l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_BIG_SIZE; + dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof(l_err)); + return false; + } size_t l_request_size = l_request->data_size + sizeof(pkt_test_t); if (l_ch_pkt->hdr.data_size != l_request_size) { log_it(L_WARNING, "Wrong CHECK_REQUEST size %u, must be %zu [pkt seq %"DAP_UINT64_FORMAT_U"]", l_ch_pkt->hdr.data_size, l_request_size, l_ch_pkt->hdr.seq_id); @@ -1272,14 +1278,8 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg) dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof(l_err)); return false; } - if(l_request->data_size_recv > DAP_CHAIN_NET_SRV_CH_REQUEST_SIZE_MAX) { - log_it(L_WARNING, "Too large payload %zu [pkt seq %"DAP_UINT64_FORMAT_U"]", l_request->data_size_recv, l_ch_pkt->hdr.seq_id); - l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_BIG_SIZE; - dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof(l_err)); - return false; - } dap_chain_hash_fast_t l_data_hash; - dap_hash_fast(l_request->data, l_request->data_size, &l_data_hash); + dap_hash_fast(l_request->data, l_request->data_size, &l_data_hash); // TODO change it to less CPU consuming algorithm if (l_request->data_size > 0 && !dap_hash_fast_compare(&l_data_hash, &l_request->data_hash)) { log_it(L_WARNING, "Wrong hash [pkt seq %"DAP_UINT64_FORMAT_U"]", l_ch_pkt->hdr.seq_id); l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_WRONG_HASH; @@ -1353,6 +1353,7 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg) return false; } dap_chain_datum_tx_receipt_t * l_receipt = (dap_chain_datum_tx_receipt_t *) l_ch_pkt->data; + // TODO calculate actual receipt size and compare it with provided packet size size_t l_receipt_size = l_ch_pkt->hdr.data_size; bool l_is_found = false; diff --git a/modules/channel/chain-net/dap_stream_ch_chain_net.c b/modules/channel/chain-net/dap_stream_ch_chain_net.c index 3039ce38e7e5efb8252d38ba6af09387e3d6334f..fe4c18c8626843aee823fb25758b151e16a0159a 100644 --- a/modules/channel/chain-net/dap_stream_ch_chain_net.c +++ b/modules/channel/chain-net/dap_stream_ch_chain_net.c @@ -125,20 +125,24 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void* a_arg) return false; } dap_stream_ch_chain_net_pkt_t *l_ch_chain_net_pkt = (dap_stream_ch_chain_net_pkt_t *)l_ch_pkt->data; - if (l_ch_chain_net_pkt->hdr.data_size + sizeof(dap_stream_ch_chain_net_pkt_t) > l_ch_pkt->hdr.data_size) { + if ((uint32_t)l_ch_chain_net_pkt->hdr.data_size + sizeof(dap_stream_ch_chain_net_pkt_t) > l_ch_pkt->hdr.data_size) { log_it(L_WARNING, "Too small stream channel N packet size %u (expected at least %zu)", l_ch_pkt->hdr.data_size, l_ch_chain_net_pkt->hdr.data_size + sizeof(dap_stream_ch_chain_net_pkt_t)); return false; } dap_chain_net_t *l_net = dap_chain_net_by_id(l_ch_chain_net_pkt->hdr.net_id); if (!l_net) { - log_it(L_ERROR, "Invalid net id in packet"); + log_it(L_ERROR, "Invalid net id 0x%016" DAP_UINT64_FORMAT_x " in stream channel N packet", l_ch_chain_net_pkt->hdr.net_id.uint64); char l_err_str[] = "ERROR_NET_INVALID_ID"; dap_stream_ch_chain_net_pkt_write(a_ch, DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_ERROR , l_ch_chain_net_pkt->hdr.net_id, l_err_str, sizeof(l_err_str)); return false; } if (l_ch_pkt->hdr.type == DAP_STREAM_CH_CHAIN_NET_PKT_TYPE_ERROR) { + if (l_ch_chain_net_pkt->data[l_ch_chain_net_pkt->hdr.data_size - 1] != '\0') { + log_it(L_WARNING, "Invalid error string format with no trailing zero"); + return false; + } char *l_err_str = (char *)l_ch_chain_net_pkt->data; log_it(L_WARNING, "Stream channel N for network communication got error on other side: %s", l_err_str); if (a_ch->stream->authorized) { diff --git a/modules/channel/chain-net/dap_stream_ch_chain_net_pkt.c b/modules/channel/chain-net/dap_stream_ch_chain_net_pkt.c index 24be3ab116c691b8d1641316cf3be559f4fe1f30..a53bb80396d6cdb37deca22c4468e84f014280f9 100644 --- a/modules/channel/chain-net/dap_stream_ch_chain_net_pkt.c +++ b/modules/channel/chain-net/dap_stream_ch_chain_net_pkt.c @@ -19,7 +19,6 @@ #include <dap_stream.h> #include <dap_stream_pkt.h> #include <dap_stream_ch_pkt.h> -#include "dap_stream_ch_chain_net.h" #include "dap_stream_ch_chain_net_pkt.h" #define LOG_TAG "dap_stream_ch_chain_net_pkt" diff --git a/modules/common/dap_chain_datum.c b/modules/common/dap_chain_datum.c index f0ac122c4eb9da05f548cfda3839cbd4f29c9d58..8394a83ea5872759fe1a25480b7602c486bfc783 100644 --- a/modules/common/dap_chain_datum.c +++ b/modules/common/dap_chain_datum.c @@ -35,6 +35,7 @@ #include "dap_chain_datum_hashtree_roots.h" #include "dap_enc_base58.h" #include "dap_sign.h" +#include "dap_tsd.h" #define LOG_TAG "dap_chain_datum" @@ -62,8 +63,8 @@ dap_chain_datum_t *dap_chain_datum_create(uint16_t a_type_id, const void *a_data } void dap_datum_token_dump_tsd_to_json(json_object * json_obj_out, dap_chain_datum_token_t *a_token, size_t a_token_size, const char *a_hash_out_type) { - dap_tsd_t *l_tsd = dap_chain_datum_token_tsd_get(a_token, a_token_size); - if (l_tsd == NULL) { + dap_tsd_t *l_tsd_begin = dap_chain_datum_token_tsd_get(a_token, a_token_size); + if (!l_tsd_begin) { json_object_object_add(json_obj_out, "status", json_object_new_string("<CORRUPTED TSD SECTION>")); return; } @@ -87,18 +88,8 @@ void dap_datum_token_dump_tsd_to_json(json_object * json_obj_out, dap_chain_datu } break; default: break; } - size_t l_tsd_size = 0; - for (size_t l_offset = 0; l_offset < l_tsd_total_size; l_offset += l_tsd_size) { - l_tsd = (dap_tsd_t *) (((byte_t*)l_tsd) + l_tsd_size); - l_tsd_size = l_tsd ? dap_tsd_size(l_tsd) : 0; - if (l_tsd_size == 0) { - log_it(L_ERROR,"Wrong zero TSD size, exiting s_datum_token_dump_tsd()"); - return; - } else if (l_tsd_size+l_offset > l_tsd_total_size) { - log_it(L_WARNING, "<CORRUPTED TSD> too big size %u when left maximum %zu", - l_tsd->size, l_tsd_total_size - l_offset); - return; - } + dap_tsd_t *l_tsd; size_t l_tsd_size; + dap_tsd_iter(l_tsd, l_tsd_size, l_tsd_begin, l_tsd_total_size) { switch(l_tsd->type) { case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_SET_FLAGS: { uint16_t l_t = 0; @@ -226,7 +217,7 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum, dap_chain_net_id_t a_net_id) { bool l_is_first = false; - dap_chain_tx_in_t *l_in_item = (dap_chain_tx_in_t *)dap_chain_datum_tx_item_get(a_datum, NULL, TX_ITEM_TYPE_IN, NULL); + dap_chain_tx_in_t *l_in_item = (dap_chain_tx_in_t *)dap_chain_datum_tx_item_get(a_datum, NULL, NULL, TX_ITEM_TYPE_IN, NULL); if (l_in_item && dap_hash_fast_is_blank(&l_in_item->header.tx_prev_hash)) l_is_first = true; char l_tmp_buf[DAP_TIME_STR_SIZE]; @@ -237,22 +228,15 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum, dap_string_append_printf(a_str_out, "transaction:%s hash %s\n TS Created: %s%s%s\n Items:\n", l_is_first ? " (emit)" : "", l_hash_str, l_tmp_buf, a_ticker ? " Token ticker: " : "", a_ticker ? a_ticker : ""); - uint32_t l_tx_items_count = 0; - uint32_t l_tx_items_size = a_datum->header.tx_items_size; - dap_hash_fast_t *l_hash_tmp = NULL; - while (l_tx_items_count < l_tx_items_size) { - uint8_t *item = a_datum->tx_items + l_tx_items_count; - size_t l_item_tx_size = dap_chain_datum_item_tx_get_size(item); - switch(dap_chain_datum_tx_item_get_type(item)){ + dap_hash_fast_t l_hash_tmp = { }; + byte_t *item; size_t l_size; + TX_ITEM_ITER_TX(item, l_size, a_datum) { + switch (*item) { case TX_ITEM_TYPE_IN: - l_hash_tmp = &((dap_chain_tx_in_t*)item)->header.tx_prev_hash; - if (dap_hash_fast_is_blank(l_hash_tmp)) { - l_hash_str = "BLANK"; - } else { - l_hash_str = dap_strcmp(a_hash_out_type, "hex") - ? dap_enc_base58_encode_hash_to_str_static(l_hash_tmp) - : dap_chain_hash_fast_to_str_static(l_hash_tmp); - } + l_hash_tmp = ((dap_chain_tx_in_t*)item)->header.tx_prev_hash; + l_hash_str = !dap_hash_fast_is_blank(&l_hash_tmp) + ? dap_strcmp(a_hash_out_type, "hex") ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp) : dap_chain_hash_fast_to_str_static(&l_hash_tmp) + : "BLANK"; dap_string_append_printf(a_str_out, "\t IN:\nTx_prev_hash: %s\n" "\t\t Tx_out_prev_idx: %u\n", l_hash_str, @@ -280,10 +264,10 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum, l_addr_str); } break; case TX_ITEM_TYPE_IN_EMS: { - l_hash_tmp = &((dap_chain_tx_in_ems_t*)item)->header.token_emission_hash; + l_hash_tmp = ((dap_chain_tx_in_ems_t*)item)->header.token_emission_hash; l_hash_str = dap_strcmp(a_hash_out_type, "hex") - ? dap_enc_base58_encode_hash_to_str_static(l_hash_tmp) - : dap_chain_hash_fast_to_str_static(l_hash_tmp); + ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp) + : dap_chain_hash_fast_to_str_static(&l_hash_tmp); dap_string_append_printf(a_str_out, "\t IN_EMS:\n" "\t\t ticker: %s \n" "\t\t token_emission_hash: %s\n" @@ -315,10 +299,10 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum, } break; */ case TX_ITEM_TYPE_IN_REWARD: { - l_hash_tmp = &((dap_chain_tx_in_reward_t *)item)->block_hash; + l_hash_tmp = ((dap_chain_tx_in_reward_t *)item)->block_hash; l_hash_str = dap_strcmp(a_hash_out_type, "hex") - ? dap_enc_base58_encode_hash_to_str_static(l_hash_tmp) - : dap_chain_hash_fast_to_str_static(l_hash_tmp); + ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp) + : dap_chain_hash_fast_to_str_static(&l_hash_tmp); dap_string_append_printf(a_str_out, "\t IN_REWARD:\n" "\t\t block_hash: %s\n", l_hash_str); @@ -393,10 +377,10 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum, ((dap_chain_tx_tsd_t*)item)->header.size); } break; case TX_ITEM_TYPE_IN_COND: - l_hash_tmp = &((dap_chain_tx_in_cond_t*)item)->header.tx_prev_hash; + l_hash_tmp = ((dap_chain_tx_in_cond_t*)item)->header.tx_prev_hash; l_hash_str = dap_strcmp(a_hash_out_type, "hex") - ? dap_enc_base58_encode_hash_to_str_static(l_hash_tmp) - : dap_chain_hash_fast_to_str_static(l_hash_tmp); + ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp) + : dap_chain_hash_fast_to_str_static(&l_hash_tmp); dap_string_append_printf(a_str_out, "\t IN COND:\n\t\tReceipt_idx: %u\n" "\t\t Tx_prev_hash: %s\n" "\t\t Tx_out_prev_idx: %u\n", @@ -421,10 +405,10 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum, case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY: { const char *l_coins_str, *l_value_str = dap_uint256_to_char( ((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.unit_price_max_datoshi, &l_coins_str ); - l_hash_tmp = &((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.pkey_hash; + l_hash_tmp = ((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.pkey_hash; l_hash_str = dap_strcmp(a_hash_out_type, "hex") - ? dap_enc_base58_encode_hash_to_str_static(l_hash_tmp) - : dap_chain_hash_fast_to_str_static(l_hash_tmp); + ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp) + : dap_chain_hash_fast_to_str_static(&l_hash_tmp); dap_string_append_printf(a_str_out, "\t\t\t unit: 0x%08x\n" "\t\t\t pkey: %s\n" "\t\t\t max price: %s (%s)\n", @@ -436,10 +420,10 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum, case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE: { dap_chain_node_addr_t *l_signer_node_addr = &((dap_chain_tx_out_cond_t*)item)->subtype.srv_stake_pos_delegate.signer_node_addr; dap_chain_addr_t *l_signing_addr = &((dap_chain_tx_out_cond_t*)item)->subtype.srv_stake_pos_delegate.signing_addr; - l_hash_tmp = &l_signing_addr->data.hash_fast; + l_hash_tmp = l_signing_addr->data.hash_fast; l_hash_str = dap_strcmp(a_hash_out_type, "hex") - ? dap_enc_base58_encode_hash_to_str_static(l_hash_tmp) - : dap_chain_hash_fast_to_str_static(l_hash_tmp); + ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp) + : dap_chain_hash_fast_to_str_static(&l_hash_tmp); dap_string_append_printf(a_str_out, "\t\t\t signing_addr: %s\n" "\t\t\t with pkey hash %s\n" "\t\t\t signer_node_addr: "NODE_ADDR_FP_STR"\n", @@ -477,8 +461,8 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum, l_value_str); } break; case TX_ITEM_TYPE_VOTING:{ - int l_tsd_size = 0; - dap_chain_tx_tsd_t *l_item = (dap_chain_tx_tsd_t *)dap_chain_datum_tx_item_get(a_datum, 0, TX_ITEM_TYPE_TSD, &l_tsd_size); + size_t l_tsd_size = 0; + dap_chain_tx_tsd_t *l_item = (dap_chain_tx_tsd_t *)dap_chain_datum_tx_item_get(a_datum, NULL, (byte_t*)item + l_size, TX_ITEM_TYPE_TSD, &l_tsd_size); if (!l_item || !l_tsd_size) break; dap_chain_datum_tx_voting_params_t *l_voting_params = dap_chain_voting_parse_tsd(a_datum); @@ -516,13 +500,6 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum, dap_string_append_printf(a_str_out, " This transaction have unknown item type \n"); break; } - l_tx_items_count += l_item_tx_size; - // Freeze protection - if(!l_item_tx_size) - { - break; - } - } dap_string_append_printf(a_str_out, "\n"); return true; @@ -547,7 +524,7 @@ bool dap_chain_datum_dump_tx_json(dap_chain_datum_tx_t *a_datum, dap_chain_net_id_t a_net_id) { bool l_is_first = false; - dap_chain_tx_in_t *l_in_item = (dap_chain_tx_in_t *)dap_chain_datum_tx_item_get(a_datum, NULL, TX_ITEM_TYPE_IN, NULL); + dap_chain_tx_in_t *l_in_item = (dap_chain_tx_in_t *)dap_chain_datum_tx_item_get(a_datum, NULL, NULL, TX_ITEM_TYPE_IN, NULL); if (l_in_item && dap_hash_fast_is_blank(&l_in_item->header.tx_prev_hash)) l_is_first = true; char l_tmp_buf[DAP_TIME_STR_SIZE]; @@ -563,24 +540,17 @@ bool dap_chain_datum_dump_tx_json(dap_chain_datum_tx_t *a_datum, json_object_object_add(json_obj_out, "TS Created", json_object_new_string(l_tmp_buf)); json_object_object_add(json_obj_out, "Token ticker", a_ticker ? json_object_new_string(a_ticker) : json_object_new_string("")); //json_object_array_add(json_arr_items, json_obj_tx); - - uint32_t l_tx_items_count = 0; - uint32_t l_tx_items_size = a_datum->header.tx_items_size; - dap_hash_fast_t *l_hash_tmp = NULL; - while (l_tx_items_count < l_tx_items_size) { + + dap_hash_fast_t l_hash_tmp = { }; + byte_t *item; size_t l_size; + TX_ITEM_ITER_TX(item, l_size, a_datum) { json_object* json_obj_item = json_object_new_object(); - uint8_t *item = a_datum->tx_items + l_tx_items_count; - size_t l_item_tx_size = dap_chain_datum_item_tx_get_size(item); - switch(dap_chain_datum_tx_item_get_type(item)){ + switch (*item) { case TX_ITEM_TYPE_IN: - l_hash_tmp = &((dap_chain_tx_in_t*)item)->header.tx_prev_hash; - if (dap_hash_fast_is_blank(l_hash_tmp)) { - l_hash_str = "BLANK"; - } else { - l_hash_str = dap_strcmp(a_hash_out_type, "hex") - ? dap_enc_base58_encode_hash_to_str_static(l_hash_tmp) - : dap_chain_hash_fast_to_str_static(l_hash_tmp); - } + l_hash_tmp = ((dap_chain_tx_in_t*)item)->header.tx_prev_hash; + l_hash_str = !dap_hash_fast_is_blank(&l_hash_tmp) + ? dap_strcmp(a_hash_out_type, "hex") ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp) : dap_chain_hash_fast_to_str_static(&l_hash_tmp) + : "BLANK"; json_object_object_add(json_obj_item,"item type", json_object_new_string("IN")); json_object_object_add(json_obj_item,"Tx prev hash", json_object_new_string(l_hash_str)); json_object_object_add(json_obj_item,"Tx out prev idx", json_object_new_uint64(((dap_chain_tx_in_t*)item)->header.tx_out_prev_idx)); @@ -603,10 +573,10 @@ bool dap_chain_datum_dump_tx_json(dap_chain_datum_tx_t *a_datum, } break; case TX_ITEM_TYPE_IN_EMS: { char l_tmp_buff[70]={0}; - l_hash_tmp = &((dap_chain_tx_in_ems_t*)item)->header.token_emission_hash; + l_hash_tmp = ((dap_chain_tx_in_ems_t*)item)->header.token_emission_hash; l_hash_str = dap_strcmp(a_hash_out_type, "hex") - ? dap_enc_base58_encode_hash_to_str_static(l_hash_tmp) - : dap_chain_hash_fast_to_str_static(l_hash_tmp); + ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp) + : dap_chain_hash_fast_to_str_static(&l_hash_tmp); json_object_object_add(json_obj_item,"item type", json_object_new_string("IN_EMS")); json_object_object_add(json_obj_item,"ticker", json_object_new_string(((dap_chain_tx_in_ems_t*)item)->header.ticker)); json_object_object_add(json_obj_item,"token_emission_hash", json_object_new_string(l_hash_str)); @@ -636,10 +606,10 @@ bool dap_chain_datum_dump_tx_json(dap_chain_datum_tx_t *a_datum, } break; */ case TX_ITEM_TYPE_IN_REWARD: { - l_hash_tmp = &((dap_chain_tx_in_reward_t *)item)->block_hash; + l_hash_tmp = ((dap_chain_tx_in_reward_t *)item)->block_hash; l_hash_str = dap_strcmp(a_hash_out_type, "hex") - ? dap_enc_base58_encode_hash_to_str_static(l_hash_tmp) - : dap_chain_hash_fast_to_str_static(l_hash_tmp); + ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp) + : dap_chain_hash_fast_to_str_static(&l_hash_tmp); json_object_object_add(json_obj_item,"item type", json_object_new_string("IN_REWARD")); json_object_object_add(json_obj_item,"block_hash", json_object_new_string(l_hash_str)); } break; @@ -704,10 +674,10 @@ bool dap_chain_datum_dump_tx_json(dap_chain_datum_tx_t *a_datum, } break; case TX_ITEM_TYPE_IN_COND: json_object_object_add(json_obj_item,"item type", json_object_new_string("IN COND")); - l_hash_tmp = &((dap_chain_tx_in_cond_t*)item)->header.tx_prev_hash; + l_hash_tmp = ((dap_chain_tx_in_cond_t*)item)->header.tx_prev_hash; l_hash_str = dap_strcmp(a_hash_out_type, "hex") - ? dap_enc_base58_encode_hash_to_str_static(l_hash_tmp) - : dap_chain_hash_fast_to_str_static(l_hash_tmp); + ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp) + : dap_chain_hash_fast_to_str_static(&l_hash_tmp); json_object_object_add(json_obj_item,"Receipt_idx", json_object_new_uint64(((dap_chain_tx_in_cond_t*)item)->header.receipt_idx)); json_object_object_add(json_obj_item,"Tx_prev_hash", json_object_new_string(l_hash_str)); json_object_object_add(json_obj_item,"Tx_out_prev_idx", json_object_new_uint64(((dap_chain_tx_in_cond_t*)item)->header.tx_out_prev_idx)); @@ -729,10 +699,10 @@ bool dap_chain_datum_dump_tx_json(dap_chain_datum_tx_t *a_datum, case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY: { const char *l_coins_str, *l_value_str = dap_uint256_to_char( ((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.unit_price_max_datoshi, &l_coins_str ); - l_hash_tmp = &((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.pkey_hash; + l_hash_tmp = ((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.pkey_hash; l_hash_str = dap_strcmp(a_hash_out_type, "hex") - ? dap_enc_base58_encode_hash_to_str_static(l_hash_tmp) - : dap_chain_hash_fast_to_str_static(l_hash_tmp); + ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp) + : dap_chain_hash_fast_to_str_static(&l_hash_tmp); sprintf(l_tmp_buff,"0x%08x",((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.unit.uint32); json_object_object_add(json_obj_item,"unit", json_object_new_string(l_tmp_buff)); json_object_object_add(json_obj_item,"pkey", json_object_new_string(l_hash_str)); @@ -743,10 +713,10 @@ bool dap_chain_datum_dump_tx_json(dap_chain_datum_tx_t *a_datum, case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE: { dap_chain_node_addr_t *l_signer_node_addr = &((dap_chain_tx_out_cond_t*)item)->subtype.srv_stake_pos_delegate.signer_node_addr; dap_chain_addr_t *l_signing_addr = &((dap_chain_tx_out_cond_t*)item)->subtype.srv_stake_pos_delegate.signing_addr; - l_hash_tmp = &l_signing_addr->data.hash_fast; + l_hash_tmp = l_signing_addr->data.hash_fast; l_hash_str = dap_strcmp(a_hash_out_type, "hex") - ? dap_enc_base58_encode_hash_to_str_static(l_hash_tmp) - : dap_chain_hash_fast_to_str_static(l_hash_tmp); + ? dap_enc_base58_encode_hash_to_str_static(&l_hash_tmp) + : dap_chain_hash_fast_to_str_static(&l_hash_tmp); json_object_object_add(json_obj_item,"signing_addr", json_object_new_string(dap_chain_addr_to_str_static(l_signing_addr))); json_object_object_add(json_obj_item,"with pkey hash", json_object_new_string(l_hash_str)); sprintf(l_tmp_buff,""NODE_ADDR_FP_STR"",NODE_ADDR_FP_ARGS(l_signer_node_addr)); @@ -779,8 +749,8 @@ bool dap_chain_datum_dump_tx_json(dap_chain_datum_tx_t *a_datum, } break; case TX_ITEM_TYPE_VOTING:{ - int l_tsd_size = 0; - dap_chain_tx_tsd_t *l_item = (dap_chain_tx_tsd_t *)dap_chain_datum_tx_item_get(a_datum, 0, TX_ITEM_TYPE_TSD, &l_tsd_size); + size_t l_tsd_size = 0; + dap_chain_tx_tsd_t *l_item = (dap_chain_tx_tsd_t *)dap_chain_datum_tx_item_get(a_datum, NULL, (byte_t*)item + l_size, TX_ITEM_TYPE_TSD, &l_tsd_size); if (!l_item || !l_tsd_size) break; dap_chain_datum_tx_voting_params_t *l_voting_params = dap_chain_voting_parse_tsd(a_datum); @@ -825,13 +795,6 @@ bool dap_chain_datum_dump_tx_json(dap_chain_datum_tx_t *a_datum, break; } json_object_array_add(json_arr_items, json_obj_item); - l_tx_items_count += l_item_tx_size; - // Freeze protection - if(!l_item_tx_size) - { - break; - } - } json_object_object_add(json_obj_out, "ITEMS", json_arr_items); return true; diff --git a/modules/common/dap_chain_datum_anchor.c b/modules/common/dap_chain_datum_anchor.c index a87618bb02b8308c80bf19bab1b72da2027df42a..d0e934bb729133e49377c867473078605564fe87 100644 --- a/modules/common/dap_chain_datum_anchor.c +++ b/modules/common/dap_chain_datum_anchor.c @@ -30,33 +30,11 @@ #define LOG_TAG "dap_chain_datum_anchor" -int dap_chain_datum_anchor_get_hash_from_data(dap_chain_datum_anchor_t* a_anchor, dap_hash_fast_t * l_out_hash) +int dap_chain_datum_anchor_get_hash_from_data(dap_chain_datum_anchor_t* a_anchor, dap_hash_fast_t *a_out_hash) { - if(!a_anchor){ - log_it(L_WARNING,"Wrong arguments"); - return -1; - } - - size_t l_tsd_offset = 0, tsd_data_size = a_anchor->header.data_size; - - while(l_tsd_offset < tsd_data_size){ - dap_tsd_t *l_tsd = (dap_tsd_t*)a_anchor->data_n_sign + l_tsd_offset; - size_t l_tsd_size = l_tsd->size + sizeof(dap_tsd_t); - if(l_tsd_size > tsd_data_size){ - log_it(L_WARNING,"TSD size is greater than all data size. It's possible corrupt data."); - return -1; - } - if (l_tsd->type == DAP_CHAIN_DATUM_ANCHOR_TSD_TYPE_DECREE_HASH){ - if(l_tsd->size > sizeof(dap_hash_fast_t)){ - log_it(L_WARNING,"Wrong fee tsd data size."); - return -1; - } - _dap_tsd_get_scalar(l_tsd, l_out_hash); - return 0; - } - l_tsd_offset += l_tsd_size; - } - return -100; + dap_return_val_if_fail(a_anchor && a_out_hash, -1); + dap_tsd_t *l_tsd = dap_tsd_find(a_anchor->data_n_sign, a_anchor->header.data_size, DAP_CHAIN_DATUM_ANCHOR_TSD_TYPE_DECREE_HASH); + return l_tsd && l_tsd->size == sizeof(dap_hash_fast_t) ? ( _dap_tsd_get_scalar(l_tsd, a_out_hash), 0 ) : 1; } void dap_chain_datum_anchor_certs_dump(dap_string_t * a_str_out, byte_t * a_signs, size_t a_certs_size, const char *a_hash_out_type) diff --git a/modules/common/dap_chain_datum_decree.c b/modules/common/dap_chain_datum_decree.c index 6f2bcabbb6ca33a4fc82cdf4410e1cdb157ec065..5ef31fc6f91a9283bf35fcbbb5eb96abecc7b0d1 100644 --- a/modules/common/dap_chain_datum_decree.c +++ b/modules/common/dap_chain_datum_decree.c @@ -68,18 +68,12 @@ int dap_chain_datum_decree_get_fee_addr(dap_chain_datum_decree_t *a_decree, dap_ return l_tsd && l_tsd->size == sizeof(dap_chain_addr_t) ? ( _dap_tsd_get_scalar(l_tsd, a_fee_wallet), 0 ) : 1; } -static void *s_cb_copy_pkeys(const void *a_pkey, UNUSED_ARG void *a_data) { - return DAP_DUP_SIZE(a_pkey, dap_pkey_get_size(a_pkey)); -} - dap_list_t *dap_chain_datum_decree_get_owners(dap_chain_datum_decree_t *a_decree, uint16_t *a_owners_num) { dap_return_val_if_fail(a_decree && a_owners_num, NULL); - dap_list_t *l_tsd_list = dap_tsd_find_all(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER); - if ( !(*a_owners_num = (uint16_t)dap_list_length(l_tsd_list)) ) - return NULL; - dap_list_t *l_ret = dap_list_copy_deep(l_tsd_list, s_cb_copy_pkeys, NULL); - dap_list_free(l_tsd_list); + dap_list_t *l_ret = dap_tsd_find_all(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER); + if (a_owners_num) + *a_owners_num = (uint16_t)dap_list_length(l_ret); return l_ret; } @@ -155,210 +149,6 @@ int dap_chain_datum_decree_get_ban_addr(dap_chain_datum_decree_t *a_decree, cons return l_tsd ? ( *a_addr = dap_tsd_get_string_const(l_tsd), !dap_strcmp(*a_addr, DAP_TSD_CORRUPTED_STRING) ) : 1; } -void dap_chain_datum_decree_dump(dap_string_t *a_str_out, dap_chain_datum_decree_t *a_decree, size_t a_decree_size, const char *a_hash_out_type) -{ - char *l_type_str = ""; - switch(a_decree->header.type) - { - case DAP_CHAIN_DATUM_DECREE_TYPE_COMMON: - l_type_str = "DECREE_TYPE_COMMON"; - break; - case DAP_CHAIN_DATUM_DECREE_TYPE_SERVICE: - l_type_str = "DECREE_TYPE_SERVICE"; - break; - default: - l_type_str = "DECREE_TYPE_UNKNOWN"; - } - dap_string_append_printf(a_str_out, "type: %s\n", l_type_str); - const char *l_subtype_str = dap_chain_datum_decree_subtype_to_str(a_decree->header.sub_type); - dap_string_append_printf(a_str_out, "subtype: %s\n", l_subtype_str); - dap_string_append_printf(a_str_out, "TSD:\n"); - for (size_t l_offset = 0; l_offset < a_decree->header.data_size;) { - dap_tsd_t *l_tsd = (dap_tsd_t *)((byte_t*)a_decree->data_n_signs + l_offset); - l_offset += dap_tsd_size(l_tsd); - switch(l_tsd->type) { - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_VALUE: - if (l_tsd->size != sizeof(uint256_t)){ - dap_string_append_printf(a_str_out, "\tValue: <WRONG SIZE>\n"); - break; - } - uint256_t l_value = uint256_0; - _dap_tsd_get_scalar(l_tsd, &l_value); - const char *l_value_str = dap_uint256_to_char(l_value, NULL); - dap_string_append_printf(a_str_out, "\tValue: %s\n", l_value_str); - break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGN: - break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE: - if (l_tsd->size != sizeof(uint256_t)){ - dap_string_append_printf(a_str_out, "\tFee: <WRONG SIZE>\n"); - break; - } - uint256_t l_fee_value = uint256_0; - _dap_tsd_get_scalar(l_tsd, &l_fee_value); - const char *l_fee_value_str = dap_uint256_to_char(l_fee_value, NULL); - dap_string_append_printf(a_str_out, "\tFee: %s\n", l_fee_value_str); - break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER: - if (l_tsd->size != sizeof(dap_pkey_t)) { - dap_string_append_printf(a_str_out, "\tOwner fingerprint: <WRONG SIZE>\n"); - break; - } - dap_pkey_t *l_owner_pkey = /*DAP_NEW_STACK_SIZE(dap_pkey_t, l_tsd->size); - memcpy(l_owner_pkey, l_tsd->data, l_tsd->size);*/ _dap_tsd_get_object(l_tsd, dap_pkey_t); - char *l_owner_pkey_str; - dap_get_data_hash_str_static(l_owner_pkey->pkey, l_owner_pkey->header.size, l_owner_pkey_str); - dap_string_append_printf(a_str_out, "\tOwner fingerprint: %s\n", l_owner_pkey_str); - break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER: - if (l_tsd->size != sizeof(uint256_t)) { - dap_string_append_printf(a_str_out, "\tOwner min: <WRONG SIZE>\n"); - break; - } - uint256_t l_owner_min = uint256_0; - _dap_tsd_get_scalar(l_tsd, &l_owner_min); - const char *l_owner_min_str = dap_uint256_to_char(l_owner_min, NULL); - dap_string_append_printf(a_str_out, "\tOwner min: %s\n", l_owner_min_str); - break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE_WALLET: - if (l_tsd->size != sizeof(dap_chain_addr_t)) { - dap_string_append_printf(a_str_out, "\tWallet for fee: <WRONG SIZE>\n"); - break; - } - dap_chain_addr_t *l_addr_fee_wallet = /*{ }; - _dap_tsd_get_scalar(l_tsd, &l_addr_fee_wallet);*/ _dap_tsd_get_object(l_tsd, dap_chain_addr_t); - dap_string_append_printf(a_str_out, "\tWallet for fee: %s\n", dap_chain_addr_to_str_static(l_addr_fee_wallet)); - break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HASH: - if (l_tsd->size != sizeof(dap_hash_fast_t)) { - dap_string_append_printf(a_str_out, "\tHash: <WRONG SIZE>\n"); - break; - } - dap_hash_fast_t *l_stake_tx = /*{ }; - _dap_tsd_get_scalar(l_tsd, &l_stake_tx);*/ _dap_tsd_get_object(l_tsd, dap_hash_fast_t); - const char *l_stake_tx_hash = dap_strcmp(a_hash_out_type, "hex") - ? dap_enc_base58_encode_hash_to_str_static(l_stake_tx) - : dap_chain_hash_fast_to_str_static(l_stake_tx); - dap_string_append_printf(a_str_out, "\tHash: %s\n", l_stake_tx_hash); - break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_VALUE: - if (l_tsd->size != sizeof(uint256_t)){ - dap_string_append_printf(a_str_out, "\tStake value: <WRONG SIZE>\n"); - break; - } - uint256_t l_stake_value = uint256_0; - _dap_tsd_get_scalar(l_tsd, &l_stake_value); - const char *l_stake_value_str = dap_uint256_to_char(l_stake_value, NULL); - dap_string_append_printf(a_str_out, "\tStake value: %s\n", l_stake_value_str); - break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNING_ADDR: - if (l_tsd->size != sizeof(dap_chain_addr_t)) { - dap_string_append_printf(a_str_out, "\tSigning addr: <WRONG SIZE>\n"); - break; - } - dap_chain_addr_t *l_stake_addr_signing = /*{ }; - _dap_tsd_get_scalar(l_tsd, &l_stake_addr_signing);*/ _dap_tsd_get_object(l_tsd, dap_chain_addr_t); - dap_string_append_printf(a_str_out, "\tSigning addr: %s\n", dap_chain_addr_to_str_static(l_stake_addr_signing)); - dap_chain_hash_fast_t l_pkey_signing = l_stake_addr_signing->data.hash_fast; - const char *l_pkey_signing_str = dap_strcmp(a_hash_out_type, "hex") - ? dap_enc_base58_encode_hash_to_str_static(&l_pkey_signing) - : dap_chain_hash_fast_to_str_static(&l_pkey_signing); - dap_string_append_printf(a_str_out, "\tSigning pkey fingerprint: %s\n", l_pkey_signing_str); - break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR: - if (l_tsd->size != sizeof(dap_chain_node_addr_t)){ - dap_string_append_printf(a_str_out, "\tNode addr: <WRONG SIZE>\n"); - break; - } - dap_chain_node_addr_t *l_node_addr = _dap_tsd_get_object(l_tsd, dap_chain_node_addr_t); - dap_string_append_printf(a_str_out, "\tNode addr: "NODE_ADDR_FP_STR"\n", - NODE_ADDR_FP_ARGS(l_node_addr)); - break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_VALUE: - if (l_tsd->size != sizeof(uint256_t)) { - dap_string_append_printf(a_str_out, "\tMin value: <WRONG SIZE>\n"); - break; - } - uint256_t l_min_value = uint256_0; - _dap_tsd_get_scalar(l_tsd, &l_min_value); - const char *l_min_value_str = dap_uint256_to_char(l_min_value, NULL); - dap_string_append_printf(a_str_out, "\tMin value: %s\n", l_min_value_str); - break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_SIGNERS_COUNT: - if (l_tsd->size != sizeof(uint256_t)) { - dap_string_append_printf(a_str_out, "\tMin signers count: <WRONG SIZE>\n"); - break; - } - uint256_t l_min_signers_count = uint256_0; - _dap_tsd_get_scalar(l_tsd, &l_min_signers_count); - const char *l_min_signers_count_str = dap_uint256_to_char(l_min_signers_count, NULL); - dap_string_append_printf(a_str_out, "\tMin signers count: %s\n", l_min_signers_count_str); - break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HOST: - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STRING: - dap_string_append_printf(a_str_out, "\tHost address: %s\n", dap_tsd_get_string(l_tsd)); - break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_ACTION: - if (l_tsd->size != sizeof(uint8_t)){ - dap_string_append_printf(a_str_out, "\tAction: <WRONG SIZE>\n"); - break; - } - uint8_t l_action = 0; - _dap_tsd_get_scalar(l_tsd, &l_action); - dap_string_append_printf(a_str_out, "\tAction: %s\n", l_action ? "add (enable)" : "delete (disable)"); - break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGNATURE_TYPE: - if (l_tsd->size != sizeof(uint32_t)){ - dap_string_append_printf(a_str_out, "\tSignature type: <WRONG SIZE>\n"); - break; - } - uint32_t l_type = 0; - _dap_tsd_get_scalar(l_tsd, &l_type); - dap_sign_type_t l_sign_type = { .type = l_type }; - dap_string_append_printf(a_str_out, "\tSignature type: %s\n", dap_sign_type_to_str(l_sign_type)); - break; - default: - dap_string_append_printf(a_str_out, "\t<UNKNOWN_TYPE_TSD_SECTION>\n"); - break; - } - } - dap_chain_datum_decree_certs_dump(a_str_out, a_decree->data_n_signs + a_decree->header.data_size, - a_decree->header.signs_size, a_hash_out_type); -} - -void dap_chain_datum_decree_certs_dump(dap_string_t * a_str_out, byte_t * a_signs, size_t a_certs_size, const char *a_hash_out_type) -{ - dap_string_append_printf(a_str_out, "signatures: "); - if (!a_certs_size) { - dap_string_append_printf(a_str_out, "<NONE>\n"); - return; - } - - dap_string_append_printf(a_str_out, "\n"); - - size_t l_offset = 0; - for (int i = 1; l_offset < (a_certs_size); i++) { - dap_sign_t *l_sign = (dap_sign_t *) (a_signs + l_offset); - l_offset += dap_sign_get_size(l_sign); - if (l_sign->header.sign_size == 0) { - dap_string_append_printf(a_str_out, "<CORRUPTED - 0 size signature>\n"); - continue; - } - - dap_chain_hash_fast_t l_pkey_hash = {0}; - if (dap_sign_get_pkey_hash(l_sign, &l_pkey_hash) == false) { - dap_string_append_printf(a_str_out, "<CORRUPTED - can't calc hash>\n"); - continue; - } - - const char *l_hash_str = dap_strcmp(a_hash_out_type, "hex") - ? dap_enc_base58_encode_hash_to_str_static(&l_pkey_hash) - : dap_chain_hash_fast_to_str_static(&l_pkey_hash); - dap_string_append_printf(a_str_out, "%d) %s, %s, %u bytes\n", i, l_hash_str, - dap_sign_type_to_str(l_sign->header.type), l_sign->header.sign_size); - } -} - void dap_chain_datum_decree_dump_json(json_object *a_json_out, dap_chain_datum_decree_t *a_decree, size_t a_decree_size, const char *a_hash_out_type) { char *l_type_str = ""; @@ -378,154 +168,151 @@ void dap_chain_datum_decree_dump_json(json_object *a_json_out, dap_chain_datum_d const char *l_subtype_str = dap_chain_datum_decree_subtype_to_str(a_decree->header.sub_type); json_object_object_add(a_json_out, "subtype", json_object_new_string(l_subtype_str)); json_object_object_add(a_json_out, "TSD", json_object_new_string("")); - for (size_t l_offset = 0; l_offset < a_decree->header.data_size;) { - dap_tsd_t *l_tsd = (dap_tsd_t *)((byte_t*)a_decree->data_n_signs + l_offset); - l_offset += dap_tsd_size(l_tsd); + dap_tsd_t *l_tsd; size_t l_tsd_size; + dap_tsd_iter(l_tsd, l_tsd_size, a_decree->data_n_signs, a_decree->header.data_size) { switch(l_tsd->type) { - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_VALUE: - if (l_tsd->size > sizeof(uint256_t)){ - json_object_object_add(a_json_out, "Value", json_object_new_string("WRONG SIZE")); - break; - } - uint256_t l_value = uint256_0; - _dap_tsd_get_scalar(l_tsd, &l_value); - const char *l_value_str = dap_uint256_to_char(l_value, NULL); - json_object_object_add(a_json_out, "Value", json_object_new_string(l_value_str)); + case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_VALUE: + if (l_tsd->size > sizeof(uint256_t)){ + json_object_object_add(a_json_out, "Value", json_object_new_string("WRONG SIZE")); break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGN: + } + uint256_t l_value = uint256_0; + _dap_tsd_get_scalar(l_tsd, &l_value); + const char *l_value_str = dap_uint256_to_char(l_value, NULL); + json_object_object_add(a_json_out, "Value", json_object_new_string(l_value_str)); break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE: - if (l_tsd->size > sizeof(uint256_t)){ - json_object_object_add(a_json_out, "Fee", json_object_new_string("WRONG SIZE")); - break; - } - uint256_t l_fee_value = uint256_0; - _dap_tsd_get_scalar(l_tsd, &l_fee_value); - const char *l_fee_value_str = dap_uint256_to_char(l_fee_value, NULL); - json_object_object_add(a_json_out, "Fee", json_object_new_string(l_fee_value_str)); - break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER: - if (l_tsd->size < sizeof(dap_pkey_t)) { - json_object_object_add(a_json_out, "Owner fingerprint", json_object_new_string("WRONG SIZE")); - break; - } - dap_pkey_t *l_owner_pkey = /*DAP_NEW_STACK_SIZE(dap_pkey_t, l_tsd->size); - memcpy(l_owner_pkey, l_tsd->data, l_tsd->size);*/ _dap_tsd_get_object(l_tsd, dap_pkey_t); - char *l_owner_pkey_str; - dap_get_data_hash_str_static(l_owner_pkey->pkey, l_owner_pkey->header.size, l_owner_pkey_str); - json_object_object_add(a_json_out, "Owner fingerprint", json_object_new_string(l_owner_pkey_str)); + case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGN: + break; + case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE: + if (l_tsd->size > sizeof(uint256_t)){ + json_object_object_add(a_json_out, "Fee", json_object_new_string("WRONG SIZE")); break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER: - if (l_tsd->size > sizeof(uint256_t)){ - json_object_object_add(a_json_out, "Owner min", json_object_new_string("WRONG SIZE")); - break; - } - uint256_t l_owner_min = uint256_0; - _dap_tsd_get_scalar(l_tsd, &l_owner_min); - const char *l_owner_min_str = dap_uint256_to_char(l_owner_min, NULL); - json_object_object_add(a_json_out, "Owner min", json_object_new_string(l_owner_min_str)); - break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE_WALLET: - if (l_tsd->size > sizeof(dap_chain_addr_t)) { - json_object_object_add(a_json_out, "Wallet for fee", json_object_new_string("WRONG SIZE")); - break; - } - dap_chain_addr_t *l_addr_fee_wallet = /*{ }; - _dap_tsd_get_scalar(l_tsd, &l_addr_fee_wallet);*/ _dap_tsd_get_object(l_tsd, dap_chain_addr_t); - json_object_object_add(a_json_out, "Wallet for fee", json_object_new_string(dap_chain_addr_to_str_static(l_addr_fee_wallet))); + } + uint256_t l_fee_value = uint256_0; + _dap_tsd_get_scalar(l_tsd, &l_fee_value); + const char *l_fee_value_str = dap_uint256_to_char(l_fee_value, NULL); + json_object_object_add(a_json_out, "Fee", json_object_new_string(l_fee_value_str)); + break; + case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER: + if (l_tsd->size < sizeof(dap_pkey_t)) { + json_object_object_add(a_json_out, "Owner fingerprint", json_object_new_string("WRONG SIZE")); break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HASH: - if (l_tsd->size > sizeof(dap_hash_fast_t)) { - json_object_object_add(a_json_out, "Stake tx", json_object_new_string("WRONG SIZE")); - break; - } - dap_hash_fast_t *l_stake_tx = /*{ }; - _dap_tsd_get_scalar(l_tsd, &l_stake_tx);*/ _dap_tsd_get_object(l_tsd, dap_hash_fast_t); - const char *l_stake_tx_hash = dap_strcmp(a_hash_out_type, "hex") - ? dap_enc_base58_encode_hash_to_str_static(l_stake_tx) - : dap_chain_hash_fast_to_str_static(l_stake_tx); - json_object_object_add(a_json_out, "Stake tx", json_object_new_string(l_stake_tx_hash)); + } + dap_pkey_t *l_owner_pkey = /*DAP_NEW_STACK_SIZE(dap_pkey_t, l_tsd->size); + memcpy(l_owner_pkey, l_tsd->data, l_tsd->size);*/ _dap_tsd_get_object(l_tsd, dap_pkey_t); + char *l_owner_pkey_str; + dap_get_data_hash_str_static(l_owner_pkey->pkey, l_owner_pkey->header.size, l_owner_pkey_str); + json_object_object_add(a_json_out, "Owner fingerprint", json_object_new_string(l_owner_pkey_str)); + break; + case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER: + if (l_tsd->size > sizeof(uint256_t)){ + json_object_object_add(a_json_out, "Owner min", json_object_new_string("WRONG SIZE")); break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_VALUE: - if (l_tsd->size > sizeof(uint256_t)){ - json_object_object_add(a_json_out, "Stake value", json_object_new_string("WRONG SIZE")); - break; - } - uint256_t l_stake_value = uint256_0; - _dap_tsd_get_scalar(l_tsd, &l_stake_value); - const char *l_stake_value_str = dap_uint256_to_char(l_stake_value, NULL); - json_object_object_add(a_json_out, "Stake value", json_object_new_string(l_stake_value_str)); + } + uint256_t l_owner_min = uint256_0; + _dap_tsd_get_scalar(l_tsd, &l_owner_min); + const char *l_owner_min_str = dap_uint256_to_char(l_owner_min, NULL); + json_object_object_add(a_json_out, "Owner min", json_object_new_string(l_owner_min_str)); + break; + case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE_WALLET: + if (l_tsd->size > sizeof(dap_chain_addr_t)) { + json_object_object_add(a_json_out, "Wallet for fee", json_object_new_string("WRONG SIZE")); break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNING_ADDR: - if (l_tsd->size > sizeof(dap_chain_addr_t)) { - json_object_object_add(a_json_out, "Signing addr", json_object_new_string("WRONG SIZE")); - break; - } - dap_chain_addr_t *l_stake_addr_signing = /*{ }; - _dap_tsd_get_scalar(l_tsd, &l_stake_addr_signing);*/ _dap_tsd_get_object(l_tsd, dap_chain_addr_t); - json_object_object_add(a_json_out, "Signing addr", json_object_new_string(dap_chain_addr_to_str_static(l_stake_addr_signing))); - dap_chain_hash_fast_t l_pkey_signing = l_stake_addr_signing->data.hash_fast; - const char *l_pkey_signing_str = dap_strcmp(a_hash_out_type, "hex") - ? dap_enc_base58_encode_hash_to_str_static(&l_pkey_signing) - : dap_chain_hash_fast_to_str_static(&l_pkey_signing); - json_object_object_add(a_json_out, "Signing pkey fingerprint", json_object_new_string(l_pkey_signing_str)); + } + dap_chain_addr_t *l_addr_fee_wallet = /*{ }; + _dap_tsd_get_scalar(l_tsd, &l_addr_fee_wallet);*/ _dap_tsd_get_object(l_tsd, dap_chain_addr_t); + json_object_object_add(a_json_out, "Wallet for fee", json_object_new_string(dap_chain_addr_to_str_static(l_addr_fee_wallet))); + case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HASH: + if (l_tsd->size > sizeof(dap_hash_fast_t)) { + json_object_object_add(a_json_out, "Stake tx", json_object_new_string("WRONG SIZE")); break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR: - if(l_tsd->size > sizeof(dap_chain_node_addr_t)){ - json_object_object_add(a_json_out, "Node addr", json_object_new_string("WRONG SIZE")); - break; - } - dap_chain_node_addr_t *l_node_addr = _dap_tsd_get_object(l_tsd, dap_chain_node_addr_t); - sprintf(l_tmp_buff, NODE_ADDR_FP_STR, NODE_ADDR_FP_ARGS(l_node_addr)); - json_object_object_add(a_json_out, "Node addr", json_object_new_string(l_tmp_buff)); + } + dap_hash_fast_t *l_stake_tx = /*{ }; + _dap_tsd_get_scalar(l_tsd, &l_stake_tx);*/ _dap_tsd_get_object(l_tsd, dap_hash_fast_t); + const char *l_stake_tx_hash = dap_strcmp(a_hash_out_type, "hex") + ? dap_enc_base58_encode_hash_to_str_static(l_stake_tx) + : dap_chain_hash_fast_to_str_static(l_stake_tx); + json_object_object_add(a_json_out, "Stake tx", json_object_new_string(l_stake_tx_hash)); + break; + case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_VALUE: + if (l_tsd->size > sizeof(uint256_t)){ + json_object_object_add(a_json_out, "Stake value", json_object_new_string("WRONG SIZE")); break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_VALUE: - if (l_tsd->size > sizeof(uint256_t)) { - json_object_object_add(a_json_out, "Min value", json_object_new_string("WRONG SIZE")); - break; - } - uint256_t l_min_value = uint256_0; - _dap_tsd_get_scalar(l_tsd, &l_min_value); - const char *l_min_value_str = dap_uint256_to_char(l_min_value, NULL); - json_object_object_add(a_json_out, "Min value", json_object_new_string(l_min_value_str)); + } + uint256_t l_stake_value = uint256_0; + _dap_tsd_get_scalar(l_tsd, &l_stake_value); + const char *l_stake_value_str = dap_uint256_to_char(l_stake_value, NULL); + json_object_object_add(a_json_out, "Stake value", json_object_new_string(l_stake_value_str)); + break; + case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNING_ADDR: + if (l_tsd->size > sizeof(dap_chain_addr_t)) { + json_object_object_add(a_json_out, "Signing addr", json_object_new_string("WRONG SIZE")); break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_SIGNERS_COUNT: - if (l_tsd->size > sizeof(uint256_t)) { - json_object_object_add(a_json_out, "Min signers count", json_object_new_string("WRONG SIZE")); - break; - } - uint256_t l_min_signers_count = uint256_0; - _dap_tsd_get_scalar(l_tsd, &l_min_signers_count); - const char *l_min_signers_count_str = dap_uint256_to_char(l_min_signers_count, NULL); - json_object_object_add(a_json_out, "Min signers count", json_object_new_string(l_min_signers_count_str)); + } + dap_chain_addr_t *l_stake_addr_signing = /*{ }; + _dap_tsd_get_scalar(l_tsd, &l_stake_addr_signing);*/ _dap_tsd_get_object(l_tsd, dap_chain_addr_t); + json_object_object_add(a_json_out, "Signing addr", json_object_new_string(dap_chain_addr_to_str_static(l_stake_addr_signing))); + dap_chain_hash_fast_t l_pkey_signing = l_stake_addr_signing->data.hash_fast; + const char *l_pkey_signing_str = dap_strcmp(a_hash_out_type, "hex") + ? dap_enc_base58_encode_hash_to_str_static(&l_pkey_signing) + : dap_chain_hash_fast_to_str_static(&l_pkey_signing); + json_object_object_add(a_json_out, "Signing pkey fingerprint", json_object_new_string(l_pkey_signing_str)); + case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR: + if(l_tsd->size > sizeof(dap_chain_node_addr_t)){ + json_object_object_add(a_json_out, "Node addr", json_object_new_string("WRONG SIZE")); break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HOST: - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STRING: - json_object_object_add(a_json_out, "Host address", json_object_new_string(dap_tsd_get_string(l_tsd))); + } + dap_chain_node_addr_t *l_node_addr = _dap_tsd_get_object(l_tsd, dap_chain_node_addr_t); + sprintf(l_tmp_buff, NODE_ADDR_FP_STR, NODE_ADDR_FP_ARGS(l_node_addr)); + json_object_object_add(a_json_out, "Node addr", json_object_new_string(l_tmp_buff)); + break; + case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_VALUE: + if (l_tsd->size > sizeof(uint256_t)) { + json_object_object_add(a_json_out, "Min value", json_object_new_string("WRONG SIZE")); break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_ACTION: - if (l_tsd->size != sizeof(uint8_t)) { - json_object_object_add(a_json_out, "Action", json_object_new_string("WRONG SIZE")); - break; - } - uint8_t l_action = 0; - _dap_tsd_get_scalar(l_tsd, &l_action); - json_object_object_add(a_json_out, "tAction", l_action ? - json_object_new_string("add (enable)") : json_object_new_string("delete (disable)")); + } + uint256_t l_min_value = uint256_0; + _dap_tsd_get_scalar(l_tsd, &l_min_value); + const char *l_min_value_str = dap_uint256_to_char(l_min_value, NULL); + json_object_object_add(a_json_out, "Min value", json_object_new_string(l_min_value_str)); + break; + case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_SIGNERS_COUNT: + if (l_tsd->size > sizeof(uint256_t)) { + json_object_object_add(a_json_out, "Min signers count", json_object_new_string("WRONG SIZE")); break; - case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGNATURE_TYPE: - if (l_tsd->size != sizeof(uint32_t)) { - json_object_object_add(a_json_out, "Signature type", json_object_new_string("WRONG SIZE")); - break; - } - uint32_t l_type = 0; - _dap_tsd_get_scalar(l_tsd, &l_type); - dap_sign_type_t l_sign_type = { .type = l_type }; - json_object_object_add(a_json_out, "Signature type", json_object_new_string(dap_sign_type_to_str(l_sign_type))); + } + uint256_t l_min_signers_count = uint256_0; + _dap_tsd_get_scalar(l_tsd, &l_min_signers_count); + const char *l_min_signers_count_str = dap_uint256_to_char(l_min_signers_count, NULL); + json_object_object_add(a_json_out, "Min signers count", json_object_new_string(l_min_signers_count_str)); + break; + case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HOST: + case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STRING: + json_object_object_add(a_json_out, "Host address", json_object_new_string(dap_tsd_get_string(l_tsd))); + break; + case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_ACTION: + if (l_tsd->size != sizeof(uint8_t)) { + json_object_object_add(a_json_out, "Action", json_object_new_string("WRONG SIZE")); break; - default: - json_object_object_add(a_json_out, "UNKNOWN_TYPE_TSD_SECTION", json_object_new_string("")); + } + uint8_t l_action = 0; + _dap_tsd_get_scalar(l_tsd, &l_action); + json_object_object_add(a_json_out, "tAction", l_action ? + json_object_new_string("add (enable)") : json_object_new_string("delete (disable)")); + break; + case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGNATURE_TYPE: + if (l_tsd->size != sizeof(uint32_t)) { + json_object_object_add(a_json_out, "Signature type", json_object_new_string("WRONG SIZE")); break; + } + uint32_t l_type = 0; + _dap_tsd_get_scalar(l_tsd, &l_type); + dap_sign_type_t l_sign_type = { .type = l_type }; + json_object_object_add(a_json_out, "Signature type", json_object_new_string(dap_sign_type_to_str(l_sign_type))); + break; + default: + json_object_object_add(a_json_out, "UNKNOWN_TYPE_TSD_SECTION", json_object_new_string("")); + break; } } dap_chain_datum_decree_certs_dump_json(a_json_out, a_decree->data_n_signs + a_decree->header.data_size, diff --git a/modules/common/dap_chain_datum_token.c b/modules/common/dap_chain_datum_token.c index f3a442a4189620c66144907d8057be89c22760a2..6383d27db0479a2dd3bc5989408c38783f10b479 100644 --- a/modules/common/dap_chain_datum_token.c +++ b/modules/common/dap_chain_datum_token.c @@ -403,16 +403,16 @@ dap_chain_datum_token_emission_t *dap_chain_datum_emission_add_tsd(dap_chain_dat byte_t *dap_chain_emission_get_tsd(dap_chain_datum_token_emission_t *a_emission, int a_type, size_t *a_size) { + if (a_size) + *a_size = 0; if (!a_emission || a_emission->hdr.type != DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_AUTH || a_emission->data.type_auth.tsd_total_size == 0) return NULL; - dap_tsd_t *l_tsd = NULL; - if (!(l_tsd = dap_tsd_find(a_emission->tsd_n_signs, a_emission->data.type_auth.tsd_total_size, a_type))) { + dap_tsd_t *l_tsd = dap_tsd_find(a_emission->tsd_n_signs, a_emission->data.type_auth.tsd_total_size, a_type); + if (!l_tsd) return NULL; - } else { - if (a_size) - *a_size = l_tsd->size; - } + else if (a_size) + *a_size = l_tsd->size; return l_tsd->data; } diff --git a/modules/common/dap_chain_datum_tx.c b/modules/common/dap_chain_datum_tx.c index 38d7ac9670839eccb3bdca241a9cd954a8e1d07b..8ea7e5f2905dc4a33b3e9bfeaf444198c162b5bd 100644 --- a/modules/common/dap_chain_datum_tx.c +++ b/modules/common/dap_chain_datum_tx.c @@ -40,12 +40,9 @@ dap_chain_datum_tx_t* dap_chain_datum_tx_create(void) { dap_chain_datum_tx_t *tx = DAP_NEW_Z(dap_chain_datum_tx_t); - if (!tx) { - log_it(L_CRITICAL, "%s", c_error_memory_alloc); - return 0; - } - tx->header.ts_created = time(NULL); - return tx; + return tx + ? tx->header.ts_created = time(NULL), tx + : ( log_it(L_CRITICAL, "%s", c_error_memory_alloc), NULL ); } /** @@ -53,8 +50,7 @@ dap_chain_datum_tx_t* dap_chain_datum_tx_create(void) */ void dap_chain_datum_tx_delete(dap_chain_datum_tx_t *a_tx) { - if(a_tx) - DAP_DELETE(a_tx); + DAP_DELETE(a_tx); } /** @@ -64,9 +60,9 @@ void dap_chain_datum_tx_delete(dap_chain_datum_tx_t *a_tx) */ size_t dap_chain_datum_tx_get_size(dap_chain_datum_tx_t *a_tx) { - if(!a_tx) - return 0; - return (sizeof(dap_chain_datum_tx_t) + a_tx->header.tx_items_size); + dap_return_val_if_fail(a_tx, 0); + return (sizeof(dap_chain_datum_tx_t) + a_tx->header.tx_items_size) > a_tx->header.tx_items_size + ? sizeof(dap_chain_datum_tx_t) + a_tx->header.tx_items_size : 0; } /** @@ -76,35 +72,30 @@ size_t dap_chain_datum_tx_get_size(dap_chain_datum_tx_t *a_tx) */ int dap_chain_datum_tx_add_item(dap_chain_datum_tx_t **a_tx, const void *a_item) { - size_t size = dap_chain_datum_item_tx_get_size(a_item); - if(!size || !a_tx || !*a_tx) - return -1; - dap_chain_datum_tx_t *tx_cur = *a_tx; - size_t l_new_size = dap_chain_datum_tx_get_size(tx_cur) + size; - tx_cur = (dap_chain_datum_tx_t*)DAP_REALLOC(tx_cur, l_new_size); - if (!tx_cur) + size_t size = 0; + if ( !a_tx || !*a_tx || !(size = dap_chain_datum_item_tx_get_size(a_item, 0)) ) return -1; - memcpy((uint8_t*) tx_cur->tx_items + tx_cur->header.tx_items_size, a_item, size); - tx_cur->header.tx_items_size += size; - *a_tx = tx_cur; + dap_chain_datum_tx_t *tx_new = DAP_REALLOC( *a_tx, dap_chain_datum_tx_get_size(*a_tx) + size ); + if (!tx_new) + return -2; + memcpy((uint8_t*) tx_new->tx_items + tx_new->header.tx_items_size, a_item, size); + tx_new->header.tx_items_size += size; + *a_tx = tx_new; return 1; } +#define dap_chain_datum_tx_add_new_generic(a_tx, type, a_item) \ + ({ type* item = a_item; item ? ( dap_chain_datum_tx_add_item(a_tx, item), DAP_DELETE(item), 1 ) : -1; }) + /** * Create 'in' item and insert to transaction * * return 1 Ok, -1 Error */ -int dap_chain_datum_tx_add_in_item(dap_chain_datum_tx_t **a_tx, dap_chain_hash_fast_t *a_tx_prev_hash, - uint32_t a_tx_out_prev_idx) +int dap_chain_datum_tx_add_in_item(dap_chain_datum_tx_t **a_tx, dap_chain_hash_fast_t *a_tx_prev_hash, uint32_t a_tx_out_prev_idx) { - dap_chain_tx_in_t *l_tx_in = dap_chain_datum_tx_item_in_create(a_tx_prev_hash, a_tx_out_prev_idx); - if(l_tx_in) { - dap_chain_datum_tx_add_item(a_tx, (const uint8_t *)l_tx_in); - DAP_DELETE(l_tx_in); - return 1; - } - return -1; + return dap_chain_datum_tx_add_new_generic( a_tx, dap_chain_tx_in_t, + dap_chain_datum_tx_item_in_create(a_tx_prev_hash, a_tx_out_prev_idx) ); } /** @@ -138,13 +129,8 @@ int dap_chain_datum_tx_add_in_cond_item(dap_chain_datum_tx_t **a_tx, dap_chain_h uint32_t a_tx_out_prev_idx, uint32_t a_receipt_idx) { - dap_chain_tx_in_cond_t *l_tx_in_cond - = dap_chain_datum_tx_item_in_cond_create(a_tx_prev_hash, a_tx_out_prev_idx, a_receipt_idx); - if (!l_tx_in_cond) - return -1; - dap_chain_datum_tx_add_item(a_tx, (uint8_t*)l_tx_in_cond); - DAP_DELETE(l_tx_in_cond); - return 0; + return dap_chain_datum_tx_add_new_generic( a_tx, dap_chain_tx_in_cond_t, + dap_chain_datum_tx_item_in_cond_create(a_tx_prev_hash, a_tx_out_prev_idx, a_receipt_idx) ); } uint256_t dap_chain_datum_tx_add_in_cond_item_list(dap_chain_datum_tx_t **a_tx, dap_list_t *a_list_used_out_cound) @@ -153,7 +139,7 @@ uint256_t dap_chain_datum_tx_add_in_cond_item_list(dap_chain_datum_tx_t **a_tx, uint256_t l_value_to_items = { }; DL_FOREACH(a_list_used_out_cound, l_item_out) { dap_chain_tx_used_out_item_t *l_item = l_item_out->data; - if (!dap_chain_datum_tx_add_in_cond_item(a_tx, &l_item->tx_hash_fast, l_item->num_idx_out,0)) { + if (1 == dap_chain_datum_tx_add_in_cond_item(a_tx, &l_item->tx_hash_fast, l_item->num_idx_out,0)) { SUM_256_256(l_value_to_items, l_item->value, &l_value_to_items); } } @@ -162,12 +148,8 @@ uint256_t dap_chain_datum_tx_add_in_cond_item_list(dap_chain_datum_tx_t **a_tx, int dap_chain_datum_tx_add_in_reward_item(dap_chain_datum_tx_t **a_tx, dap_chain_hash_fast_t *a_block_hash) { - dap_chain_tx_in_reward_t *l_tx_in_reward = dap_chain_datum_tx_item_in_reward_create(a_block_hash); - if (!l_tx_in_reward) - return -1; - dap_chain_datum_tx_add_item(a_tx, (uint8_t*)l_tx_in_reward); - DAP_DELETE(l_tx_in_reward); - return 1; + return dap_chain_datum_tx_add_new_generic( a_tx, dap_chain_tx_in_reward_t, + dap_chain_datum_tx_item_in_reward_create(a_block_hash) ); } /** @@ -177,46 +159,33 @@ int dap_chain_datum_tx_add_in_reward_item(dap_chain_datum_tx_t **a_tx, dap_chain */ int dap_chain_datum_tx_add_fee_item(dap_chain_datum_tx_t **a_tx, uint256_t a_value) { - dap_chain_tx_out_cond_t *l_tx_out_fee = dap_chain_datum_tx_item_out_cond_create_fee(a_value); - if (l_tx_out_fee) { - dap_chain_datum_tx_add_item(a_tx, (const uint8_t *)l_tx_out_fee); - DAP_DELETE(l_tx_out_fee); - return 1; - } - return -1; + return dap_chain_datum_tx_add_new_generic( a_tx, dap_chain_tx_out_cond_t, + dap_chain_datum_tx_item_out_cond_create_fee(a_value) ); } int dap_chain_datum_tx_get_fee_value(dap_chain_datum_tx_t *a_tx, uint256_t *a_value) { if (!a_value) return -2; - int l_ret = -1; - dap_list_t *l_items_list = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT_COND, NULL), *l_item; - DL_FOREACH(l_items_list, l_item) { - dap_chain_tx_out_cond_t *l_out_item = (dap_chain_tx_out_cond_t*)l_item->data; - if (l_out_item->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE){ - *a_value = l_out_item->header.value; - l_ret = 0; + byte_t *l_item; size_t l_tx_item_size; + dap_chain_tx_out_cond_t *l_out_item; + TX_ITEM_ITER_TX(l_item, l_tx_item_size, a_tx) { + switch (*l_item) { + case TX_ITEM_TYPE_OUT_COND: + l_out_item = (dap_chain_tx_out_cond_t*)l_item; + if (l_out_item->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE) + return (*a_value = l_out_item->header.value), 0; + default: break; } } - dap_list_free(l_items_list); - return l_ret; + return -1; } dap_sign_t *dap_chain_datum_tx_get_sign(dap_chain_datum_tx_t *a_tx, int a_sign_num) { dap_return_val_if_fail(a_tx, NULL); - if (!a_sign_num) { - dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_SIG, NULL); - return dap_chain_datum_tx_item_sign_get_sig(l_tx_sig); - } - dap_list_t *l_items_list = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_SIG, NULL); - if (dap_list_length(l_items_list) <= (uint64_t)a_sign_num) - return NULL; - dap_sign_t *l_ret = dap_list_nth_data(l_items_list, a_sign_num); - dap_list_free(l_items_list); - return l_ret; + return dap_chain_datum_tx_item_sign_get_sig( (dap_chain_tx_sig_t*) dap_chain_datum_tx_item_get_nth(a_tx, TX_ITEM_TYPE_SIG, a_sign_num) ); } /** @@ -226,13 +195,8 @@ dap_sign_t *dap_chain_datum_tx_get_sign(dap_chain_datum_tx_t *a_tx, int a_sign_n */ int dap_chain_datum_tx_add_out_item(dap_chain_datum_tx_t **a_tx, const dap_chain_addr_t *a_addr, uint256_t a_value) { - dap_chain_tx_out_t *l_tx_out = dap_chain_datum_tx_item_out_create(a_addr, a_value); - if(l_tx_out) { - dap_chain_datum_tx_add_item(a_tx, (const uint8_t *)l_tx_out); - DAP_DELETE(l_tx_out); - return 1; - } - return -1; + return dap_chain_datum_tx_add_new_generic( a_tx, dap_chain_tx_out_t, + dap_chain_datum_tx_item_out_create(a_addr, a_value) ); } /** @@ -242,13 +206,8 @@ int dap_chain_datum_tx_add_out_item(dap_chain_datum_tx_t **a_tx, const dap_chain */ int dap_chain_datum_tx_add_out_ext_item(dap_chain_datum_tx_t **a_tx, const dap_chain_addr_t *a_addr, uint256_t a_value, const char *a_token) { - dap_chain_tx_out_ext_t *l_tx_out = dap_chain_datum_tx_item_out_ext_create(a_addr, a_value, a_token); - if(l_tx_out) { - dap_chain_datum_tx_add_item(a_tx, (const uint8_t *)l_tx_out); - DAP_DELETE(l_tx_out); - return 1; - } - return -1; + return dap_chain_datum_tx_add_new_generic( a_tx, dap_chain_tx_out_ext_t, + dap_chain_datum_tx_item_out_ext_create(a_addr, a_value, a_token) ); } /** @@ -259,14 +218,8 @@ int dap_chain_datum_tx_add_out_ext_item(dap_chain_datum_tx_t **a_tx, const dap_c int dap_chain_datum_tx_add_out_cond_item(dap_chain_datum_tx_t **a_tx, dap_pkey_t *a_key, dap_chain_net_srv_uid_t a_srv_uid, uint256_t a_value, uint256_t a_value_max_per_unit, dap_chain_net_srv_price_unit_uid_t a_unit, const void *a_cond, size_t a_cond_size) { - dap_chain_tx_out_cond_t *l_tx_out = dap_chain_datum_tx_item_out_cond_create_srv_pay( - a_key, a_srv_uid,a_value, a_value_max_per_unit, a_unit, a_cond, a_cond_size ); - if(l_tx_out) { - dap_chain_datum_tx_add_item(a_tx, (const uint8_t *) l_tx_out); - DAP_DELETE(l_tx_out); - return 1; - } - return -1; + return dap_chain_datum_tx_add_new_generic( a_tx, dap_chain_tx_out_cond_t, + dap_chain_datum_tx_item_out_cond_create_srv_pay( a_key, a_srv_uid,a_value, a_value_max_per_unit, a_unit, a_cond, a_cond_size )); } @@ -277,18 +230,8 @@ int dap_chain_datum_tx_add_out_cond_item(dap_chain_datum_tx_t **a_tx, dap_pkey_t */ int dap_chain_datum_tx_add_sign_item(dap_chain_datum_tx_t **a_tx, dap_enc_key_t *a_key) { - if(!a_tx || !a_key) - return -1; - // sign all previous items in transaction - const void *l_data = (*a_tx)->tx_items; - const size_t l_data_size = (*a_tx)->header.tx_items_size; - dap_chain_tx_sig_t *l_tx_sig = dap_chain_datum_tx_item_sign_create(a_key, l_data, l_data_size); - if(l_tx_sig) { - int l_ret = dap_chain_datum_tx_add_item(a_tx, (const uint8_t*) l_tx_sig); - DAP_DELETE(l_tx_sig); - return l_ret; - } - return -1; + return a_tx && a_key ? dap_chain_datum_tx_add_new_generic( a_tx, dap_chain_tx_sig_t, + dap_chain_datum_tx_item_sign_create( a_key, (*a_tx)->tx_items, (*a_tx)->header.tx_items_size )) : -1; } /** @@ -300,32 +243,17 @@ int dap_chain_datum_tx_verify_sign(dap_chain_datum_tx_t *a_tx) { dap_return_val_if_pass(!a_tx, -1); int l_ret = 0; - uint32_t tx_items_pos = 0, tx_items_size = a_tx->header.tx_items_size; - while(tx_items_pos < tx_items_size) { - uint8_t *item = a_tx->tx_items + tx_items_pos; - size_t l_item_tx_size = dap_chain_datum_item_tx_get_size(item); - if(!l_item_tx_size || l_item_tx_size > tx_items_size) - return -2; - if(dap_chain_datum_tx_item_get_type(item) == TX_ITEM_TYPE_SIG) { - dap_chain_tx_sig_t *l_item_tx_sig = (dap_chain_tx_sig_t*) item; - dap_sign_t *l_sign = (dap_sign_t*) l_item_tx_sig->sig; - if ( ( l_sign->header.sign_size + l_sign->header.sign_pkey_size +sizeof (l_sign->header) ) - > l_item_tx_size ){ - log_it(L_WARNING,"Incorrect signature's header, possible corrupted data"); - return -3; - } - if ((l_ret = dap_sign_verify_all(l_sign, tx_items_size, a_tx->tx_items, tx_items_pos))) { - // invalid signature - tx_items_pos += l_item_tx_size; + byte_t *l_item; size_t l_size; + dap_sign_t *l_sign; + TX_ITEM_ITER_TX(l_item, l_size, a_tx) { + if (*l_item == TX_ITEM_TYPE_SIG) { + l_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t*)l_item); + const size_t l_offset = (size_t)(l_item - a_tx->tx_items); + if ( 0 != ( l_ret = dap_sign_get_size(l_sign) > l_size + ? log_it(L_WARNING, "Incorrect signature header, possible corrupted data"), -3 + : dap_sign_verify_all(l_sign, a_tx->header.tx_items_size - l_offset, a_tx->tx_items, l_offset) )) break; - } } - // sign item or items must be at the end, therefore ret will be changed later anyway - else - l_ret = -4; - // go to text item - tx_items_pos += l_item_tx_size; } - assert(tx_items_pos == tx_items_size); return l_ret; } diff --git a/modules/common/dap_chain_datum_tx_items.c b/modules/common/dap_chain_datum_tx_items.c index 68fb6e0e49f2806c0bb32518922eaa7a3b883682..6bcc83c9e4325fe0750c24cbed8c92c97c725687 100644 --- a/modules/common/dap_chain_datum_tx_items.c +++ b/modules/common/dap_chain_datum_tx_items.c @@ -36,98 +36,6 @@ #define LOG_TAG "dap_chain_datum_tx_items" -static size_t dap_chain_tx_in_get_size(const dap_chain_tx_in_t *a_item) -{ - (void) a_item; - size_t size = sizeof(dap_chain_tx_in_t); // + item->header.sig_size; - return size; -} - -static size_t dap_chain_tx_in_cond_get_size(const dap_chain_tx_in_cond_t *a_item) -{ - UNUSED(a_item); - size_t size = sizeof(dap_chain_tx_in_cond_t); - return size; -} - -static size_t dap_chain_tx_out_old_get_size(const dap_chain_tx_out_old_t *a_item) -{ - (void) a_item; - size_t size = sizeof(dap_chain_tx_out_old_t); - return size; -} - -// 256 -static size_t dap_chain_tx_out_get_size(const dap_chain_tx_out_t *a_item) -{ - (void) a_item; - size_t size = sizeof(dap_chain_tx_out_t); - return size; -} - -// 256 -static size_t dap_chain_tx_out_ext_get_size(const dap_chain_tx_out_ext_t *a_item) -{ - (void) a_item; - size_t size = sizeof(dap_chain_tx_out_ext_t); - return size; -} - -static size_t dap_chain_tx_out_cond_get_size(const dap_chain_tx_out_cond_t *a_item) -{ - size_t size = sizeof(dap_chain_tx_out_cond_t) + a_item->tsd_size; - return size; -} - -static size_t dap_chain_tx_pkey_get_size(const dap_chain_tx_pkey_t *a_item) -{ - size_t size = sizeof(dap_chain_tx_pkey_t) + a_item->header.sig_size; - return size; -} - -static size_t dap_chain_tx_sig_get_size(const dap_chain_tx_sig_t *a_item) -{ - size_t size = sizeof(dap_chain_tx_sig_t) + a_item->header.sig_size; - return size; -} - -static size_t dap_chain_tx_in_ems_get_size(const dap_chain_tx_in_ems_t *a_item) -{ - (void) a_item; - size_t size = sizeof(dap_chain_tx_in_ems_t); - return size; -} - -static size_t dap_chain_tx_in_reward_get_size(const dap_chain_tx_in_reward_t UNUSED_ARG *a_item) -{ - size_t size = sizeof(dap_chain_tx_in_reward_t); - return size; -} - -static size_t dap_chain_datum_tx_receipt_get_size(const dap_chain_datum_tx_receipt_t *a_item) -{ - size_t size = a_item->size; - return size; -} - -static size_t dap_chain_tx_tsd_get_size(const dap_chain_tx_tsd_t *a_item) -{ - return sizeof(dap_chain_tx_tsd_t) + a_item->header.size; -} - -static size_t dap_chain_tx_voting_get_size(const dap_chain_tx_voting_t *a_item) -{ - (void) a_item; - size_t size = sizeof(dap_chain_tx_voting_t); - return size; -} - -static size_t dap_chain_tx_vote_get_size(const dap_chain_tx_vote_t *a_item) -{ - (void) a_item; - size_t size = sizeof(dap_chain_tx_vote_t); - return size; -} /** * Get item type by item name * @@ -188,73 +96,45 @@ dap_chain_tx_out_cond_subtype_t dap_chain_tx_out_cond_subtype_from_str(const cha return DAP_CHAIN_TX_OUT_COND_SUBTYPE_UNDEFINED; } -/** - * Get item type - * - * return type, or TX_ITEM_TYPE_ANY if error - */ -dap_chain_tx_item_type_t dap_chain_datum_tx_item_get_type(const void *a_item) -{ - dap_chain_tx_item_type_t type = a_item ? *(dap_chain_tx_item_type_t *)a_item : TX_ITEM_TYPE_UNKNOWN; - return type; -} - /** * Get item size * * return size, 0 Error */ -size_t dap_chain_datum_item_tx_get_size(const void *a_item) -{ - dap_chain_tx_item_type_t type = dap_chain_datum_tx_item_get_type(a_item); - size_t size = 0; - switch (type) { - case TX_ITEM_TYPE_IN: // Transaction inputs - size = dap_chain_tx_in_get_size((const dap_chain_tx_in_t*) a_item); - break; - case TX_ITEM_TYPE_OUT_OLD: //64 - size = dap_chain_tx_out_old_get_size((const dap_chain_tx_out_old_t*) a_item); - break; - case TX_ITEM_TYPE_OUT: // Transaction outputs - size = dap_chain_tx_out_get_size((const dap_chain_tx_out_t*) a_item); - break; - case TX_ITEM_TYPE_OUT_EXT: // Exchange transaction outputs - size = dap_chain_tx_out_ext_get_size((const dap_chain_tx_out_ext_t*) a_item); - break; - case TX_ITEM_TYPE_RECEIPT: // Receipt: - size = dap_chain_datum_tx_receipt_get_size((const dap_chain_datum_tx_receipt_t *)a_item); - break; - case TX_ITEM_TYPE_IN_COND: // Transaction inputs with condition - size = dap_chain_tx_in_cond_get_size((const dap_chain_tx_in_cond_t*) a_item); - break; - case TX_ITEM_TYPE_OUT_COND: // Condtional output - size = dap_chain_tx_out_cond_get_size((const dap_chain_tx_out_cond_t *)a_item); - break; - case TX_ITEM_TYPE_PKEY: // Transaction public keys - size = dap_chain_tx_pkey_get_size((const dap_chain_tx_pkey_t*) a_item); - break; - case TX_ITEM_TYPE_SIG: // Transaction signatures - size = dap_chain_tx_sig_get_size((const dap_chain_tx_sig_t*) a_item); - break; - case TX_ITEM_TYPE_IN_EMS: // token emission pointer - size = dap_chain_tx_in_ems_get_size((const dap_chain_tx_in_ems_t*) a_item); - break; - case TX_ITEM_TYPE_IN_REWARD: // block emission pointer - size = dap_chain_tx_in_reward_get_size((const dap_chain_tx_in_reward_t *)a_item); - break; - case TX_ITEM_TYPE_TSD: - size = dap_chain_tx_tsd_get_size((const dap_chain_tx_tsd_t*)a_item); - break; - case TX_ITEM_TYPE_VOTING: - size = dap_chain_tx_voting_get_size((const dap_chain_tx_voting_t*)a_item); - break; - case TX_ITEM_TYPE_VOTE: - size = dap_chain_tx_vote_get_size((const dap_chain_tx_vote_t*)a_item); - break; - default: - return 0; + +size_t dap_chain_datum_item_tx_get_size(const byte_t *a_item, size_t a_max_size) { + dap_return_val_if_fail(a_item, TX_ITEM_TYPE_UNKNOWN); + size_t l_ret = 0; +#define m_tx_item_size(t) ( !a_max_size || sizeof(t) <= a_max_size ? sizeof(t) : 0 ) +#define m_tx_item_size_ext(t, size_field) \ + ( !a_max_size || \ + ( sizeof(t) < a_max_size && a_max_size > ((t*)a_item)->size_field && sizeof(t) <= a_max_size - ((t*)a_item)->size_field ) \ + ? sizeof(t) + ((t*)a_item)->size_field : 0 ); + + switch (*a_item) { + case TX_ITEM_TYPE_IN: return m_tx_item_size(dap_chain_tx_in_t); + case TX_ITEM_TYPE_OUT_OLD: return m_tx_item_size(dap_chain_tx_out_old_t); + case TX_ITEM_TYPE_OUT: return m_tx_item_size(dap_chain_tx_out_t); + case TX_ITEM_TYPE_OUT_EXT: return m_tx_item_size(dap_chain_tx_out_ext_t); + case TX_ITEM_TYPE_IN_COND: return m_tx_item_size(dap_chain_tx_in_cond_t); + case TX_ITEM_TYPE_IN_EMS: return m_tx_item_size(dap_chain_tx_in_ems_t); + case TX_ITEM_TYPE_IN_REWARD:return m_tx_item_size(dap_chain_tx_in_reward_t); + case TX_ITEM_TYPE_VOTING: return m_tx_item_size(dap_chain_tx_voting_t); + case TX_ITEM_TYPE_VOTE: return m_tx_item_size(dap_chain_tx_vote_t); + // Access data size by struct field + case TX_ITEM_TYPE_TSD: return m_tx_item_size_ext(dap_chain_tx_tsd_t, header.size); + case TX_ITEM_TYPE_OUT_COND: return m_tx_item_size_ext(dap_chain_tx_out_cond_t, tsd_size); + case TX_ITEM_TYPE_PKEY: return m_tx_item_size_ext(dap_chain_tx_pkey_t, header.sig_size); + case TX_ITEM_TYPE_SIG: return m_tx_item_size_ext(dap_chain_tx_sig_t, header.sig_size); + // Receipt size calculation is non-trivial... + case TX_ITEM_TYPE_RECEIPT: { + typedef dap_chain_datum_tx_receipt_t t; + return !a_max_size || ( sizeof(t) < a_max_size && ((t*)a_item)->size < a_max_size ) ? ((t*)a_item)->size : 0; } - return size; + default: return 0; + } +#undef m_tx_item_size +#undef m_tx_item_size_ext } /** @@ -542,7 +422,7 @@ dap_chain_tx_sig_t* dap_chain_datum_tx_item_sign_create(dap_enc_key_t *a_key, co */ dap_sign_t* dap_chain_datum_tx_item_sign_get_sig(dap_chain_tx_sig_t *a_tx_sig) { - return a_tx_sig && a_tx_sig->header.sig_size ? (dap_sign_t*)a_tx_sig->sig : NULL; + return a_tx_sig && a_tx_sig->header.sig_size > sizeof(dap_sign_t) ? (dap_sign_t*)a_tx_sig->sig : NULL; } /** @@ -571,41 +451,49 @@ byte_t *dap_chain_datum_tx_item_get_data(dap_chain_tx_tsd_t *a_tx_tsd, int *a_ty * return item data, NULL Error index or bad format transaction */ uint8_t* dap_chain_datum_tx_item_get( dap_chain_datum_tx_t *a_tx, int *a_item_idx, - dap_chain_tx_item_type_t a_type, int *a_item_out_size) -{ - if(!a_tx) - return NULL; - uint32_t l_tx_items_pos = 0, l_tx_items_size = a_tx->header.tx_items_size; - int l_item_idx = 0; - while (l_tx_items_pos < l_tx_items_size) { - uint8_t *l_item = a_tx->tx_items + l_tx_items_pos; - int l_item_size = dap_chain_datum_item_tx_get_size(l_item); - if(!l_item_size) - return NULL; - // check index - if(!a_item_idx || l_item_idx >= *a_item_idx) { - // check type - dap_chain_tx_item_type_t l_type = dap_chain_datum_tx_item_get_type(l_item); - if (a_type == TX_ITEM_TYPE_ANY || a_type == l_type || - (a_type == TX_ITEM_TYPE_OUT_ALL && l_type == TX_ITEM_TYPE_OUT) || - (a_type == TX_ITEM_TYPE_OUT_ALL && l_type == TX_ITEM_TYPE_OUT_OLD) || - (a_type == TX_ITEM_TYPE_OUT_ALL && l_type == TX_ITEM_TYPE_OUT_COND) || - (a_type == TX_ITEM_TYPE_OUT_ALL && l_type == TX_ITEM_TYPE_OUT_EXT) || - (a_type == TX_ITEM_TYPE_IN_ALL && l_type == TX_ITEM_TYPE_IN) || - (a_type == TX_ITEM_TYPE_IN_ALL && l_type == TX_ITEM_TYPE_IN_COND) || - (a_type == TX_ITEM_TYPE_IN_ALL && l_type == TX_ITEM_TYPE_IN_EMS) || - (a_type == TX_ITEM_TYPE_IN_ALL && l_type == TX_ITEM_TYPE_IN_REWARD)) { - if(a_item_idx) - *a_item_idx = l_item_idx; - if(a_item_out_size) - *a_item_out_size = l_item_size; - return l_item; - } + byte_t *a_iter, dap_chain_tx_item_type_t a_type, size_t *a_item_out_size) +{ + if (!a_tx) + return NULL; + int i = a_item_idx ? *a_item_idx : 0, j = -1; + byte_t *l_end = a_tx->tx_items + a_tx->header.tx_items_size, + *l_begin = i || !a_iter || a_iter < a_tx->tx_items || a_iter > l_end ? a_tx->tx_items : a_iter; + size_t l_left_size = (size_t)(l_end - l_begin), l_tx_item_size; + byte_t *l_item; +#define m_item_idx_n_size(item, idx, size) ({ \ + if (a_item_idx) *a_item_idx = idx; \ + if (a_item_out_size) *a_item_out_size = size; \ + item; \ +}) + TX_ITEM_ITER(l_item, l_tx_item_size, l_begin, l_left_size) { + if (++j < i) + continue; + switch (a_type) { + case TX_ITEM_TYPE_ANY: + break; + case TX_ITEM_TYPE_OUT_ALL: + switch (*l_item) { + case TX_ITEM_TYPE_OUT: case TX_ITEM_TYPE_OUT_OLD: case TX_ITEM_TYPE_OUT_COND: case TX_ITEM_TYPE_OUT_EXT: + break; + default: + continue; + } break; + case TX_ITEM_TYPE_IN_ALL: + switch (*l_item) { + case TX_ITEM_TYPE_IN: case TX_ITEM_TYPE_IN_COND: case TX_ITEM_TYPE_IN_EMS: case TX_ITEM_TYPE_IN_REWARD: + break; + default: + continue; + } break; + default: + if (*l_item == a_type) + break; + else continue; } - l_tx_items_pos += l_item_size; - l_item_idx++; + return m_item_idx_n_size(l_item, j, l_tx_item_size); } - return NULL; + return m_item_idx_n_size(NULL, -1, 0); +#undef m_item_idx_n_size } /** @@ -619,33 +507,23 @@ uint8_t* dap_chain_datum_tx_item_get( dap_chain_datum_tx_t *a_tx, int *a_item_id dap_list_t* dap_chain_datum_tx_items_get(dap_chain_datum_tx_t *a_tx, dap_chain_tx_item_type_t a_type, int *a_item_count) { dap_list_t *items_list = NULL; - int l_items_count = 0, l_item_idx_start = 0; - uint8_t *l_tx_item; - - // Get a_type items from transaction - while ((l_tx_item = dap_chain_datum_tx_item_get(a_tx, &l_item_idx_start, a_type, NULL)) != NULL) - { + uint8_t *l_tx_item = NULL; + size_t l_size; int i, q = 0; + TX_ITEM_ITER_TX_TYPE(l_tx_item, a_type, l_size, i, a_tx) { items_list = dap_list_append(items_list, l_tx_item); - ++l_items_count; - ++l_item_idx_start; + ++q; } - - if(a_item_count) - *a_item_count = l_items_count; - - return items_list; + return (a_item_count ? (*a_item_count = q) : 0), items_list; } uint8_t *dap_chain_datum_tx_item_get_nth(dap_chain_datum_tx_t *a_tx, dap_chain_tx_item_type_t a_type, int a_item_idx) { - uint8_t *l_tx_item = NULL; - int l_item_idx = 0; - for (int l_type_idx = 0; l_type_idx <= a_item_idx; ++l_type_idx, ++l_item_idx) { - l_tx_item = dap_chain_datum_tx_item_get(a_tx, &l_item_idx, a_type, NULL); - if (!l_tx_item) - break; + uint8_t *l_tx_item = NULL; size_t l_size; int i; + TX_ITEM_ITER_TX_TYPE(l_tx_item, a_type, l_size, i, a_tx) { + if (!a_item_idx--) + return l_tx_item; } - return l_tx_item; + return NULL; } /** @@ -656,193 +534,149 @@ uint8_t *dap_chain_datum_tx_item_get_nth(dap_chain_datum_tx_t *a_tx, dap_chain_t * a_out_num[out] found index of item in transaction, -1 if not found * return tx_out_cond, or NULL */ -dap_chain_tx_out_cond_t *dap_chain_datum_tx_out_cond_get(dap_chain_datum_tx_t *a_tx, dap_chain_tx_item_type_t a_cond_type, int *a_out_num) -{ - dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT_ALL, NULL), *l_item; - int l_prev_cond_idx = 0; - dap_chain_tx_out_cond_t *l_res = NULL; - for (dap_list_t *l_item = l_list_out_items; l_item; l_item = l_item->next, ++l_prev_cond_idx) { - // Start from *a_out_num + 1 item if a_out_num != NULL - if (a_out_num && l_prev_cond_idx < *a_out_num) - continue; - if (*(byte_t*)l_item->data == TX_ITEM_TYPE_OUT_COND && - ((dap_chain_tx_out_cond_t*)l_item->data)->header.subtype == a_cond_type) { - l_res = l_item->data; +dap_chain_tx_out_cond_t *dap_chain_datum_tx_out_cond_get(dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_subtype_t a_cond_subtype, int *a_out_num) +{ + int l_idx = a_out_num && *a_out_num > 0 ? -*a_out_num : 0; + byte_t *l_item; size_t l_tx_item_size; + TX_ITEM_ITER_TX(l_item, l_tx_item_size, a_tx) { + switch (*l_item) { + case TX_ITEM_TYPE_OUT_COND: + if ( l_idx >= 0 && ((dap_chain_tx_out_cond_t*)l_item)->header.subtype == a_cond_subtype ) + return (a_out_num ? (*a_out_num = l_idx) : 0), (dap_chain_tx_out_cond_t*)l_item; + case TX_ITEM_TYPE_OUT: case TX_ITEM_TYPE_OUT_OLD: case TX_ITEM_TYPE_OUT_EXT: + ++l_idx; + default: break; } } - dap_list_free(l_list_out_items); - if (a_out_num) { - *a_out_num = l_res ? l_prev_cond_idx : -1; - } - return l_res; -} - -uint8_t *dap_chain_datum_tx_out_get_by_out_idx(dap_chain_datum_tx_t *a_tx, int a_out_num) -{ - uint8_t *l_ret = NULL; - dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_OUT_ALL, NULL), *l_item; - if (!l_list_out_items) - return NULL; - - l_item = dap_list_nth(l_list_out_items, a_out_num); - - if(!l_item){ - dap_list_free(l_list_out_items); - return NULL; - } - - l_ret = l_item->data; - dap_list_free(l_list_out_items); - return l_ret; - + return (a_out_num ? (*a_out_num = -1) : 0), NULL; } void dap_chain_datum_tx_group_items_free( dap_chain_datum_tx_item_groups_t *a_items_groups) { - if (a_items_groups->items_in) dap_list_free(a_items_groups->items_in); - if (a_items_groups->items_in_cond) dap_list_free(a_items_groups->items_in_cond); - if (a_items_groups->items_in_reward) dap_list_free(a_items_groups->items_in_reward); - if (a_items_groups->items_sig) dap_list_free(a_items_groups->items_sig); - if (a_items_groups->items_out) dap_list_free(a_items_groups->items_out); - if (a_items_groups->items_out_ext) dap_list_free(a_items_groups->items_out_ext); - if (a_items_groups->items_out_cond) dap_list_free(a_items_groups->items_out_cond); - if (a_items_groups->items_out_cond_srv_fee) dap_list_free(a_items_groups->items_out_cond_srv_fee); - if (a_items_groups->items_out_cond_srv_pay) dap_list_free(a_items_groups->items_out_cond_srv_pay); - if (a_items_groups->items_out_cond_srv_xchange) dap_list_free(a_items_groups->items_out_cond_srv_xchange); - if (a_items_groups->items_out_cond_srv_stake_pos_delegate) dap_list_free(a_items_groups->items_out_cond_srv_stake_pos_delegate); - if (a_items_groups->items_out_cond_srv_stake_lock) dap_list_free(a_items_groups->items_out_cond_srv_stake_lock); - if (a_items_groups->items_in_ems) dap_list_free(a_items_groups->items_in_ems); - if (a_items_groups->items_vote) dap_list_free(a_items_groups->items_vote); - if (a_items_groups->items_voting) dap_list_free(a_items_groups->items_voting); - if (a_items_groups->items_tsd) dap_list_free(a_items_groups->items_tsd); - if (a_items_groups->items_pkey) dap_list_free(a_items_groups->items_pkey); - if (a_items_groups->items_receipt) dap_list_free(a_items_groups->items_receipt); - if (a_items_groups->items_unknown) dap_list_free(a_items_groups->items_unknown); - if (a_items_groups->items_out_old) dap_list_free(a_items_groups->items_out_old); - if (a_items_groups->items_out_cond_unknonwn) dap_list_free(a_items_groups->items_out_cond_unknonwn); - if (a_items_groups->items_out_cond_undefined) dap_list_free(a_items_groups->items_out_cond_undefined); - if (a_items_groups->items_out_all) dap_list_free(a_items_groups->items_out_all); - if (a_items_groups->items_in_all) dap_list_free(a_items_groups->items_in_all); + dap_list_free(a_items_groups->items_in); + dap_list_free(a_items_groups->items_in_cond); + dap_list_free(a_items_groups->items_in_reward); + dap_list_free(a_items_groups->items_sig); + dap_list_free(a_items_groups->items_out); + dap_list_free(a_items_groups->items_out_ext); + dap_list_free(a_items_groups->items_out_cond); + dap_list_free(a_items_groups->items_out_cond_srv_fee); + dap_list_free(a_items_groups->items_out_cond_srv_pay); + dap_list_free(a_items_groups->items_out_cond_srv_xchange); + dap_list_free(a_items_groups->items_out_cond_srv_stake_pos_delegate); + dap_list_free(a_items_groups->items_out_cond_srv_stake_lock); + dap_list_free(a_items_groups->items_in_ems); + dap_list_free(a_items_groups->items_vote); + dap_list_free(a_items_groups->items_voting); + dap_list_free(a_items_groups->items_tsd); + dap_list_free(a_items_groups->items_pkey); + dap_list_free(a_items_groups->items_receipt); + dap_list_free(a_items_groups->items_unknown); + dap_list_free(a_items_groups->items_out_old); + dap_list_free(a_items_groups->items_out_cond_unknonwn); + dap_list_free(a_items_groups->items_out_cond_undefined); + dap_list_free(a_items_groups->items_out_all); + dap_list_free(a_items_groups->items_in_all); } #define DAP_LIST_SAPPEND(X, Y) X = dap_list_append(X,Y) bool dap_chain_datum_tx_group_items(dap_chain_datum_tx_t *a_tx, dap_chain_datum_tx_item_groups_t *a_res_group) { - if(!a_tx || !a_res_group) return NULL; - uint32_t l_tx_items_pos = 0, l_tx_items_size = a_tx->header.tx_items_size; - - int l_item_idx = 0; - - while (l_tx_items_pos < l_tx_items_size) { - - uint8_t *l_item = a_tx->tx_items + l_tx_items_pos; - int l_item_size = dap_chain_datum_item_tx_get_size(l_item); - - if(!l_item_size) - return false; - - dap_chain_tx_item_type_t l_type = dap_chain_datum_tx_item_get_type(l_item); - - switch (l_type) - { - case TX_ITEM_TYPE_IN: - DAP_LIST_SAPPEND(a_res_group->items_in, l_item); - DAP_LIST_SAPPEND(a_res_group->items_in_all, l_item); - break; - - case TX_ITEM_TYPE_IN_COND: - DAP_LIST_SAPPEND(a_res_group->items_in_cond, l_item); - DAP_LIST_SAPPEND(a_res_group->items_in_all, l_item); - break; + byte_t *l_item; size_t l_tx_item_size; + TX_ITEM_ITER_TX(l_item, l_tx_item_size, a_tx) { + switch (*l_item) { + case TX_ITEM_TYPE_IN: + DAP_LIST_SAPPEND(a_res_group->items_in, l_item); + DAP_LIST_SAPPEND(a_res_group->items_in_all, l_item); + break; - case TX_ITEM_TYPE_IN_REWARD: - DAP_LIST_SAPPEND(a_res_group->items_in_reward, l_item); - DAP_LIST_SAPPEND(a_res_group->items_in_all, l_item); - break; + case TX_ITEM_TYPE_IN_COND: + DAP_LIST_SAPPEND(a_res_group->items_in_cond, l_item); + DAP_LIST_SAPPEND(a_res_group->items_in_all, l_item); + break; - case TX_ITEM_TYPE_IN_EMS: - DAP_LIST_SAPPEND(a_res_group->items_in_ems, l_item); - DAP_LIST_SAPPEND(a_res_group->items_in_all, l_item); - break; + case TX_ITEM_TYPE_IN_REWARD: + DAP_LIST_SAPPEND(a_res_group->items_in_reward, l_item); + DAP_LIST_SAPPEND(a_res_group->items_in_all, l_item); + break; - case TX_ITEM_TYPE_OUT_OLD: - DAP_LIST_SAPPEND(a_res_group->items_out_old, l_item); - DAP_LIST_SAPPEND(a_res_group->items_out_all, l_item); - break; + case TX_ITEM_TYPE_IN_EMS: + DAP_LIST_SAPPEND(a_res_group->items_in_ems, l_item); + DAP_LIST_SAPPEND(a_res_group->items_in_all, l_item); + break; - case TX_ITEM_TYPE_OUT_EXT: - DAP_LIST_SAPPEND(a_res_group->items_out_ext, l_item); - DAP_LIST_SAPPEND(a_res_group->items_out_all, l_item); - break; + case TX_ITEM_TYPE_OUT_OLD: + DAP_LIST_SAPPEND(a_res_group->items_out_old, l_item); + DAP_LIST_SAPPEND(a_res_group->items_out_all, l_item); + break; - case TX_ITEM_TYPE_OUT: - DAP_LIST_SAPPEND(a_res_group->items_out, l_item); - DAP_LIST_SAPPEND(a_res_group->items_out_all, l_item); - break; + case TX_ITEM_TYPE_OUT_EXT: + DAP_LIST_SAPPEND(a_res_group->items_out_ext, l_item); + DAP_LIST_SAPPEND(a_res_group->items_out_all, l_item); + break; - case TX_ITEM_TYPE_OUT_COND: { - switch ( ((dap_chain_tx_out_cond_t *)l_item)->header.subtype ) - { - case DAP_CHAIN_TX_OUT_COND_SUBTYPE_UNDEFINED: - DAP_LIST_SAPPEND(a_res_group->items_out_cond_undefined, l_item); - break; - case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY: - DAP_LIST_SAPPEND(a_res_group->items_out_cond_srv_pay, l_item); - break; - case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE: - DAP_LIST_SAPPEND(a_res_group->items_out_cond_srv_xchange, l_item); - break; - case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE: - DAP_LIST_SAPPEND(a_res_group->items_out_cond_srv_stake_pos_delegate, l_item); - break; - case DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE: - DAP_LIST_SAPPEND(a_res_group->items_out_cond_srv_fee, l_item); - break; - case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK: - DAP_LIST_SAPPEND(a_res_group->items_out_cond_srv_stake_lock, l_item); - break; - default: - DAP_LIST_SAPPEND(a_res_group->items_out_cond_unknonwn, l_item); - break; - } - - DAP_LIST_SAPPEND(a_res_group->items_out_cond, l_item); - DAP_LIST_SAPPEND(a_res_group->items_out_all, l_item); - } - break; + case TX_ITEM_TYPE_OUT: + DAP_LIST_SAPPEND(a_res_group->items_out, l_item); + DAP_LIST_SAPPEND(a_res_group->items_out_all, l_item); + break; - case TX_ITEM_TYPE_PKEY: - DAP_LIST_SAPPEND(a_res_group->items_pkey, l_item); + case TX_ITEM_TYPE_OUT_COND: { + switch ( ((dap_chain_tx_out_cond_t *)l_item)->header.subtype ) { + case DAP_CHAIN_TX_OUT_COND_SUBTYPE_UNDEFINED: + DAP_LIST_SAPPEND(a_res_group->items_out_cond_undefined, l_item); break; - case TX_ITEM_TYPE_SIG: - DAP_LIST_SAPPEND(a_res_group->items_sig, l_item); + case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY: + DAP_LIST_SAPPEND(a_res_group->items_out_cond_srv_pay, l_item); break; - case TX_ITEM_TYPE_RECEIPT: - DAP_LIST_SAPPEND(a_res_group->items_receipt, l_item); + case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE: + DAP_LIST_SAPPEND(a_res_group->items_out_cond_srv_xchange, l_item); break; - case TX_ITEM_TYPE_TSD: - DAP_LIST_SAPPEND(a_res_group->items_tsd, l_item); + case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE: + DAP_LIST_SAPPEND(a_res_group->items_out_cond_srv_stake_pos_delegate, l_item); break; - - case TX_ITEM_TYPE_VOTING: - DAP_LIST_SAPPEND(a_res_group->items_voting, l_item); + case DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE: + DAP_LIST_SAPPEND(a_res_group->items_out_cond_srv_fee, l_item); break; - - case TX_ITEM_TYPE_VOTE: - DAP_LIST_SAPPEND(a_res_group->items_vote, l_item); + case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK: + DAP_LIST_SAPPEND(a_res_group->items_out_cond_srv_stake_lock, l_item); break; default: - DAP_LIST_SAPPEND(a_res_group->items_unknown, l_item); + DAP_LIST_SAPPEND(a_res_group->items_out_cond_unknonwn, l_item); + break; + } + DAP_LIST_SAPPEND(a_res_group->items_out_cond, l_item); + DAP_LIST_SAPPEND(a_res_group->items_out_all, l_item); + } + break; + + case TX_ITEM_TYPE_PKEY: + DAP_LIST_SAPPEND(a_res_group->items_pkey, l_item); + break; + case TX_ITEM_TYPE_SIG: + DAP_LIST_SAPPEND(a_res_group->items_sig, l_item); + break; + case TX_ITEM_TYPE_RECEIPT: + DAP_LIST_SAPPEND(a_res_group->items_receipt, l_item); + break; + case TX_ITEM_TYPE_TSD: + DAP_LIST_SAPPEND(a_res_group->items_tsd, l_item); + break; + + case TX_ITEM_TYPE_VOTING: + DAP_LIST_SAPPEND(a_res_group->items_voting, l_item); + break; + + case TX_ITEM_TYPE_VOTE: + DAP_LIST_SAPPEND(a_res_group->items_vote, l_item); + break; + default: + DAP_LIST_SAPPEND(a_res_group->items_unknown, l_item); } - - l_tx_items_pos += l_item_size; - l_item_idx++; } - return true; } diff --git a/modules/common/dap_chain_datum_tx_receipt.c b/modules/common/dap_chain_datum_tx_receipt.c index b4e4c836c4632987d4243461d94b071ebd510673..ef1618beebc9f92daec607b3398e528dd3af66b6 100644 --- a/modules/common/dap_chain_datum_tx_receipt.c +++ b/modules/common/dap_chain_datum_tx_receipt.c @@ -53,6 +53,7 @@ dap_chain_datum_tx_receipt_t * dap_chain_datum_tx_receipt_create( dap_chain_net_ l_ret->receipt_info.srv_uid = a_srv_uid; l_ret->receipt_info.units = a_units; l_ret->receipt_info.value_datoshi = a_value_datoshi; + l_ret->receipt_info.version = 1; l_ret->size = sizeof(dap_chain_datum_tx_receipt_t) + a_ext_size; if (a_ext_size && a_ext) { @@ -96,26 +97,24 @@ dap_chain_datum_tx_receipt_t *dap_chain_datum_tx_receipt_sign_add(dap_chain_datu * @param a_sign_position * @return */ -dap_sign_t* dap_chain_datum_tx_receipt_sign_get(dap_chain_datum_tx_receipt_t *a_receipt, size_t a_receipt_size, uint16_t a_sign_position) +dap_sign_t *dap_chain_datum_tx_receipt_sign_get(dap_chain_datum_tx_receipt_t *a_receipt, size_t a_receipt_size, uint16_t a_sign_position) { - dap_return_val_if_fail(a_receipt && a_receipt_size == a_receipt->size && - a_receipt_size >= sizeof(dap_chain_datum_tx_receipt_t) + a_receipt->exts_size, - NULL); - if (a_receipt_size < sizeof(dap_chain_datum_tx_receipt_t) + a_receipt->exts_size + sizeof(dap_sign_t)) - return NULL; // No signs at all - dap_sign_t *l_sign = (dap_sign_t *)(a_receipt->exts_n_signs + a_receipt->exts_size); - uint16_t l_sign_position; - for (l_sign_position = a_sign_position; - l_sign_position && a_receipt_size > (size_t)((byte_t *)l_sign - (byte_t *)a_receipt) + sizeof(dap_sign_t); - l_sign_position--) { - l_sign = (dap_sign_t *)((byte_t *)l_sign + dap_sign_get_size(l_sign)); - } - // not enough signs in receipt - if (l_sign_position > 0) + if (dap_chain_datum_tx_receipt_check_size(a_receipt, a_receipt_size)) { + log_it(L_WARNING, "Receipt size check error"); return NULL; - // too big sign size - if (dap_sign_get_size(l_sign) + ((byte_t *)l_sign - a_receipt->exts_n_signs) + sizeof(dap_chain_datum_tx_receipt_t) > a_receipt_size) + } + size_t l_offset = a_receipt->exts_size; + size_t l_total_signs_size = a_receipt->size - sizeof(dap_chain_datum_tx_receipt_t) - a_receipt->exts_size; + if (!l_total_signs_size) return NULL; + dap_sign_t *l_sign = NULL; + for (uint16_t l_sign_position = a_sign_position + 1; l_sign_position; l_sign_position--) { + l_sign = (dap_sign_t *)(a_receipt->exts_n_signs + l_offset); + uint64_t l_sign_size = dap_sign_get_size(l_sign); + l_offset += l_sign_size; + if (l_offset > l_total_signs_size) + return NULL; + } return l_sign; } @@ -147,17 +146,38 @@ uint256_t dap_chain_datum_tx_receipt_value_get(dap_chain_datum_tx_receipt_t *a * @param a_receipt_size * @return */ -uint16_t dap_chain_datum_tx_receipt_signs_count(dap_chain_datum_tx_receipt_t * a_receipt, size_t a_receipt_size) +uint16_t dap_chain_datum_tx_receipt_signs_count(dap_chain_datum_tx_receipt_t *a_receipt) { uint16_t l_ret = 0; - if(!a_receipt) - return 0; + dap_return_val_if_fail(a_receipt, 0); dap_sign_t *l_sign; - for (l_sign = (dap_sign_t *)a_receipt->exts_n_signs; a_receipt_size > (size_t) ( (byte_t *) l_sign - (byte_t *) a_receipt ) ; + for (l_sign = (dap_sign_t *)a_receipt->exts_n_signs; a_receipt->size > (size_t) ( (byte_t *) l_sign - (byte_t *) a_receipt ) ; l_sign =(dap_sign_t *) (((byte_t*) l_sign)+ dap_sign_get_size( l_sign )) ){ l_ret++; } - if(a_receipt_size != (size_t) ((byte_t *) l_sign - (byte_t *) a_receipt) ) - log_it(L_ERROR, "Receipt 0x%zu (size=%zu) is corrupted", (size_t)a_receipt, a_receipt_size); return l_ret; } + +int dap_chain_datum_tx_receipt_check_size(dap_chain_datum_tx_receipt_t *a_receipt, size_t a_control_size) +{ + dap_return_val_if_fail(a_receipt && a_control_size == a_receipt->size && + a_control_size >= sizeof(dap_chain_datum_tx_receipt_t) + a_receipt->exts_size, + -1); // Main controls incosistentency + if (a_control_size == sizeof(dap_chain_datum_tx_receipt_t) + a_receipt->exts_size) + return 0; // No signs at receipt, it's OK + if (a_control_size < sizeof(dap_chain_datum_tx_receipt_t) + a_receipt->exts_size + sizeof(dap_sign_t)) + return -2; + dap_sign_t *l_sign = (dap_sign_t *)(a_receipt->exts_n_signs + a_receipt->exts_size); + for (uint16_t l_sign_position = 2; l_sign_position; l_sign_position--) { + size_t l_sign_offset = (byte_t *)l_sign - (byte_t *)a_receipt; + if (a_control_size < l_sign_offset + sizeof(dap_sign_t)) + return -2; // Left space is too samll to contain a sign + uint64_t l_sign_size = dap_sign_get_size(l_sign); + if (l_sign_size + l_sign_offset <= l_sign_offset || l_sign_size + l_sign_offset > a_control_size) + return -3; + l_sign = (dap_sign_t *)((byte_t *)l_sign + l_sign_size); + } + size_t l_sign_offset = (byte_t *)l_sign - (byte_t *)a_receipt; + // Receipt is lagrer that two signs need + return l_sign_offset == a_control_size ? 0 : (a_receipt->receipt_info.version ? -4 : 0); +} diff --git a/modules/common/dap_chain_datum_tx_voting.c b/modules/common/dap_chain_datum_tx_voting.c index 305ed3937eb719693ef64506a8077d511d13ccea..2a161dd3a93ce110042cf4c8c30030a536e9ec28 100644 --- a/modules/common/dap_chain_datum_tx_voting.c +++ b/modules/common/dap_chain_datum_tx_voting.c @@ -31,26 +31,21 @@ dap_chain_datum_tx_voting_params_t* dap_chain_voting_parse_tsd(dap_chain_datum_t { if (!a_tx) return NULL; - - dap_list_t* l_tsd_list = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_TSD, NULL); - dap_chain_datum_tx_voting_params_t *l_voting_parms = DAP_NEW_Z_SIZE(dap_chain_datum_tx_voting_params_t, - sizeof(dap_chain_datum_tx_voting_params_t)); - char *l_buf_string = NULL; - dap_list_t* l_temp = l_tsd_list; - while (l_temp){ - dap_tsd_t *l_tsd = (dap_tsd_t *)((dap_chain_tx_tsd_t*)l_temp->data)->tsd; + dap_chain_datum_tx_voting_params_t *l_voting_parms = DAP_NEW_Z(dap_chain_datum_tx_voting_params_t); + char *l_buf_string; + byte_t *l_item; size_t l_tx_item_size; + TX_ITEM_ITER_TX(l_item, l_tx_item_size, a_tx) { + if (*l_item != TX_ITEM_TYPE_TSD) + continue; + dap_tsd_t *l_tsd = (dap_tsd_t*)((dap_chain_tx_tsd_t*)l_item)->tsd; switch(l_tsd->type){ case VOTING_TSD_TYPE_QUESTION: l_buf_string = DAP_NEW_Z_SIZE(char, l_tsd->size + 1); - memcpy(l_buf_string, l_tsd->data, l_tsd->size); - l_buf_string[l_tsd->size] = '\0'; - l_voting_parms->voting_question = l_buf_string; + l_voting_parms->voting_question = memcpy(l_buf_string, l_tsd->data, l_tsd->size); break; case VOTING_TSD_TYPE_ANSWER: l_buf_string = DAP_NEW_Z_SIZE(char, l_tsd->size + 1); - memcpy(l_buf_string, l_tsd->data, l_tsd->size); - l_buf_string[l_tsd->size] = '\0'; - l_voting_parms->answers_list = dap_list_append(l_voting_parms->answers_list, l_buf_string); + l_voting_parms->answers_list = dap_list_append(l_voting_parms->answers_list, memcpy(l_buf_string, l_tsd->data, l_tsd->size)); l_voting_parms->answers_count++; break; case VOTING_TSD_TYPE_EXPIRE: @@ -68,11 +63,7 @@ dap_chain_datum_tx_voting_params_t* dap_chain_voting_parse_tsd(dap_chain_datum_t default: break; } - - l_temp = l_temp->next; } - dap_list_free(l_tsd_list); - return l_voting_parms; } @@ -117,16 +108,18 @@ dap_chain_tx_tsd_t* dap_chain_datum_voting_max_votes_count_tsd_create(uint64_t a return l_tsd; } -dap_chain_tx_tsd_t* dap_chain_datum_voting_delegated_key_required_tsd_create(bool a_delegate_key_required) +dap_chain_tx_tsd_t* dap_chain_datum_voting_delegated_key_required_tsd_create(bool a_delegated_key_required) { - dap_chain_tx_tsd_t* l_tsd = dap_chain_datum_tx_item_tsd_create(&a_delegate_key_required, VOTING_TSD_TYPE_DELEGATED_KEY_REQUIRED, sizeof(bool)); + byte_t l_value = a_delegated_key_required; + dap_chain_tx_tsd_t* l_tsd = dap_chain_datum_tx_item_tsd_create(&l_value, VOTING_TSD_TYPE_DELEGATED_KEY_REQUIRED, sizeof(byte_t)); return l_tsd; } dap_chain_tx_tsd_t* dap_chain_datum_voting_vote_changing_allowed_tsd_create(bool a_vote_changing_allowed) { - dap_chain_tx_tsd_t* l_tsd = dap_chain_datum_tx_item_tsd_create(&a_vote_changing_allowed, VOTING_TSD_TYPE_VOTE_CHANGING_ALLOWED, sizeof(bool)); + byte_t l_value = a_vote_changing_allowed; + dap_chain_tx_tsd_t* l_tsd = dap_chain_datum_tx_item_tsd_create(&l_value, VOTING_TSD_TYPE_VOTE_CHANGING_ALLOWED, sizeof(byte_t)); return l_tsd; } @@ -151,29 +144,17 @@ dap_chain_tx_voting_t *dap_chain_datum_tx_item_voting_create(void) } const char *s_tx_voting_get_answer_text_by_idx(dap_chain_datum_tx_t *a_tx, uint64_t a_idx) { - dap_list_t *l_answers_list = NULL; - size_t l_anwers_count = 0; - dap_list_t* l_tsd_list = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_TSD, NULL); - dap_list_t* l_temp = l_tsd_list; - while (l_temp){ - dap_tsd_t* l_tsd = (dap_tsd_t *)((dap_chain_tx_tsd_t*)l_temp->data)->tsd; - if (l_tsd->type == VOTING_TSD_TYPE_ANSWER) { - char *l_buf_string = DAP_NEW_Z_SIZE(char, l_tsd->size + 1); - memcpy(l_buf_string, l_tsd->data, l_tsd->size); - l_buf_string[l_tsd->size] = '\0'; - l_answers_list = dap_list_append(l_answers_list, l_buf_string); - l_anwers_count++; - } - l_temp = l_temp->next; + byte_t *l_item; size_t l_tx_item_size; + dap_tsd_t *l_tsd; + TX_ITEM_ITER_TX(l_item, l_tx_item_size, a_tx) { + if ( *l_item != TX_ITEM_TYPE_TSD + || ( l_tsd = (dap_tsd_t*)((dap_chain_tx_tsd_t*)l_item)->tsd, l_tsd->type != VOTING_TSD_TYPE_ANSWER ) + || a_idx-- ) + continue; + char *l_ret = DAP_NEW_Z_SIZE(char, l_tsd->size + 1); + return memcpy(l_ret, l_tsd->data, l_tsd->size); } - dap_list_free(l_tsd_list); - if (l_anwers_count < a_idx) { - dap_list_free_full(l_answers_list, NULL); - return NULL; - } - char *l_ret = dap_strdup(dap_list_nth_data(l_answers_list, a_idx)); - dap_list_free_full(l_answers_list, NULL); - return l_ret; + return NULL; } json_object *dap_chain_datum_tx_item_voting_tsd_to_json(dap_chain_datum_tx_t* a_tx) @@ -181,45 +162,36 @@ json_object *dap_chain_datum_tx_item_voting_tsd_to_json(dap_chain_datum_tx_t* a_ if (!a_tx) return NULL; - json_object *l_object = json_object_new_object(); - json_object *l_answer_array_object = json_object_new_array(); - json_object *l_json_obj = NULL; - dap_list_t* l_tsd_list = dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_TSD, NULL); - dap_list_t* l_temp = l_tsd_list; - while (l_temp){ - dap_tsd_t* l_tsd = (dap_tsd_t *)((dap_chain_tx_tsd_t*)l_temp->data)->tsd; - switch(l_tsd->type){ + json_object *l_object = json_object_new_object(), *l_answer_array_object = json_object_new_array(); + byte_t *l_item; size_t l_tx_item_size; + dap_tsd_t *l_tsd; + TX_ITEM_ITER_TX(l_item, l_tx_item_size, a_tx) { + if (*l_item != TX_ITEM_TYPE_TSD) + continue; + l_tsd = (dap_tsd_t*)((dap_chain_tx_tsd_t*)l_item)->tsd; + switch(l_tsd->type) { case VOTING_TSD_TYPE_QUESTION: - l_json_obj = json_object_new_string_len((char*)l_tsd->data, l_tsd->size); - json_object_object_add(l_object, "question", l_json_obj); + json_object_object_add(l_object, "question", json_object_new_string_len((char*)l_tsd->data, l_tsd->size)); break; case VOTING_TSD_TYPE_ANSWER: - l_json_obj = json_object_new_string_len((char*)l_tsd->data, l_tsd->size); - json_object_array_add(l_answer_array_object, l_json_obj); + json_object_array_add(l_answer_array_object, json_object_new_string_len((char*)l_tsd->data, l_tsd->size)); break; case VOTING_TSD_TYPE_EXPIRE: - l_json_obj = json_object_new_uint64(*(uint64_t*)l_tsd->data); - json_object_object_add(l_object, "exired", l_json_obj); + json_object_object_add(l_object, "exired", json_object_new_uint64(*(uint64_t*)l_tsd->data)); break; case VOTING_TSD_TYPE_MAX_VOTES_COUNT: - l_json_obj = json_object_new_uint64(*(uint64_t*)l_tsd->data); - json_object_object_add(l_object, "maxVotes", l_json_obj); + json_object_object_add(l_object, "maxVotes", json_object_new_uint64(*(uint64_t*)l_tsd->data)); break; case VOTING_TSD_TYPE_DELEGATED_KEY_REQUIRED: - l_json_obj = json_object_new_boolean(*(bool*)l_tsd->data); - json_object_object_add(l_object, "delegateKeyRequired", l_json_obj); + json_object_object_add(l_object, "delegateKeyRequired", json_object_new_boolean(*(bool*)l_tsd->data)); break; case VOTING_TSD_TYPE_VOTE_CHANGING_ALLOWED: - l_json_obj = json_object_new_boolean(*(bool*)l_tsd->data); - json_object_object_add(l_object, "voteChangingAllowed", l_json_obj); + json_object_object_add(l_object, "voteChangingAllowed", json_object_new_boolean(*(bool*)l_tsd->data)); break; default: break; } - l_temp = l_temp->next; } - dap_list_free(l_tsd_list); - json_object_object_add(l_object, "answers", l_answer_array_object); return l_object; } diff --git a/modules/common/include/dap_chain_common.h b/modules/common/include/dap_chain_common.h index 3ae8e849771803033be56fcf2e743d3f1c36b8aa..f3c8a93b92ebc504a91ae28894983090920a8539 100644 --- a/modules/common/include/dap_chain_common.h +++ b/modules/common/include/dap_chain_common.h @@ -199,6 +199,7 @@ extern "C" { size_t dap_chain_hash_slow_to_str(dap_chain_hash_slow_t * a_hash, char * a_str, size_t a_str_max); const char *dap_chain_addr_to_str_static(const dap_chain_addr_t *a_addr); +#define dap_chain_addr_to_str dap_chain_addr_to_str_static dap_chain_addr_t* dap_chain_addr_from_str(const char *str); bool dap_chain_addr_is_blank(const dap_chain_addr_t *a_addr); diff --git a/modules/common/include/dap_chain_datum.h b/modules/common/include/dap_chain_datum.h index 74f39e9ca3bff1a76be6016a9e46479d56f4e246..8227287524f67ead3b3f73a2286552bc7da333c8 100644 --- a/modules/common/include/dap_chain_datum.h +++ b/modules/common/include/dap_chain_datum.h @@ -134,11 +134,11 @@ typedef struct dap_chain_datum{ * @param a_datum * @return */ -DAP_STATIC_INLINE size_t dap_chain_datum_size(const dap_chain_datum_t *a_datum) +DAP_STATIC_INLINE uint64_t dap_chain_datum_size(const dap_chain_datum_t *a_datum) { if (!a_datum) return 0; - return sizeof(a_datum->header) + a_datum->header.data_size; + return (uint64_t)sizeof(a_datum->header) + a_datum->header.data_size; } DAP_STATIC_INLINE void dap_chain_datum_calc_hash(const dap_chain_datum_t *a_datum, dap_hash_fast_t *a_out_hash) diff --git a/modules/common/include/dap_chain_datum_anchor.h b/modules/common/include/dap_chain_datum_anchor.h index 16c1ab915990752fbdae51a3851f621c2981dda8..79a0c48102707bb2f9b4acd0975e0c9411f45ced 100644 --- a/modules/common/include/dap_chain_datum_anchor.h +++ b/modules/common/include/dap_chain_datum_anchor.h @@ -48,7 +48,7 @@ DAP_STATIC_INLINE size_t dap_chain_datum_anchor_get_size(dap_chain_datum_anchor_ return sizeof(*a_datum_anchor) + a_datum_anchor->header.data_size + a_datum_anchor->header.signs_size; } -int dap_chain_datum_anchor_get_hash_from_data(dap_chain_datum_anchor_t* a_anchor, dap_hash_fast_t * l_out_hash); +int dap_chain_datum_anchor_get_hash_from_data(dap_chain_datum_anchor_t* a_anchor, dap_hash_fast_t * a_out_hash); void dap_chain_datum_anchor_certs_dump(dap_string_t * a_str_out, byte_t * a_signs, size_t a_certs_size, const char *a_hash_out_type); diff --git a/modules/common/include/dap_chain_datum_tx.h b/modules/common/include/dap_chain_datum_tx.h index e8a6ec192e5cdd3764526e9b2340aa223d5563d9..cd161e671ca1c367dfcc80b26e830bdedfe955ad 100644 --- a/modules/common/include/dap_chain_datum_tx.h +++ b/modules/common/include/dap_chain_datum_tx.h @@ -33,13 +33,28 @@ * @struct dap_chain_datum_tx * @brief Transaction section, consists from lot of tx_items */ -typedef struct dap_chain_datum_tx{ +typedef struct dap_chain_datum_tx { struct { dap_time_t ts_created; - uint32_t tx_items_size; // size of next sequencly lying tx_item sections would be decided to belong this transaction + uint32_t tx_items_size; // total size of sequential tx_items } DAP_ALIGN_PACKED header; uint8_t tx_items[]; } DAP_ALIGN_PACKED dap_chain_datum_tx_t; + +#define TX_ITEM_ITER(item, item_size, data, total_size) \ + for ( byte_t *l_pos = (byte_t*)(data), *l_end = l_pos + (total_size) > l_pos ? l_pos + (total_size) : l_pos; \ + !!( item = l_pos < l_end \ + && (item_size = dap_chain_datum_item_tx_get_size(l_pos, l_end - l_pos)) \ + ? l_pos : NULL ); \ + l_pos += item_size ) + +#define TX_ITEM_ITER_TX(item, item_size, tx) \ + TX_ITEM_ITER(item, item_size, tx->tx_items, tx->header.tx_items_size) + +#define TX_ITEM_ITER_TX_TYPE(item, item_type, item_size, item_index, tx) \ + for ( item_size = 0, item_index = 0, item = NULL; \ + !!( item = dap_chain_datum_tx_item_get(tx, &item_index, (byte_t*)item + item_size, item_type, &item_size) );\ + item_index = 0 ) /** * Create empty transaction * @@ -161,12 +176,8 @@ int dap_chain_datum_tx_get_fee_value (dap_chain_datum_tx_t *a_tx, uint256_t *a_v * @param a_tx * @return */ -DAP_STATIC_INLINE dap_chain_hash_fast_t* dap_chain_node_datum_tx_calc_hash(dap_chain_datum_tx_t *a_tx) +DAP_STATIC_INLINE dap_hash_fast_t dap_chain_node_datum_tx_calc_hash(dap_chain_datum_tx_t *a_tx) { - dap_chain_hash_fast_t *tx_hash = DAP_NEW_Z(dap_chain_hash_fast_t); - if (!tx_hash) { - return NULL; - } - dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), tx_hash); - return tx_hash; + dap_hash_fast_t l_res; + return dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), &l_res), l_res; } diff --git a/modules/common/include/dap_chain_datum_tx_items.h b/modules/common/include/dap_chain_datum_tx_items.h index e0799f815b712d1bc3bdb74e21ccad07c47effd3..2f5480e7f30b7608c66c0ae3ea0ca7416248ba98 100644 --- a/modules/common/include/dap_chain_datum_tx_items.h +++ b/modules/common/include/dap_chain_datum_tx_items.h @@ -44,47 +44,6 @@ #include "dap_chain_datum_tx_tsd.h" #include "dap_chain_datum_tx_in_reward.h" -/** - * Get item type - * - * return type, or TX_ITEM_TYPE_ANY if error - */ -dap_chain_tx_item_type_t dap_chain_datum_tx_item_get_type(const void *a_item); - -typedef struct dap_chain_datum_tx_item -{ - dap_chain_tx_item_type_t type; - byte_t data[]; -} DAP_ALIGN_PACKED dap_chain_datum_tx_item_t; - -/** - * Get item name by item type - * - * return name, or UNDEFINED - */ -DAP_STATIC_INLINE const char * dap_chain_datum_tx_item_type_to_str(dap_chain_tx_item_type_t a_item_type) -{ - switch(a_item_type){ - case TX_ITEM_TYPE_IN: return "TX_ITEM_TYPE_IN"; - case TX_ITEM_TYPE_OUT_OLD: return "TX_ITEM_TYPE_OUT_OLD"; - case TX_ITEM_TYPE_OUT: return "TX_ITEM_TYPE_OUT"; // 256 - case TX_ITEM_TYPE_OUT_EXT: return "TX_ITEM_TYPE_OUT_EXT"; // 256 - case TX_ITEM_TYPE_PKEY: return "TX_ITEM_TYPE_PKEY"; - case TX_ITEM_TYPE_SIG: return "TX_ITEM_TYPE_SIG"; - case TX_ITEM_TYPE_IN_EMS: return "TX_ITEM_TYPE_IN_EMS"; - case TX_ITEM_TYPE_IN_REWARD: return "TX_ITEM_TYPE_IN_REWARD"; - case TX_ITEM_TYPE_IN_COND: return "TX_ITEM_TYPE_IN_COND"; - case TX_ITEM_TYPE_OUT_COND: return "TX_ITEM_TYPE_OUT_COND"; // 256 - case TX_ITEM_TYPE_RECEIPT: return "TX_ITEM_TYPE_RECEIPT"; - case TX_ITEM_TYPE_TSD: return "TX_ITEM_TYPE_TSD"; - case TX_ITEM_TYPE_OUT_ALL: return "TX_ITEM_TYPE_OUT_OLDALL"; - case TX_ITEM_TYPE_ANY: return "TX_ITEM_TYPE_ANY"; - case TX_ITEM_TYPE_VOTING: return "TX_ITEM_TYPE_VOTING"; - case TX_ITEM_TYPE_VOTE: return "TX_ITEM_TYPE_VOTE"; - default: return "UNDEFINED"; - } -} - typedef struct dap_chain_datum_tx_item_groups { dap_list_t *items_in_all; @@ -118,6 +77,34 @@ typedef struct dap_chain_datum_tx_item_groups { } dap_chain_datum_tx_item_groups_t; +/** + * Get item name by item type + * + * return name, or UNDEFINED + */ +DAP_STATIC_INLINE const char * dap_chain_datum_tx_item_type_to_str(dap_chain_tx_item_type_t a_item_type) +{ + switch(a_item_type){ + case TX_ITEM_TYPE_IN: return "TX_ITEM_TYPE_IN"; + case TX_ITEM_TYPE_OUT_OLD: return "TX_ITEM_TYPE_OUT_OLD"; + case TX_ITEM_TYPE_OUT: return "TX_ITEM_TYPE_OUT"; // 256 + case TX_ITEM_TYPE_OUT_EXT: return "TX_ITEM_TYPE_OUT_EXT"; // 256 + case TX_ITEM_TYPE_PKEY: return "TX_ITEM_TYPE_PKEY"; + case TX_ITEM_TYPE_SIG: return "TX_ITEM_TYPE_SIG"; + case TX_ITEM_TYPE_IN_EMS: return "TX_ITEM_TYPE_IN_EMS"; + case TX_ITEM_TYPE_IN_REWARD: return "TX_ITEM_TYPE_IN_REWARD"; + case TX_ITEM_TYPE_IN_COND: return "TX_ITEM_TYPE_IN_COND"; + case TX_ITEM_TYPE_OUT_COND: return "TX_ITEM_TYPE_OUT_COND"; // 256 + case TX_ITEM_TYPE_RECEIPT: return "TX_ITEM_TYPE_RECEIPT"; + case TX_ITEM_TYPE_TSD: return "TX_ITEM_TYPE_TSD"; + case TX_ITEM_TYPE_OUT_ALL: return "TX_ITEM_TYPE_OUT_OLDALL"; + case TX_ITEM_TYPE_ANY: return "TX_ITEM_TYPE_ANY"; + case TX_ITEM_TYPE_VOTING: return "TX_ITEM_TYPE_VOTING"; + case TX_ITEM_TYPE_VOTE: return "TX_ITEM_TYPE_VOTE"; + default: return "UNDEFINED"; + } +} + bool dap_chain_datum_tx_group_items(dap_chain_datum_tx_t *a_tx, dap_chain_datum_tx_item_groups_t *a_res_group); void dap_chain_datum_tx_group_items_free( dap_chain_datum_tx_item_groups_t *a_group); @@ -140,7 +127,7 @@ dap_chain_tx_out_cond_subtype_t dap_chain_tx_out_cond_subtype_from_str(const cha * * return size, 0 Error */ -size_t dap_chain_datum_item_tx_get_size(const void *a_item); +size_t dap_chain_datum_item_tx_get_size(const byte_t *a_item, size_t a_max_size); /** * Create item dap_chain_tx_in_ems_t @@ -223,7 +210,9 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_xchange(dap json_object* dap_chain_datum_tx_item_out_cond_srv_xchange_to_json(dap_chain_tx_out_cond_t* a_srv_xchange); -DAP_STATIC_INLINE uint32_t dap_chain_datum_tx_item_out_cond_create_srv_stake_get_tsd_size() { return sizeof(dap_chain_addr_t) + sizeof(uint256_t) + 2 * sizeof(dap_tsd_t); } +DAP_STATIC_INLINE uint32_t dap_chain_datum_tx_item_out_cond_create_srv_stake_get_tsd_size() { + return sizeof(dap_chain_addr_t) + sizeof(uint256_t) + 2 * sizeof(dap_tsd_t); +} /** * Create item dap_chain_tx_out_cond_t for stake service @@ -272,13 +261,14 @@ byte_t *dap_chain_datum_tx_item_get_data(dap_chain_tx_tsd_t *a_tx_tsd, int *a_ty * return item data, NULL Error index or bad format transaction */ uint8_t* dap_chain_datum_tx_item_get( dap_chain_datum_tx_t *a_tx, int *a_item_idx_start, - dap_chain_tx_item_type_t a_type, int *a_item_out_size); + byte_t *a_iter, dap_chain_tx_item_type_t a_type, size_t *a_item_out_size); // Get Nth item of pointed type uint8_t *dap_chain_datum_tx_item_get_nth(dap_chain_datum_tx_t *a_tx, dap_chain_tx_item_type_t a_type, int a_item_idx); // Get all item from transaction by type dap_list_t* dap_chain_datum_tx_items_get(dap_chain_datum_tx_t *a_tx, dap_chain_tx_item_type_t a_type, int *a_item_count); // Get conditional out item with it's idx -dap_chain_tx_out_cond_t *dap_chain_datum_tx_out_cond_get(dap_chain_datum_tx_t *a_tx, dap_chain_tx_item_type_t a_cond_type, int *a_out_num); +dap_chain_tx_out_cond_t *dap_chain_datum_tx_out_cond_get(dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_subtype_t a_cond_subtype, int *a_out_num); // Get output by output index -uint8_t *dap_chain_datum_tx_out_get_by_out_idx(dap_chain_datum_tx_t *a_tx, int a_out_num); +#define dap_chain_datum_tx_out_get_by_out_idx(a_tx, a_out_num) \ + dap_chain_datum_tx_item_get_nth(a_tx, TX_ITEM_TYPE_OUT_ALL, a_out_num); diff --git a/modules/common/include/dap_chain_datum_tx_receipt.h b/modules/common/include/dap_chain_datum_tx_receipt.h index cbbb246d2ac7caff59dab448d94f0506233628e7..5210c4fff5a322515ed52fcb96b6f376ecd5da0f 100644 --- a/modules/common/include/dap_chain_datum_tx_receipt.h +++ b/modules/common/include/dap_chain_datum_tx_receipt.h @@ -33,7 +33,8 @@ typedef struct dap_chain_receipt_info { uint64_t addition; #endif dap_chain_net_srv_price_unit_uid_t units_type; - byte_t padding[4]; + byte_t version; + byte_t padding[3]; uint64_t units; // Unit of service (seconds, megabytes, etc.) Only for SERV_CLASS_PERMANENT uint256_t value_datoshi; // Receipt value } DAP_ALIGN_PACKED dap_chain_receipt_info_t; @@ -67,7 +68,8 @@ uint32_t dap_chain_datum_tx_receipt_utype_get(dap_chain_datum_tx_receipt_t *a uint64_t dap_chain_datum_tx_receipt_srv_uid_get(dap_chain_datum_tx_receipt_t *a_receipt); uint64_t dap_chain_datum_tx_receipt_units_get(dap_chain_datum_tx_receipt_t *a_receipt); uint256_t dap_chain_datum_tx_receipt_value_get(dap_chain_datum_tx_receipt_t *a_receipt); -uint16_t dap_chain_datum_tx_receipt_signs_count(dap_chain_datum_tx_receipt_t *a_receipt, size_t a_receipt_size); +uint16_t dap_chain_datum_tx_receipt_signs_count(dap_chain_datum_tx_receipt_t *a_receipt); +int dap_chain_datum_tx_receipt_check_size(dap_chain_datum_tx_receipt_t *a_receipt, size_t a_control_size); #ifdef __cplusplus } diff --git a/modules/common/include/dap_chain_datum_tx_voting.h b/modules/common/include/dap_chain_datum_tx_voting.h index 331cb806f80f929b7b33af509b38b3e8117bfafa..d9a991a839a48be78ccbe6a4de762398d6f6f372 100644 --- a/modules/common/include/dap_chain_datum_tx_voting.h +++ b/modules/common/include/dap_chain_datum_tx_voting.h @@ -22,9 +22,10 @@ #pragma once #include <stdint.h> +#include "dap_chain.h" #include "dap_chain_common.h" -#include "dap_chain_datum_tx.h" -#include "dap_chain_datum_tx_items.h" +//#include "dap_chain_datum_tx.h" +//#include "dap_chain_datum_tx_items.h" #include "dap_chain_ledger.h" #include "dap_time.h" #include "dap_list.h" @@ -79,7 +80,7 @@ dap_chain_tx_tsd_t* dap_chain_datum_voting_question_tsd_create(const char* a_que dap_chain_tx_tsd_t* dap_chain_datum_voting_answer_tsd_create(const char* a_answer_str, size_t str_len); dap_chain_tx_tsd_t* dap_chain_datum_voting_expire_tsd_create(dap_time_t a_expire); dap_chain_tx_tsd_t* dap_chain_datum_voting_max_votes_count_tsd_create(uint64_t a_max_count); -dap_chain_tx_tsd_t* dap_chain_datum_voting_delegated_key_required_tsd_create(bool a_delegate_key_required); +dap_chain_tx_tsd_t *dap_chain_datum_voting_delegated_key_required_tsd_create(bool a_delegated_key_required); dap_chain_tx_tsd_t* dap_chain_datum_voting_vote_changing_allowed_tsd_create(bool a_vote_changing_allowed); dap_chain_tx_tsd_t* dap_chain_datum_voting_vote_tx_cond_tsd_create(dap_chain_hash_fast_t a_tx_hash, int a_out_idx); diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c index 112e5bc495c4d63e4757b8894932712506ad290e..9b1e629107767a4294f513b3998a33875343a9ec 100644 --- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c +++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c @@ -2000,7 +2000,7 @@ static int s_session_directive_apply(dap_chain_esbocs_directive_t *a_directive, switch (a_directive->type) { case DAP_CHAIN_ESBOCS_DIRECTIVE_KICK: case DAP_CHAIN_ESBOCS_DIRECTIVE_LIFT: { - dap_chain_addr_t *l_key_addr = (dap_chain_addr_t *)(((dap_tsd_t *)a_directive->tsd)->data); + dap_chain_addr_t *l_key_addr = (dap_chain_addr_t *)((dap_tsd_t *)a_directive->tsd)->data; int l_status = dap_chain_net_srv_stake_key_delegated(l_key_addr); const char *l_key_str = dap_chain_addr_to_str_static(l_key_addr); if (l_status == 0) { @@ -2128,7 +2128,7 @@ static bool s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg) dap_chain_esbocs_message_t *l_message = (dap_chain_esbocs_message_t *)l_ch_pkt->data; size_t l_message_size = l_ch_pkt->hdr.data_size; if (l_message_size < sizeof(dap_chain_esbocs_message_t) || - l_message_size > DAP_CHAIN_CS_BLOCKS_MAX_BLOCK_SIZE + PKT_SIGN_N_HDR_OVERHEAD || + l_message_size > DAP_CHAIN_ATOM_MAX_SIZE + PKT_SIGN_N_HDR_OVERHEAD || l_message_size != sizeof(*l_message) + l_message->hdr.sign_size + l_message->hdr.message_size) { log_it(L_WARNING, "Invalid message size %zu, drop this packet", l_message_size); return false; diff --git a/modules/mempool/dap_chain_mempool.c b/modules/mempool/dap_chain_mempool.c index b2980610c5cd2286628bfebcd70f9232bc3a8b33..8fc3ad433d34ad4c9d290455a8c7292d15091d75 100644 --- a/modules/mempool/dap_chain_mempool.c +++ b/modules/mempool/dap_chain_mempool.c @@ -588,7 +588,7 @@ int dap_chain_mempool_tx_create_massive( dap_chain_t * a_chain, dap_enc_key_t *a 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_list_t *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); + a_addr_from, l_value_need, &l_value_transfer); if (!l_list_used_out) { log_it(L_WARNING,"Not enough funds to transfer"); DAP_DELETE(l_objs); @@ -596,8 +596,8 @@ int dap_chain_mempool_tx_create_massive( dap_chain_t * a_chain, dap_enc_key_t *a } dap_chain_hash_fast_t l_tx_new_hash = {0}; - for (size_t i=0; i< a_tx_num ; i++){ - log_it(L_DEBUG, "Prepare tx %zu",i); + for (size_t i=0; i < a_tx_num; ++i){ + log_it(L_DEBUG, "Prepare tx %zu", i); // find the transactions from which to take away coins // create empty transaction @@ -613,7 +613,7 @@ int dap_chain_mempool_tx_create_massive( dap_chain_t * a_chain, dap_enc_key_t *a dap_chain_hash_fast_to_str(&l_item->tx_hash_fast, l_in_hash_str, sizeof(l_in_hash_str)); l_balance = dap_uint256_to_char(l_item->value, NULL); - if (dap_chain_datum_tx_add_in_item(&l_tx_new, &l_item->tx_hash_fast, l_item->num_idx_out)) { + if (1 == dap_chain_datum_tx_add_in_item(&l_tx_new, &l_item->tx_hash_fast, l_item->num_idx_out)) { SUM_256_256(l_value_to_items, l_item->value, &l_value_to_items); log_it(L_DEBUG, "Added input %s with %s datoshi", l_in_hash_str, l_balance); } else { @@ -688,48 +688,35 @@ int dap_chain_mempool_tx_create_massive( dap_chain_t * a_chain, dap_enc_key_t *a } // now tx is formed - calc size and hash size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx_new); - dap_hash_fast(l_tx_new, l_tx_size, &l_tx_new_hash); // If we have value back - update balance cache if (!IS_ZERO_256(l_value_back)) { //log_it(L_DEBUG,"We have value back %"DAP_UINT64_FORMAT_U" now lets see how many outputs we have", l_value_back); - int l_item_count = 0; - dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get( l_tx_new, TX_ITEM_TYPE_OUT_ALL, - &l_item_count); - dap_list_t *l_list_tmp = l_list_out_items; - int l_out_idx_tmp = 0; // current index of 'out' item - //log_it(L_DEBUG,"We have %d outputs in new TX", l_item_count); - while(l_list_tmp) { - dap_chain_tx_out_t *l_out = l_list_tmp->data; - if( ! l_out){ - log_it(L_WARNING, "Output is NULL, continue check outputs..."); - l_out_idx_tmp++; - continue; - } - if (l_out->header.type == TX_ITEM_TYPE_OUT_COND) { - l_list_tmp = l_list_tmp->next; - l_out_idx_tmp++; + int l_out_idx = 0; + byte_t *l_item; size_t l_size; + TX_ITEM_ITER_TX(l_item, l_size, l_tx_new) { + switch (*l_item) { + case TX_ITEM_TYPE_OUT_COND: + ++l_out_idx; continue; - } - if ( memcmp(&l_out->addr, a_addr_from, sizeof (*a_addr_from))==0 ){ - dap_chain_tx_used_out_item_t *l_item_back = DAP_NEW_Z(dap_chain_tx_used_out_item_t); - if (!l_item_back) { - log_it(L_CRITICAL, "%s", c_error_memory_alloc); - dap_list_free_full(l_list_used_out, NULL); - DAP_DELETE(l_objs); - return -6; + case TX_ITEM_TYPE_OUT: case TX_ITEM_TYPE_OUT_OLD: case TX_ITEM_TYPE_OUT_EXT: + if ( dap_chain_addr_compare(a_addr_from, &((dap_chain_tx_out_t*)l_item)->addr) ) { + ++l_out_idx; + continue; } + dap_chain_tx_used_out_item_t *l_item_back = DAP_NEW_Z(dap_chain_tx_used_out_item_t); *l_item_back = (dap_chain_tx_used_out_item_t) { - .tx_hash_fast = l_tx_new_hash, - .num_idx_out = l_out_idx_tmp, - .value = l_value_back + .tx_hash_fast = l_tx_new_hash, + .num_idx_out = l_out_idx, + .value = l_value_back }; l_list_used_out = dap_list_prepend(l_list_used_out, l_item_back); log_it(L_DEBUG,"Found change back output, stored back in UTXO table"); break; - } - l_list_tmp = l_list_tmp->next; - l_out_idx_tmp++; + default: + continue; + } + break; // Chargeback out found, exit iteration } } SUBTRACT_256_256(l_value_transfer, l_value_pack, &l_value_transfer); @@ -802,20 +789,20 @@ char* dap_chain_mempool_tx_create_cond_input(dap_chain_net_t *a_net, dap_chain_h *a_ret_status = DAP_CHAIN_MEMPOOl_RET_STATUS_WRONG_ADDR; return NULL; } - dap_chain_hash_fast_t *l_tx_final_hash = dap_ledger_get_final_chain_tx_hash(l_ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY, a_tx_prev_hash); - if (!l_tx_final_hash) { + dap_chain_hash_fast_t l_tx_final_hash = dap_ledger_get_final_chain_tx_hash(l_ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY, a_tx_prev_hash); + if ( dap_hash_fast_is_blank(&l_tx_final_hash) ) { log_it(L_WARNING, "Requested conditional transaction is already used out"); if (a_ret_status) *a_ret_status = DAP_CHAIN_MEMPOOl_RET_STATUS_CANT_FIND_FINAL_TX_HASH; return NULL; } - if (dap_strcmp(a_net->pub.native_ticker, dap_ledger_tx_get_token_ticker_by_hash(l_ledger, l_tx_final_hash))) { + if (dap_strcmp(a_net->pub.native_ticker, dap_ledger_tx_get_token_ticker_by_hash(l_ledger, &l_tx_final_hash))) { log_it(L_WARNING, "Pay for service should be only in native token ticker"); if (a_ret_status) *a_ret_status = DAP_CHAIN_MEMPOOl_RET_STATUS_NOT_NATIVE_TOKEN; return NULL; } - dap_chain_datum_tx_t *l_tx_cond = dap_ledger_tx_find_by_hash(l_ledger, l_tx_final_hash); + dap_chain_datum_tx_t *l_tx_cond = dap_ledger_tx_find_by_hash(l_ledger, &l_tx_final_hash); int l_out_cond_idx = 0; dap_chain_tx_out_cond_t *l_out_cond = dap_chain_datum_tx_out_cond_get(l_tx_cond, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY, &l_out_cond_idx); if (!l_out_cond) { @@ -844,7 +831,7 @@ char* dap_chain_mempool_tx_create_cond_input(dap_chain_net_t *a_net, dap_chain_h dap_chain_datum_tx_t *l_tx = dap_chain_datum_tx_create(); dap_chain_datum_tx_add_item(&l_tx, (byte_t*)a_receipt); // add 'in_cond' items - if (dap_chain_datum_tx_add_in_cond_item(&l_tx, l_tx_final_hash, l_out_cond_idx, 0)) { + if (1 != dap_chain_datum_tx_add_in_cond_item(&l_tx, &l_tx_final_hash, l_out_cond_idx, 0)) { dap_chain_datum_tx_delete(l_tx); log_it( L_ERROR, "Can`t add tx cond input"); if (a_ret_status) diff --git a/modules/net/dap_chain_ledger.c b/modules/net/dap_chain_ledger.c index 3c05f9fc287bfe13380529bbc41c35ec44646bc7..827e3cc46527df108467db3d33474b1640e35822 100644 --- a/modules/net/dap_chain_ledger.c +++ b/modules/net/dap_chain_ledger.c @@ -602,29 +602,31 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain bool l_was_tx_recv_allow_copied = false, l_was_tx_recv_block_copied = false, l_was_tx_send_allow_copied = false, l_was_tx_send_block_copied = false; - int ret = DAP_LEDGER_CHECK_OK; - size_t l_tsd_size = 0; +#define m_ret_cleanup(ret_code) ({ \ + DAP_DELETE_COUNT(l_new_pkeys, l_new_signs_total); \ + DAP_DEL_MULTY(l_new_tx_recv_allow, l_new_tx_recv_block, \ + l_new_tx_send_allow, l_new_tx_send_block, \ + l_new_pkeys, l_new_pkey_hashes); \ + ret_code; }) + uint64_t l_tsd_size = 0; dap_tsd_t *l_tsd = (dap_tsd_t *)a_tsd; - for (size_t l_offset = 0; l_offset < a_tsd_total_size; l_offset += l_tsd_size) { - if (l_offset + sizeof(dap_tsd_t) > a_tsd_total_size) { + for (uint64_t l_offset = 0; l_offset < a_tsd_total_size; l_offset += l_tsd_size) { + if (l_offset + sizeof(dap_tsd_t) > a_tsd_total_size || l_offset + sizeof(dap_tsd_t) < l_offset) { log_it(L_WARNING, "Incorrect TSD section size, less than header"); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } l_tsd = (dap_tsd_t *)((byte_t *)l_tsd + l_tsd_size); l_tsd_size = dap_tsd_size(l_tsd); - if (l_offset + l_tsd_size > a_tsd_total_size) { + if (l_offset + l_tsd_size > a_tsd_total_size || l_offset + l_tsd_size < l_offset) { log_it(L_WARNING, "Wrong TSD size %zu, exiting TSD parse", l_tsd_size); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } switch (l_tsd->type) { // set flags case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_SET_FLAGS: { if (l_tsd->size != sizeof(uint16_t)) { log_it(L_WARNING, "Wrong SET_FLAGS TSD size %zu, exiting TSD parse", l_tsd_size); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } if (!a_apply) break; @@ -635,8 +637,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_UNSET_FLAGS: { if (l_tsd->size != sizeof(uint16_t)) { log_it(L_WARNING, "Wrong UNSET_FLAGS TSD size %zu, exiting TSD parse", l_tsd_size); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } if (!a_apply) break; @@ -647,20 +648,17 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY: { // 256 if (l_tsd->size != sizeof(uint256_t)) { log_it(L_WARNING, "Wrong TOTAL_SUPPLY TSD size %zu, exiting TSD parse", l_tsd_size); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } if (!a_item_apply_to) { log_it(L_WARNING, "Unexpected TOTAL_SUPPLY TSD section in datum token declaration"); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_FORBIDDEN; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_FORBIDDEN); } uint256_t l_new_supply = dap_tsd_get_scalar(l_tsd, uint256_t); if (!IS_ZERO_256(a_item_apply_to->total_supply) && !IS_ZERO_256(l_new_supply) && compare256(a_item_apply_to->total_supply, l_new_supply) < 0) { //compare old 'total_supply' can be updated log_it(L_WARNING, "Can't update token with ticker '%s' because the new 'total_supply' can't be smaller than the old one", a_item_apply_to->ticker); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_SUPPLY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_SUPPLY); } if (!a_apply) break; @@ -671,15 +669,13 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD: { if (l_tsd->size != sizeof(dap_chain_addr_t)) { log_it(L_WARNING, "Wrong TX_RECEIVER_ALLOWED_ADD TSD size %zu, exiting TSD parse", l_tsd_size); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } // Check if its correct dap_chain_addr_t *l_add_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t); if (dap_chain_addr_check_sum(l_add_addr)) { log_it(L_WARNING, "Wrong address checksum in TSD param TX_RECEIVER_ALLOWED_ADD"); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR); } if (!l_new_tx_recv_allow && l_new_tx_recv_allow_size && !l_was_tx_recv_allow_copied) { assert(a_item_apply_to->tx_recv_allow); @@ -687,8 +683,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain l_new_tx_recv_allow = DAP_DUP_SIZE(a_item_apply_to->tx_recv_allow, l_new_tx_recv_allow_size * sizeof(dap_chain_addr_t)); if (!l_new_tx_recv_allow) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); } } l_was_tx_recv_allow_copied = true; @@ -697,8 +692,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain if (dap_chain_addr_compare(l_new_tx_recv_allow + i, l_add_addr)) { // Found log_it(L_WARNING, "TSD param TX_RECEIVER_ALLOWED_ADD has address %s thats already present in list", dap_chain_addr_to_str_static(l_add_addr)); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH); } } l_new_tx_recv_allow = l_new_tx_recv_allow @@ -706,8 +700,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain : DAP_NEW_Z(dap_chain_addr_t); if (!l_new_tx_recv_allow) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); } l_new_tx_recv_allow[l_new_tx_recv_allow_size++] = *l_add_addr; } break; @@ -715,15 +708,13 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_REMOVE: { if (l_tsd->size != sizeof(dap_chain_addr_t)) { log_it(L_WARNING, "Wrong TX_RECEIVER_ALLOWED_REMOVE TSD size %zu, exiting TSD parse", l_tsd_size); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } // Check if its correct dap_chain_addr_t *l_add_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t); if (dap_chain_addr_check_sum(l_add_addr)) { log_it(L_WARNING, "Wrong address checksum in TSD param TX_RECEIVER_ALLOWED_REMOVE"); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR); } if (!l_new_tx_recv_allow && l_new_tx_recv_allow_size && !l_was_tx_recv_allow_copied) { assert(a_item_apply_to->tx_recv_allow); @@ -731,8 +722,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain l_new_tx_recv_allow = DAP_DUP_SIZE(a_item_apply_to->tx_recv_allow, l_new_tx_recv_allow_size * sizeof(dap_chain_addr_t)); if (!l_new_tx_recv_allow) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); } } l_was_tx_recv_allow_copied = true; @@ -744,8 +734,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain if (i == l_new_tx_recv_allow_size) { log_it(L_WARNING, "TSD param TX_RECEIVER_ALLOWED_REMOVE has address %s thats not present in list", dap_chain_addr_to_str_static(l_add_addr)); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH); } // Addr removing if (--l_new_tx_recv_allow_size > i) @@ -762,8 +751,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_CLEAR: { if (l_tsd->size != 0) { log_it(L_WARNING, "Wrong TX_RECEIVER_ALLOWED_CLEAR TSD size %zu, exiting TSD parse", l_tsd_size); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } DAP_DEL_Z(l_new_tx_recv_allow); l_new_tx_recv_allow_size = 0; @@ -774,15 +762,13 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD: { if (l_tsd->size != sizeof(dap_chain_addr_t)) { log_it(L_WARNING, "Wrong TX_RECEIVER_BLOCKED_ADD TSD size %zu, exiting TSD parse", l_tsd_size); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } // Check if its correct dap_chain_addr_t *l_add_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t); if (dap_chain_addr_check_sum(l_add_addr)) { log_it(L_WARNING, "Wrong address checksum in TSD param TX_RECEIVER_BLOCKED_ADD"); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR); } if (!l_new_tx_recv_block && l_new_tx_recv_block_size && !l_was_tx_recv_block_copied) { assert(a_item_apply_to->tx_recv_block); @@ -790,8 +776,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain l_new_tx_recv_block = DAP_DUP_SIZE(a_item_apply_to->tx_recv_block, l_new_tx_recv_block_size * sizeof(dap_chain_addr_t)); if (!l_new_tx_recv_block) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); } } l_was_tx_recv_block_copied = true; @@ -800,8 +785,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain if (dap_chain_addr_compare(l_new_tx_recv_block + i, l_add_addr)) { // Found log_it(L_WARNING, "TSD param TX_RECEIVER_BLOCKED_ADD has address %s thats already present in list", dap_chain_addr_to_str_static(l_add_addr)); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH); } } l_new_tx_recv_block = l_new_tx_recv_block @@ -809,8 +793,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain : DAP_NEW_Z(dap_chain_addr_t); if (!l_new_tx_recv_block) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); } l_new_tx_recv_block[l_new_tx_recv_block_size++] = *l_add_addr; } break; @@ -818,15 +801,13 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_REMOVE: { if (l_tsd->size != sizeof(dap_chain_addr_t)) { log_it(L_WARNING, "Wrong TX_RECEIVER_BLOCKED_REMOVE TSD size %zu, exiting TSD parse", l_tsd_size); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } // Check if its correct dap_chain_addr_t *l_add_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t); if (dap_chain_addr_check_sum(l_add_addr)) { log_it(L_WARNING, "Wrong address checksum in TSD param TX_RECEIVER_BLOCKED_REMOVE"); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR); } if (!l_new_tx_recv_block && l_new_tx_recv_block_size && !l_was_tx_recv_block_copied) { assert(a_item_apply_to->tx_recv_block); @@ -834,8 +815,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain l_new_tx_recv_block = DAP_DUP_SIZE(a_item_apply_to->tx_recv_block, l_new_tx_recv_block_size * sizeof(dap_chain_addr_t)); if (!l_new_tx_recv_block) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); } } l_was_tx_recv_block_copied = true; @@ -847,8 +827,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain if (i == l_new_tx_recv_block_size) { log_it(L_WARNING, "TSD param TX_RECEIVER_BLOCKED_REMOVE has address %s thats not present in list", dap_chain_addr_to_str_static(l_add_addr)); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH); } // Addr removing if (--l_new_tx_recv_block_size > i) @@ -865,8 +844,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_CLEAR: { if (l_tsd->size != 0) { log_it(L_WARNING, "Wrong TX_RECEIVER_BLOCKED_CLEAR TSD size %zu, exiting TSD parse", l_tsd_size); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } DAP_DEL_Z(l_new_tx_recv_block); l_new_tx_recv_block_size = 0; @@ -877,15 +855,13 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD: { if (l_tsd->size != sizeof(dap_chain_addr_t)) { log_it(L_WARNING, "Wrong TX_SENDER_ALLOWED_ADD TSD size %zu, exiting TSD parse", l_tsd_size); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } // Check if its correct dap_chain_addr_t *l_add_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t); if (dap_chain_addr_check_sum(l_add_addr)) { log_it(L_WARNING, "Wrong address checksum in TSD param TX_SENDER_ALLOWED_ADD"); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR); } if (!l_new_tx_send_allow && l_new_tx_send_allow_size && !l_was_tx_send_allow_copied) { assert(a_item_apply_to->tx_send_allow); @@ -893,8 +869,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain l_new_tx_send_allow = DAP_DUP_SIZE(a_item_apply_to->tx_send_allow, l_new_tx_send_allow_size * sizeof(dap_chain_addr_t)); if (!l_new_tx_send_allow) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); } } l_was_tx_send_allow_copied = true; @@ -903,8 +878,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain if (dap_chain_addr_compare(l_new_tx_send_allow + i, l_add_addr)) { // Found log_it(L_WARNING, "TSD param TX_SENDER_ALLOWED_ADD has address %s thats already present in list", dap_chain_addr_to_str_static(l_add_addr)); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH); } } l_new_tx_send_allow = l_new_tx_send_allow @@ -912,8 +886,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain : DAP_NEW_Z(dap_chain_addr_t); if (!l_new_tx_send_allow) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); } l_new_tx_send_allow[l_new_tx_send_allow_size++] = *l_add_addr; } break; @@ -921,15 +894,13 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_REMOVE: { if (l_tsd->size != sizeof(dap_chain_addr_t)) { log_it(L_WARNING, "Wrong TX_SENDER_ALLOWED_REMOVE TSD size %zu, exiting TSD parse", l_tsd_size); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } // Check if its correct dap_chain_addr_t *l_add_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t); if (dap_chain_addr_check_sum(l_add_addr)) { log_it(L_WARNING, "Wrong address checksum in TSD param TX_SENDER_ALLOWED_REMOVE"); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR); } if (!l_new_tx_send_allow && l_new_tx_send_allow_size && !l_was_tx_send_allow_copied) { @@ -938,8 +909,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain l_new_tx_send_allow = DAP_DUP_SIZE(a_item_apply_to->tx_send_allow, l_new_tx_send_allow_size * sizeof(dap_chain_addr_t)); if (!l_new_tx_send_allow) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); } } l_was_tx_send_allow_copied = true; @@ -951,8 +921,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain if (i == l_new_tx_send_allow_size) { log_it(L_WARNING, "TSD param TX_SENDER_ALLOWED_REMOVE has address %s thats not present in list", dap_chain_addr_to_str_static(l_add_addr)); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH); } // Addr removing if (--l_new_tx_send_allow_size > i) @@ -969,8 +938,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_CLEAR: { if (l_tsd->size != 0) { log_it(L_WARNING, "Wrong TX_SENDER_ALLOWED_CLEAR TSD size %zu, exiting TSD parse", l_tsd_size); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } DAP_DEL_Z(l_new_tx_send_allow); l_new_tx_send_allow_size = 0; @@ -981,15 +949,13 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD: { if (l_tsd->size != sizeof(dap_chain_addr_t)) { log_it(L_WARNING, "Wrong TX_SENDER_BLOCKED_ADD TSD size %zu, exiting TSD parse", l_tsd_size); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } // Check if its correct dap_chain_addr_t *l_add_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t); if (dap_chain_addr_check_sum(l_add_addr)) { log_it(L_WARNING, "Wrong address checksum in TSD param TX_SENDER_BLOCKED_ADD"); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR); } if (!l_new_tx_send_block && l_new_tx_send_block_size && !l_was_tx_send_block_copied) { assert(a_item_apply_to->tx_send_block); @@ -997,8 +963,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain l_new_tx_send_block = DAP_DUP_SIZE(a_item_apply_to->tx_send_block, l_new_tx_send_block_size * sizeof(dap_chain_addr_t)); if (!l_new_tx_send_block) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); } } l_was_tx_send_block_copied = true; @@ -1007,8 +972,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain if (dap_chain_addr_compare(l_new_tx_send_block + i, l_add_addr)) { // Found log_it(L_WARNING, "TSD param TX_SENDER_BLOCKED_ADD has address %s thats already present in list", dap_chain_addr_to_str_static(l_add_addr)); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH); } } if (!a_apply) @@ -1018,8 +982,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain : DAP_NEW_Z(dap_chain_addr_t); if (!l_new_tx_send_block) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); } l_new_tx_send_block[l_new_tx_send_block_size++] = *l_add_addr; } break; @@ -1027,15 +990,13 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_REMOVE: { if (l_tsd->size != sizeof(dap_chain_addr_t)) { log_it(L_WARNING, "Wrong TX_SENDER_BLOCKED_REMOVE TSD size %zu, exiting TSD parse", l_tsd_size); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } // Check if its correct dap_chain_addr_t *l_add_addr = dap_tsd_get_object(l_tsd, dap_chain_addr_t); if (dap_chain_addr_check_sum(l_add_addr)) { log_it(L_WARNING, "Wrong address checksum in TSD param TX_SENDER_BLOCKED_REMOVE"); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_INVALID_ADDR); } if (!l_new_tx_send_block && l_new_tx_send_block_size && !l_was_tx_send_block_copied) { assert(a_item_apply_to->tx_send_block); @@ -1043,8 +1004,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain l_new_tx_send_block = DAP_DUP_SIZE(a_item_apply_to->tx_send_block, l_new_tx_send_block_size * sizeof(dap_chain_addr_t)); if (!l_new_tx_send_block) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); } } l_was_tx_send_block_copied = true; @@ -1056,8 +1016,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain if (i == l_new_tx_send_block_size) { log_it(L_WARNING, "TSD param TX_SENDER_BLOCKED_REMOVE has address %s thats not present in list", dap_chain_addr_to_str_static(l_add_addr)); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_ADDR_MISMATCH); } // Addr removing if (--l_new_tx_send_block_size > i) @@ -1074,8 +1033,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_CLEAR: { if (l_tsd->size != 0) { log_it(L_WARNING, "Wrong TX_SENDER_BLOCKED_CLEAR TSD size %zu, exiting TSD parse", l_tsd_size); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } DAP_DEL_Z(l_new_tx_send_block); l_new_tx_send_block_size = 0; @@ -1085,8 +1043,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain case DAP_CHAIN_DATUM_TOKEN_TSD_TOKEN_DESCRIPTION: { if (l_tsd->size == 0 || l_tsd->data[l_tsd->size - 1] != 0) { log_it(L_ERROR, "Wrong TOKEN_DESCRIPTION TSD format or size %zu, exiting TSD parse", l_tsd_size); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } if (!a_apply) break; @@ -1098,8 +1055,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID: { if (l_tsd->size != sizeof(uint16_t)) { log_it(L_WARNING, "Wrong SIGNS_VALID TSD size %zu, exiting TSD parse", l_tsd_size); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } l_new_signs_valid = dap_tsd_get_scalar(l_tsd, uint16_t); } break; @@ -1107,8 +1063,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_ADD: { if (l_tsd->size < sizeof(dap_pkey_t) || l_tsd->size != dap_pkey_get_size((dap_pkey_t *)l_tsd->data)) { log_it(L_WARNING, "Wrong TOTAL_PKEYS_ADD TSD size %zu, exiting TSD parse", l_tsd_size); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } if (!l_new_pkeys && l_new_signs_total && !l_was_pkeys_copied) { assert(a_item_apply_to->auth_pkeys); @@ -1117,23 +1072,20 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain l_new_pkeys = DAP_NEW_SIZE(dap_pkey_t *, l_new_signs_total * sizeof(dap_pkey_t *)); if (!l_new_pkeys) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); } for (size_t i = 0; i < l_new_signs_total; i++) { l_new_pkeys[i] = DAP_DUP_SIZE(a_item_apply_to->auth_pkeys[i], dap_pkey_get_size(a_item_apply_to->auth_pkeys[i])); if (!l_new_pkeys[i]) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); } } assert(!l_new_pkey_hashes); l_new_pkey_hashes = DAP_DUP_SIZE(a_item_apply_to->auth_pkey_hashes, l_new_signs_total * sizeof(dap_hash_t)); if (!l_new_pkey_hashes) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); } } l_was_pkeys_copied = true; @@ -1144,8 +1096,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain l_pkey_type_correction = dap_pkey_type_from_sign_type(l_sign_type); if (l_pkey_type_correction.type == DAP_PKEY_TYPE_NULL) { log_it(L_WARNING, "Unknonw public key type %hu", l_new_auth_pkey->header.type.type); - ret = DAP_LEDGER_CHECK_PARSE_ERROR; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_PARSE_ERROR); } } // Check if its already present @@ -1155,23 +1106,20 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain if (dap_pkey_compare(l_new_auth_pkey, l_new_pkeys[i])) { log_it(L_WARNING, "TSD param TOTAL_PKEYS_ADD has pkey %s thats already present in list", dap_hash_fast_to_str_static(&l_new_auth_pkey_hash)); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_PKEY_MISMATCH; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_PKEY_MISMATCH); } } l_new_pkeys = l_new_pkeys ? DAP_REALLOC(l_new_pkeys, (l_new_signs_total + 1) * sizeof(dap_pkey_t *)) : DAP_NEW_Z(dap_pkey_t *); if (!l_new_pkeys) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); } // Pkey adding l_new_pkeys[l_new_signs_total] = DAP_DUP_SIZE(l_new_auth_pkey, dap_pkey_get_size(l_new_auth_pkey)); if (!l_new_pkeys[l_new_signs_total]) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); } if (l_pkey_type_correction.type != DAP_PKEY_TYPE_NULL) l_new_pkeys[l_new_signs_total]->header.type = l_pkey_type_correction; @@ -1180,8 +1128,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain : DAP_NEW_Z(dap_hash_t); if (!l_new_pkey_hashes) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); } l_new_pkey_hashes[l_new_signs_total++] = l_new_auth_pkey_hash; } break; @@ -1189,8 +1136,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_REMOVE: { if (l_tsd->size != sizeof(dap_hash_t)) { log_it(L_WARNING, "Wrong TOTAL_PKEYS_REMOVE TSD size %zu, exiting TSD parse", l_tsd_size); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } if (!l_new_pkeys && l_new_signs_total && !l_was_pkeys_copied) { assert(a_item_apply_to->auth_pkeys); @@ -1199,23 +1145,20 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain l_new_pkeys = DAP_NEW_SIZE(dap_pkey_t *, l_new_signs_total * sizeof(dap_pkey_t *)); if (!l_new_pkeys) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); } for (size_t i = 0; i < l_new_signs_total; i++) { l_new_pkeys[i] = DAP_DUP_SIZE(a_item_apply_to->auth_pkeys[i], dap_pkey_get_size(a_item_apply_to->auth_pkeys[i])); if (!l_new_pkeys[i]) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); } } assert(!l_new_pkey_hashes); l_new_pkey_hashes = DAP_DUP_SIZE(a_item_apply_to->auth_pkey_hashes, l_new_signs_total * sizeof(dap_hash_t)); if (!l_new_pkey_hashes) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY); } } l_was_pkeys_copied = true; @@ -1228,8 +1171,7 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain if (i == l_new_signs_total) { log_it(L_WARNING, "TSD param TOTAL_PKEYS_REMOVE has public key hash %s thats not present in list", dap_hash_fast_to_str_static(&l_new_auth_pkey_hash)); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_PKEY_MISMATCH; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_PKEY_MISMATCH); } // Pkey removing DAP_DELETE(l_new_pkeys[i]); @@ -1248,14 +1190,12 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK: { if (a_current_datum->subtype != DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE) { log_it(L_WARNING, "TSD section DELEGATE_EMISSION_FROM_STAKE_LOCK allowed for NATIVE subtype only"); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_FORBIDDEN; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_FORBIDDEN); } if (l_tsd->size != sizeof(dap_chain_datum_token_tsd_delegate_from_stake_lock_t) && l_tsd->size != sizeof(dap_chain_datum_token_tsd_delegate_from_stake_lock_t) + 256 /* Legacy size */) { log_it(L_WARNING, "Wrong DELEGATE_EMISSION_FROM_STAKE_LOCK TSD size %zu, exiting TSD parse", l_tsd_size); - ret = DAP_LEDGER_CHECK_INVALID_SIZE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_INVALID_SIZE); } dap_chain_datum_token_tsd_delegate_from_stake_lock_t *l_delegate = dap_tsd_get_object(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t); const char *l_basic_token_ticker = (const char *)l_delegate->ticker_token_from; @@ -1263,20 +1203,17 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain dap_chain_datum_token_get_delegated_ticker(l_delegated_ticker, l_basic_token_ticker); if (dap_strcmp(l_delegated_ticker, a_current_datum->ticker)) { log_it(L_WARNING, "Unexpected delegated token ticker %s (expected %s)", a_current_datum->ticker, l_delegated_ticker); - ret = DAP_LEDGER_TOKEN_ADD_CHECK_TSD_OTHER_TICKER_EXPECTED; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_TOKEN_ADD_CHECK_TSD_OTHER_TICKER_EXPECTED); } dap_ledger_token_item_t *l_basic_token = NULL; HASH_FIND_STR(PVT(a_ledger)->tokens, l_basic_token_ticker, l_basic_token); if (!l_basic_token) { log_it(L_WARNING, "Basic token ticker %s for delegated token isn't found", l_basic_token_ticker); - ret = DAP_LEDGER_CHECK_TICKER_NOT_FOUND; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_TICKER_NOT_FOUND); } if (IS_ZERO_256(l_delegate->emission_rate)) { log_it(L_WARNING, "Emission rate for delegated toke should not be a zero"); - ret = DAP_LEDGER_CHECK_ZERO_VALUE; - goto ret_n_clear; + return m_ret_cleanup(DAP_LEDGER_CHECK_ZERO_VALUE); } if (!a_apply) break; @@ -1288,54 +1225,47 @@ static int s_token_tsd_parse(dap_ledger_token_item_t *a_item_apply_to, dap_chain default: log_it(L_ERROR, "Unexpected TSD type %hu", l_tsd->type); - ret = DAP_LEDGER_CHECK_PARSE_ERROR; - goto ret_n_clear; - } - } - if (l_new_signs_total < l_new_signs_valid) { - ret = DAP_LEDGER_CHECK_NOT_ENOUGH_VALID_SIGNS; - goto ret_n_clear; - } - if (a_apply) { - if (l_was_tx_recv_allow_copied) { - a_item_apply_to->tx_recv_allow_size = l_new_tx_recv_allow_size; - DAP_DEL_Z(a_item_apply_to->tx_recv_allow); - a_item_apply_to->tx_recv_allow = l_new_tx_recv_allow; - } - if (l_was_tx_recv_block_copied) { - a_item_apply_to->tx_recv_block_size = l_new_tx_recv_block_size; - DAP_DEL_Z(a_item_apply_to->tx_recv_block); - a_item_apply_to->tx_recv_block = l_new_tx_recv_block; - } - if (l_was_tx_send_allow_copied) { - a_item_apply_to->tx_send_allow_size = l_new_tx_send_allow_size; - DAP_DEL_Z(a_item_apply_to->tx_send_allow); - a_item_apply_to->tx_send_allow = l_new_tx_send_allow; - } - if (l_was_tx_send_block_copied) { - a_item_apply_to->tx_send_block_size = l_new_tx_send_block_size; - DAP_DEL_Z(a_item_apply_to->tx_send_block); - a_item_apply_to->tx_send_block = l_new_tx_send_block; - } - a_item_apply_to->auth_signs_valid = l_new_signs_valid; - if (l_was_pkeys_copied) { - for (size_t i = 0; i < a_item_apply_to->auth_signs_total; i++) - DAP_DELETE(a_item_apply_to->auth_pkeys[i]); - DAP_DEL_Z(a_item_apply_to->auth_pkeys); - DAP_DEL_Z(a_item_apply_to->auth_pkey_hashes); - a_item_apply_to->auth_signs_total = l_new_signs_total; - a_item_apply_to->auth_pkeys = l_new_pkeys; - a_item_apply_to->auth_pkey_hashes = l_new_pkey_hashes; - } - return DAP_LEDGER_CHECK_OK; + return m_ret_cleanup(DAP_LEDGER_CHECK_PARSE_ERROR); + } + } + if (l_new_signs_total < l_new_signs_valid) + return m_ret_cleanup(DAP_LEDGER_CHECK_NOT_ENOUGH_VALID_SIGNS); + + if (!a_apply) + return m_ret_cleanup(DAP_LEDGER_CHECK_OK); +#undef m_ret_cleanup + + if (l_was_tx_recv_allow_copied) { + a_item_apply_to->tx_recv_allow_size = l_new_tx_recv_allow_size; + DAP_DEL_Z(a_item_apply_to->tx_recv_allow); + a_item_apply_to->tx_recv_allow = l_new_tx_recv_allow; + } + if (l_was_tx_recv_block_copied) { + a_item_apply_to->tx_recv_block_size = l_new_tx_recv_block_size; + DAP_DEL_Z(a_item_apply_to->tx_recv_block); + a_item_apply_to->tx_recv_block = l_new_tx_recv_block; + } + if (l_was_tx_send_allow_copied) { + a_item_apply_to->tx_send_allow_size = l_new_tx_send_allow_size; + DAP_DEL_Z(a_item_apply_to->tx_send_allow); + a_item_apply_to->tx_send_allow = l_new_tx_send_allow; + } + if (l_was_tx_send_block_copied) { + a_item_apply_to->tx_send_block_size = l_new_tx_send_block_size; + DAP_DEL_Z(a_item_apply_to->tx_send_block); + a_item_apply_to->tx_send_block = l_new_tx_send_block; + } + a_item_apply_to->auth_signs_valid = l_new_signs_valid; + if (l_was_pkeys_copied) { + for (size_t i = 0; i < a_item_apply_to->auth_signs_total; i++) + DAP_DELETE(a_item_apply_to->auth_pkeys[i]); + DAP_DEL_Z(a_item_apply_to->auth_pkeys); + DAP_DEL_Z(a_item_apply_to->auth_pkey_hashes); + a_item_apply_to->auth_signs_total = l_new_signs_total; + a_item_apply_to->auth_pkeys = l_new_pkeys; + a_item_apply_to->auth_pkey_hashes = l_new_pkey_hashes; } - // Checks passed -ret_n_clear: - if (l_new_pkeys) - for (size_t i = 0; i < l_new_signs_total; i++) - DAP_DELETE(l_new_pkeys[i]); - DAP_DEL_MULTY(l_new_tx_recv_allow, l_new_tx_recv_block, l_new_tx_send_allow, l_new_tx_send_block, l_new_pkeys, l_new_pkey_hashes); - return ret; + return DAP_LEDGER_CHECK_OK; } /** @@ -1459,7 +1389,8 @@ int s_token_add_check(dap_ledger_t *a_ledger, byte_t *a_token, size_t a_token_si return DAP_LEDGER_CHECK_PARSE_ERROR; } } - if (l_token_size < sizeof(dap_chain_datum_token_t) + l_size_tsd_section) { + if (sizeof(dap_chain_datum_token_t) + l_size_tsd_section > l_token_size || + sizeof(dap_chain_datum_token_t) + l_size_tsd_section < l_size_tsd_section) { log_it(L_WARNING, "Incorrect size %zu of datum token, expected at least %zu", l_token_size, sizeof(dap_chain_datum_token_t) + l_size_tsd_section); DAP_DELETE(l_token); @@ -1467,16 +1398,23 @@ int s_token_add_check(dap_ledger_t *a_ledger, byte_t *a_token, size_t a_token_si } // Check signs byte_t *l_signs_ptr = l_token->tsd_n_signs + l_size_tsd_section; - size_t l_signs_size = 0, l_signs_offset = sizeof(dap_chain_datum_token_t) + l_size_tsd_section; + uint64_t l_signs_size = 0, l_signs_offset = sizeof(dap_chain_datum_token_t) + l_size_tsd_section; for (uint16_t l_signs_passed = 0; l_signs_passed < l_token->signs_total; l_signs_passed++) { dap_sign_t *l_sign = (dap_sign_t *)(l_signs_ptr + l_signs_size); - if (l_token_size < l_signs_offset + l_signs_size + sizeof(dap_sign_t)) { + if (l_signs_offset + l_signs_size + sizeof(dap_sign_t) > l_token_size || + l_signs_offset + l_signs_size + sizeof(dap_sign_t) < l_signs_offset) { log_it(L_WARNING, "Incorrect size %zu of datum token, expected at least %zu", l_token_size, l_signs_offset + l_signs_size + sizeof(dap_sign_t)); DAP_DELETE(l_token); return DAP_LEDGER_CHECK_INVALID_SIZE; } - l_signs_size += dap_sign_get_size(l_sign); + uint64_t l_sign_size = dap_sign_get_size(l_sign); + if (!l_sign_size || l_sign_size + l_signs_size < l_signs_size) { + log_it(L_WARNING, "Incorrect size %zu of datum token sign", l_sign_size); + DAP_DELETE(l_token); + return DAP_LEDGER_CHECK_INVALID_SIZE; + } + l_signs_size += l_sign_size; } if (l_token_size != l_signs_offset + l_signs_size) { log_it(L_WARNING, "Incorrect size %zu of datum token, expected %zu", l_token_size, l_signs_offset + l_signs_size); @@ -1825,127 +1763,119 @@ static void s_tx_header_print(json_object *a_json_out, dap_chain_datum_tx_t *a_t json_object_object_add(a_json_out, "time ", json_object_new_string(l_time_str)); } -static void s_dump_datum_tx_for_addr(dap_ledger_tx_item_t *a_item, bool a_unspent, dap_ledger_t *a_ledger, dap_chain_addr_t *a_addr, const char *a_hash_out_type, json_object *json_arr_out) { +static void s_dump_datum_tx_for_addr(dap_ledger_tx_item_t *a_item, bool a_unspent, dap_ledger_t *a_ledger, + dap_chain_addr_t *a_addr, const char *a_hash_out_type, json_object *json_arr_out) { if (a_unspent && a_item->cache_data.ts_spent) { // With 'unspent' flag spent ones are ignored return; } dap_chain_datum_tx_t *l_tx = a_item->tx; - dap_chain_hash_fast_t *l_tx_hash = &a_item->tx_hash_fast; - dap_list_t *l_list_in_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_IN_ALL, NULL); - if (!l_list_in_items) { // a bad tx - return; - } - dap_chain_addr_t *l_src_addr = NULL; + dap_chain_hash_fast_t l_tx_hash = a_item->tx_hash_fast; + dap_chain_addr_t l_src_addr = { }, l_dst_addr = { }; bool l_base_tx = false; const char *l_src_token = NULL; int l_src_subtype = DAP_CHAIN_TX_OUT_COND_SUBTYPE_UNDEFINED; - dap_list_t *l_in_item; - DL_FOREACH(l_list_in_items, l_in_item) { - //assert(it->data); - dap_chain_hash_fast_t *l_tx_prev_hash; - int l_tx_prev_out_idx; - dap_chain_datum_tx_t *l_tx_prev = NULL; - if (*(byte_t*)l_in_item->data == TX_ITEM_TYPE_IN) { - dap_chain_tx_in_t *l_tx_in = (dap_chain_tx_in_t*)l_in_item->data; - l_tx_prev_hash = &l_tx_in->header.tx_prev_hash; + dap_hash_fast_t l_tx_prev_hash = { }; + byte_t *l_item; size_t l_size; int idx, l_tx_prev_out_idx; + TX_ITEM_ITER_TX_TYPE(l_item, TX_ITEM_TYPE_IN_ALL, l_size, idx, l_tx) { + switch (*l_item) { + case TX_ITEM_TYPE_IN: { + dap_chain_tx_in_t *l_tx_in = (dap_chain_tx_in_t*)l_item; + l_tx_prev_hash = l_tx_in->header.tx_prev_hash; l_tx_prev_out_idx = l_tx_in->header.tx_out_prev_idx; - } else { // TX_ITEM_TYPE_IN_COND - dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t*)l_in_item->data; - l_tx_prev_hash = &l_tx_in_cond->header.tx_prev_hash; + } break; + case TX_ITEM_TYPE_IN_COND: { + dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t*)l_item; + l_tx_prev_hash = l_tx_in_cond->header.tx_prev_hash; l_tx_prev_out_idx = l_tx_in_cond->header.tx_out_prev_idx; + } break; + default: + continue; } - if (dap_hash_fast_is_blank(l_tx_prev_hash)) { + if ( dap_hash_fast_is_blank(&l_tx_prev_hash) ) { l_base_tx = true; - dap_chain_tx_in_ems_t *l_token = (dap_chain_tx_in_ems_t *)dap_chain_datum_tx_item_get( - l_tx, NULL, TX_ITEM_TYPE_IN_EMS, NULL); + dap_chain_tx_in_ems_t *l_token = (dap_chain_tx_in_ems_t*) + dap_chain_datum_tx_item_get(l_tx, NULL, NULL, TX_ITEM_TYPE_IN_EMS, NULL); if (l_token) l_src_token = l_token->header.ticker; break; } - l_tx_prev = dap_ledger_tx_find_by_hash (a_ledger,l_tx_prev_hash); - if (l_tx_prev) { - uint8_t *l_prev_out_union = dap_chain_datum_tx_item_get_nth(l_tx_prev, TX_ITEM_TYPE_OUT_ALL, l_tx_prev_out_idx); - if (!l_prev_out_union) - continue; - switch (*l_prev_out_union) { - case TX_ITEM_TYPE_OUT: - l_src_addr = &((dap_chain_tx_out_t *)l_prev_out_union)->addr; - break; - case TX_ITEM_TYPE_OUT_EXT: - l_src_addr = &((dap_chain_tx_out_ext_t *)l_prev_out_union)->addr; - l_src_token = (const char *)(((dap_chain_tx_out_ext_t *)l_prev_out_union)->token); - break; - case TX_ITEM_TYPE_OUT_COND: - l_src_subtype = ((dap_chain_tx_out_cond_t *)l_prev_out_union)->header.subtype; - default: - break; - } - } - else - { - continue; //temporary stub + dap_chain_datum_tx_t *l_tx_prev = dap_ledger_tx_find_by_hash(a_ledger, &l_tx_prev_hash); + if ( !l_tx_prev ) + continue; + uint8_t *l_prev_out_union = dap_chain_datum_tx_item_get_nth(l_tx_prev, TX_ITEM_TYPE_OUT_ALL, l_tx_prev_out_idx); + if (!l_prev_out_union) + continue; + switch (*l_prev_out_union) { + case TX_ITEM_TYPE_OUT: + l_src_addr = ((dap_chain_tx_out_t *)l_prev_out_union)->addr; + break; + case TX_ITEM_TYPE_OUT_EXT: + l_src_addr = ((dap_chain_tx_out_ext_t *)l_prev_out_union)->addr; + l_src_token = (const char*)(((dap_chain_tx_out_ext_t *)l_prev_out_union)->token); + break; + case TX_ITEM_TYPE_OUT_COND: + l_src_subtype = ((dap_chain_tx_out_cond_t *)l_prev_out_union)->header.subtype; + default: + break; } - if (!l_src_token){ + if ( !dap_chain_addr_compare(&l_src_addr, a_addr) ) + break; //it's not our addr + if (!l_src_token) { l_src_token = a_item->cache_data.token_ticker; } - if (l_src_addr && memcmp(l_src_addr, a_addr, sizeof(dap_chain_addr_t))) - break; //it's not our addr } - dap_list_free(l_list_in_items); bool l_header_printed = false; - dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT_ALL, NULL); - if(!l_list_out_items) - return; - for(dap_list_t *l_list_out = l_list_out_items; l_list_out; l_list_out = dap_list_next(l_list_out)) { - assert(l_list_out->data); - dap_chain_addr_t *l_dst_addr = NULL; - dap_chain_tx_item_type_t l_type = *(uint8_t *)l_list_out->data; + l_item = NULL; + TX_ITEM_ITER_TX_TYPE(l_item, TX_ITEM_TYPE_OUT_ALL, l_size, idx, l_tx) { + dap_chain_tx_item_type_t l_type = *l_item; uint256_t l_value; switch (l_type) { case TX_ITEM_TYPE_OUT: - l_dst_addr = &((dap_chain_tx_out_t *)l_list_out->data)->addr; - l_value = ((dap_chain_tx_out_t *)l_list_out->data)->header.value; + l_dst_addr = ((dap_chain_tx_out_t*)l_item)->addr; + l_value = ((dap_chain_tx_out_t*)l_item)->header.value; break; case TX_ITEM_TYPE_OUT_EXT: - l_dst_addr = &((dap_chain_tx_out_ext_t *)l_list_out->data)->addr; - l_value = ((dap_chain_tx_out_ext_t *)l_list_out->data)->header.value; + l_dst_addr = ((dap_chain_tx_out_ext_t*)l_item)->addr; + l_value = ((dap_chain_tx_out_ext_t *)l_item)->header.value; break; case TX_ITEM_TYPE_OUT_COND: - l_value = ((dap_chain_tx_out_cond_t *)l_list_out->data)->header.value; + l_value = ((dap_chain_tx_out_cond_t *)l_item)->header.value; default: break; } - if (l_src_addr && l_dst_addr && !memcmp(l_dst_addr, l_src_addr, sizeof(dap_chain_addr_t))) + if ( !dap_chain_addr_is_blank(&l_src_addr) && !dap_chain_addr_is_blank(&l_dst_addr) + && dap_chain_addr_compare(&l_dst_addr, &l_src_addr) ) continue; // send to self - if (l_src_addr && !memcmp(l_src_addr, a_addr, sizeof(dap_chain_addr_t))) { + if ( dap_chain_addr_compare(&l_src_addr, a_addr)) { json_object * l_json_obj_datum = json_object_new_object(); if (!l_header_printed) { - s_tx_header_print(l_json_obj_datum, l_tx, a_hash_out_type, l_tx_hash); + s_tx_header_print(l_json_obj_datum, l_tx, a_hash_out_type, &l_tx_hash); l_header_printed = true; } //const char *l_token_ticker = dap_ledger_tx_get_token_ticker_by_hash(l_ledger, &l_tx_hash); - const char *l_dst_addr_str = l_dst_addr ? dap_chain_addr_to_str_static(l_dst_addr) - : dap_chain_tx_out_cond_subtype_to_str( - ((dap_chain_tx_out_cond_t *)l_list_out->data)->header.subtype); + const char *l_dst_addr_str = !dap_chain_addr_is_blank(&l_dst_addr) + ? dap_chain_addr_to_str_static(&l_dst_addr) + : dap_chain_tx_out_cond_subtype_to_str( ((dap_chain_tx_out_cond_t *)l_item)->header.subtype ); json_object_object_add(l_json_obj_datum, "send", json_object_new_string(dap_uint256_to_char(l_value, NULL))); json_object_object_add(l_json_obj_datum, "to addr", json_object_new_string(l_dst_addr_str)); json_object_object_add(l_json_obj_datum, "token", l_src_token ? json_object_new_string(l_src_token) : json_object_new_string("UNKNOWN")); json_object_array_add(json_arr_out, l_json_obj_datum); } - if (l_dst_addr && !memcmp(l_dst_addr, a_addr, sizeof(dap_chain_addr_t))) { + if ( dap_chain_addr_compare(&l_dst_addr, a_addr) ) { json_object * l_json_obj_datum = json_object_new_object(); if (!l_header_printed) { - s_tx_header_print(l_json_obj_datum, l_tx, a_hash_out_type, l_tx_hash); + s_tx_header_print(l_json_obj_datum, l_tx, a_hash_out_type, &l_tx_hash); l_header_printed = true; } const char *l_dst_token = (l_type == TX_ITEM_TYPE_OUT_EXT) ? - (const char *)(((dap_chain_tx_out_ext_t *)l_list_out->data)->token) : NULL; - const char *l_src_addr_str = l_base_tx ? "emission" - : (l_src_addr ? dap_chain_addr_to_str_static(l_src_addr) - : dap_chain_tx_out_cond_subtype_to_str( - l_src_subtype)); + (const char *)(((dap_chain_tx_out_ext_t *)l_item)->token) : NULL; + const char *l_src_addr_str = l_base_tx + ? "emission" + : ( !dap_chain_addr_is_blank(&l_src_addr) + ? dap_chain_addr_to_str_static(&l_src_addr) + : dap_chain_tx_out_cond_subtype_to_str(l_src_subtype) ); json_object_object_add(l_json_obj_datum, "recv ", json_object_new_string(dap_uint256_to_char(l_value, NULL))); json_object_object_add(l_json_obj_datum, "token ", l_dst_token ? json_object_new_string(l_dst_token) : (l_src_token ? json_object_new_string(l_src_token) : json_object_new_string("UNKNOWN"))); @@ -1953,7 +1883,6 @@ static void s_dump_datum_tx_for_addr(dap_ledger_tx_item_t *a_item, bool a_unspen json_object_array_add(json_arr_out, l_json_obj_datum); } } - dap_list_free(l_list_out_items); } json_object *dap_ledger_token_tx_item_list(dap_ledger_t * a_ledger, dap_chain_addr_t *a_addr, const char *a_hash_out_type, bool a_unspent_only) @@ -2799,7 +2728,8 @@ int s_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_ switch (l_emission->hdr.type) { case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_AUTH: { - size_t l_sign_data_check_size = sizeof(dap_chain_datum_token_emission_t) + l_emission->data.type_auth.tsd_total_size; + size_t l_sign_data_check_size = sizeof(dap_chain_datum_token_emission_t) + l_emission->data.type_auth.tsd_total_size >= sizeof(dap_chain_datum_token_emission_t) + ? sizeof(dap_chain_datum_token_emission_t) + l_emission->data.type_auth.tsd_total_size : 0; if (l_sign_data_check_size > l_emission_size) { if (!s_check_hal(a_ledger, a_emission_hash)) { log_it(L_WARNING, "Incorrect size %zu of datum emission, expected at least %zu", l_emission_size, l_sign_data_check_size); @@ -2808,7 +2738,8 @@ int s_emission_add_check(dap_ledger_t *a_ledger, byte_t *a_token_emission, size_ } goto ret_success; } - size_t l_emission_check_size = sizeof(dap_chain_datum_token_emission_t) + l_emission->data.type_auth.tsd_n_signs_size; + size_t l_emission_check_size = sizeof(dap_chain_datum_token_emission_t) + l_emission->data.type_auth.tsd_n_signs_size >= sizeof(dap_chain_datum_token_emission_t) + ? sizeof(dap_chain_datum_token_emission_t) + l_emission->data.type_auth.tsd_n_signs_size : 0; if (l_emission_check_size != l_emission_size) { log_it(L_WARNING, "Incorrect size %zu of datum emission, must be %zu", l_emission_size, l_emission_check_size); DAP_DELETE(l_emission); @@ -3175,14 +3106,11 @@ const char *dap_ledger_get_description_by_ticker(dap_ledger_t *a_ledger, const c * * return transaction, or NULL if transaction not found in the cache */ -static dap_chain_datum_tx_t* s_find_datum_tx_by_hash(dap_ledger_t *a_ledger, const dap_chain_hash_fast_t *a_tx_hash, +dap_chain_datum_tx_t* dap_ledger_tx_find_datum_by_hash(dap_ledger_t *a_ledger, const dap_chain_hash_fast_t *a_tx_hash, dap_ledger_tx_item_t **a_item_out, bool a_unspent_only) { - if(!a_tx_hash) + if ( !a_tx_hash || dap_hash_fast_is_blank(a_tx_hash) ) return NULL; - -// log_it( L_ERROR, "s_find_datum_tx_by_hash( )..."); - dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger); dap_chain_datum_tx_t *l_tx_ret = NULL; dap_ledger_tx_item_t *l_tx_item = NULL; @@ -3199,84 +3127,48 @@ static dap_chain_datum_tx_t* s_find_datum_tx_by_hash(dap_ledger_t *a_ledger, con return l_tx_ret; } -/** - * @brief dap_ledger_tx_find_by_hash - * @param a_tx_hash - * @return - */ - -dap_chain_datum_tx_t *dap_ledger_tx_find_by_hash(dap_ledger_t *a_ledger, const dap_chain_hash_fast_t *a_tx_hash) -{ - return s_find_datum_tx_by_hash(a_ledger, a_tx_hash, NULL, false); -} - -dap_chain_datum_tx_t *dap_ledger_tx_unspent_find_by_hash(dap_ledger_t *a_ledger, const dap_chain_hash_fast_t *a_tx_hash) -{ - return s_find_datum_tx_by_hash(a_ledger, a_tx_hash, NULL, true); -} -dap_hash_fast_t *dap_ledger_get_final_chain_tx_hash(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_cond_type, dap_chain_hash_fast_t *a_tx_hash) -{ - if (!a_ledger || !a_tx_hash || dap_hash_fast_is_blank(a_tx_hash)) - return NULL; - dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger); - dap_ledger_tx_item_t *l_item = NULL; - unsigned l_hash_value; - dap_chain_hash_fast_t *l_tx_hash = a_tx_hash; - pthread_rwlock_rdlock(&l_ledger_pvt->ledger_rwlock); - while (l_tx_hash) { - HASH_VALUE(l_tx_hash, sizeof(*l_tx_hash), l_hash_value); - HASH_FIND_BYHASHVALUE(hh, l_ledger_pvt->ledger_items, l_tx_hash, sizeof(*l_tx_hash), l_hash_value, l_item); - if (!l_item) { - l_tx_hash = NULL; - break; // Not found in ledger - } - int l_out_num = 0; - if (!dap_chain_datum_tx_out_cond_get(l_item->tx, a_cond_type, &l_out_num) || dap_hash_fast_is_blank(&l_item->cache_data.tx_hash_spent_fast[l_out_num])) - break; // Unused conditional output found, that's what we need - else { - l_tx_hash = &l_item->cache_data.tx_hash_spent_fast[l_out_num]; - continue; // Conditional output is used out - } - } - pthread_rwlock_unlock(&l_ledger_pvt->ledger_rwlock); - return l_tx_hash; -} - -dap_hash_fast_t* dap_ledger_get_first_chain_tx_hash(dap_ledger_t *a_ledger, dap_chain_datum_tx_t * a_tx, dap_chain_tx_out_cond_t *a_cond_out) +dap_hash_fast_t dap_ledger_get_first_chain_tx_hash(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_tx_out_cond_t *a_cond_out) { - dap_hash_fast_t *l_ret_hash = NULL; - + dap_hash_fast_t l_hash = { }, l_hash_tmp; if (!a_ledger || !a_cond_out || !a_tx){ log_it(L_ERROR, "Argument is NULL in dap_ledger_get_first_chain_tx_hash()"); - return NULL; + return l_hash; } - - dap_chain_tx_out_cond_subtype_t l_type = a_cond_out->header.subtype; - - int l_item_idx = 0; - dap_chain_datum_tx_t * l_prev_tx = a_tx; - byte_t *l_tx_item_temp = NULL; - dap_hash_fast_t l_hash = {}; - while((l_tx_item_temp = dap_chain_datum_tx_item_get(l_prev_tx, &l_item_idx, TX_ITEM_TYPE_IN_COND , NULL)) != NULL){ - dap_chain_tx_in_cond_t * l_in_cond_temp = (dap_chain_tx_in_cond_t *) l_tx_item_temp; - dap_chain_datum_tx_t *l_prev_tx_temp = dap_ledger_tx_find_by_hash(a_ledger, &l_in_cond_temp->header.tx_prev_hash); - dap_chain_tx_out_cond_t *l_out_cond_temp = dap_chain_datum_tx_out_cond_get(l_prev_tx_temp, l_type, NULL); - if (l_out_cond_temp){ - l_item_idx = l_in_cond_temp->header.tx_out_prev_idx; - l_hash = l_in_cond_temp->header.tx_prev_hash; + dap_chain_datum_tx_t *l_prev_tx = a_tx; + byte_t *l_iter = a_tx->tx_items; + while (( l_iter = dap_chain_datum_tx_item_get(l_prev_tx, NULL, l_iter, TX_ITEM_TYPE_IN_COND, NULL) )) { + l_hash_tmp = ((dap_chain_tx_in_cond_t *)l_iter)->header.tx_prev_hash; + if ( dap_hash_fast_is_blank(&l_hash_tmp) ) + return l_hash_tmp; + if (( l_prev_tx = dap_ledger_tx_find_by_hash(a_ledger, &l_hash_tmp) ) && + ( dap_chain_datum_tx_out_cond_get(l_prev_tx, a_cond_out->header.subtype, NULL) )) { + l_hash = l_hash_tmp; + l_iter = l_prev_tx->tx_items; } - l_prev_tx = l_prev_tx_temp; } + return l_hash; +} - if(l_prev_tx && !dap_hash_fast_is_blank(&l_hash)){ - l_ret_hash = DAP_NEW_SIZE(dap_hash_fast_t, sizeof(dap_hash_fast_t)); - *l_ret_hash = l_hash; +dap_hash_fast_t dap_ledger_get_final_chain_tx_hash(dap_ledger_t *a_ledger, dap_chain_tx_out_cond_subtype_t a_cond_type, dap_chain_hash_fast_t *a_tx_hash) +{ + dap_chain_hash_fast_t l_hash = { }, l_hash_tmp; + if (!a_ledger || !a_tx_hash || dap_hash_fast_is_blank(a_tx_hash)) + return l_hash; + + dap_chain_datum_tx_t *l_tx = NULL; + l_hash = *a_tx_hash; + int l_out_num = 0; + dap_ledger_tx_item_t *l_item = NULL; + while (( l_tx = dap_ledger_tx_find_datum_by_hash(a_ledger, &l_hash, &l_item, false) )) { + l_hash_tmp = l_item->cache_data.tx_hash_spent_fast[l_out_num]; + if ( !dap_chain_datum_tx_out_cond_get(l_tx, a_cond_type, &l_out_num) + || dap_hash_fast_is_blank(&l_hash_tmp) ) + break; + l_hash = l_hash_tmp; } - - return l_ret_hash; + return l_hash; } - /** * Check whether used 'out' items (local function) */ @@ -3328,7 +3220,7 @@ static int s_callback_sign_compare(dap_list_t *a_list_elem, dap_list_t *a_sign_e bool dap_ledger_tx_poa_signed(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx) { - dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_SIG, NULL); + dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(a_tx, NULL, NULL, TX_ITEM_TYPE_SIG, NULL); dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_tx_sig); return dap_list_find(a_ledger->net->pub.keys, l_sign, s_callback_sign_compare); } @@ -3447,9 +3339,8 @@ bool dap_ledger_deduct_tx_tag(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx if (l_deductions_ok > 1) { char l_tx_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE]; - dap_chain_hash_fast_t * l_tx_hash = dap_chain_node_datum_tx_calc_hash(a_tx); - dap_chain_hash_fast_to_str(l_tx_hash, l_tx_hash_str, sizeof(l_tx_hash_str)); - + dap_chain_hash_fast_t l_tx_hash = dap_chain_node_datum_tx_calc_hash(a_tx); + dap_chain_hash_fast_to_str(&l_tx_hash, l_tx_hash_str, sizeof(l_tx_hash_str)); log_it(L_WARNING, "Transaction %s identyfied by multiple services (%d):", l_tx_hash_str, l_deductions_ok); @@ -3575,11 +3466,11 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, } dap_hash_fast_t *l_emission_hash = &l_tx_in_ems->header.token_emission_hash; // 2. Check current transaction for doubles in input items list - for (dap_list_t *l_iter = l_list_in; l_iter; l_iter = l_iter->next) { + for (dap_list_t *l_iter = it->next; l_iter; l_iter = l_iter->next) { dap_chain_tx_in_ems_t *l_in_ems_check = l_iter->data; - if (l_tx_in_ems != l_in_ems_check && - l_in_ems_check->header.type == TX_ITEM_TYPE_IN_EMS && - dap_hash_fast_compare(&l_in_ems_check->header.token_emission_hash, l_emission_hash) && !a_check_for_removing) { + if (l_in_ems_check->header.type == TX_ITEM_TYPE_IN_EMS && + dap_hash_fast_compare(&l_in_ems_check->header.token_emission_hash, l_emission_hash) && !a_check_for_removing) + { debug_if(s_debug_more, L_ERROR, "Emission output already used in current tx"); l_err_num = DAP_LEDGER_TX_CHECK_PREV_OUT_ALREADY_USED_IN_CURRENT_TX; break; @@ -3660,7 +3551,7 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, uint256_t l_stake_lock_ems_value = {}; int l_item_idx = 0; do { - l_tx_out_ext = (dap_chain_tx_out_ext_t *)dap_chain_datum_tx_item_get(a_tx, &l_item_idx, TX_ITEM_TYPE_OUT_EXT, NULL); + l_tx_out_ext = (dap_chain_tx_out_ext_t *)dap_chain_datum_tx_item_get(a_tx, &l_item_idx, NULL, TX_ITEM_TYPE_OUT_EXT, NULL); if (!l_tx_out_ext) { if (l_girdled_ems) { debug_if(s_debug_more, L_WARNING, "No OUT_EXT for girdled IN_EMS [%s]", l_tx_in_ems->header.ticker); @@ -3671,7 +3562,7 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, l_item_idx++; } while (strcmp(l_tx_out_ext->token, l_token)); if (!l_tx_out_ext) { - dap_chain_tx_out_t *l_tx_out = (dap_chain_tx_out_t *)dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_OUT, NULL); + dap_chain_tx_out_t *l_tx_out = (dap_chain_tx_out_t *)dap_chain_datum_tx_item_get(a_tx, NULL, NULL, TX_ITEM_TYPE_OUT, NULL); if (!l_tx_out) { debug_if(true, L_WARNING, "Can't find OUT nor OUT_EXT item for base TX with IN_EMS [%s]", l_tx_in_ems->header.ticker); l_err_num = DAP_LEDGER_TX_CHECK_NO_OUT_ITEMS_FOR_BASE_TX; @@ -3755,7 +3646,7 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, break; if (!l_tx_first_sign_pkey) { // Get sign item - dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t*) dap_chain_datum_tx_item_get(a_tx, NULL, + dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t*) dap_chain_datum_tx_item_get(a_tx, NULL, NULL, TX_ITEM_TYPE_SIG, NULL); assert(l_tx_sig); // Get sign from sign item @@ -3862,7 +3753,7 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, } // Get previous transaction in the cache by hash dap_ledger_tx_item_t *l_item_out = NULL; - l_tx_prev = s_find_datum_tx_by_hash(a_ledger, l_tx_prev_hash, &l_item_out, false); + l_tx_prev = dap_ledger_tx_find_datum_by_hash(a_ledger, l_tx_prev_hash, &l_item_out, false); char l_tx_prev_hash_str[DAP_HASH_FAST_STR_SIZE]; dap_hash_fast_to_str(l_tx_prev_hash, l_tx_prev_hash_str, DAP_HASH_FAST_STR_SIZE); if (!l_tx_prev) { // Unchained transaction or previous TX was already spent and removed from ledger @@ -3897,7 +3788,7 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, } if (dap_hash_fast_is_blank(&l_tx_first_sign_pkey_hash)) { // Get sign item - dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t*) dap_chain_datum_tx_item_get(a_tx, NULL, + dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t*) dap_chain_datum_tx_item_get(a_tx, NULL, NULL, TX_ITEM_TYPE_SIG, NULL); assert(l_tx_sig); // Get sign from sign item @@ -3966,15 +3857,13 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, // 5a. Check for condition owner // Get owner tx - dap_hash_fast_t *l_owner_tx_hash = dap_ledger_get_first_chain_tx_hash(a_ledger, l_tx_prev, l_tx_prev_out_cond); - dap_chain_datum_tx_t *l_owner_tx = l_tx_prev; - if (l_owner_tx_hash){ - l_owner_tx = dap_ledger_tx_find_by_hash(a_ledger, l_owner_tx_hash); - DAP_DEL_Z(l_owner_tx_hash); - } - dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_SIG, NULL); + dap_hash_fast_t l_owner_tx_hash = dap_ledger_get_first_chain_tx_hash(a_ledger, l_tx_prev, l_tx_prev_out_cond); + dap_chain_datum_tx_t *l_owner_tx = dap_hash_fast_is_blank(&l_owner_tx_hash) + ? l_tx_prev + : dap_ledger_tx_find_by_hash(a_ledger, &l_owner_tx_hash); + dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(a_tx, NULL, NULL, TX_ITEM_TYPE_SIG, NULL); dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_tx_sig); - dap_chain_tx_sig_t *l_owner_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(l_owner_tx, NULL, TX_ITEM_TYPE_SIG, NULL); + dap_chain_tx_sig_t *l_owner_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(l_owner_tx, NULL, NULL, TX_ITEM_TYPE_SIG, NULL); dap_sign_t *l_owner_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_owner_tx_sig); bool l_owner = false; @@ -3992,6 +3881,7 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, l_err_num = DAP_LEDGER_TX_CHECK_NO_VERIFICATOR_SET; break; } + int l_verificator_error = l_verificator->callback(a_ledger, l_tx_prev_out_cond, a_tx, l_owner); if (l_verificator_error != DAP_LEDGER_CHECK_OK) { // TODO add string representation for verificator return codes debug_if(s_debug_more, L_WARNING, "Verificator check error %d for conditional output %s", @@ -4046,9 +3936,8 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, } } - if (l_list_in) - dap_list_free(l_list_in); - DAP_DEL_Z(l_tx_first_sign_pkey); + dap_list_free(l_list_in); + DAP_DELETE(l_tx_first_sign_pkey); if (l_err_num) { if ( l_list_bound_items ) dap_list_free_full(l_list_bound_items, NULL); @@ -4094,16 +3983,15 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, bool l_tax_check = l_key_item && !dap_chain_addr_is_blank(&l_key_item->sovereign_addr) && !IS_ZERO_256(l_key_item->sovereign_tax); // find 'out' items - dap_list_t *l_list_out = dap_chain_datum_tx_items_get((dap_chain_datum_tx_t*) a_tx, TX_ITEM_TYPE_OUT_ALL, NULL); uint256_t l_value = {}, l_fee_sum = {}, l_tax_sum = {}; bool l_fee_check = !IS_ZERO_256(a_ledger->net->pub.fee_value) && !dap_chain_addr_is_blank(&a_ledger->net->pub.fee_addr); int l_item_idx = 0; - for (dap_list_t *it = l_list_out; it; it = it->next, l_item_idx++) { - dap_chain_tx_item_type_t l_type = *(uint8_t *)it->data; - dap_chain_addr_t l_tx_out_to={0}; - switch (l_type) { + byte_t *it; size_t l_size; + TX_ITEM_ITER_TX(it, l_size, a_tx) { + dap_chain_addr_t l_tx_out_to = { }; + switch ( *it ) { case TX_ITEM_TYPE_OUT_OLD: { - dap_chain_tx_out_old_t *l_tx_out = (dap_chain_tx_out_old_t *)it->data; + dap_chain_tx_out_old_t *l_tx_out = (dap_chain_tx_out_old_t*)it; if (l_multichannel) { // token ticker is mandatory for multichannel transactions l_err_num = DAP_LEDGER_TX_CHECK_NO_MAIN_TICKER; break; @@ -4113,7 +4001,7 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, l_list_tx_out = dap_list_append(l_list_tx_out, l_tx_out); } break; case TX_ITEM_TYPE_OUT: { // 256 - dap_chain_tx_out_t *l_tx_out = (dap_chain_tx_out_t *)it->data; + dap_chain_tx_out_t *l_tx_out = (dap_chain_tx_out_t *)it; if (l_multichannel) { // token ticker is mandatory for multichannel transactions if (l_main_ticker) l_token = l_main_ticker; @@ -4127,7 +4015,7 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, l_list_tx_out = dap_list_append(l_list_tx_out, l_tx_out); } break; case TX_ITEM_TYPE_OUT_EXT: { // 256 - dap_chain_tx_out_ext_t *l_tx_out = (dap_chain_tx_out_ext_t *)it->data; + dap_chain_tx_out_ext_t *l_tx_out = (dap_chain_tx_out_ext_t *)it; if (!l_multichannel) { // token ticker is forbiden for single-channel transactions l_err_num = DAP_LEDGER_TX_CHECK_UNEXPECTED_TOKENIZED_OUT; break; @@ -4138,7 +4026,7 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, l_list_tx_out = dap_list_append(l_list_tx_out, l_tx_out); } break; case TX_ITEM_TYPE_OUT_COND: { - dap_chain_tx_out_cond_t *l_tx_out = (dap_chain_tx_out_cond_t *)it->data; + dap_chain_tx_out_cond_t *l_tx_out = (dap_chain_tx_out_cond_t *)it; if (l_multichannel) { if (l_tx_out->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE) l_token = (char *)a_ledger->net->pub.native_ticker; @@ -4159,8 +4047,10 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, break; } } break; - default: {} + default: + continue; } + if (l_err_num) break; if (l_multichannel) { @@ -4205,9 +4095,6 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, SUM_256_256(l_tax_sum, l_value, &l_tax_sum); } - if ( l_list_out ) - dap_list_free(l_list_out); - // Check for transaction consistency (sum(ins) == sum(outs)) if (!l_err_num) { HASH_ITER(hh, l_values_from_prev_tx, l_value_cur, l_tmp) { @@ -4261,31 +4148,28 @@ static int s_tx_cache_check(dap_ledger_t *a_ledger, if (!l_err_num) { // TODO move it to service tag deduction - dap_list_t *l_items_voting; - if ((l_items_voting = dap_chain_datum_tx_items_get((dap_chain_datum_tx_t*) a_tx, TX_ITEM_TYPE_VOTING, NULL))) { - if (s_voting_callbacks.voting_callback){ - if (!s_voting_callbacks.voting_callback(a_ledger, TX_ITEM_TYPE_VOTING, a_tx, false)){ - debug_if(s_debug_more, L_WARNING, "Verificator check error for voting."); + if ( dap_chain_datum_tx_item_get(a_tx, NULL, NULL, TX_ITEM_TYPE_VOTING, NULL ) ) { + if (s_voting_callbacks.voting_callback) { + if ((l_err_num = s_voting_callbacks.voting_callback(a_ledger, TX_ITEM_TYPE_VOTING, a_tx, a_tx_hash, false))) { + debug_if(s_debug_more, L_WARNING, "Verificator check error %d for voting", l_err_num); l_err_num = DAP_LEDGER_TX_CHECK_VERIFICATOR_CHECK_FAILURE; } } else { debug_if(s_debug_more, L_WARNING, "Verificator check error for voting item"); l_err_num = DAP_LEDGER_TX_CHECK_NO_VERIFICATOR_SET; } - dap_list_free(l_items_voting); if (a_tag) a_tag->uint64 = DAP_CHAIN_TX_TAG_ACTION_VOTING; - }else if ((l_items_voting = dap_chain_datum_tx_items_get((dap_chain_datum_tx_t*) a_tx, TX_ITEM_TYPE_VOTE, NULL))) { - if (s_voting_callbacks.voting_callback){ - if (!s_voting_callbacks.voting_callback(a_ledger, TX_ITEM_TYPE_VOTE, a_tx, false)){ - debug_if(s_debug_more, L_WARNING, "Verificator check error for vote."); + } else if ( dap_chain_datum_tx_item_get(a_tx, NULL, NULL, TX_ITEM_TYPE_VOTE, NULL) ) { + if (s_voting_callbacks.voting_callback) { + if ((l_err_num = s_voting_callbacks.voting_callback(a_ledger, TX_ITEM_TYPE_VOTE, a_tx, a_tx_hash, false))) { + debug_if(s_debug_more, L_WARNING, "Verificator check error %d for vote", l_err_num); l_err_num = DAP_LEDGER_TX_CHECK_VERIFICATOR_CHECK_FAILURE; } } else { debug_if(s_debug_more, L_WARNING, "Verificator check error for vote item"); l_err_num = DAP_LEDGER_TX_CHECK_NO_VERIFICATOR_SET; } - dap_list_free(l_items_voting); if (a_tag) a_tag->uint64 = DAP_CHAIN_TX_TAG_ACTION_VOTE; } @@ -4680,12 +4564,14 @@ int dap_ledger_tx_add(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_ha s_balance_cache_update(a_ledger, wallet_balance); } } + int l_err_num = 0; if (s_voting_callbacks.voting_callback) { if (l_tag.uint64 == DAP_CHAIN_TX_TAG_ACTION_VOTING) - s_voting_callbacks.voting_callback(a_ledger, TX_ITEM_TYPE_VOTING, a_tx, true); + l_err_num = s_voting_callbacks.voting_callback(a_ledger, TX_ITEM_TYPE_VOTING, a_tx, a_tx_hash, true); else if (l_tag.uint64 == DAP_CHAIN_TX_TAG_ACTION_VOTE) - s_voting_callbacks.voting_callback(a_ledger, TX_ITEM_TYPE_VOTE, a_tx, true); + l_err_num = s_voting_callbacks.voting_callback(a_ledger, TX_ITEM_TYPE_VOTE, a_tx, a_tx_hash, true); } + assert(!l_err_num); // add transaction to the cache list dap_ledger_tx_item_t *l_tx_item = DAP_NEW_Z(dap_ledger_tx_item_t); @@ -5245,7 +5131,7 @@ uint64_t dap_ledger_count_from_to(dap_ledger_t * a_ledger, dap_nanotime_t a_ts_f bool dap_ledger_tx_hash_is_used_out_item(dap_ledger_t *a_ledger, dap_chain_hash_fast_t *a_tx_hash, int a_idx_out, dap_hash_fast_t *a_out_spender) { dap_ledger_tx_item_t *l_item_out = NULL; - /*dap_chain_datum_tx_t *l_tx =*/ s_find_datum_tx_by_hash(a_ledger, a_tx_hash, &l_item_out, false); + /*dap_chain_datum_tx_t *l_tx =*/ dap_ledger_tx_find_datum_by_hash(a_ledger, a_tx_hash, &l_item_out, false); return l_item_out ? s_ledger_tx_hash_is_used_out_item(l_item_out, a_idx_out, a_out_spender) : true; } @@ -5289,76 +5175,42 @@ uint256_t dap_ledger_calc_balance_full(dap_ledger_t *a_ledger, const dap_chain_a HASH_ITER(hh, l_ledger_pvt->ledger_items , l_iter_current, l_item_tmp) { dap_chain_datum_tx_t *l_cur_tx = l_iter_current->tx; - - // dap_chain_hash_fast_t *l_cur_tx_hash = &l_iter_current->tx_hash_fast; - // int l_n_outs_used = l_iter_current->n_outs_used; // number of used 'out' items - // Get 'out' items from transaction - int l_out_item_count = 0; - dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(l_cur_tx, TX_ITEM_TYPE_OUT_ALL, &l_out_item_count); - if(l_out_item_count >= MAX_OUT_ITEMS) { - if(s_debug_more) - log_it(L_ERROR, "Too many 'out' items=%d in transaction (max=%d)", l_out_item_count, MAX_OUT_ITEMS); - if (l_out_item_count >= MAX_OUT_ITEMS){ - // uint128_t l_ret; - uint256_t l_ret = uint256_0; - memset(&l_ret,0,sizeof(l_ret)); - return l_ret; - } - } - int l_out_idx_tmp = 0; - for (dap_list_t *it = l_list_out_items; it; it = it->next, l_out_idx_tmp++) { - assert(it->data); - dap_chain_tx_item_type_t l_type = *(uint8_t *)it->data; - if (l_type == TX_ITEM_TYPE_OUT_COND) + int l_out_idx = 0; + byte_t *it; size_t l_size; + TX_ITEM_ITER_TX(it, l_size, l_cur_tx) { + if ( l_out_idx > MAX_OUT_ITEMS ) + return log_it(L_ERROR, "Number of 'out' items exeeds max number %d", MAX_OUT_ITEMS), uint256_0; + uint256_t l_add = { }; + dap_chain_addr_t l_out_addr = { }; + switch (*it) { + case TX_ITEM_TYPE_OUT_OLD: { + dap_chain_tx_out_old_t *l_tx_out = (dap_chain_tx_out_old_t*)it; + l_add = dap_chain_uint256_from(l_tx_out->header.value); + l_out_addr = l_tx_out->addr; + } break; + case TX_ITEM_TYPE_OUT: { + dap_chain_tx_out_t *l_tx_out = (dap_chain_tx_out_t*)it; + l_add = l_tx_out->header.value; + l_out_addr = l_tx_out->addr; + } break; + case TX_ITEM_TYPE_OUT_EXT: { + dap_chain_tx_out_ext_t *l_tx_out = (dap_chain_tx_out_ext_t*)it; + l_add = l_tx_out->header.value; + l_out_addr = l_tx_out->addr; + } break; + case TX_ITEM_TYPE_OUT_COND: + ++l_out_idx; + default: continue; - if (l_type == TX_ITEM_TYPE_OUT_OLD) { // 64 - const dap_chain_tx_out_old_t *l_tx_out = (const dap_chain_tx_out_old_t*) it->data; - // Check for token name - if (!strcmp(a_token_ticker, l_iter_current->cache_data.token_ticker)) - { // if transaction has the out item with requested addr - if (!memcmp(a_addr, &l_tx_out->addr, sizeof(dap_chain_addr_t))) { - // if 'out' item not used & transaction is valid - if(!s_ledger_tx_hash_is_used_out_item(l_iter_current, l_out_idx_tmp, NULL) && - !dap_chain_datum_tx_verify_sign(l_cur_tx)) { - uint256_t l_add = dap_chain_uint256_from(l_tx_out->header.value); - SUM_256_256(balance, l_add, &balance); - } - } - } - } - if (l_type == TX_ITEM_TYPE_OUT) { // 256 - const dap_chain_tx_out_t *l_tx_out = (const dap_chain_tx_out_t*) it->data; - // const dap_chain_tx_out_old_t *l_tx_out = (const dap_chain_tx_out_old_t*) it->data; - // Check for token name - if (!strcmp(a_token_ticker, l_iter_current->cache_data.token_ticker)) - { // if transaction has the out item with requested addr - if (!memcmp(a_addr, &l_tx_out->addr, sizeof(dap_chain_addr_t))) { - // if 'out' item not used & transaction is valid - if(!s_ledger_tx_hash_is_used_out_item(l_iter_current, l_out_idx_tmp, NULL) && - !dap_chain_datum_tx_verify_sign(l_cur_tx)) { - SUM_256_256(balance, l_tx_out->header.value, &balance); - } - } - } - } - if (l_type == TX_ITEM_TYPE_OUT_EXT) { // 256 - const dap_chain_tx_out_ext_t *l_tx_out = (const dap_chain_tx_out_ext_t*) it->data; - // const dap_chain_tx_out_ext_t *l_tx_out = (const dap_chain_tx_out_ext_t*) it->data; - // Check for token name - if (!strcmp(a_token_ticker, l_tx_out->token)) - { // if transaction has the out item with requested addr - if (!memcmp(a_addr, &l_tx_out->addr, sizeof(dap_chain_addr_t))) { - // if 'out' item not used & transaction is valid - if(!s_ledger_tx_hash_is_used_out_item(l_iter_current, l_out_idx_tmp, NULL) && - !dap_chain_datum_tx_verify_sign(l_cur_tx)) { - SUM_256_256(balance, l_tx_out->header.value, &balance); - } - } - } } + ++l_out_idx; + if ( !dap_strcmp( a_token_ticker, l_iter_current->cache_data.token_ticker ) // Tokens match + && !dap_chain_addr_compare( a_addr, &l_out_addr ) // Addresses match + && !s_ledger_tx_hash_is_used_out_item( l_iter_current, l_out_idx, NULL ) // Output is unused + && !dap_chain_datum_tx_verify_sign(l_cur_tx) // Signs are valid + ) SUM_256_256(balance, l_add, &balance); } - dap_list_free(l_list_out_items); } pthread_rwlock_unlock(&l_ledger_pvt->ledger_rwlock); return balance; @@ -5377,7 +5229,8 @@ static dap_ledger_tx_item_t *tx_item_find_by_addr(dap_ledger_t *a_ledger, const if(!a_addr || !a_tx_first_hash) return NULL; dap_ledger_private_t *l_ledger_pvt = PVT(a_ledger); - bool is_tx_found = false; + + bool is_tx_found = false, is_search_started = dap_hash_fast_is_blank(a_tx_first_hash); dap_ledger_tx_item_t *l_iter_start = NULL, *l_iter_current, *l_item_tmp; pthread_rwlock_rdlock(&l_ledger_pvt->ledger_rwlock); if (!dap_hash_fast_is_blank(a_tx_first_hash)) { @@ -5397,55 +5250,41 @@ static dap_ledger_tx_item_t *tx_item_find_by_addr(dap_ledger_t *a_ledger, const // Now work with it dap_chain_datum_tx_t *l_tx = l_iter_current->tx; dap_chain_hash_fast_t *l_tx_hash = &l_iter_current->tx_hash_fast; + // start searching from the next hash after a_tx_first_hash + if (!is_search_started) { + is_search_started = dap_hash_fast_compare(l_tx_hash, a_tx_first_hash); + continue; + } // Get 'out' items from transaction - dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT_ALL, NULL); - for(dap_list_t *it = l_list_out_items; it; it = dap_list_next(it)) { - assert(it->data); - dap_chain_tx_item_type_t l_type = *(uint8_t *)it->data; - if (l_type == TX_ITEM_TYPE_OUT_COND) + byte_t *it; size_t l_size; + TX_ITEM_ITER_TX(it, l_size, l_tx) { + dap_chain_addr_t l_addr = { }; + switch (*it) { + case TX_ITEM_TYPE_OUT: + l_addr = ((dap_chain_tx_out_t*)it)->addr; + break; + case TX_ITEM_TYPE_OUT_OLD: + l_addr = ((dap_chain_tx_out_old_t*)it)->addr; + break; + case TX_ITEM_TYPE_OUT_EXT: + if ( a_token && dap_strcmp(a_token, ((dap_chain_tx_out_ext_t*)it)->token) ) + continue; + l_addr = ((dap_chain_tx_out_ext_t*)it)->addr; + break; + default: continue; - if (l_type == TX_ITEM_TYPE_OUT) { - const dap_chain_tx_out_t *l_tx_out = (const dap_chain_tx_out_t *)it->data; - // if transaction has the out item with requested addr - if(!memcmp(a_addr, &l_tx_out->addr, sizeof(dap_chain_addr_t))) { - memcpy(a_tx_first_hash, l_tx_hash, sizeof(dap_chain_hash_fast_t)); - is_tx_found = true; - break; - } - } - if (l_type == TX_ITEM_TYPE_OUT_OLD) { - const dap_chain_tx_out_old_t *l_tx_out = (const dap_chain_tx_out_old_t *)it->data; - // if transaction has the out item with requested addr - if(!memcmp(a_addr, &l_tx_out->addr, sizeof(dap_chain_addr_t))) { - memcpy(a_tx_first_hash, l_tx_hash, sizeof(dap_chain_hash_fast_t)); - is_tx_found = true; - break; - } } - if (l_type == TX_ITEM_TYPE_OUT_EXT) { - const dap_chain_tx_out_ext_t *l_tx_out_ext = (const dap_chain_tx_out_ext_t *)it->data; - // If a_token is setup we check if its not our token - miss it - if (a_token && dap_strcmp(l_tx_out_ext->token, a_token)) { - continue; - } // if transaction has the out item with requested addr - if(!memcmp(a_addr, &l_tx_out_ext->addr, sizeof(dap_chain_addr_t))) { - memcpy(a_tx_first_hash, l_tx_hash, sizeof(dap_chain_hash_fast_t)); - is_tx_found = true; - break; - } + if ( dap_chain_addr_compare(a_addr, &l_addr) ) { + *a_tx_first_hash = *l_tx_hash; + is_tx_found = true; + break; } } - dap_list_free(l_list_out_items); - // already found transaction - if(is_tx_found) + if (is_tx_found) break; - } pthread_rwlock_unlock(&l_ledger_pvt->ledger_rwlock); - if(is_tx_found) - return l_iter_current; - else - return NULL; + return is_tx_found ? l_iter_current : NULL; } /** @@ -5463,34 +5302,29 @@ static dap_ledger_tx_item_t *tx_item_find_by_addr(dap_ledger_t *a_ledger, const bool dap_ledger_tx_check_recipient(dap_ledger_t* a_ledger, dap_chain_hash_fast_t* a_tx_prev_hash, dap_chain_addr_t *a_addr) { - dap_chain_datum_tx_t *l_tx; - l_tx = dap_ledger_tx_find_by_hash(a_ledger,a_tx_prev_hash); - dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT_ALL, NULL), *l_item; - if(!l_list_out_items) - return false; - bool l_ret = false; - DL_FOREACH(l_list_out_items, l_item) { - dap_chain_addr_t *l_dst_addr = NULL; - dap_chain_tx_item_type_t l_type = *(uint8_t*)l_item->data; - switch (l_type) { - case TX_ITEM_TYPE_OUT: - l_dst_addr = &((dap_chain_tx_out_t*)l_item->data)->addr; - break; - case TX_ITEM_TYPE_OUT_EXT: - l_dst_addr = &((dap_chain_tx_out_ext_t*)l_item->data)->addr; - break; - case TX_ITEM_TYPE_OUT_OLD: - l_dst_addr = &((dap_chain_tx_out_old_t*)l_item->data)->addr; - default: - break; - } - if(l_dst_addr && !memcmp(l_dst_addr, a_addr, sizeof(dap_chain_addr_t))) { - l_ret = true; - break; - } - } - dap_list_free(l_list_out_items); - return l_ret; + dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_hash(a_ledger, a_tx_prev_hash); + if ( !l_tx ) + return false; + dap_chain_addr_t l_dst_addr = { }; + byte_t *it; size_t l_size; + TX_ITEM_ITER_TX(it, l_size, l_tx) { + switch (*it) { + case TX_ITEM_TYPE_OUT: + l_dst_addr = ((dap_chain_tx_out_t*)it)->addr; + break; + case TX_ITEM_TYPE_OUT_EXT: + l_dst_addr = ((dap_chain_tx_out_ext_t*)it)->addr; + break; + case TX_ITEM_TYPE_OUT_OLD: + l_dst_addr = ((dap_chain_tx_out_old_t*)it)->addr; + break; + default: + continue; + } + if ( dap_chain_addr_compare(a_addr, &l_dst_addr) ) + return true; + } + return false; } /** @@ -5516,14 +5350,13 @@ const dap_chain_datum_tx_t* dap_ledger_tx_find_by_pkey(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *l_tx_tmp = l_iter_current->tx; dap_chain_hash_fast_t *l_tx_hash_tmp = &l_iter_current->tx_hash_fast; // start searching from the next hash after a_tx_first_hash - if(!is_search_enable) { - if(dap_hash_fast_compare(l_tx_hash_tmp, a_tx_first_hash)) - is_search_enable = true; + if (!is_search_enable) { + is_search_enable = dap_hash_fast_compare(l_tx_hash_tmp, a_tx_first_hash); continue; } // Get sign item from transaction dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t*) dap_chain_datum_tx_item_get(l_tx_tmp, NULL, - TX_ITEM_TYPE_SIG, NULL); + NULL, TX_ITEM_TYPE_SIG, NULL); // Get dap_sign_t from item dap_sign_t *l_sig = dap_chain_datum_tx_item_sign_get_sig(l_tx_sig); if(l_sig) { @@ -5553,12 +5386,11 @@ dap_list_t* dap_ledger_tx_cache_find_out_cond_all(dap_ledger_t *a_ledger, dap_ch dap_ledger_tx_item_t *l_iter_current = NULL, *l_item_tmp = NULL; HASH_ITER(hh, l_ledger_pvt->ledger_items, l_iter_current, l_item_tmp) { dap_chain_datum_tx_t *l_tx = l_iter_current->tx; - dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT_COND, NULL), *l_out_item; - DL_FOREACH(l_list_out_items, l_out_item) { - if (((dap_chain_tx_out_cond_t*)l_out_item->data)->header.srv_uid.uint64 == a_srv_uid.uint64) // is srv uid is same as we're searching for? + byte_t *item; size_t l_size; + TX_ITEM_ITER_TX(item, l_size, l_tx) { + if (*item == TX_ITEM_TYPE_OUT_COND && ((dap_chain_tx_out_cond_t*)item)->header.srv_uid.uint64 == a_srv_uid.uint64) l_ret = dap_list_append(l_ret, l_tx); } - dap_list_free(l_list_out_items); } return l_ret; } @@ -5586,9 +5418,8 @@ dap_chain_datum_tx_t* dap_ledger_tx_cache_find_out_cond(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *l_tx_tmp = l_iter_current->tx; dap_chain_hash_fast_t *l_tx_hash_tmp = &l_iter_current->tx_hash_fast; // start searching from the next hash after a_tx_first_hash - if(!is_search_enable) { - if(dap_hash_fast_compare(l_tx_hash_tmp, a_tx_first_hash)) - is_search_enable = true; + if (!is_search_enable) { + is_search_enable = dap_hash_fast_compare(l_tx_hash_tmp, a_tx_first_hash); continue; } // Get out_cond item from transaction @@ -5664,157 +5495,118 @@ dap_list_t *dap_ledger_get_list_tx_outs_with_val(dap_ledger_t *a_ledger, const c uint256_t a_value_need, uint256_t *a_value_transfer) { dap_list_t *l_list_used_out = NULL; // list of transaction with 'out' items - dap_chain_hash_fast_t l_tx_cur_hash = { 0 }; - uint256_t l_value_transfer = {}; - while(compare256(l_value_transfer, a_value_need) == -1) + dap_chain_hash_fast_t l_tx_cur_hash = { }; + uint256_t l_value_transfer = { }; + dap_chain_datum_tx_t *l_tx; + while ( compare256(l_value_transfer, a_value_need) == -1 + && (l_tx = dap_ledger_tx_find_by_addr(a_ledger, a_token_ticker, a_addr_from, &l_tx_cur_hash)) ) { - // Get the transaction in the cache by the addr in out item - dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_addr(a_ledger, a_token_ticker, a_addr_from, - &l_tx_cur_hash); - if(!l_tx) - break; // Get all item from transaction by type - dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT_ALL, NULL); - - uint32_t l_out_idx_tmp = 0; // current index of 'out' item - for (dap_list_t *it = l_list_out_items; it; it = dap_list_next(it), l_out_idx_tmp++) { - dap_chain_tx_item_type_t l_type = *(uint8_t *)it->data; - uint256_t l_value = {}; + byte_t *it; size_t l_size; int i, l_out_idx_tmp = -1; + dap_chain_addr_t l_out_addr = { }; + TX_ITEM_ITER_TX_TYPE(it, TX_ITEM_TYPE_OUT_ALL, l_size, i, l_tx) { + ++l_out_idx_tmp; + dap_chain_tx_item_type_t l_type = *it; + 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 *)it->data; - if (!l_out->header.value || memcmp(a_addr_from, &l_out->addr, sizeof(dap_chain_addr_t))) - 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 *)it->data; - if (memcmp(a_addr_from, &l_out->addr, sizeof(dap_chain_addr_t)) || - dap_strcmp(dap_ledger_tx_get_token_ticker_by_hash(a_ledger, &l_tx_cur_hash), a_token_ticker) || - IS_ZERO_256(l_out->header.value)) - continue; - l_value = l_out->header.value; - } break; - case TX_ITEM_TYPE_OUT_EXT: { - dap_chain_tx_out_ext_t *l_out_ext = (dap_chain_tx_out_ext_t *)it->data; - if (memcmp(a_addr_from, &l_out_ext->addr, sizeof(dap_chain_addr_t)) || - strcmp((char *)a_token_ticker, l_out_ext->token) || - IS_ZERO_256(l_out_ext->header.value) ) { - continue; - } - l_value = l_out_ext->header.value; - } break; - case TX_ITEM_TYPE_OUT_COND: - default: + case TX_ITEM_TYPE_OUT_OLD: { + dap_chain_tx_out_old_t *l_out = (dap_chain_tx_out_old_t*)it; + l_out_addr = l_out->addr; + if ( !l_out->header.value || !dap_chain_addr_compare(a_addr_from, &l_out_addr) ) + 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*)it; + l_out_addr = l_out->addr; + if ( !dap_chain_addr_compare(a_addr_from, &l_out_addr) + || dap_strcmp(dap_ledger_tx_get_token_ticker_by_hash(a_ledger, &l_tx_cur_hash), a_token_ticker) + || IS_ZERO_256(l_out->header.value) ) + continue; + l_value = l_out->header.value; + } break; + case TX_ITEM_TYPE_OUT_EXT: { + dap_chain_tx_out_ext_t *l_out_ext = (dap_chain_tx_out_ext_t*)it; + l_out_addr = l_out_ext->addr; + if ( !dap_chain_addr_compare(a_addr_from, &l_out_addr) + || strcmp((char *)a_token_ticker, l_out_ext->token) + || 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_ledger, &l_tx_cur_hash, l_out_idx_tmp, NULL)) { + if ( !dap_ledger_tx_hash_is_used_out_item (a_ledger, &l_tx_cur_hash, l_out_idx_tmp, NULL) ) { dap_chain_tx_used_out_item_t *l_item = DAP_NEW_Z(dap_chain_tx_used_out_item_t); - if ( !l_item ) { - log_it(L_CRITICAL, "Out of memory"); - if (l_list_used_out) - dap_list_free_full(l_list_used_out, NULL); - dap_list_free(l_list_out_items); - return NULL; - } - l_item->tx_hash_fast = l_tx_cur_hash; - l_item->num_idx_out = l_out_idx_tmp; - l_item->value = l_value; + *l_item = (dap_chain_tx_used_out_item_t) { l_tx_cur_hash, (uint32_t)l_out_idx_tmp, 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) != -1) { + if ( compare256(l_value_transfer, a_value_need) != -1 ) { break; } } } - dap_list_free(l_list_out_items); } - - // nothing to tranfer (not enough funds) - if(!l_list_used_out || compare256(l_value_transfer, a_value_need) == -1) { - dap_list_free_full(l_list_used_out, NULL); - return NULL; - } - - if (a_value_transfer) { - *a_value_transfer = l_value_transfer; - } - return l_list_used_out; + return compare256(l_value_transfer, a_value_need) >= 0 && l_list_used_out + ? ({ if (a_value_transfer) *a_value_transfer = l_value_transfer; l_list_used_out; }) + : ( dap_list_free_full(l_list_used_out, NULL), NULL ); } dap_list_t *dap_ledger_get_list_tx_outs(dap_ledger_t *a_ledger, const char *a_token_ticker, const dap_chain_addr_t *a_addr_from, uint256_t *a_value_transfer) { dap_list_t *l_list_used_out = NULL; // list of transaction with 'out' items - dap_chain_hash_fast_t l_tx_cur_hash = { 0 }; + dap_chain_hash_fast_t l_tx_cur_hash = { }; uint256_t l_value_transfer = {}; - dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_addr(a_ledger, a_token_ticker, a_addr_from, - &l_tx_cur_hash); - - while(l_tx) - { - // Get all item from transaction by type - dap_list_t *l_list_out_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT_ALL, NULL); - - uint32_t l_out_idx_tmp = 0; // current index of 'out' item - for (dap_list_t *it = l_list_out_items; it; it = dap_list_next(it), l_out_idx_tmp++) { - dap_chain_tx_item_type_t l_type = *(uint8_t *)it->data; - uint256_t l_value = {}; - switch (l_type) { + dap_chain_datum_tx_t *l_tx; + while (( l_tx = dap_ledger_tx_find_by_addr(a_ledger, a_token_ticker, a_addr_from, &l_tx_cur_hash) )) { + byte_t *it; size_t l_size; int i, l_out_idx_tmp = -1; + dap_chain_addr_t l_out_addr = { }; + TX_ITEM_ITER_TX_TYPE(it, TX_ITEM_TYPE_OUT_ALL, l_size, i, l_tx) { + ++l_out_idx_tmp; + uint256_t l_value = { }; + switch (*it) { case TX_ITEM_TYPE_OUT_OLD: { - dap_chain_tx_out_old_t *l_out = (dap_chain_tx_out_old_t *)it->data; - if (!l_out->header.value || memcmp(a_addr_from, &l_out->addr, sizeof(dap_chain_addr_t))) + dap_chain_tx_out_old_t *l_out = (dap_chain_tx_out_old_t*)it; + l_out_addr = l_out->addr; + if ( !l_out->header.value || !dap_chain_addr_compare(a_addr_from, &l_out_addr) ) 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 *)it->data; - if (memcmp(a_addr_from, &l_out->addr, sizeof(dap_chain_addr_t)) || - dap_strcmp(dap_ledger_tx_get_token_ticker_by_hash(a_ledger, &l_tx_cur_hash), a_token_ticker) || - IS_ZERO_256(l_out->header.value)) + dap_chain_tx_out_t *l_out = (dap_chain_tx_out_t*)it; + l_out_addr = l_out->addr; + if ( !dap_chain_addr_compare(a_addr_from, &l_out_addr) + || dap_strcmp( dap_ledger_tx_get_token_ticker_by_hash(a_ledger, &l_tx_cur_hash), a_token_ticker ) + || IS_ZERO_256(l_out->header.value)) continue; l_value = l_out->header.value; } break; case TX_ITEM_TYPE_OUT_EXT: { - dap_chain_tx_out_ext_t *l_out_ext = (dap_chain_tx_out_ext_t *)it->data; - if (memcmp(a_addr_from, &l_out_ext->addr, sizeof(dap_chain_addr_t)) || - strcmp((char *)a_token_ticker, l_out_ext->token) || - IS_ZERO_256(l_out_ext->header.value) ) { + dap_chain_tx_out_ext_t *l_out_ext = (dap_chain_tx_out_ext_t *)it; + l_out_addr = l_out_ext->addr; + if ( !dap_chain_addr_compare(a_addr_from, &l_out_addr) + || strcmp((char*)a_token_ticker, l_out_ext->token) + || IS_ZERO_256(l_out_ext->header.value) ) continue; - } l_value = l_out_ext->header.value; } break; - case TX_ITEM_TYPE_OUT_COND: default: continue; } // Check whether used 'out' items - if (!dap_ledger_tx_hash_is_used_out_item (a_ledger, &l_tx_cur_hash, l_out_idx_tmp, NULL)) { + if ( !dap_ledger_tx_hash_is_used_out_item(a_ledger, &l_tx_cur_hash, l_out_idx_tmp, NULL) ) { dap_chain_tx_used_out_item_t *l_item = DAP_NEW_Z(dap_chain_tx_used_out_item_t); - if ( !l_item ) { - log_it(L_CRITICAL, "Out of memory"); - if (l_list_used_out) - dap_list_free_full(l_list_used_out, NULL); - dap_list_free(l_list_out_items); - return NULL; - } - l_item->tx_hash_fast = l_tx_cur_hash; - l_item->num_idx_out = l_out_idx_tmp; - l_item->value = l_value; + *(l_item) = (dap_chain_tx_used_out_item_t) { l_tx_cur_hash, (uint32_t)l_out_idx_tmp, 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); } } - dap_list_free(l_list_out_items); - l_tx = dap_ledger_tx_find_by_addr(a_ledger, a_token_ticker, a_addr_from, - &l_tx_cur_hash); - } - - if (a_value_transfer) { - *a_value_transfer = l_value_transfer; } + if (a_value_transfer) *a_value_transfer = l_value_transfer; return l_list_used_out; } @@ -5970,122 +5762,55 @@ dap_list_t *dap_ledger_get_list_tx_cond_outs_with_val(dap_ledger_t *a_ledger, co dap_list_t *l_list_used_out = NULL; // list of transaction with 'out' items dap_chain_hash_fast_t l_tx_cur_hash = { 0 }; uint256_t l_value_transfer = { }; - while(compare256(l_value_transfer, a_value_need) == -1) + dap_chain_datum_tx_t *l_tx; + while( compare256(l_value_transfer, a_value_need) == -1 + && ( l_tx = dap_ledger_tx_find_by_addr(a_ledger, a_token_ticker, a_addr_from, &l_tx_cur_hash)) ) { - // Get the transaction in the cache by the addr in out item - dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_addr(a_ledger, a_token_ticker, a_addr_from, &l_tx_cur_hash); - if(!l_tx) - break; - // Get all item from transaction by type - dap_list_t *l_list_out_cond_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT_COND, NULL); - - uint32_t l_out_idx_tmp = 0; // current index of 'out' item - for(dap_list_t *it = l_list_out_cond_items; it; it = dap_list_next(it), l_out_idx_tmp++) { - dap_chain_tx_item_type_t l_type = *(uint8_t*) it->data; - uint256_t l_value = { }; - switch (l_type) { - case TX_ITEM_TYPE_OUT_COND: { - dap_chain_tx_out_cond_t *l_out_cond = (dap_chain_tx_out_cond_t*) it->data; - if(IS_ZERO_256(l_out_cond->header.value) || a_subtype != l_out_cond->header.subtype) { - continue; - } - l_value = l_out_cond->header.value; - } - break; - default: + byte_t *it; size_t l_size; int i, l_out_idx_tmp = -1; + TX_ITEM_ITER_TX_TYPE(it, TX_ITEM_TYPE_OUT_COND, l_size, i, l_tx) { + ++l_out_idx_tmp; + dap_chain_tx_out_cond_t *l_out_cond = (dap_chain_tx_out_cond_t*) it; + if (a_subtype != l_out_cond->header.subtype || IS_ZERO_256(l_out_cond->header.value) ) continue; - } - if (!IS_ZERO_256(l_value)) { - dap_chain_tx_used_out_item_t *l_item = DAP_NEW_Z(dap_chain_tx_used_out_item_t); - if ( !l_item ) { - if (l_list_used_out) - dap_list_free_full(l_list_used_out, NULL); - dap_list_free(l_list_out_cond_items); - return NULL; - } - l_item->tx_hash_fast = l_tx_cur_hash; - l_item->num_idx_out = l_out_idx_tmp; - l_item->value = 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) != -1) { - break; - } + 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_tx_cur_hash, (uint32_t)l_out_idx_tmp, l_out_cond->header.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) != -1 ) { + break; } } - dap_list_free(l_list_out_cond_items); } - - // nothing to tranfer (not enough funds) - if(!l_list_used_out || compare256(l_value_transfer, a_value_need) == -1) { - dap_list_free_full(l_list_used_out, NULL); - return NULL; - } - - if (a_value_transfer) { - *a_value_transfer = l_value_transfer; - } - return l_list_used_out; + return compare256(l_value_transfer, a_value_need) > -1 && l_list_used_out + ? ({ if (a_value_transfer) *a_value_transfer = l_value_transfer; l_list_used_out; }) + : ( dap_list_free_full(l_list_used_out, NULL), NULL ); } dap_list_t *dap_ledger_get_list_tx_cond_outs(dap_ledger_t *a_ledger, const char *a_token_ticker, const dap_chain_addr_t *a_addr_from, dap_chain_tx_out_cond_subtype_t a_subtype, uint256_t *a_value_transfer) { dap_list_t *l_list_used_out = NULL; // list of transaction with 'out' items - dap_chain_hash_fast_t l_tx_cur_hash = { 0 }; + dap_chain_hash_fast_t l_tx_cur_hash = { }; uint256_t l_value_transfer = { }; - dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_addr(a_ledger, a_token_ticker, a_addr_from, &l_tx_cur_hash); - while(l_tx) - { - // Get all item from transaction by type - dap_list_t *l_list_out_cond_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT_COND, NULL); - - uint32_t l_out_idx_tmp = 0; // current index of 'out' item - for(dap_list_t *it = l_list_out_cond_items; it; it = dap_list_next(it), l_out_idx_tmp++) { - dap_chain_tx_item_type_t l_type = *(uint8_t*) it->data; - uint256_t l_value = { }; - switch (l_type) { - case TX_ITEM_TYPE_OUT_COND: { - dap_chain_tx_out_cond_t *l_out_cond = (dap_chain_tx_out_cond_t*) it->data; - if(IS_ZERO_256(l_out_cond->header.value) || a_subtype != l_out_cond->header.subtype) { - continue; - } - l_value = l_out_cond->header.value; - } - break; - default: + dap_chain_datum_tx_t *l_tx; + while(( l_tx = dap_ledger_tx_find_by_addr(a_ledger, a_token_ticker, a_addr_from, &l_tx_cur_hash) )) { + byte_t *it; size_t l_size; int i, l_out_idx_tmp = -1; + TX_ITEM_ITER_TX_TYPE(it, TX_ITEM_TYPE_OUT_COND, l_size, i, l_tx) { + ++l_out_idx_tmp; + dap_chain_tx_out_cond_t *l_out_cond = (dap_chain_tx_out_cond_t*)it; + if ( a_subtype != l_out_cond->header.subtype || IS_ZERO_256(l_out_cond->header.value) ) continue; - } - if (!IS_ZERO_256(l_value)) { - dap_chain_tx_used_out_item_t *l_item = DAP_NEW_Z(dap_chain_tx_used_out_item_t); - if ( !l_item ) { - if (l_list_used_out) - dap_list_free_full(l_list_used_out, NULL); - dap_list_free(l_list_out_cond_items); - return NULL; - } - l_item->tx_hash_fast = l_tx_cur_hash; - l_item->num_idx_out = l_out_idx_tmp; - l_item->value = 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); - } + 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_tx_cur_hash, (uint32_t)l_out_idx_tmp, l_out_cond->header.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); } - dap_list_free(l_list_out_cond_items); - l_tx = dap_ledger_tx_find_by_addr(a_ledger, a_token_ticker, a_addr_from, &l_tx_cur_hash); } - // nothing to tranfer (not enough funds) - if(!l_list_used_out) { - dap_list_free_full(l_list_used_out, NULL); - return NULL; - } - - if (a_value_transfer) { - *a_value_transfer = l_value_transfer; - } - return l_list_used_out; + return l_list_used_out + ? ({ if (a_value_transfer) *a_value_transfer = l_value_transfer; l_list_used_out; }) + : ( dap_list_free_full(l_list_used_out, NULL), NULL ); } void dap_ledger_tx_add_notify(dap_ledger_t *a_ledger, dap_ledger_tx_add_notify_t a_callback, void *a_arg) { @@ -6134,11 +5859,10 @@ void dap_ledger_set_cache_tx_check_callback(dap_ledger_t *a_ledger, dap_ledger_c const char *dap_ledger_tx_calculate_main_ticker(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, int *a_ledger_rc) { static _Thread_local char s_main_ticker[DAP_CHAIN_TICKER_SIZE_MAX] = { '\0' }; - dap_chain_hash_fast_t *l_tx_hash = dap_chain_node_datum_tx_calc_hash(a_tx); - int l_rc = s_tx_cache_check(a_ledger, a_tx, l_tx_hash, false, NULL, NULL, s_main_ticker, NULL, NULL, false); + dap_hash_fast_t l_tx_hash = dap_chain_node_datum_tx_calc_hash(a_tx); + int l_rc = s_tx_cache_check(a_ledger, a_tx, &l_tx_hash, false, NULL, NULL, s_main_ticker, NULL, NULL, false); if (l_rc == DAP_LEDGER_CHECK_ALREADY_CACHED) - dap_strncpy( s_main_ticker, dap_ledger_tx_get_token_ticker_by_hash(a_ledger, l_tx_hash), DAP_CHAIN_TICKER_SIZE_MAX ); - DAP_DEL_Z(l_tx_hash); + dap_strncpy( s_main_ticker, dap_ledger_tx_get_token_ticker_by_hash(a_ledger, &l_tx_hash), DAP_CHAIN_TICKER_SIZE_MAX ); if (a_ledger_rc) *a_ledger_rc = l_rc; return s_main_ticker; diff --git a/modules/net/dap_chain_net_tx.c b/modules/net/dap_chain_net_tx.c index f6222d67745a4e8d3f2dff15e670503ef343798e..368d9acd63ce33f6a22a2ceeca24dc148b2444b7 100644 --- a/modules/net/dap_chain_net_tx.c +++ b/modules/net/dap_chain_net_tx.c @@ -50,72 +50,45 @@ typedef struct cond_all_by_srv_uid_arg{ static void s_tx_cond_all_with_spends_by_srv_uid_callback(dap_chain_net_t* a_net, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, void *a_arg) { cond_all_with_spends_by_srv_uid_arg_t *l_arg = (cond_all_with_spends_by_srv_uid_arg_t*)a_arg; - dap_chain_datum_tx_t *l_tx = a_tx; - dap_chain_datum_tx_spends_items_t * l_ret = l_arg->ret; - - if(l_arg->time_from && l_tx->header.ts_created < l_arg->time_from) - return; - - // Check for time to - if(l_arg->time_to && l_tx->header.ts_created > l_arg->time_to) - return; - - // Go through all items - uint32_t l_tx_items_pos = 0, l_tx_items_size = l_tx->header.tx_items_size; - while (l_tx_items_pos < l_tx_items_size) { - uint8_t *l_item = l_tx->tx_items + l_tx_items_pos; - int l_item_size = dap_chain_datum_item_tx_get_size(l_item); - if(!l_item_size) - break; - // check type - dap_chain_tx_item_type_t l_item_type = dap_chain_datum_tx_item_get_type(l_item); - switch (l_item_type){ - case TX_ITEM_TYPE_IN_COND:{ - dap_chain_tx_in_cond_t * l_tx_in_cond = (dap_chain_tx_in_cond_t *) l_item; - dap_chain_datum_tx_spends_item_t *l_tx_prev_out_item = NULL; - HASH_FIND(hh, l_ret->tx_outs, &l_tx_in_cond->header.tx_prev_hash,sizeof(l_tx_in_cond->header.tx_prev_hash), l_tx_prev_out_item); - - if (l_tx_prev_out_item){ // we found previous out_cond with target srv_uid - dap_chain_datum_tx_spends_item_t *l_item_in = DAP_NEW_Z(dap_chain_datum_tx_spends_item_t); - if (!l_item_in) { - log_it(L_CRITICAL, "%s", c_error_memory_alloc); - return ; - } - size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx); - dap_chain_datum_tx_t * l_tx_dup = DAP_DUP_SIZE(l_tx,l_tx_size); - l_item_in->tx_hash = *a_tx_hash; - - l_item_in->tx = l_tx_dup; - // Calc same offset from tx duplicate - l_item_in->in_cond = (dap_chain_tx_in_cond_t*) (l_tx_dup->tx_items + l_tx_items_pos); - HASH_ADD(hh,l_ret->tx_ins, tx_hash, sizeof(dap_chain_hash_fast_t), l_item_in); - - // Link previous out with current in - l_tx_prev_out_item->tx_next = l_tx_dup; + dap_chain_datum_tx_spends_items_t *l_ret = l_arg->ret; + + dap_return_if_pass(( l_arg->time_from && a_tx->header.ts_created < l_arg->time_from ) + || ( l_arg->time_to && a_tx->header.ts_created > l_arg->time_to )); + byte_t *l_item; size_t l_size; + TX_ITEM_ITER_TX(l_item, l_size, a_tx) { + switch (*l_item) { + case TX_ITEM_TYPE_IN_COND: { + dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t*)l_item; + dap_chain_datum_tx_spends_item_t *l_spends = NULL; + dap_hash_fast_t l_prev_hash = l_tx_in_cond->header.tx_prev_hash; + HASH_FIND(hh, l_ret->tx_outs, &l_prev_hash, sizeof(l_prev_hash), l_spends); + if (l_spends) { + dap_chain_datum_tx_spends_item_t *l_in = DAP_NEW_Z(dap_chain_datum_tx_spends_item_t); + *l_in = (dap_chain_datum_tx_spends_item_t) { + .tx = a_tx, + .tx_hash = *a_tx_hash, + .in_cond = l_tx_in_cond + }; + HASH_ADD(hh, l_ret->tx_ins, tx_hash, sizeof(dap_chain_hash_fast_t), l_in); + l_spends->tx_next = a_tx; } - }break; - case TX_ITEM_TYPE_OUT_COND:{ - dap_chain_tx_out_cond_t * l_tx_out_cond = (dap_chain_tx_out_cond_t *)l_item; - if(l_tx_out_cond->header.srv_uid.uint64 == l_arg->srv_uid.uint64){ - dap_chain_datum_tx_spends_item_t * l_item = DAP_NEW_Z(dap_chain_datum_tx_spends_item_t); - if (!l_item) { - log_it(L_CRITICAL, "%s", c_error_memory_alloc); - return ; - } - size_t l_tx_size = dap_chain_datum_tx_get_size(l_tx); - dap_chain_datum_tx_t * l_tx_dup = DAP_DUP_SIZE(l_tx,l_tx_size); - l_item->tx_hash = *a_tx_hash; - l_item->tx = l_tx_dup; - // Calc same offset from tx duplicate - l_item->out_cond = (dap_chain_tx_out_cond_t*) (l_tx_dup->tx_items + l_tx_items_pos); - - HASH_ADD(hh,l_ret->tx_outs, tx_hash, sizeof(dap_chain_hash_fast_t), l_item); - break; // We're seaching only for one specified OUT_COND output per transaction + } break; + case TX_ITEM_TYPE_OUT_COND: { + dap_chain_tx_out_cond_t *l_tx_out_cond = (dap_chain_tx_out_cond_t*)l_item; + if (l_tx_out_cond->header.srv_uid.uint64 == l_arg->srv_uid.uint64) { + dap_chain_datum_tx_spends_item_t *l_out = DAP_NEW_Z(dap_chain_datum_tx_spends_item_t); + *l_out = (dap_chain_datum_tx_spends_item_t) { + .tx = a_tx, + .tx_hash = *a_tx_hash, + .out_cond = l_tx_out_cond + }; + HASH_ADD(hh, l_ret->tx_outs, tx_hash, sizeof(dap_chain_hash_fast_t), l_out); + // ??? TODO? } } break; - default:; + default: + break; } - l_tx_items_pos += l_item_size; } } @@ -265,13 +238,12 @@ struct get_tx_cond_all_from_tx static void s_get_tx_cond_chain_callback(dap_chain_net_t* a_net, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, void *a_arg) { struct get_tx_cond_all_from_tx * l_args = (struct get_tx_cond_all_from_tx* ) a_arg; - if( l_args->ret ){ int l_item_idx = 0; byte_t *l_tx_item; dap_hash_fast_t * l_tx_hash = a_tx_hash; // Get items from transaction - while ((l_tx_item = dap_chain_datum_tx_item_get(a_tx, &l_item_idx, TX_ITEM_TYPE_IN_COND , NULL)) != NULL){ + while ((l_tx_item = dap_chain_datum_tx_item_get(a_tx, &l_item_idx, NULL, TX_ITEM_TYPE_IN_COND , NULL)) != NULL){ dap_chain_tx_in_cond_t * l_in_cond = (dap_chain_tx_in_cond_t *) l_tx_item; if(dap_hash_fast_compare(&l_in_cond->header.tx_prev_hash, &l_args->tx_last_hash) && (uint32_t)l_args->tx_last_cond_idx == l_in_cond->header.tx_out_prev_idx ){ // Found output @@ -360,79 +332,75 @@ static void s_get_tx_cond_all_for_addr_callback(dap_chain_net_t* a_net, dap_chai UNUSED(a_net); UNUSED(a_hash); struct get_tx_cond_all_for_addr * l_args = (struct get_tx_cond_all_for_addr* ) a_arg; - int l_item_idx = 0; - dap_chain_datum_tx_item_t *l_tx_item; + bool l_tx_for_addr = false; // TX with output related with our address bool l_tx_from_addr = false; // TX with input that take assets from our address //const char *l_tx_from_addr_token = NULL; bool l_tx_collected = false; // We already collected this TX in return list - + byte_t *l_tx_item = NULL; size_t l_size = 0; int l_idx = 0; // Get in items to detect is in or in_cond from target address - while ((l_tx_item = (dap_chain_datum_tx_item_t *) dap_chain_datum_tx_item_get(a_datum_tx, &l_item_idx, TX_ITEM_TYPE_ANY , NULL)) != NULL){ - switch (l_tx_item->type){ - case TX_ITEM_TYPE_IN:{ - dap_chain_tx_in_t * l_in = (dap_chain_tx_in_t *) l_tx_item; - if( l_tx_from_addr) // Already detected thats spends from addr - break; + TX_ITEM_ITER_TX(l_tx_item, l_size, a_datum_tx) { + switch (*l_tx_item) { + case TX_ITEM_TYPE_IN: { + dap_chain_tx_in_t * l_in = (dap_chain_tx_in_t *) l_tx_item; + if( l_tx_from_addr) // Already detected thats spends from addr + break; // dap_chain_tx_t * l_tx = dap_chain_tx_hh_find( l_args->tx_all_hh, &l_in->header.tx_prev_hash); - if( dap_chain_tx_hh_find( l_args->tx_all_hh, &l_in->header.tx_prev_hash) ){ // Its input thats closing output for target address - we note it - l_tx_from_addr = true; - //l_tx_from_addr_token = dap_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, &l_tx->hash); - } - }break; - case TX_ITEM_TYPE_IN_COND:{ - if(l_tx_collected) // Already collected - break; - dap_chain_tx_in_cond_t * l_in_cond = (dap_chain_tx_in_cond_t *) l_tx_item; + if( dap_chain_tx_hh_find( l_args->tx_all_hh, &l_in->header.tx_prev_hash) ){ // Its input thats closing output for target address - we note it + l_tx_from_addr = true; + //l_tx_from_addr_token = dap_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, &l_tx->hash); + } + } break; + case TX_ITEM_TYPE_IN_COND: { + if(l_tx_collected) // Already collected + break; + dap_chain_tx_in_cond_t * l_in_cond = (dap_chain_tx_in_cond_t *) l_tx_item; // dap_chain_tx_t * l_tx = dap_chain_tx_hh_find( l_args->tx_all_hh, &l_in_cond->header.tx_prev_hash); - if( dap_chain_tx_hh_find( l_args->tx_all_hh, &l_in_cond->header.tx_prev_hash) ){ // Its input thats closing conditioned tx related with target address, collect it - //dap_chain_tx_t *l_tx_add = dap_chain_tx_wrap_packed(a_datum_tx); - l_args->ret = dap_list_append(l_args->ret, a_datum_tx); - l_tx_collected = true; - } - }break; + if( dap_chain_tx_hh_find( l_args->tx_all_hh, &l_in_cond->header.tx_prev_hash) ){ // Its input thats closing conditioned tx related with target address, collect it + //dap_chain_tx_t *l_tx_add = dap_chain_tx_wrap_packed(a_datum_tx); + l_args->ret = dap_list_append(l_args->ret, a_datum_tx); + l_tx_collected = true; + } + } break; } - l_item_idx++; } //dap_chain_datum_tx_out_cond_get(a_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_out_item_idx) // Get out items from transaction - l_item_idx = 0; - while ((l_tx_item = (dap_chain_datum_tx_item_t *) dap_chain_datum_tx_item_get(a_datum_tx, &l_item_idx, TX_ITEM_TYPE_OUT_ALL , NULL)) != NULL){ - switch (l_tx_item->type){ - case TX_ITEM_TYPE_OUT:{ - if(l_tx_for_addr) // Its already added - break; - dap_chain_tx_out_t * l_out = (dap_chain_tx_out_t*) l_tx_item; - if ( memcmp(&l_out->addr, l_args->addr, sizeof(*l_args->addr)) == 0){ // Its our address tx - dap_chain_tx_t * l_tx = dap_chain_tx_wrap_packed(a_datum_tx); - dap_chain_tx_hh_add(&l_args->tx_all_hh, l_tx); - l_tx_for_addr = true; - } - }break; - case TX_ITEM_TYPE_OUT_EXT:{ - if(l_tx_for_addr) // Its already added - break; - dap_chain_tx_out_ext_t * l_out = (dap_chain_tx_out_ext_t*) l_tx_item; - if ( memcmp(&l_out->addr, l_args->addr, sizeof(*l_args->addr)) == 0){ // Its our address tx - dap_chain_tx_t * l_tx = dap_chain_tx_wrap_packed(a_datum_tx); - dap_chain_tx_hh_add(&l_args->tx_all_hh, l_tx); - l_tx_for_addr = true; - } - }break; - case TX_ITEM_TYPE_OUT_COND:{ - dap_chain_tx_out_cond_t * l_out_cond = (dap_chain_tx_out_cond_t*) l_tx_item; - if(l_tx_collected) // Already collected for return list - break; + TX_ITEM_ITER_TX(l_tx_item, l_size, a_datum_tx) { + switch (*l_tx_item) { + case TX_ITEM_TYPE_OUT: { + if(l_tx_for_addr) // Its already added + break; + dap_chain_tx_out_t * l_out = (dap_chain_tx_out_t*) l_tx_item; + if ( memcmp(&l_out->addr, l_args->addr, sizeof(*l_args->addr)) == 0){ // Its our address tx + dap_chain_tx_t * l_tx = dap_chain_tx_wrap_packed(a_datum_tx); + dap_chain_tx_hh_add(&l_args->tx_all_hh, l_tx); + l_tx_for_addr = true; + } + } break; + case TX_ITEM_TYPE_OUT_EXT:{ + if(l_tx_for_addr) // Its already added + break; + dap_chain_tx_out_ext_t * l_out = (dap_chain_tx_out_ext_t*) l_tx_item; + if ( memcmp(&l_out->addr, l_args->addr, sizeof(*l_args->addr)) == 0){ // Its our address tx + dap_chain_tx_t * l_tx = dap_chain_tx_wrap_packed(a_datum_tx); + dap_chain_tx_hh_add(&l_args->tx_all_hh, l_tx); + l_tx_for_addr = true; + } + } break; + case TX_ITEM_TYPE_OUT_COND:{ + dap_chain_tx_out_cond_t * l_out_cond = (dap_chain_tx_out_cond_t*) l_tx_item; + if(l_tx_collected) // Already collected for return list + break; - // If this output spends monies from our address - if(l_tx_from_addr && l_out_cond->header.srv_uid.uint64 == l_args->srv_uid.uint64){ - //dap_chain_tx_t *l_tx_add = dap_chain_tx_wrap_packed(a_datum_tx); - l_args->ret = dap_list_append(l_args->ret, a_datum_tx); - l_tx_collected = true; - } - } break; - } - l_item_idx++; + // If this output spends monies from our address + if(l_tx_from_addr && l_out_cond->header.srv_uid.uint64 == l_args->srv_uid.uint64){ + //dap_chain_tx_t *l_tx_add = dap_chain_tx_wrap_packed(a_datum_tx); + l_args->ret = dap_list_append(l_args->ret, a_datum_tx); + l_tx_collected = true; + } + } break; + } } } @@ -460,32 +428,18 @@ dap_list_t * dap_chain_net_get_tx_cond_all_for_addr(dap_chain_net_t * a_net, dap return l_ret; } -static void s_tx_cond_all_by_srv_uid_callback(dap_chain_net_t* a_net, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, void *a_arg) +static void s_tx_cond_all_by_srv_uid_callback(UNUSED_ARG dap_chain_net_t* a_net, dap_chain_datum_tx_t *a_tx, UNUSED_ARG dap_hash_fast_t *a_tx_hash, void *a_arg) { - UNUSED(a_net); - UNUSED(a_tx_hash); - - cond_all_by_srv_uid_arg_t *l_ret = (cond_all_by_srv_uid_arg_t *)a_arg; - dap_chain_datum_tx_t *l_tx = a_tx; - - // Check for time from - if(l_ret->time_from && l_tx->header.ts_created < l_ret->time_from) - return; + cond_all_by_srv_uid_arg_t *l_ret = (cond_all_by_srv_uid_arg_t*)a_arg; - // Check for time to - if(l_ret->time_to && l_tx->header.ts_created > l_ret->time_to) + if (( l_ret->time_from && a_tx->header.ts_created < l_ret->time_from ) + || ( l_ret->time_to && a_tx->header.ts_created > l_ret->time_to )) return; - // Check for OUT_COND items - dap_list_t *l_list_out_cond_items = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_OUT_COND, NULL), *l_out_cond_item; - if(l_list_out_cond_items) { - DL_FOREACH(l_list_out_cond_items, l_out_cond_item) { - dap_chain_tx_out_cond_t *l_tx_out_cond = (dap_chain_tx_out_cond_t*)l_out_cond_item->data; - if (l_tx_out_cond && l_tx_out_cond->header.srv_uid.uint64 == l_ret->srv_uid.uint64) { - l_ret->ret = dap_list_append(l_ret->ret, l_tx); - } - } - dap_list_free(l_list_out_cond_items); + byte_t *item; size_t l_size; + TX_ITEM_ITER_TX(item, l_size, a_tx) { + if ( *item == TX_ITEM_TYPE_OUT_COND && l_ret->srv_uid.uint64 == ((dap_chain_tx_out_cond_t*)item)->header.srv_uid.uint64 ) + l_ret->ret = dap_list_append(l_ret->ret, a_tx); } } diff --git a/modules/net/dap_chain_node_cli_cmd.c b/modules/net/dap_chain_node_cli_cmd.c index 3811e7e4f4a2597cd3728000a55510018533225b..a65a28b99060eb025468d290b8f4cd27ef985c8b 100644 --- a/modules/net/dap_chain_node_cli_cmd.c +++ b/modules/net/dap_chain_node_cli_cmd.c @@ -2883,10 +2883,9 @@ void s_com_mempool_list_print_for_chain(dap_chain_net_t * a_net, dap_chain_t * a json_object_object_add(l_jobj_datum, "action", json_object_new_string("UNKNOWN")); } - - dap_list_t *l_list_sig_item = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_SIG, NULL); dap_list_t *l_list_in_ems = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_IN_EMS, NULL); - if (!l_list_sig_item) { + dap_chain_tx_sig_t *l_sig = (dap_chain_tx_sig_t*)dap_chain_datum_tx_item_get(l_tx, NULL, NULL, TX_ITEM_TYPE_SIG, NULL); + if (!l_sig) { json_object *l_jobj_wgn = json_object_new_string( "An item with a type TX_ITEM_TYPE_SIG for the " "transaction was not found, the transaction may " @@ -2894,13 +2893,11 @@ void s_com_mempool_list_print_for_chain(dap_chain_net_t * a_net, dap_chain_t * a json_object_object_add(l_jobj_datum, "warning", l_jobj_wgn); break; } - dap_chain_tx_sig_t *l_sig = l_list_sig_item->data; dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig(l_sig); dap_chain_addr_fill_from_sign(&l_addr_from, l_sign, a_net->pub.id); if (l_wallet_addr && dap_chain_addr_compare(l_wallet_addr, &l_addr_from)) { datum_is_accepted_addr = true; } - dap_list_free(l_list_sig_item); dap_list_t *l_list_in_reward = dap_chain_datum_tx_items_get(l_tx, TX_ITEM_TYPE_IN_REWARD, NULL); if (l_list_in_reward) { /*json_object *l_obj_in_reward_arary = json_object_new_array(); @@ -4335,7 +4332,7 @@ static int s_parse_additional_token_decl_arg(int a_argc, char ** a_argv, void ** l_tsd_offset += l_tsd_size; } a_params->ext.tsd_total_size = l_tsd_total_size; - + dap_list_free_full(l_tsd_list, NULL); return 0; } @@ -4656,6 +4653,7 @@ int com_token_decl(int a_argc, char ** a_argv, void **a_str_reply) l_datum_data_offset += l_params->ext.tsd_total_size; DAP_DELETE(l_params->ext.parsed_tsd); } + dap_list_free_full(l_tsd_list, NULL); log_it(L_DEBUG, "%s token declaration '%s' initialized", l_params->subtype == DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE ? "Private" : "CF20", l_datum_token->ticker); }break;//end @@ -5482,15 +5480,13 @@ int com_tx_cond_remove(int a_argc, char ** a_argv, void **reply) continue; } // Get owner tx - dap_hash_fast_t *l_owner_tx_hash = dap_ledger_get_first_chain_tx_hash(l_ledger, l_cond_tx, l_tx_out_cond); - dap_chain_datum_tx_t *l_owner_tx = l_cond_tx; - if (l_owner_tx_hash){ - l_owner_tx = dap_ledger_tx_find_by_hash(l_ledger, l_owner_tx_hash); - DAP_DEL_Z(l_owner_tx_hash); - } + dap_hash_fast_t l_owner_tx_hash = dap_ledger_get_first_chain_tx_hash(l_ledger, l_cond_tx, l_tx_out_cond); + dap_chain_datum_tx_t *l_owner_tx = dap_hash_fast_is_blank(&l_owner_tx_hash) + ? l_cond_tx: + dap_ledger_tx_find_by_hash(l_ledger, &l_owner_tx_hash); if (!l_owner_tx) continue; - dap_chain_tx_sig_t *l_owner_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(l_owner_tx, NULL, TX_ITEM_TYPE_SIG, NULL); + dap_chain_tx_sig_t *l_owner_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(l_owner_tx, NULL, NULL, TX_ITEM_TYPE_SIG, NULL); dap_sign_t *l_owner_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_owner_tx_sig); if (!l_owner_sign) { @@ -5504,9 +5500,9 @@ int com_tx_cond_remove(int a_argc, char ** a_argv, void **reply) } // get final tx - dap_hash_fast_t *l_final_hash = dap_ledger_get_final_chain_tx_hash(l_ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY, l_hash); - dap_chain_datum_tx_t *l_final_tx = dap_ledger_tx_find_by_hash(l_ledger, l_final_hash); - if (!l_final_tx){ + dap_hash_fast_t l_final_hash = dap_ledger_get_final_chain_tx_hash(l_ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY, l_hash); + dap_chain_datum_tx_t *l_final_tx = dap_ledger_tx_find_by_hash(l_ledger, &l_final_hash); + if (!l_final_tx) { log_it(L_WARNING, "Only get final tx hash or tx is already used out."); continue; } @@ -5521,7 +5517,7 @@ int com_tx_cond_remove(int a_argc, char ** a_argv, void **reply) // add in_cond to new tx // add 'in' item to buy from conditional transaction - dap_chain_datum_tx_add_in_cond_item(&l_tx, l_final_hash, l_final_cond_idx, 0); + dap_chain_datum_tx_add_in_cond_item(&l_tx, &l_final_hash, l_final_cond_idx, 0); SUM_256_256(l_cond_value_sum, l_final_tx_out_cond->header.value, &l_cond_value_sum); } dap_list_free_full(l_hashes_list, NULL); @@ -5754,16 +5750,14 @@ int com_tx_cond_unspent_find(int a_argc, char **a_argv, void **reply) } // Check sign - dap_hash_fast_t *l_owner_tx_hash = dap_ledger_get_first_chain_tx_hash(l_ledger, l_data_tx->tx, l_out_cond); - dap_chain_datum_tx_t *l_owner_tx = l_tx; - if (l_owner_tx_hash){ - l_owner_tx = dap_ledger_tx_find_by_hash(l_ledger, l_owner_tx_hash); - DAP_DEL_Z(l_owner_tx_hash); - } + dap_hash_fast_t l_owner_tx_hash = dap_ledger_get_first_chain_tx_hash(l_ledger, l_data_tx->tx, l_out_cond); + dap_chain_datum_tx_t *l_owner_tx = dap_hash_fast_is_blank(&l_owner_tx_hash) + ? l_tx + : dap_ledger_tx_find_by_hash(l_ledger, &l_owner_tx_hash); if (!l_owner_tx) continue; - dap_chain_tx_sig_t *l_owner_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(l_owner_tx, NULL, TX_ITEM_TYPE_SIG, NULL); + dap_chain_tx_sig_t *l_owner_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(l_owner_tx, NULL, NULL, TX_ITEM_TYPE_SIG, NULL); dap_sign_t *l_owner_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_owner_tx_sig); @@ -8354,7 +8348,6 @@ static int s_sign_file(const char *a_filename, dap_sign_signer_file_t a_flags, c l_shift = 1; dap_list_t *l_std_list = NULL; - for (int i = 0; i < l_count_meta; i++) { if (l_shift | a_flags) { dap_tsd_t *l_item = s_alloc_metadata(a_filename, l_shift & a_flags); @@ -8365,23 +8358,24 @@ static int s_sign_file(const char *a_filename, dap_sign_signer_file_t a_flags, c l_shift <<= 1; } - dap_cert_t *l_cert = dap_cert_find_by_name(a_cert_name); - if (!l_cert) { - DAP_DELETE(l_buffer); - return 0; - } - if (!dap_hash_fast(l_buffer, l_file_content_size, a_hash)) { + dap_list_free_full(l_std_list, NULL); DAP_DELETE(l_buffer); return 0; } size_t l_full_size_for_sign; uint8_t *l_data = s_concat_hash_and_mimetypes(a_hash, l_std_list, &l_full_size_for_sign); + dap_list_free_full(l_std_list, NULL); if (!l_data) { DAP_DELETE(l_buffer); return 0; } + dap_cert_t *l_cert = dap_cert_find_by_name(a_cert_name); + if (!l_cert) { + DAP_DELETE(l_buffer); + return 0; + } *a_signed = dap_sign_create(l_cert->enc_key, l_data, l_full_size_for_sign, 0); if (*a_signed == NULL) { DAP_DELETE(l_buffer); diff --git a/modules/net/dap_chain_node_cli_cmd_tx.c b/modules/net/dap_chain_node_cli_cmd_tx.c index b28680716f06337311dc487d48782957194cb17c..ccd6b5fde52ff42cf7246287cc323393a6032aa1 100644 --- a/modules/net/dap_chain_node_cli_cmd_tx.c +++ b/modules/net/dap_chain_node_cli_cmd_tx.c @@ -101,34 +101,23 @@ bool s_dap_chain_datum_tx_out_data(dap_chain_datum_tx_t *a_datum, json_object_object_add(json_obj_out, "Token_description", l_description ? json_object_new_string(l_description) : json_object_new_null()); dap_chain_datum_dump_tx_json(a_datum, l_ticker, json_obj_out, a_hash_out_type, a_tx_hash, a_ledger->net->pub.id); - - dap_list_t *l_out_items = dap_chain_datum_tx_items_get(a_datum, TX_ITEM_TYPE_OUT_ALL, NULL); - int l_out_idx = 0; json_object* json_arr_items = json_object_new_array(); bool l_spent = false; - for (dap_list_t *l_item = l_out_items; l_item; l_item = l_item->next, ++l_out_idx) { - switch (*(dap_chain_tx_item_type_t*)l_item->data) { - case TX_ITEM_TYPE_OUT: - case TX_ITEM_TYPE_OUT_OLD: - case TX_ITEM_TYPE_OUT_EXT: - case TX_ITEM_TYPE_OUT_COND: { - dap_hash_fast_t l_spender = { }; - if (dap_ledger_tx_hash_is_used_out_item(a_ledger, a_tx_hash, l_out_idx, &l_spender)) { - char l_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE] = { '\0' }; - dap_hash_fast_to_str(&l_spender, l_hash_str, sizeof(l_hash_str)); - json_object * l_json_obj_datum = json_object_new_object(); - json_object_object_add(l_json_obj_datum, "OUT - ", json_object_new_int(l_out_idx)); - json_object_object_add(l_json_obj_datum, "is spent by tx", json_object_new_string(l_hash_str)); - json_object_array_add(json_arr_items, l_json_obj_datum); - l_spent = true; - } - break; - } - default: - break; + byte_t *l_item; size_t l_size; int i, l_out_idx = -1; + TX_ITEM_ITER_TX_TYPE(l_item, TX_ITEM_TYPE_OUT_ALL, l_size, i, a_datum) { + ++l_out_idx; + dap_hash_fast_t l_spender = { }; + if ( dap_ledger_tx_hash_is_used_out_item(a_ledger, a_tx_hash, l_out_idx, &l_spender) ) { + char l_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE] = { '\0' }; + dap_hash_fast_to_str(&l_spender, l_hash_str, sizeof(l_hash_str)); + json_object * l_json_obj_datum = json_object_new_object(); + json_object_object_add(l_json_obj_datum, "OUT - ", json_object_new_int(l_out_idx)); + json_object_object_add(l_json_obj_datum, "is spent by tx", json_object_new_string(l_hash_str)); + json_object_array_add(json_arr_items, l_json_obj_datum); + l_spent = true; } + break; } - dap_list_free(l_out_items); json_object_object_add(json_obj_out, "Spent OUTs", json_arr_items); json_object_object_add(json_obj_out, "all OUTs yet unspent", l_spent ? json_object_new_string("no") : json_object_new_string("yes")); return true; diff --git a/modules/net/include/dap_chain_ledger.h b/modules/net/include/dap_chain_ledger.h index b536f7572f8d4c928eec6138f2d95aef8a2fcedd..7aafc5faef5b37b81b9f379a766583e1dec3b50c 100644 --- a/modules/net/include/dap_chain_ledger.h +++ b/modules/net/include/dap_chain_ledger.h @@ -45,6 +45,7 @@ typedef struct dap_ledger { void *_internal; } dap_ledger_t; +typedef struct dap_ledger_tx_item dap_ledger_tx_item_t; /** * @brief Error codes for accepting a transaction to the ledger. */ @@ -203,7 +204,7 @@ typedef void (* dap_ledger_tx_add_notify_t)(void *a_arg, dap_ledger_t *a_ledger, typedef void (* dap_ledger_bridged_tx_notify_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, void *a_arg, dap_chan_ledger_notify_opcodes_t a_opcode); typedef bool (*dap_ledger_cache_tx_check_callback_t)(dap_ledger_t *a_ledger, dap_hash_fast_t *a_tx_hash); typedef struct dap_chain_net dap_chain_net_t; -typedef bool (*dap_chain_ledger_voting_callback_t)(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx, bool a_apply); +typedef int (*dap_chain_ledger_voting_callback_t)(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, bool a_apply); typedef bool (*dap_chain_ledger_voting_delete_callback_t)(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx); typedef bool (*dap_ledger_tag_check_callback_t)(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_datum_tx_item_groups_t *a_items_grp, dap_chain_tx_tag_action_type_t *a_action); @@ -384,10 +385,15 @@ uint256_t dap_ledger_calc_balance_full(dap_ledger_t *a_ledger, const dap_chain_a * * return transaction, or NULL if transaction not found in the cache */ -dap_chain_datum_tx_t *dap_ledger_tx_find_by_hash(dap_ledger_t *a_ledger, const dap_chain_hash_fast_t *a_tx_hash); -dap_chain_datum_tx_t *dap_ledger_tx_unspent_find_by_hash(dap_ledger_t *a_ledger, const dap_chain_hash_fast_t *a_tx_hash); -dap_hash_fast_t *dap_ledger_get_final_chain_tx_hash(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_cond_type, dap_chain_hash_fast_t *a_tx_hash); -dap_hash_fast_t *dap_ledger_get_first_chain_tx_hash(dap_ledger_t *a_ledger, dap_chain_datum_tx_t * a_tx, dap_chain_tx_out_cond_t *a_cond_out); +dap_chain_datum_tx_t *dap_ledger_tx_find_datum_by_hash( dap_ledger_t *a_ledger, const dap_chain_hash_fast_t *a_tx_hash, + dap_ledger_tx_item_t **a_item_out, bool a_unspent_only ); +#define dap_ledger_tx_find_by_hash(a_ledger, a_tx_hash) \ + dap_ledger_tx_find_datum_by_hash(a_ledger, a_tx_hash, NULL, false) +#define dap_ledger_tx_unspent_find_by_hash(a_ledger, a_tx_hash) \ + dap_ledger_tx_find_datum_by_hash(a_ledger, a_tx_hash, NULL, true) + +dap_hash_fast_t dap_ledger_get_final_chain_tx_hash(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_cond_type, dap_chain_hash_fast_t *a_tx_hash); +dap_hash_fast_t dap_ledger_get_first_chain_tx_hash(dap_ledger_t *a_ledger, dap_chain_datum_tx_t * a_tx, dap_chain_tx_out_cond_t *a_cond_out); // Get the transaction in the cache by the addr in out item dap_chain_datum_tx_t* dap_ledger_tx_find_by_addr(dap_ledger_t *a_ledger, const char * a_token, diff --git a/modules/net/srv/dap_chain_net_srv.c b/modules/net/srv/dap_chain_net_srv.c index de8618dbd6f60b4058fd820b101b887d4dcb7c83..88ca4c3c6e5f89a51e53659adb7875bd82ce1804 100644 --- a/modules/net/srv/dap_chain_net_srv.c +++ b/modules/net/srv/dap_chain_net_srv.c @@ -52,7 +52,6 @@ #include "dap_chain_net_tx.h" #include "dap_chain_net_srv_order.h" #include "dap_chain_net_srv_stream_session.h" -#include "dap_chain_net_tx.h" #include "dap_stream_ch_chain_net_srv.h" #include "dap_chain_cs_blocks.h" #ifdef DAP_MODULES_DYNAMIC @@ -667,7 +666,7 @@ static int s_fee_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_out_c DL_FOREACH(l_net->pub.chains, l_chain) { if (!l_chain->callback_block_find_by_tx_hash) continue; - dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(a_tx_in, 0, TX_ITEM_TYPE_IN_COND, 0); + dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t*)dap_chain_datum_tx_item_get(a_tx_in, NULL, NULL, TX_ITEM_TYPE_IN_COND, NULL); if (!l_tx_in_cond) return -1; if (dap_hash_fast_is_blank(&l_tx_in_cond->header.tx_prev_hash)) @@ -682,7 +681,7 @@ static int s_fee_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_out_c return -3; // TX sign is already verified, just compare pkeys - dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(a_tx_in, NULL, TX_ITEM_TYPE_SIG, NULL); + dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(a_tx_in, NULL, NULL, TX_ITEM_TYPE_SIG, NULL); dap_sign_t *l_sign_tx = dap_chain_datum_tx_item_sign_get_sig(l_tx_sig); return dap_sign_compare_pkeys(l_sign_block, l_sign_tx) ? 0 : -5; } @@ -703,15 +702,16 @@ static int s_pay_verificator_callback(dap_ledger_t * a_ledger, dap_chain_tx_out_ { if (a_owner) return 0; + size_t l_receipt_size = 0; dap_chain_datum_tx_receipt_t *l_receipt = (dap_chain_datum_tx_receipt_t *) - dap_chain_datum_tx_item_get(a_tx_in, NULL, TX_ITEM_TYPE_RECEIPT, NULL); + dap_chain_datum_tx_item_get(a_tx_in, NULL, NULL, TX_ITEM_TYPE_RECEIPT, &l_receipt_size); if (!l_receipt){ log_it(L_ERROR, "Can't find receipt."); return -1; } // Check provider sign - dap_sign_t *l_sign = dap_chain_datum_tx_receipt_sign_get(l_receipt, l_receipt->size, 0); + dap_sign_t *l_sign = dap_chain_datum_tx_receipt_sign_get(l_receipt, l_receipt_size, 0); if (!l_sign){ log_it(L_ERROR, "Can't get provider sign from receipt."); @@ -731,8 +731,8 @@ static int s_pay_verificator_callback(dap_ledger_t * a_ledger, dap_chain_tx_out_ return -4; } - int l_item_size = 0; - uint8_t* l_sig = dap_chain_datum_tx_item_get(a_tx_in, 0, TX_ITEM_TYPE_SIG, &l_item_size); + size_t l_item_size = 0; + uint8_t* l_sig = dap_chain_datum_tx_item_get(a_tx_in, NULL, NULL, TX_ITEM_TYPE_SIG, &l_item_size); if(!l_sig){ log_it(L_ERROR, "Can't get item with provider signature from tx"); return false; @@ -755,7 +755,7 @@ static int s_pay_verificator_callback(dap_ledger_t * a_ledger, dap_chain_tx_out_ } // Check client sign - l_sign = dap_chain_datum_tx_receipt_sign_get(l_receipt, l_receipt->size, 1); + l_sign = dap_chain_datum_tx_receipt_sign_get(l_receipt, l_receipt_size, 1); if (!l_sign){ log_it(L_ERROR, "Can't get client signature from receipt."); return -8; @@ -772,16 +772,16 @@ static int s_pay_verificator_callback(dap_ledger_t * a_ledger, dap_chain_tx_out_ } // Check price is less than maximum - dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(a_tx_in, 0, TX_ITEM_TYPE_IN_COND, 0); + dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t*)dap_chain_datum_tx_item_get(a_tx_in, NULL, NULL, TX_ITEM_TYPE_IN_COND, NULL); dap_chain_datum_tx_t *l_tx_prev = dap_ledger_tx_find_by_hash(a_ledger , &l_tx_in_cond->header.tx_prev_hash); dap_chain_tx_out_cond_t *l_prev_out_cond = dap_chain_datum_tx_out_cond_get(l_tx_prev, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY, NULL); uint256_t l_unit_price = {}; - if (l_receipt->receipt_info.units != 0){ - DIV_256(l_receipt->receipt_info.value_datoshi, GET_256_FROM_64(l_receipt->receipt_info.units), &l_unit_price); - } else { + if (!l_receipt->receipt_info.units) { + log_it(L_ERROR, "Receipt units can't be a zero"); return -11; } + DIV_256(l_receipt->receipt_info.value_datoshi, GET_256_FROM_64(l_receipt->receipt_info.units), &l_unit_price); if( !IS_ZERO_256(l_prev_out_cond->subtype.srv_pay.unit_price_max_datoshi) && compare256(l_unit_price, l_prev_out_cond->subtype.srv_pay.unit_price_max_datoshi) > 0){ @@ -791,42 +791,43 @@ static int s_pay_verificator_callback(dap_ledger_t * a_ledger, dap_chain_tx_out_ // check remainder on srv pay cond out is valid // find 'out' items - dap_list_t *l_list_out = dap_chain_datum_tx_items_get((dap_chain_datum_tx_t*) a_tx_in, TX_ITEM_TYPE_OUT_ALL, NULL); uint256_t l_value = l_receipt->receipt_info.value_datoshi; uint256_t l_cond_out_value = {}; - dap_chain_addr_t l_network_fee_addr = {}; + dap_chain_addr_t l_network_fee_addr = {}, l_out_addr = {}; dap_chain_net_tx_get_fee(a_ledger->net->pub.id, NULL, &l_network_fee_addr); - int l_item_idx = 0; - for (dap_list_t * l_list_tmp = l_list_out; l_list_tmp; l_list_tmp = dap_list_next(l_list_tmp), l_item_idx++) { - dap_chain_tx_item_type_t l_type = *(uint8_t *)l_list_tmp->data; - switch (l_type) { + byte_t *l_item; size_t l_size; int i, l_item_idx = -1; + TX_ITEM_ITER_TX_TYPE(l_item, TX_ITEM_TYPE_OUT_ALL, l_size, i, a_tx_in) { + ++l_item_idx; + switch (*l_item) { case TX_ITEM_TYPE_OUT: { // 256 - dap_chain_tx_out_t *l_tx_out = (dap_chain_tx_out_t *)l_list_tmp->data; - if (dap_chain_addr_compare(&l_tx_out->addr, &l_network_fee_addr)){ - SUM_256_256(l_value, l_tx_out->header.value, &l_value); + dap_chain_tx_out_t *l_tx_out = (dap_chain_tx_out_t*)l_item; + l_out_addr = l_tx_out->addr; + if (dap_chain_addr_compare(&l_out_addr, &l_network_fee_addr) && + SUM_256_256(l_value, l_tx_out->header.value, &l_value)) { + log_it(L_WARNING, "Integer overflow while sum of outs calculation"); + return -14; } } break; case TX_ITEM_TYPE_OUT_COND: { - dap_chain_tx_out_cond_t *l_tx_out = (dap_chain_tx_out_cond_t *)l_list_tmp->data; - if (l_tx_out->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE){ - SUM_256_256(l_value, l_tx_out->header.value, &l_value); + dap_chain_tx_out_cond_t *l_tx_out = (dap_chain_tx_out_cond_t*)l_item; + if (l_tx_out->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_FEE) { + if (SUM_256_256(l_value, l_tx_out->header.value, &l_value)) { + log_it(L_WARNING, "Integer overflow while sum of outs calculation"); + return -14; + } } else if (l_tx_out->header.subtype == DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY){ l_cond_out_value = l_tx_out->header.value; } } break; - default: {} + default: + break; } } - - - SUBTRACT_256_256(l_prev_out_cond->header.value, l_value, &l_value); - if (compare256(l_value, l_cond_out_value)){ - log_it(L_ERROR, "Value in tx out is invalid!"); - dap_list_free(l_list_out); - return -13; + if (SUBTRACT_256_256(l_prev_out_cond->header.value, l_value, &l_value)) { + log_it(L_WARNING, "Integer overflow while payback calculation"); + return -14; } - dap_list_free(l_list_out); - return 0; + return compare256(l_value, l_cond_out_value) ? log_it(L_ERROR, "Value in tx out is invalid!"), -13 : 0; } dap_chain_net_srv_price_t * dap_chain_net_srv_get_price_from_order(dap_chain_net_srv_t *a_srv, const char *a_config_section, dap_chain_hash_fast_t* a_order_hash){ diff --git a/modules/net/srv/dap_chain_net_srv_order.c b/modules/net/srv/dap_chain_net_srv_order.c index f8d627ae2faad2cd910eec6d3fd163caa875df86..9dd95fdcd9a700e4a42a94a599c65311b39b5693 100644 --- a/modules/net/srv/dap_chain_net_srv_order.c +++ b/modules/net/srv/dap_chain_net_srv_order.c @@ -81,13 +81,14 @@ void dap_chain_net_srv_order_deinit() } -size_t dap_chain_net_srv_order_get_size(const dap_chain_net_srv_order_t *a_order) +uint64_t dap_chain_net_srv_order_get_size(const dap_chain_net_srv_order_t *a_order) { if (!a_order || a_order->version != 3) return 0; dap_sign_t *l_sign = (dap_sign_t *)(a_order->ext_n_sign + a_order->ext_size); - size_t l_sign_size = l_sign->header.type.type == SIG_TYPE_NULL ? sizeof(dap_sign_type_t) : dap_sign_get_size(l_sign); - return sizeof(dap_chain_net_srv_order_t) + a_order->ext_size + l_sign_size; + uint64_t l_sign_size = l_sign->header.type.type == SIG_TYPE_NULL ? sizeof(dap_sign_type_t) : dap_sign_get_size(l_sign); + uint64_t l_size_without_sign = (uint64_t)sizeof(dap_chain_net_srv_order_t) + a_order->ext_size; + return l_size_without_sign + l_sign_size < l_size_without_sign ? 0 : l_size_without_sign + l_sign_size; } const dap_chain_net_srv_order_t *dap_chain_net_srv_order_check(const char *a_order_hash_str, const byte_t *a_order, size_t a_order_size) diff --git a/modules/net/srv/include/dap_chain_net_srv_order.h b/modules/net/srv/include/dap_chain_net_srv_order.h index 0898053d89a2700892c6a825dc3596455a925851..5d20752b1e153aadc26f97ae6b63f39c5423fb29 100644 --- a/modules/net/srv/include/dap_chain_net_srv_order.h +++ b/modules/net/srv/include/dap_chain_net_srv_order.h @@ -55,7 +55,7 @@ typedef struct dap_chain_net_srv_order int dap_chain_net_srv_order_init(); void dap_chain_net_srv_order_deinit(void); -size_t dap_chain_net_srv_order_get_size(const dap_chain_net_srv_order_t *a_order); +uint64_t dap_chain_net_srv_order_get_size(const dap_chain_net_srv_order_t *a_order); const dap_chain_net_srv_order_t *dap_chain_net_srv_order_check(const char *a_order_hash_str, const byte_t *a_order, size_t a_order_size); bool dap_chain_net_srv_order_set_continent_region(dap_chain_net_srv_order_t **a_order, uint8_t a_continent_num, const char *a_region); diff --git a/modules/service/datum/dap_chain_net_srv_datum.c b/modules/service/datum/dap_chain_net_srv_datum.c index 25e4862174418d897f28102f5242d24cb79eed64..be719c45455d3cece2f4751aa2700d83e4c8bdd5 100644 --- a/modules/service/datum/dap_chain_net_srv_datum.c +++ b/modules/service/datum/dap_chain_net_srv_datum.c @@ -254,9 +254,9 @@ void s_order_notficator(dap_store_obj_t *a_obj, void *a_arg) log_it(L_DEBUG, "Invalid tx cond datum hash"); return; } - int l_tx_out_cond_size; + size_t l_tx_out_cond_size = 0; dap_chain_tx_out_cond_t *l_cond_out = (dap_chain_tx_out_cond_t *) - dap_chain_datum_tx_item_get(l_tx_cond, NULL, TX_ITEM_TYPE_OUT_COND, &l_tx_out_cond_size); + dap_chain_datum_tx_item_get(l_tx_cond, NULL, NULL, TX_ITEM_TYPE_OUT_COND, &l_tx_out_cond_size); if (!l_cond_out || l_cond_out->header.subtype != DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY) { log_it(L_DEBUG, "Condition with required subtype SRV_PAY not found in requested tx"); } diff --git a/modules/service/stake/dap_chain_net_srv_stake_lock.c b/modules/service/stake/dap_chain_net_srv_stake_lock.c index f6f15e6b0637e3cdc022d98144aab3547e3664cf..53a216607537db1cbf3f2d8f92c4b1ea1852b6d6 100644 --- a/modules/service/stake/dap_chain_net_srv_stake_lock.c +++ b/modules/service/stake/dap_chain_net_srv_stake_lock.c @@ -572,7 +572,7 @@ static enum error_code s_cli_take(int a_argc, char **a_argv, int a_arg_index, da uint8_t *l_owner_pkey = dap_enc_key_serialize_pub_key(l_owner_key, &l_owner_pkey_size); dap_sign_t *l_owner_sign = NULL; dap_chain_tx_sig_t *l_tx_sign = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get( - l_cond_tx, NULL, TX_ITEM_TYPE_SIG, NULL); + l_cond_tx, NULL, NULL, TX_ITEM_TYPE_SIG, NULL); if (l_tx_sign) l_owner_sign = dap_chain_datum_tx_item_sign_get_sig(l_tx_sign); if (!l_owner_sign || l_owner_pkey_size != l_owner_sign->header.sign_pkey_size || @@ -1006,7 +1006,7 @@ static int s_stake_lock_callback_verificator(dap_ledger_t *a_ledger, dap_chain_t return -2; if (NULL == (l_tx_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get( - a_tx_in, 0, TX_ITEM_TYPE_IN_COND, 0))) + a_tx_in, NULL, NULL, TX_ITEM_TYPE_IN_COND, NULL))) return -3; if (dap_hash_fast_is_blank(&l_tx_in_cond->header.tx_prev_hash)) return false; @@ -1027,12 +1027,14 @@ static int s_stake_lock_callback_verificator(dap_ledger_t *a_ledger, dap_chain_t MULT_256_COIN(a_cond->header.value, l_emission_rate, &l_value_delegated) || IS_ZERO_256(l_value_delegated)) return -6; - - l_receipt = (dap_chain_datum_tx_receipt_t *)dap_chain_datum_tx_item_get(a_tx_in, 0, TX_ITEM_TYPE_RECEIPT, 0); + size_t l_receipt_size = 0; + l_receipt = (dap_chain_datum_tx_receipt_t *)dap_chain_datum_tx_item_get(a_tx_in, NULL, NULL, TX_ITEM_TYPE_RECEIPT, &l_receipt_size); if (l_receipt) { + if (dap_chain_datum_tx_receipt_check_size(l_receipt, l_receipt_size)) + return -13; if (!dap_chain_net_srv_uid_compare_scalar(l_receipt->receipt_info.srv_uid, DAP_CHAIN_NET_SRV_STAKE_LOCK_ID)) return -7; - if (!l_receipt->exts_size) + if (l_receipt->exts_size < sizeof(dap_hash_fast_t)) return -8; l_burning_tx_hash = *(dap_hash_fast_t*)l_receipt->exts_n_signs; if (dap_hash_fast_is_blank(&l_burning_tx_hash)) @@ -1050,45 +1052,43 @@ static int s_stake_lock_callback_verificator(dap_ledger_t *a_ledger, dap_chain_t } else l_burning_tx = a_tx_in; - dap_list_t *l_outs_list = dap_chain_datum_tx_items_get(l_burning_tx, TX_ITEM_TYPE_OUT_ALL, NULL); uint256_t l_blank_out_value = {}; - for (dap_list_t *it = l_outs_list; it; it = it->next) { - byte_t l_type = *(byte_t *)it->data; - if (l_type == TX_ITEM_TYPE_OUT) { - dap_chain_tx_out_t *l_out = it->data; - if (dap_chain_addr_is_blank(&l_out->addr)) { + dap_chain_addr_t l_out_addr = {}; + byte_t *l_item; size_t l_size; int i; + TX_ITEM_ITER_TX_TYPE(l_item, TX_ITEM_TYPE_OUT_ALL, l_size, i, l_burning_tx) { + if (*l_item == TX_ITEM_TYPE_OUT) { + dap_chain_tx_out_t *l_out = (dap_chain_tx_out_t*)l_item; + l_out_addr = l_out->addr; + if ( dap_chain_addr_is_blank(&l_out_addr) ) { l_blank_out_value = l_out->header.value; break; } - } else if (l_type == TX_ITEM_TYPE_OUT_EXT) { - dap_chain_tx_out_ext_t *l_out = it->data; - if (dap_chain_addr_is_blank(&l_out->addr) && - !strcmp(l_out->token, l_delegated_ticker_str)) { + } else if (*l_item == TX_ITEM_TYPE_OUT_EXT) { + dap_chain_tx_out_ext_t *l_out = (dap_chain_tx_out_ext_t*)l_item; + l_out_addr = l_out->addr; + if ( dap_chain_addr_is_blank(&l_out_addr) && !strcmp(l_out->token, l_delegated_ticker_str) ) { l_blank_out_value = l_out->header.value; break; } } } - dap_list_free(l_outs_list); if (IS_ZERO_256(l_blank_out_value)) { log_it(L_ERROR, "Can't find OUT with BLANK addr in burning TX"); return -11; } if (s_debug_more) { - char *str1 = dap_chain_balance_print(a_cond->header.value); - char *str2 = dap_chain_balance_print(l_value_delegated); - char *str3 = dap_chain_balance_print(l_blank_out_value); - log_it(L_INFO, "hold/take_value: %s", str1); - log_it(L_INFO, "delegated_value: %s", str2); - log_it(L_INFO, "burning_value: %s", str3); + char *str1 = dap_chain_balance_to_coins(a_cond->header.value); + char *str2 = dap_chain_balance_to_coins(l_value_delegated); + char *str3 = dap_chain_balance_to_coins(l_blank_out_value); + log_it(L_INFO, "hold/take_value: %s, delegated_value: %s, burning_value: %s", str1, str2, str3); DAP_DEL_MULTY(str1, str2, str3); } if (!EQUAL_256(l_blank_out_value, l_value_delegated)) { // !!! A terrible legacy crutch, TODO !!! - SUM_256_256(l_value_delegated, GET_256_FROM_64(10), &l_value_delegated); - if (!EQUAL_256(l_blank_out_value, l_value_delegated)) { + if (SUM_256_256(l_value_delegated, GET_256_FROM_64(10), &l_value_delegated) || + !EQUAL_256(l_blank_out_value, l_value_delegated)) { log_it(L_ERROR, "Burning and delegated value mismatch"); return -12; } diff --git a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c index e62cbb57759d3fc73cafe101dc5bc9ebaf547b03..494ae6cd9eab56720468c56ea16bdb808b801a69 100644 --- a/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c +++ b/modules/service/stake/dap_chain_net_srv_stake_pos_delegate.c @@ -236,41 +236,18 @@ static int s_stake_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_out return 0; } // It's a delegation conitional TX - dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(a_tx_in, 0, TX_ITEM_TYPE_IN_COND, 0); + dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(a_tx_in, NULL, NULL, TX_ITEM_TYPE_IN_COND, NULL); if (!l_tx_in_cond) { log_it(L_ERROR, "Conditional in item not found in checking tx"); return -6; } + // ATTENTION: It's correct only with single IN_COND TX item dap_hash_fast_t *l_prev_hash = &l_tx_in_cond->header.tx_prev_hash; if (dap_hash_fast_is_blank(l_prev_hash)) { log_it(L_ERROR, "Blank hash of prev tx in tx_in_cond"); return -7; } - dap_chain_datum_tx_t *l_prev_tx = dap_ledger_tx_find_by_hash(a_ledger, l_prev_hash); - if (!l_prev_tx) { - log_it(L_ERROR, "Previous tx not found for now but is found in ledger before"); - return -8; - } - bool l_owner = false; - dap_chain_tx_in_cond_t *l_tx_prev_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(l_prev_tx, 0, TX_ITEM_TYPE_IN_COND, 0); - if (!l_tx_prev_in_cond) - l_owner = a_owner; - else { - dap_hash_fast_t *l_owner_tx_hash = &l_tx_prev_in_cond->header.tx_prev_hash; - dap_chain_datum_tx_t *l_owner_tx = dap_ledger_tx_find_by_hash(a_ledger, l_owner_tx_hash); - dap_sign_t *l_owner_sign = dap_chain_datum_tx_get_sign(l_owner_tx, 0); - if (!l_owner_sign) { - log_it(L_ERROR, "Can't get owner sign"); - return -9; - } - dap_sign_t *l_taker_sign = dap_chain_datum_tx_get_sign(a_tx_in, 0); - if (!l_taker_sign) { - log_it(L_ERROR, "Can't get taker sign"); - return -10; - } - l_owner = dap_sign_compare_pkeys(l_taker_sign, l_owner_sign); - } - if (!l_owner) { + if (!a_owner) { log_it(L_WARNING, "Trying to spend conditional tx not by owner"); return -11; } @@ -689,7 +666,7 @@ static dap_chain_datum_tx_t *s_stake_tx_create(dap_chain_net_t * a_net, dap_enc_ int l_out_num = 0; dap_chain_datum_tx_out_cond_get(a_prev_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE, &l_out_num); // add 'in' item to buy from conditional transaction - if (dap_chain_datum_tx_add_in_cond_item(&l_tx, &l_prev_tx_hash, l_out_num, -1)) { + if (1 != dap_chain_datum_tx_add_in_cond_item(&l_tx, &l_prev_tx_hash, l_out_num, -1)) { log_it(L_ERROR, "Can't compose the transaction conditional input"); goto tx_fail; } @@ -984,7 +961,7 @@ static dap_chain_datum_tx_t *s_stake_tx_invalidate(dap_chain_net_t *a_net, dap_h log_it(L_WARNING, "Requested conditional transaction is already used out by %s", l_hash_str); return NULL; } - dap_chain_tx_in_cond_t *l_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(l_cond_tx, 0, TX_ITEM_TYPE_IN_COND, 0); + dap_chain_tx_in_cond_t *l_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(l_cond_tx, NULL, NULL, TX_ITEM_TYPE_IN_COND, NULL); if (l_in_cond) { l_cond_tx = dap_ledger_tx_find_by_hash(l_ledger, &l_in_cond->header.tx_prev_hash); if (!l_cond_tx) { @@ -993,7 +970,7 @@ static dap_chain_datum_tx_t *s_stake_tx_invalidate(dap_chain_net_t *a_net, dap_h } } // Get sign item - dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t*) dap_chain_datum_tx_item_get(l_cond_tx, NULL, + dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t*) dap_chain_datum_tx_item_get(l_cond_tx, NULL, NULL, TX_ITEM_TYPE_SIG, NULL); // Get sign from sign item dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig(l_tx_sig); diff --git a/modules/service/voting/dap_chain_net_srv_voting.c b/modules/service/voting/dap_chain_net_srv_voting.c index f4805ddea2990db7754c5cc1559c165cf35396fb..84b2689868d76f591cbbc8a314f57e4d8f11ce93 100644 --- a/modules/service/voting/dap_chain_net_srv_voting.c +++ b/modules/service/voting/dap_chain_net_srv_voting.c @@ -44,19 +44,13 @@ typedef struct dap_chain_net_voting_params_offsets{ dap_chain_datum_tx_t* voting_tx; size_t voting_question_offset; size_t voting_question_length; - dap_list_t* option_offsets_list; - size_t voting_expire_offset; - size_t votes_max_count_offset; - size_t delegate_key_required_offset; - size_t vote_changing_allowed_offset; + dap_list_t *option_offsets_list; + dap_time_t voting_expire; + uint64_t votes_max_count; + bool delegate_key_required; + bool vote_changing_allowed; } dap_chain_net_voting_params_offsets_t; - -typedef struct dap_chain_net_voting{ - dap_hash_fast_t hash_vote; - dap_chain_net_id_t net_id; -}dap_chain_net_voting_t; - typedef struct dap_chain_net_vote_option { size_t vote_option_offset; size_t vote_option_length; @@ -93,8 +87,8 @@ static pthread_rwlock_t s_votings_rwlock; static int s_datum_tx_voting_coin_check_cond_out(dap_chain_net_t *a_net, dap_hash_fast_t a_voting_hash, dap_hash_fast_t a_tx_cond_hash, int a_cond_out_idx); /// -1 error, 0 - unspent, 1 - spent -static int s_datum_tx_voting_coin_check_spent(dap_chain_net_t *a_net, dap_hash_fast_t a_voting_hash, dap_hash_fast_t a_tx_prev_hash, int a_out_idx); -static bool s_datum_tx_voting_verification_callback(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx_in, bool a_apply); +static int s_datum_tx_voting_coin_check_spent(dap_chain_net_t *a_net, dap_hash_fast_t a_voting_hash, dap_hash_fast_t a_tx_prev_hash, int a_out_idx, dap_hash_fast_t *a_pkey_hash); +static int s_datum_tx_voting_verification_callback(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx_in, dap_hash_fast_t *a_tx_hash, bool a_apply); static bool s_datum_tx_voting_verification_delete_callback(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx_in); static int s_cli_voting(int argc, char **argv, void **a_str_reply); @@ -178,319 +172,298 @@ uint64_t* dap_chain_net_voting_get_result(dap_ledger_t* a_ledger, dap_chain_hash } - -bool s_datum_tx_voting_verification_callback(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx_in, bool a_apply) +static int s_voting_verificator(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx_in, dap_hash_fast_t *a_tx_hash, bool a_apply) { - - dap_hash_fast_t l_hash = {}; - dap_hash_fast(a_tx_in, dap_chain_datum_tx_get_size(a_tx_in), &l_hash); - - if (a_type == TX_ITEM_TYPE_VOTING){ - if (!a_apply){ - dap_chain_net_votings_t * l_voting = NULL; - pthread_rwlock_rdlock(&s_votings_rwlock); - HASH_FIND(hh, s_votings, &l_hash, sizeof(dap_hash_fast_t), l_voting); - pthread_rwlock_unlock(&s_votings_rwlock); - if(l_voting && l_voting->net_id.uint64 == a_ledger->net->pub.id.uint64){ - char* l_hash_str = dap_hash_fast_to_str_new(&l_hash); - log_it(L_ERROR, "Voting with hash %s is already presents in net %s", l_hash_str, a_ledger->net->pub.name); - DAP_DEL_Z(l_hash_str); - return false; - } - - dap_list_t* l_tsd_list = dap_chain_datum_tx_items_get(a_tx_in, TX_ITEM_TYPE_TSD, NULL); - dap_list_t* l_temp = l_tsd_list; - size_t l_question_len = 0; - size_t l_options_count = 0; - while (l_temp){ - dap_tsd_t* l_tsd = (dap_tsd_t*)((dap_chain_tx_tsd_t*)l_temp->data)->tsd; - dap_chain_net_vote_option_t *l_vote_option = NULL; - switch(l_tsd->type){ - case VOTING_TSD_TYPE_QUESTION: - l_question_len = l_tsd->size; - break; - case VOTING_TSD_TYPE_ANSWER: - l_options_count++; - break; - default: - break; - } - l_temp = l_temp->next; - } - dap_list_free(l_tsd_list); - - if (!l_question_len || !l_options_count) - return false; - - return true; + if (!a_apply) { + dap_chain_net_votings_t * l_voting = NULL; + pthread_rwlock_rdlock(&s_votings_rwlock); + HASH_FIND(hh, s_votings, a_tx_hash, sizeof(dap_hash_fast_t), l_voting); + pthread_rwlock_unlock(&s_votings_rwlock); + if (l_voting && l_voting->net_id.uint64 == a_ledger->net->pub.id.uint64) { + log_it(L_DEBUG, "Voting with hash %s is already presents in net %s", dap_hash_fast_to_str_static(a_tx_hash), a_ledger->net->pub.name); + return -1; } - dap_chain_net_votings_t *l_item = DAP_NEW_Z_SIZE(dap_chain_net_votings_t, sizeof(dap_chain_net_votings_t)); - l_item->voting_hash = l_hash; - l_item->voting_params.voting_tx = a_tx_in; - l_item->net_id = a_ledger->net->pub.id; - pthread_rwlock_init(&l_item->s_tx_outs_rwlock, NULL); - dap_list_t* l_tsd_list = dap_chain_datum_tx_items_get(a_tx_in, TX_ITEM_TYPE_TSD, NULL); - dap_list_t* l_temp = l_tsd_list; - while (l_temp){ - dap_tsd_t* l_tsd = (dap_tsd_t*)((dap_chain_tx_tsd_t*)l_temp->data)->tsd; - dap_chain_net_vote_option_t *l_vote_option = NULL; - switch(l_tsd->type){ + size_t l_question_len = 0, l_options_count = 0; + for (dap_list_t *it = l_tsd_list; it; it = it->next) { + dap_tsd_t *l_tsd = (dap_tsd_t *)((dap_chain_tx_tsd_t *)it->data)->tsd; + switch (l_tsd->type) { case VOTING_TSD_TYPE_QUESTION: - l_item->voting_params.voting_question_offset = (size_t)(l_tsd->data - (byte_t*)l_item->voting_params.voting_tx); - l_item->voting_params.voting_question_length = l_tsd->size; + l_question_len = l_tsd->size; break; case VOTING_TSD_TYPE_ANSWER: - l_vote_option = DAP_NEW_Z(dap_chain_net_vote_option_t); - l_vote_option->vote_option_offset = (size_t)(l_tsd->data - (byte_t*)l_item->voting_params.voting_tx); - l_vote_option->vote_option_length = l_tsd->size; - l_item->voting_params.option_offsets_list = dap_list_append(l_item->voting_params.option_offsets_list, l_vote_option); - break; - case VOTING_TSD_TYPE_EXPIRE: - l_item->voting_params.voting_expire_offset = (size_t)(l_tsd->data - (byte_t*)l_item->voting_params.voting_tx); - break; - case VOTING_TSD_TYPE_MAX_VOTES_COUNT: - l_item->voting_params.votes_max_count_offset = (size_t)(l_tsd->data - (byte_t*)l_item->voting_params.voting_tx); - break; - case VOTING_TSD_TYPE_DELEGATED_KEY_REQUIRED: - l_item->voting_params.delegate_key_required_offset = (size_t)(l_tsd->data - (byte_t*)l_item->voting_params.voting_tx); - break; - case VOTING_TSD_TYPE_VOTE_CHANGING_ALLOWED: - l_item->voting_params.vote_changing_allowed_offset = (size_t)(l_tsd->data - (byte_t*)l_item->voting_params.voting_tx); + l_options_count++; break; default: break; } - l_temp = l_temp->next; } dap_list_free(l_tsd_list); - pthread_rwlock_wrlock(&s_votings_rwlock); - HASH_ADD(hh, s_votings, voting_hash, sizeof(dap_hash_fast_t), l_item); - pthread_rwlock_unlock(&s_votings_rwlock); - return true; - } else if (a_type == TX_ITEM_TYPE_VOTE){ - dap_chain_tx_vote_t *l_vote_tx_item = (dap_chain_tx_vote_t *)dap_chain_datum_tx_item_get(a_tx_in, 0, TX_ITEM_TYPE_VOTE, NULL); - if(!l_vote_tx_item){ - log_it(L_ERROR, "Can't find vote item"); - return false; + if (!l_question_len || !l_options_count) { + log_it(L_WARNING, "Voting with hash %s contain no question or answer options", dap_hash_fast_to_str_static(a_tx_hash)); + return -2; } - dap_chain_net_votings_t * l_voting = NULL; - pthread_rwlock_wrlock(&s_votings_rwlock); - HASH_FIND(hh, s_votings, &l_vote_tx_item->voting_hash, sizeof(dap_hash_fast_t), l_voting); - pthread_rwlock_unlock(&s_votings_rwlock); - if(!l_voting || l_voting->net_id.uint64 != a_ledger->net->pub.id.uint64) { - log_it(L_ERROR, "Can't find voting with hash %s in net %s", - dap_chain_hash_fast_to_str_static(&l_hash), a_ledger->net->pub.name); - return false; - } + return DAP_LEDGER_CHECK_OK; + } - if (!a_apply){ - if (l_vote_tx_item->answer_idx > dap_list_length(l_voting->voting_params.option_offsets_list)){ - log_it(L_ERROR, "Invalid vote option index."); - return false; + dap_chain_net_votings_t *l_item; + DAP_NEW_Z_SIZE_RET_VAL(l_item, dap_chain_net_votings_t, sizeof(dap_chain_net_votings_t), -DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY, NULL); + l_item->voting_hash = *a_tx_hash; + l_item->voting_params.voting_tx = a_tx_in; + l_item->net_id = a_ledger->net->pub.id; + pthread_rwlock_init(&l_item->s_tx_outs_rwlock, NULL); + + dap_list_t* l_tsd_list = dap_chain_datum_tx_items_get(a_tx_in, TX_ITEM_TYPE_TSD, NULL); + for (dap_list_t *it = l_tsd_list; it; it = it->next) { + dap_tsd_t* l_tsd = (dap_tsd_t *)((dap_chain_tx_tsd_t*)it->data)->tsd; + dap_chain_net_vote_option_t *l_vote_option = NULL; + switch(l_tsd->type){ + case VOTING_TSD_TYPE_QUESTION: + l_item->voting_params.voting_question_offset = (size_t)(l_tsd->data - (byte_t*)l_item->voting_params.voting_tx); + l_item->voting_params.voting_question_length = l_tsd->size; + break; + case VOTING_TSD_TYPE_ANSWER: + l_vote_option = DAP_NEW_Z(dap_chain_net_vote_option_t); + l_vote_option->vote_option_offset = (size_t)(l_tsd->data - (byte_t*)l_item->voting_params.voting_tx); + l_vote_option->vote_option_length = l_tsd->size; + l_item->voting_params.option_offsets_list = dap_list_append(l_item->voting_params.option_offsets_list, l_vote_option); + break; + case VOTING_TSD_TYPE_EXPIRE: + if (l_tsd->size != sizeof(dap_time_t)) { + log_it(L_WARNING, "Incorrect size %u of TSD section EXPIRE vot voting %s", l_tsd->size, dap_hash_fast_to_str_static(a_tx_hash)); + return -DAP_LEDGER_CHECK_INVALID_SIZE; } - - if(l_voting->voting_params.votes_max_count_offset){ - uint64_t l_votes_max_count = *(uint64_t*)((byte_t*)l_voting->voting_params.voting_tx + l_voting->voting_params.votes_max_count_offset); - if (l_votes_max_count && dap_list_length(l_voting->votes) >= l_votes_max_count){ - log_it(L_ERROR, "The required number of votes has been collected."); - return false; - } + l_item->voting_params.voting_expire = *(dap_time_t *)l_tsd->data; + break; + case VOTING_TSD_TYPE_MAX_VOTES_COUNT: + if (l_tsd->size != sizeof(uint64_t)) { + log_it(L_WARNING, "Incorrect size %u of TSD section MAX_VOTES_COUNT vot voting %s", l_tsd->size, dap_hash_fast_to_str_static(a_tx_hash)); + return -DAP_LEDGER_CHECK_INVALID_SIZE; } - - if(l_voting->voting_params.voting_expire_offset){ - dap_time_t l_expire = *(dap_time_t*)((byte_t*)l_voting->voting_params.voting_tx + l_voting->voting_params.voting_expire_offset); - if( l_expire && l_expire <= a_tx_in->header.ts_created){ - log_it(L_ERROR, "The voting has been expired."); - return false; - } + l_item->voting_params.votes_max_count = *(uint64_t *)l_tsd->data; + break; + case VOTING_TSD_TYPE_DELEGATED_KEY_REQUIRED: + if (l_tsd->size != sizeof(byte_t)) { + log_it(L_WARNING, "Incorrect size %u of TSD section DELEGATED_KEY_REQUIRED vot voting %s", l_tsd->size, dap_hash_fast_to_str_static(a_tx_hash)); + return -DAP_LEDGER_CHECK_INVALID_SIZE; + } + l_item->voting_params.delegate_key_required = *(byte_t *)l_tsd->data; + break; + case VOTING_TSD_TYPE_VOTE_CHANGING_ALLOWED: + if (l_tsd->size != sizeof(byte_t)) { + log_it(L_WARNING, "Incorrect size %u of TSD section VOTE_CHANGING_ALLOWED vot voting %s", l_tsd->size, dap_hash_fast_to_str_static(a_tx_hash)); + return -DAP_LEDGER_CHECK_INVALID_SIZE; } + l_item->voting_params.vote_changing_allowed = *(byte_t *)l_tsd->data; + break; + default: + break; + } + } + dap_list_free(l_tsd_list); - dap_hash_fast_t pkey_hash = {}; - dap_chain_tx_sig_t *l_vote_sig = NULL; - int l_item_cnt = 0; - dap_list_t* l_signs_list = NULL; - l_signs_list = dap_chain_datum_tx_items_get(a_tx_in, TX_ITEM_TYPE_SIG, &l_item_cnt); + pthread_rwlock_wrlock(&s_votings_rwlock); + HASH_ADD(hh, s_votings, voting_hash, sizeof(dap_hash_fast_t), l_item); + pthread_rwlock_unlock(&s_votings_rwlock); + return DAP_LEDGER_CHECK_OK; +} - if(!l_signs_list){ - log_it(L_ERROR, "Can't get sign."); - return false; - } - l_vote_sig = (dap_chain_tx_sig_t *)(dap_list_last(l_signs_list)->data); - dap_sign_get_pkey_hash((dap_sign_t*)l_vote_sig->sig, &pkey_hash); - if (l_voting->voting_params.delegate_key_required_offset && - *(bool*)((byte_t*)l_voting->voting_params.voting_tx + l_voting->voting_params.delegate_key_required_offset)){ - if (!dap_chain_net_srv_stake_check_pkey_hash(a_ledger->net->pub.id, &pkey_hash)){ - log_it(L_ERROR, "The voting required a delegated key."); - dap_list_free(l_signs_list); - return false; - } - } +static int s_vote_verificator(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx_in, dap_hash_fast_t *a_tx_hash, bool a_apply) +{ + dap_chain_tx_vote_t *l_vote_tx_item = (dap_chain_tx_vote_t*)dap_chain_datum_tx_item_get(a_tx_in, NULL, NULL, TX_ITEM_TYPE_VOTE, NULL); + if (!l_vote_tx_item) { + log_it(L_ERROR, "Can't find vote item for tx %s", dap_chain_hash_fast_to_str_static(a_tx_hash)); + return -4; + } - dap_list_t *l_temp = l_voting->votes; - while(l_temp){ - if (dap_hash_fast_compare(&((dap_chain_net_vote_t *)l_temp->data)->pkey_hash, &pkey_hash)){ - if(l_voting->voting_params.vote_changing_allowed_offset && - *(bool*)((byte_t*)l_voting->voting_params.voting_tx + l_voting->voting_params.vote_changing_allowed_offset)){ - //delete conditional outputs - dap_chain_datum_tx_t *l_old_tx = dap_ledger_tx_find_by_hash(a_ledger, &((dap_chain_net_vote_t *)l_temp->data)->vote_hash); - - dap_list_t* l_tsd_list = dap_chain_datum_tx_items_get(l_old_tx, TX_ITEM_TYPE_TSD, NULL); - dap_list_t* l_tsd_temp = l_tsd_list; - while (l_tsd_temp){ - dap_tsd_t* l_tsd = (dap_tsd_t*)((dap_chain_tx_tsd_t*)l_tsd_temp->data)->tsd; - dap_hash_fast_t l_hash = ((dap_chain_tx_voting_tx_cond_t*)l_tsd->data)->tx_hash; - if(l_tsd->type == VOTING_TSD_TYPE_VOTE_TX_COND){ - dap_chain_net_voting_cond_outs_t *l_tx_outs = NULL; - pthread_rwlock_wrlock(&l_voting->s_tx_outs_rwlock); - HASH_FIND(hh, l_voting->voting_spent_cond_outs, &l_hash, sizeof(dap_hash_fast_t), l_tx_outs); - if(l_tx_outs) - HASH_DELETE(hh, l_voting->voting_spent_cond_outs, l_tx_outs); - pthread_rwlock_unlock(&l_voting->s_tx_outs_rwlock); - } - l_tsd_temp = l_tsd_temp->next; - } - dap_list_free(l_tsd_list); - - - //delete vote - l_voting->votes = dap_list_remove(l_voting->votes, l_temp->data); - break; - } else { - log_it(L_ERROR, "The voting don't allow change your vote."); - return false; - } - } - l_temp = l_temp->next; - } - dap_list_free(l_signs_list); - } + dap_chain_net_votings_t *l_voting = NULL; + pthread_rwlock_wrlock(&s_votings_rwlock); + HASH_FIND(hh, s_votings, &l_vote_tx_item->voting_hash, sizeof(dap_hash_fast_t), l_voting); + pthread_rwlock_unlock(&s_votings_rwlock); + if (!l_voting || l_voting->net_id.uint64 != a_ledger->net->pub.id.uint64) { + log_it(L_ERROR, "Can't find voting with hash %s in net %s", + dap_chain_hash_fast_to_str_static(&l_vote_tx_item->voting_hash), a_ledger->net->pub.name); + return -5; + } - uint256_t l_weight = {}; + dap_hash_fast_t pkey_hash = {}; + int l_item_cnt = 0; + dap_list_t *l_signs_list = dap_chain_datum_tx_items_get(a_tx_in, TX_ITEM_TYPE_SIG, &l_item_cnt); - // check out conds - dap_list_t* l_tsd_list = dap_chain_datum_tx_items_get(a_tx_in, TX_ITEM_TYPE_TSD, NULL); - dap_list_t* l_tsd_temp = l_tsd_list; - while (l_tsd_temp){ - dap_tsd_t* l_tsd = (dap_tsd_t*)((dap_chain_tx_tsd_t*)l_tsd_temp->data)->tsd; - dap_hash_fast_t l_hash = ((dap_chain_tx_voting_tx_cond_t*)l_tsd->data)->tx_hash; - int l_out_idx = ((dap_chain_tx_voting_tx_cond_t*)l_tsd->data)->out_idx; - if(l_tsd->type == VOTING_TSD_TYPE_VOTE_TX_COND){ - if (s_datum_tx_voting_coin_check_cond_out(a_ledger->net, l_vote_tx_item->voting_hash, - l_hash, l_out_idx) != 0){ - l_tsd_temp = l_tsd_temp->next; - continue; - } - dap_chain_datum_tx_t *l_tx_prev_temp = dap_ledger_tx_find_by_hash(a_ledger, &l_hash); - dap_chain_tx_out_cond_t *l_prev_out = (dap_chain_tx_out_cond_t*)dap_chain_datum_tx_item_get(l_tx_prev_temp, &l_out_idx, TX_ITEM_TYPE_OUT_COND, NULL); - if(!l_prev_out || l_prev_out->header.subtype != DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK){ - l_tsd_temp = l_tsd_temp->next; - continue; + if (!l_signs_list) { + log_it(L_WARNING, "Can't get signs from tx %s", dap_chain_hash_fast_to_str_static(a_tx_hash)); + return -9; + } + dap_chain_tx_sig_t *l_vote_sig = (dap_chain_tx_sig_t *)(dap_list_last(l_signs_list)->data); + dap_sign_get_pkey_hash((dap_sign_t*)l_vote_sig->sig, &pkey_hash); + dap_list_free(l_signs_list); + + if (!a_apply) { + if (l_vote_tx_item->answer_idx > dap_list_length(l_voting->voting_params.option_offsets_list)) { + log_it(L_WARNING, "Invalid vote option index %" DAP_UINT64_FORMAT_U " for vote tx %s", + l_vote_tx_item->answer_idx, dap_chain_hash_fast_to_str_static(a_tx_hash)); + return -6; + } + if (l_voting->voting_params.votes_max_count && dap_list_length(l_voting->votes) >= l_voting->voting_params.votes_max_count){ + log_it(L_WARNING, "The required number of votes has been collected for voting %s", dap_chain_hash_fast_to_str_static(&l_voting->voting_hash)); + return -7; + } + if (l_voting->voting_params.voting_expire && l_voting->voting_params.voting_expire <= a_tx_in->header.ts_created) { + log_it(L_WARNING, "The voting %s has been expired", dap_chain_hash_fast_to_str_static(&l_voting->voting_hash)); + return -8; + } + + if (l_voting->voting_params.delegate_key_required && + !dap_chain_net_srv_stake_check_pkey_hash(a_ledger->net->pub.id, &pkey_hash)){ + log_it(L_WARNING, "Voting %s required a delegated key", dap_chain_hash_fast_to_str_static(&l_voting->voting_hash)); + return -10; + } + + for (dap_list_t *it = l_voting->votes; it; it = it->next) { + if (dap_hash_fast_compare(&((dap_chain_net_vote_t *)it->data)->pkey_hash, &pkey_hash)) { + dap_hash_fast_t *l_vote_hash = &((dap_chain_net_vote_t *)it->data)->vote_hash; + if (!l_voting->voting_params.vote_changing_allowed) { + char l_vote_hash_str[DAP_HASH_FAST_STR_SIZE]; + dap_hash_fast_to_str(l_vote_hash, l_vote_hash_str, DAP_HASH_FAST_STR_SIZE); + log_it(L_WARNING, "The voting %s don't allow change your vote %s", + dap_hash_fast_to_str_static(&l_voting->voting_hash), l_vote_hash_str); + return -11; } - SUM_256_256(l_weight, l_prev_out->header.value, &l_weight); - - dap_chain_net_voting_cond_outs_t *l_item = DAP_NEW_Z_SIZE(dap_chain_net_voting_cond_outs_t, sizeof(dap_chain_net_voting_cond_outs_t)); - l_item->tx_hash = l_hash; - l_item->out_idx = l_out_idx; - pthread_rwlock_wrlock(&l_voting->s_tx_outs_rwlock); - HASH_ADD(hh, l_voting->voting_spent_cond_outs, tx_hash, sizeof(dap_hash_fast_t), l_item); - pthread_rwlock_unlock(&l_voting->s_tx_outs_rwlock); + break; } - l_tsd_temp = l_tsd_temp->next; } - dap_list_free(l_tsd_list); - // check inputs - dap_list_t *l_ins_list = dap_chain_datum_tx_items_get(a_tx_in, TX_ITEM_TYPE_IN, NULL); - if (!l_ins_list){ - log_it(L_ERROR, "Can't get inputs from tx"); - return -1; - } - dap_list_t *l_in_temp = l_ins_list; - while(l_in_temp){ - dap_chain_tx_in_t *l_tx_in = (dap_chain_tx_in_t *)l_in_temp->data; - if (s_datum_tx_voting_coin_check_spent(a_ledger->net, l_vote_tx_item->voting_hash, l_tx_in->header.tx_prev_hash, l_tx_in->header.tx_out_prev_idx) == 0){ - dap_chain_datum_tx_t *l_tx_prev_temp = dap_ledger_tx_find_by_hash(a_ledger, &l_tx_in->header.tx_prev_hash); - int l_out_prev_idx = (int)l_tx_in->header.tx_out_prev_idx; - dap_chain_tx_out_t *l_prev_out_union = (dap_chain_tx_out_t *)dap_chain_datum_tx_out_get_by_out_idx(l_tx_prev_temp, l_out_prev_idx); - if (!l_prev_out_union){ - l_in_temp = l_in_temp->next; - continue; - } + } - switch (l_prev_out_union->header.type) { - case TX_ITEM_TYPE_OUT: - case TX_ITEM_TYPE_OUT_EXT: - SUM_256_256(l_weight, l_prev_out_union->header.value, &l_weight); - } + uint256_t l_weight = {}; + + // check out conds + dap_list_t *l_tsd_list = dap_chain_datum_tx_items_get(a_tx_in, TX_ITEM_TYPE_TSD, NULL); + for (dap_list_t *it = l_tsd_list; it; it = it->next) { + dap_tsd_t *l_tsd = (dap_tsd_t *)((dap_chain_tx_tsd_t*)it->data)->tsd; + dap_hash_fast_t l_hash = ((dap_chain_tx_voting_tx_cond_t*)l_tsd->data)->tx_hash; + int l_out_idx = ((dap_chain_tx_voting_tx_cond_t*)l_tsd->data)->out_idx; + if (l_tsd->type == VOTING_TSD_TYPE_VOTE_TX_COND) { + if (s_datum_tx_voting_coin_check_cond_out(a_ledger->net, l_vote_tx_item->voting_hash, l_hash, l_out_idx)) + continue; + dap_chain_datum_tx_t *l_tx_prev_temp = dap_ledger_tx_find_by_hash(a_ledger, &l_hash); + dap_chain_tx_out_cond_t *l_prev_out = (dap_chain_tx_out_cond_t*)dap_chain_datum_tx_item_get(l_tx_prev_temp, &l_out_idx, NULL, TX_ITEM_TYPE_OUT_COND, NULL); + if (!l_prev_out || l_prev_out->header.subtype != DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK) + continue; + if (SUM_256_256(l_weight, l_prev_out->header.value, &l_weight)) { + log_it(L_WARNING, "Integer overflow while parsing vote tx %s", dap_chain_hash_fast_to_str_static(a_tx_hash)); + return -DAP_LEDGER_CHECK_INTEGER_OVERFLOW; } - l_in_temp = l_in_temp->next; - } - dap_list_free(l_ins_list); - if (IS_ZERO_256(l_weight)){ - log_it(L_ERROR, "No unspent coins"); - return false; + dap_chain_net_voting_cond_outs_t *l_item; + DAP_NEW_Z_SIZE_RET_VAL(l_item, dap_chain_net_voting_cond_outs_t, sizeof(dap_chain_net_voting_cond_outs_t), -DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY, NULL); + l_item->tx_hash = l_hash; + l_item->out_idx = l_out_idx; + pthread_rwlock_wrlock(&l_voting->s_tx_outs_rwlock); + HASH_ADD(hh, l_voting->voting_spent_cond_outs, tx_hash, sizeof(dap_hash_fast_t), l_item); + pthread_rwlock_unlock(&l_voting->s_tx_outs_rwlock); } + } + dap_list_free(l_tsd_list); + // check inputs + dap_list_t *l_ins_list = dap_chain_datum_tx_items_get(a_tx_in, TX_ITEM_TYPE_IN, NULL); + if (!l_ins_list) { + log_it(L_WARNING, "Can't get inputs from vote tx %s", dap_chain_hash_fast_to_str_static(a_tx_hash)); + return -12; + } + for (dap_list_t *it = l_ins_list; it; it = it->next) { + dap_chain_tx_in_t *l_tx_in = (dap_chain_tx_in_t *)it->data; + if (!s_datum_tx_voting_coin_check_spent(a_ledger->net, l_vote_tx_item->voting_hash, + l_tx_in->header.tx_prev_hash, l_tx_in->header.tx_out_prev_idx, &pkey_hash)) { + dap_chain_datum_tx_t *l_tx_prev_temp = dap_ledger_tx_find_by_hash(a_ledger, &l_tx_in->header.tx_prev_hash); + dap_chain_tx_out_t *l_prev_out_union = (dap_chain_tx_out_t *)dap_chain_datum_tx_out_get_by_out_idx(l_tx_prev_temp, l_tx_in->header.tx_out_prev_idx); + if (!l_prev_out_union) + continue; + if ((l_prev_out_union->header.type == TX_ITEM_TYPE_OUT || l_prev_out_union->header.type == TX_ITEM_TYPE_OUT_EXT) && + SUM_256_256(l_weight, l_prev_out_union->header.value, &l_weight)) { + log_it(L_WARNING, "Integer overflow while parsing vote tx %s", dap_chain_hash_fast_to_str_static(a_tx_hash)); + return -DAP_LEDGER_CHECK_INTEGER_OVERFLOW; + } + } + } + dap_list_free(l_ins_list); + if (IS_ZERO_256(l_weight)) { + log_it(L_ERROR, "No unspent coins found in vote tx %s", dap_chain_hash_fast_to_str_static(a_tx_hash)); + return -13; + } - if (a_apply){ - dap_hash_fast_t pkey_hash = {}; - dap_chain_tx_sig_t *l_vote_sig = NULL; - int l_item_cnt = 0; - dap_list_t* l_signs_list = NULL; - l_signs_list = dap_chain_datum_tx_items_get(a_tx_in, TX_ITEM_TYPE_SIG, &l_item_cnt); - - if(!l_signs_list){ - log_it(L_ERROR, "Can't get sign."); - return false; - } - l_vote_sig = (dap_chain_tx_sig_t *)(dap_list_last(l_signs_list)->data); - dap_sign_get_pkey_hash((dap_sign_t*)l_vote_sig->sig, &pkey_hash); - - dap_chain_net_vote_t *l_vote_item = DAP_NEW_Z(dap_chain_net_vote_t); - if (!l_vote_item){ - log_it(L_CRITICAL, "Memory allocate_error!"); - dap_list_free(l_signs_list); - return false; - } - l_vote_item->vote_hash = l_hash; - l_vote_item->pkey_hash = pkey_hash; - l_vote_item->answer_idx = l_vote_tx_item->answer_idx; - l_vote_item->weight = l_weight; - - dap_list_t *l_temp = l_voting->votes; - while(l_temp){ - if (dap_hash_fast_compare(&((dap_chain_net_vote_t *)l_temp->data)->pkey_hash, &pkey_hash)){ - if(l_voting->voting_params.vote_changing_allowed_offset && - *(bool*)((byte_t*)l_voting->voting_params.voting_tx + l_voting->voting_params.vote_changing_allowed_offset)){ - - l_voting->votes = dap_list_append(l_voting->votes, l_vote_item); - - log_it(L_ERROR, "Vote is changed."); - dap_list_free(l_signs_list); - return true; - } else { - log_it(L_ERROR, "The voting don't allow change your vote."); - dap_list_free(l_signs_list); - DAP_DELETE(l_vote_item); - return false; + if (a_apply) { + + dap_chain_net_vote_t *l_vote_item; + DAP_NEW_Z_RET_VAL(l_vote_item, dap_chain_net_vote_t, -DAP_LEDGER_CHECK_NOT_ENOUGH_MEMORY, NULL); + l_vote_item->vote_hash = *a_tx_hash; + l_vote_item->pkey_hash = pkey_hash; + l_vote_item->answer_idx = l_vote_tx_item->answer_idx; + l_vote_item->weight = l_weight; + + // cycle is safe cause return after link deletion + for (dap_list_t *it = l_voting->votes; it; it = it->next) { + if (dap_hash_fast_compare(&((dap_chain_net_vote_t *)it->data)->pkey_hash, &pkey_hash)){ + if (!l_voting->voting_params.vote_changing_allowed) { + char l_vote_hash_str[DAP_HASH_FAST_STR_SIZE]; + dap_hash_fast_to_str(a_tx_hash, l_vote_hash_str, DAP_HASH_FAST_STR_SIZE); + log_it(L_WARNING, "The voting %s don't allow change your vote %s", + dap_hash_fast_to_str_static(&l_voting->voting_hash), l_vote_hash_str); + DAP_DELETE(l_vote_item); + return -11; + } + dap_hash_fast_t *l_vote_hash = &((dap_chain_net_vote_t *)it->data)->vote_hash; + //delete conditional outputs + dap_chain_datum_tx_t *l_old_tx = dap_ledger_tx_find_by_hash(a_ledger, l_vote_hash); + if (!l_old_tx) { + char l_vote_hash_str[DAP_HASH_FAST_STR_SIZE]; + dap_hash_fast_to_str(l_vote_hash, l_vote_hash_str, DAP_HASH_FAST_STR_SIZE); + log_it(L_ERROR, "Can't find old vote %s of voting %s in ledger", + l_vote_hash_str, dap_hash_fast_to_str_static(&l_voting->voting_hash)); + } + dap_list_t* l_tsd_list = dap_chain_datum_tx_items_get(l_old_tx, TX_ITEM_TYPE_TSD, NULL); + for (dap_list_t *it_tsd = l_tsd_list; it_tsd; it_tsd = it_tsd->next) { + dap_tsd_t* l_tsd = (dap_tsd_t*)((dap_chain_tx_tsd_t*)it_tsd->data)->tsd; + dap_hash_fast_t *l_hash = &((dap_chain_tx_voting_tx_cond_t*)l_tsd->data)->tx_hash; + if (l_tsd->type == VOTING_TSD_TYPE_VOTE_TX_COND) { + dap_chain_net_voting_cond_outs_t *l_tx_outs = NULL; + pthread_rwlock_wrlock(&l_voting->s_tx_outs_rwlock); + HASH_FIND(hh, l_voting->voting_spent_cond_outs, l_hash, sizeof(dap_hash_fast_t), l_tx_outs); + if(l_tx_outs) + HASH_DELETE(hh, l_voting->voting_spent_cond_outs, l_tx_outs); + pthread_rwlock_unlock(&l_voting->s_tx_outs_rwlock); } } - l_temp = l_temp->next; + dap_list_free(l_tsd_list); + // change vote & move it to the end of list + l_voting->votes = dap_list_remove_link(l_voting->votes, it); + DAP_DELETE(it->data); + l_voting->votes = dap_list_append(l_voting->votes, l_vote_item); + char l_vote_hash_str[DAP_HASH_FAST_STR_SIZE]; + dap_hash_fast_to_str(&((dap_chain_net_vote_t *)it->data)->vote_hash, l_vote_hash_str, DAP_HASH_FAST_STR_SIZE); + log_it(L_INFO, "Vote %s of voting %s has been changed", l_vote_hash_str, dap_hash_fast_to_str_static(&l_voting->voting_hash)); + return DAP_LEDGER_CHECK_OK; } - dap_list_free(l_signs_list); - log_it(L_INFO, "Vote is accepted."); - l_voting->votes = dap_list_append(l_voting->votes, l_vote_item); } - return true; - } else { - log_it(L_ERROR, "Item is not supported in votings."); + l_voting->votes = dap_list_append(l_voting->votes, l_vote_item); + char l_vote_hash_str[DAP_HASH_FAST_STR_SIZE]; + dap_hash_fast_to_str(a_tx_hash, l_vote_hash_str, DAP_HASH_FAST_STR_SIZE); + log_it(L_INFO, "Vote %s of voting %s has been accepted", l_vote_hash_str, dap_hash_fast_to_str_static(&l_voting->voting_hash)); } + return DAP_LEDGER_CHECK_OK; +} - return false; +int s_datum_tx_voting_verification_callback(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx_in, dap_hash_fast_t *a_tx_hash, bool a_apply) +{ + if (a_type == TX_ITEM_TYPE_VOTING) + return s_voting_verificator(a_ledger, a_type, a_tx_in, a_tx_hash, a_apply); + if (a_type == TX_ITEM_TYPE_VOTE) + return s_vote_verificator(a_ledger, a_type, a_tx_in, a_tx_hash, a_apply); + log_it(L_ERROR, "Item %d is not supported in votings", a_type); + return -3; } static bool s_datum_tx_voting_verification_delete_callback(dap_ledger_t *a_ledger, dap_chain_tx_item_type_t a_type, dap_chain_datum_tx_t *a_tx_in) @@ -532,7 +505,7 @@ static bool s_datum_tx_voting_verification_delete_callback(dap_ledger_t *a_ledge return true; } else if (a_type == TX_ITEM_TYPE_VOTE){ - dap_chain_tx_vote_t *l_vote_tx_item = (dap_chain_tx_vote_t *)dap_chain_datum_tx_item_get(a_tx_in, 0, TX_ITEM_TYPE_VOTE, NULL); + dap_chain_tx_vote_t *l_vote_tx_item = (dap_chain_tx_vote_t *)dap_chain_datum_tx_item_get(a_tx_in, NULL, NULL, TX_ITEM_TYPE_VOTE, NULL); if(!l_vote_tx_item){ log_it(L_ERROR, "Can't find vote item"); return false; @@ -549,14 +522,13 @@ static bool s_datum_tx_voting_verification_delete_callback(dap_ledger_t *a_ledge return false; } - dap_list_t *l_vote = l_voting->votes; - while(l_vote){ + for (dap_list_t *l_vote = l_voting->votes; l_vote; l_vote = l_vote->next) { if (dap_hash_fast_compare(&((dap_chain_net_vote_t *)l_vote->data)->vote_hash, &l_hash)){ // Delete vote + DAP_DELETE(l_vote->data); l_voting->votes = dap_list_remove(l_voting->votes, l_vote->data); break; } - l_vote = l_vote->next; } } @@ -1006,20 +978,18 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply) l_voting->voting_params.voting_question_length); dap_string_append(l_str_out, "\n\n"); - if(l_voting->voting_params.voting_expire_offset){ + if (l_voting->voting_params.voting_expire) { char l_tmp_buf[DAP_TIME_STR_SIZE]; - dap_time_t l_expire = *(dap_time_t*)((byte_t*)l_voting->voting_params.voting_tx + l_voting->voting_params.voting_expire_offset); - dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, l_expire); - dap_string_append_printf(l_str_out, "\t Voting expire: %s \n", l_tmp_buf); + dap_time_to_str_rfc822(l_tmp_buf, DAP_TIME_STR_SIZE, l_voting->voting_params.voting_expire); + dap_string_append_printf(l_str_out, "\t Voting expire: %s\n", l_tmp_buf); dap_string_truncate(l_str_out, l_str_out->len - 1); - dap_string_append_printf(l_str_out, " (%s)\n", l_expire > dap_time_now() ? "active" : "expired"); + dap_string_append_printf(l_str_out, " (%s)\n", l_voting->voting_params.voting_expire > dap_time_now() ? "active" : "expired"); } - if (l_voting->voting_params.votes_max_count_offset){ - uint64_t l_max_count = *(uint64_t*)((byte_t*)l_voting->voting_params.voting_tx + l_voting->voting_params.votes_max_count_offset); - dap_string_append_printf(l_str_out, "\t Votes max count: %"DAP_UINT64_FORMAT_U" (%s)\n", l_max_count, l_max_count <= l_votes_count ? "closed" : "active"); - } - dap_string_append_printf(l_str_out, "\t Changing vote is %s available.\n", l_voting->voting_params.vote_changing_allowed_offset ? "" : "not"); - dap_string_append_printf(l_str_out, "\t A delegated key is%s required to participate in voting. \n", l_voting->voting_params.delegate_key_required_offset ? "" : " not"); + if (l_voting->voting_params.votes_max_count) + dap_string_append_printf(l_str_out, "\t Votes max count: %"DAP_UINT64_FORMAT_U" (%s)\n", l_voting->voting_params.votes_max_count, + l_voting->voting_params.votes_max_count <= l_votes_count ? "closed" : "active"); + dap_string_append_printf(l_str_out, "\t Changing vote is %s available.\n", l_voting->voting_params.vote_changing_allowed ? "" : "not"); + dap_string_append_printf(l_str_out, "\t A delegated key is%s required to participate in voting. \n", l_voting->voting_params.delegate_key_required ? "" : " not"); dap_string_append_printf(l_str_out, "\n\nResults:\n\n"); for (uint64_t i = 0; i < dap_list_length(l_voting->voting_params.option_offsets_list); i++){ dap_string_append_printf(l_str_out, "%"DAP_UINT64_FORMAT_U") ", i); @@ -1053,7 +1023,7 @@ static int s_cli_voting(int a_argc, char **a_argv, void **a_str_reply) return 0; } -static int s_datum_tx_voting_coin_check_spent(dap_chain_net_t *a_net, dap_hash_fast_t a_voting_hash, dap_hash_fast_t a_tx_prev_hash, int a_out_idx) +static int s_datum_tx_voting_coin_check_spent(dap_chain_net_t *a_net, dap_hash_fast_t a_voting_hash, dap_hash_fast_t a_tx_prev_hash, int a_out_idx, dap_hash_fast_t *a_pkey_hash) { int l_coin_is_spent = 0; @@ -1082,22 +1052,22 @@ static int s_datum_tx_voting_coin_check_spent(dap_chain_net_t *a_net, dap_hash_f return 1; } - dap_chain_tx_vote_t *l_vote =(dap_chain_tx_vote_t *) dap_chain_datum_tx_item_get(l_tx, NULL, TX_ITEM_TYPE_VOTE, NULL); - if(l_vote && dap_hash_fast_compare(&l_vote->voting_hash, &a_voting_hash)){ + dap_chain_tx_vote_t *l_vote = (dap_chain_tx_vote_t *)dap_chain_datum_tx_item_get(l_tx, NULL, NULL, TX_ITEM_TYPE_VOTE, NULL); + if (l_vote && dap_hash_fast_compare(&l_vote->voting_hash, &a_voting_hash)) { dap_chain_net_votings_t *l_voting = NULL; pthread_rwlock_wrlock(&s_votings_rwlock); HASH_FIND(hh, s_votings, &a_voting_hash, sizeof(dap_hash_fast_t), l_voting); pthread_rwlock_unlock(&s_votings_rwlock); - if (l_voting) - { - dap_list_t *l_temp = l_voting->votes; - while (l_temp){ - dap_chain_net_vote_t *l_vote = (dap_chain_net_vote_t *)l_temp->data; - if (dap_hash_fast_compare(&l_vote->vote_hash, &a_tx_prev_hash)){ - l_coin_is_spent = 1; + if (l_voting) { + for (dap_list_t *it = l_voting->votes; it; it = it->next) { + dap_chain_net_vote_t *l_vote = (dap_chain_net_vote_t *)it->data; + if (dap_hash_fast_compare(&l_vote->vote_hash, &a_tx_prev_hash)) { + if (l_voting->voting_params.vote_changing_allowed && + !dap_hash_fast_is_blank(a_pkey_hash) && + dap_hash_fast_compare(&l_vote->pkey_hash, a_pkey_hash)) + break; // it's vote changing, allow it return 1; } - l_temp = l_temp->next; } } } @@ -1126,10 +1096,9 @@ static int s_datum_tx_voting_coin_check_spent(dap_chain_net_t *a_net, dap_hash_f dap_list_t *l_ins_list = (dap_list_t*)l_tx_temp->data; dap_chain_tx_in_t* l_temp_in = (dap_chain_tx_in_t*)l_ins_list->data; dap_chain_datum_tx_t *l_tx_prev_temp = dap_ledger_tx_find_by_hash(l_ledger, &l_temp_in->header.tx_prev_hash); - int l_out_prev_idx = (int)l_temp_in->header.tx_out_prev_idx; const char* l_tx_token = NULL; - dap_chain_tx_out_t *l_prev_out_union = (dap_chain_tx_out_t*)dap_chain_datum_tx_out_get_by_out_idx(l_tx_prev_temp, l_out_prev_idx); + dap_chain_tx_out_t *l_prev_out_union = (dap_chain_tx_out_t*)dap_chain_datum_tx_out_get_by_out_idx(l_tx_prev_temp, l_temp_in->header.tx_out_prev_idx); if (!l_prev_out_union){ l_tx_temp->data = dap_list_remove(l_tx_temp->data, l_temp_in); if (l_tx_temp->data == NULL){ @@ -1173,7 +1142,7 @@ static int s_datum_tx_voting_coin_check_spent(dap_chain_net_t *a_net, dap_hash_f } - dap_chain_tx_vote_t *l_vote =(dap_chain_tx_vote_t *) dap_chain_datum_tx_item_get(l_tx_prev_temp, NULL, TX_ITEM_TYPE_VOTE, NULL); + dap_chain_tx_vote_t *l_vote =(dap_chain_tx_vote_t *) dap_chain_datum_tx_item_get(l_tx_prev_temp, NULL, NULL, TX_ITEM_TYPE_VOTE, NULL); if(l_vote && dap_hash_fast_compare(&l_vote->voting_hash, &a_voting_hash)){ dap_chain_net_votings_t *l_voting = NULL; pthread_rwlock_wrlock(&s_votings_rwlock); @@ -1420,58 +1389,36 @@ int dap_chain_net_vote_voting(dap_cert_t *a_cert, uint256_t a_fee, dap_chain_wal pthread_rwlock_rdlock(&s_votings_rwlock); HASH_FIND(hh, s_votings, &a_hash, sizeof(dap_hash_fast_t),l_voting); pthread_rwlock_unlock(&s_votings_rwlock); - if(!l_voting || l_voting->net_id.uint64 != a_net->pub.id.uint64){ + if (!l_voting || l_voting->net_id.uint64 != a_net->pub.id.uint64) return DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_FIND_VOTE; - } - if(l_voting->voting_params.votes_max_count_offset){ - uint64_t l_max_count = *(uint64_t*)((byte_t*)l_voting->voting_params.voting_tx + l_voting->voting_params.votes_max_count_offset); - if (l_max_count && dap_list_length(l_voting->votes) >= l_max_count){ - return DAP_CHAIN_NET_VOTE_VOTING_THIS_VOTING_HAVE_MAX_VALUE_VOTES; - } - } - - if(l_voting->voting_params.voting_expire_offset){ - dap_time_t l_expire = *(dap_time_t*)((byte_t*)l_voting->voting_params.voting_tx + l_voting->voting_params.voting_expire_offset); - dap_time_t l_time_now = dap_time_now(); - if (l_expire && l_time_now > l_expire){ - return DAP_CHAIN_NET_VOTE_VOTING_ALREADY_EXPIRED; - } - } + if (l_voting->voting_params.votes_max_count && dap_list_length(l_voting->votes) >= l_voting->voting_params.votes_max_count) + return DAP_CHAIN_NET_VOTE_VOTING_THIS_VOTING_HAVE_MAX_VALUE_VOTES; - if(l_voting->voting_params.delegate_key_required_offset && - *(bool*)((byte_t*)l_voting->voting_params.voting_tx + l_voting->voting_params.delegate_key_required_offset) ){ - if (!a_cert) { - return DAP_CHAIN_NET_VOTE_VOTING_CERT_REQUIRED; - } else { - if (a_cert->enc_key == NULL) { - return DAP_CHAIN_NET_VOTE_VOTING_NO_KEY_FOUND_IN_CERT; - } - // Get publivc key hash - size_t l_pub_key_size = 0; - uint8_t *l_pub_key = dap_enc_key_serialize_pub_key(a_cert->enc_key, &l_pub_key_size);; - if (l_pub_key == NULL) { - return DAP_CHAIN_NET_VOTE_VOTING_NO_PUBLIC_KEY_IN_CERT; - } + if (l_voting->voting_params.voting_expire && dap_time_now() > l_voting->voting_params.voting_expire) + return DAP_CHAIN_NET_VOTE_VOTING_ALREADY_EXPIRED; - dap_hash_fast_t l_pkey_hash = {0}; + dap_hash_fast_t l_pkey_hash = {0}; - dap_hash_fast(l_pub_key, l_pub_key_size, &l_pkey_hash); - DAP_DELETE(l_pub_key); - if (!dap_chain_net_srv_stake_check_pkey_hash(a_net->pub.id, &l_pkey_hash)) { - return DAP_CHAIN_NET_VOTE_VOTING_KEY_IS_NOT_DELEGATED; - } - dap_list_t *l_temp = l_voting->votes; - while(l_temp){ - if (dap_hash_fast_compare(&((dap_chain_net_vote_t *)l_temp->data)->pkey_hash, &l_pkey_hash)){ - if(!l_voting->voting_params.vote_changing_allowed_offset || - !*(bool*)((byte_t*)l_voting->voting_params.voting_tx + l_voting->voting_params.vote_changing_allowed_offset)){ - return DAP_CHAIN_NET_VOTE_VOTING_DOES_NOT_ALLOW_CHANGE_YOUR_VOTE; - } - } - l_temp = l_temp->next; - } - } + if (l_voting->voting_params.delegate_key_required) { + if (!a_cert) + return DAP_CHAIN_NET_VOTE_VOTING_CERT_REQUIRED; + if (!a_cert->enc_key) + return DAP_CHAIN_NET_VOTE_VOTING_NO_KEY_FOUND_IN_CERT; + // Get publivc key hash + size_t l_pub_key_size = 0; + uint8_t *l_pub_key = dap_enc_key_serialize_pub_key(a_cert->enc_key, &l_pub_key_size);; + if (l_pub_key == NULL) + return DAP_CHAIN_NET_VOTE_VOTING_NO_PUBLIC_KEY_IN_CERT; + + dap_hash_fast(l_pub_key, l_pub_key_size, &l_pkey_hash); + DAP_DELETE(l_pub_key); + if (!dap_chain_net_srv_stake_check_pkey_hash(a_net->pub.id, &l_pkey_hash)) + return DAP_CHAIN_NET_VOTE_VOTING_KEY_IS_NOT_DELEGATED; + for (dap_list_t *it = l_voting->votes; it; it = it->next) + if (dap_hash_fast_compare(&((dap_chain_net_vote_t *)it->data)->pkey_hash, &l_pkey_hash) && + !l_voting->voting_params.vote_changing_allowed) + return DAP_CHAIN_NET_VOTE_VOTING_DOES_NOT_ALLOW_CHANGE_YOUR_VOTE; } dap_enc_key_t *l_priv_key = NULL; @@ -1480,9 +1427,8 @@ int dap_chain_net_vote_voting(dap_cert_t *a_cert, uint256_t a_fee, dap_chain_wal const dap_chain_addr_t *l_addr_from = (const dap_chain_addr_t *) dap_chain_wallet_get_addr(a_wallet, a_net->pub.id); - if(!l_addr_from) { + if (!l_addr_from) return DAP_CHAIN_NET_VOTE_VOTING_SOURCE_ADDRESS_INVALID; - } const char *l_native_ticker = a_net->pub.native_ticker; uint256_t l_net_fee = {}, l_total_fee = {}, l_value_transfer; @@ -1496,22 +1442,18 @@ int dap_chain_net_vote_voting(dap_cert_t *a_cert, uint256_t a_fee, dap_chain_wal return DAP_CHAIN_NET_VOTE_VOTING_NOT_ENOUGH_FUNDS_TO_TRANSFER; } - // check outputs UTXOs - dap_list_t *l_utxo_temp = l_list_used_out; uint256_t l_value_transfer_new = {}; - while(l_utxo_temp){ - dap_chain_tx_used_out_item_t *l_out = (dap_chain_tx_used_out_item_t *)l_utxo_temp->data; - if (s_datum_tx_voting_coin_check_spent(a_net, a_hash, l_out->tx_hash_fast, l_out->num_idx_out) != 0 && - (!l_voting->voting_params.vote_changing_allowed_offset || - !*(bool*)((byte_t*)l_voting->voting_params.voting_tx + l_voting->voting_params.vote_changing_allowed_offset))){ - dap_list_t *l_temp = l_utxo_temp; - l_utxo_temp = l_utxo_temp->next; - dap_list_delete_link(l_list_used_out, l_temp); + dap_list_t *it, *tmp; + DL_FOREACH_SAFE(l_list_used_out, it, tmp) { + dap_chain_tx_used_out_item_t *l_out = (dap_chain_tx_used_out_item_t *)it->data; + if (s_datum_tx_voting_coin_check_spent(a_net, a_hash, l_out->tx_hash_fast, l_out->num_idx_out, &l_pkey_hash) && + !l_voting->voting_params.vote_changing_allowed) { + dap_list_delete_link(l_list_used_out, it); continue; } - SUM_256_256(l_value_transfer_new, l_out->value, &l_value_transfer_new); - l_utxo_temp = l_utxo_temp->next; + if (SUM_256_256(l_value_transfer_new, l_out->value, &l_value_transfer_new)) + return DAP_CHAIN_NET_VOTE_VOTING_INTEGER_OVERFLOW; } if (IS_ZERO_256(l_value_transfer_new) || compare256(l_value_transfer_new, l_total_fee) <= 0){ @@ -1633,17 +1575,10 @@ dap_chain_net_vote_info_t *s_dap_chain_net_vote_extract_info(dap_chain_net_votin l_info->question.question_size = a_voting->voting_params.voting_question_length; l_info->question.question_str = (char*)((byte_t*)a_voting->voting_params.voting_tx + a_voting->voting_params.voting_question_offset); l_info->hash = a_voting->voting_hash; - - l_info->is_expired = a_voting->voting_params.voting_expire_offset; - if(a_voting->voting_params.voting_expire_offset){ - l_info->expired = *(dap_time_t*)((byte_t*)a_voting->voting_params.voting_tx + a_voting->voting_params.voting_expire_offset); - } - l_info->is_max_count_votes = a_voting->voting_params.votes_max_count_offset; - if (a_voting->voting_params.votes_max_count_offset){ - l_info->max_count_votes = *(uint64_t*)((byte_t*)a_voting->voting_params.voting_tx + a_voting->voting_params.votes_max_count_offset); - } - l_info->is_changing_allowed = a_voting->voting_params.vote_changing_allowed_offset; - l_info->is_delegate_key_required = a_voting->voting_params.delegate_key_required_offset; + l_info->is_expired = (l_info->expired = a_voting->voting_params.voting_expire); + l_info->is_max_count_votes = (l_info->max_count_votes = a_voting->voting_params.votes_max_count); + l_info->is_changing_allowed = a_voting->voting_params.vote_changing_allowed; + l_info->is_delegate_key_required = a_voting->voting_params.delegate_key_required; l_info->options.count_option = dap_list_length(a_voting->voting_params.option_offsets_list); dap_chain_net_vote_info_option_t **l_options = DAP_NEW_Z_COUNT(dap_chain_net_vote_info_option_t*, l_info->options.count_option); for (uint64_t i = 0; i < l_info->options.count_option; i++){ diff --git a/modules/service/voting/include/dap_chain_net_srv_voting.h b/modules/service/voting/include/dap_chain_net_srv_voting.h index 6fcf2f9a45bb1d02cf2bf3b2d53b4beb2799dac0..f21c10d291c7ade08ae4ec1ddb21592fec321955 100644 --- a/modules/service/voting/include/dap_chain_net_srv_voting.h +++ b/modules/service/voting/include/dap_chain_net_srv_voting.h @@ -110,7 +110,8 @@ enum DAP_CHAIN_NET_VOTE_VOTING_ERROR{ DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_ADD_NET_FEE_OUT, DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_ADD_OUT_WITH_VALUE_BACK, DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_SIGN_TX, - DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_POOL_IN_MEMPOOL + DAP_CHAIN_NET_VOTE_VOTING_CAN_NOT_POOL_IN_MEMPOOL, + DAP_CHAIN_NET_VOTE_VOTING_INTEGER_OVERFLOW }; int dap_chain_net_vote_voting(dap_cert_t *a_cert, uint256_t a_fee, dap_chain_wallet_t *a_wallet, dap_hash_fast_t a_hash, uint64_t a_option_idx, dap_chain_net_t *a_net, const char *a_hash_out_type, diff --git a/modules/service/vpn/dap_chain_net_srv_vpn.c b/modules/service/vpn/dap_chain_net_srv_vpn.c index 9ba8db186f44b867cb924aa7c20c6ad6c3310fc5..e64992b108c503592d5911a7a484f9c75e80f383 100644 --- a/modules/service/vpn/dap_chain_net_srv_vpn.c +++ b/modules/service/vpn/dap_chain_net_srv_vpn.c @@ -1065,8 +1065,6 @@ static int s_callback_receipt_next_success(dap_chain_net_srv_t * a_srv, uint32_t const dap_chain_datum_tx_receipt_t * l_receipt_next = (const dap_chain_datum_tx_receipt_t *) a_receipt_next; size_t l_receipt_next_size = a_receipt_next_size; - - log_it(L_INFO, "Next receipt successfuly accepted"); // usage is present, we've accepted packets dap_stream_ch_set_ready_to_read_unsafe( l_srv_ch_vpn->ch , true ); diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c index 87efb2f7871551493bc7f18ef8d1d3d9e29b89c3..42cea326359093a8f25eeb79c879444c329ebb39 100644 --- a/modules/service/xchange/dap_chain_net_srv_xchange.c +++ b/modules/service/xchange/dap_chain_net_srv_xchange.c @@ -34,7 +34,6 @@ #include "dap_time.h" #include "dap_chain_net_srv.h" #include "dap_chain_ledger.h" -#include "dap_chain_net_srv_order.h" #include "dap_common.h" #include "dap_hash.h" #include "dap_math_ops.h" @@ -75,7 +74,7 @@ static bool s_string_append_tx_cond_info( dap_string_t * a_reply_str, dap_chain_ dap_chain_net_srv_xchange_price_t *s_xchange_price_from_order(dap_chain_net_t *a_net, dap_chain_datum_tx_t *a_order, uint256_t *a_fee, bool a_ret_is_invalid); static dap_chain_net_srv_xchange_t *s_srv_xchange; -static bool s_debug_more = true; +static bool s_debug_more = false; static bool s_tag_check_xchange(dap_ledger_t *a_ledger, dap_chain_datum_tx_t *a_tx, dap_chain_datum_tx_item_groups_t *a_items_grp, dap_chain_tx_tag_action_type_t *a_action) @@ -249,7 +248,7 @@ static int s_xchange_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_o if(!a_tx_in || !a_tx_out_cond) return -1; - dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(a_tx_in, 0, TX_ITEM_TYPE_IN_COND, 0); + dap_chain_tx_in_cond_t *l_tx_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(a_tx_in, NULL, NULL, TX_ITEM_TYPE_IN_COND, NULL); if (!l_tx_in_cond) return -2; if (dap_hash_fast_is_blank(&l_tx_in_cond->header.tx_prev_hash)) @@ -261,8 +260,6 @@ static int s_xchange_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_o uint256_t l_buy_val = {}, l_fee_val = {}, l_sell_again_val = {}, l_service_fee_val = {}; - int l_item_idx_start = 0; - byte_t * l_tx_item; dap_chain_addr_t l_service_fee_addr, *l_seller_addr = &a_tx_out_cond->subtype.srv_xchange.seller_addr; uint16_t l_service_fee_type = 0; @@ -271,39 +268,44 @@ static int s_xchange_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_o const char *l_native_ticker = l_net->pub.native_ticker; const char *l_service_ticker = (l_service_fee_type == SERVICE_FEE_OWN_FIXED || l_service_fee_type == SERVICE_FEE_OWN_PERCENT) ? l_buy_ticker : l_native_ticker; - while ((l_tx_item = dap_chain_datum_tx_item_get(a_tx_in, &l_item_idx_start, TX_ITEM_TYPE_OUT_ALL, NULL)) != NULL) - { - dap_chain_tx_item_type_t l_tx_out_type = dap_chain_datum_tx_item_get_type(l_tx_item); - switch(l_tx_out_type){ - case TX_ITEM_TYPE_OUT_EXT: { - dap_chain_tx_out_ext_t *l_tx_in_output = (dap_chain_tx_out_ext_t *)l_tx_item; - const char * l_out_token = l_tx_in_output->token; - const uint256_t *l_out_value = &l_tx_in_output->header.value; - dap_chain_addr_t * l_out_addr = &l_tx_in_output->addr; - // Out is with token to buy - if (!strcmp(l_out_token, l_buy_ticker) && - !memcmp(l_out_addr, l_seller_addr, sizeof(*l_out_addr))) - SUM_256_256(l_buy_val, *l_out_value, &l_buy_val); - // Out is with token to fee - if (l_service_fee_used && !strcmp(l_out_token, l_service_ticker) && - !memcmp(l_out_addr, &l_service_fee_addr, sizeof(*l_out_addr))) - SUM_256_256(l_fee_val, *l_out_value, &l_fee_val); - } break; - case TX_ITEM_TYPE_OUT_COND: { - dap_chain_tx_out_cond_t *l_tx_in_output = (dap_chain_tx_out_cond_t *)l_tx_item; - if (l_tx_in_output->header.subtype == a_tx_out_cond->header.subtype && // Same subtype - l_tx_in_output->header.srv_uid.uint64 == a_tx_out_cond->header.srv_uid.uint64 && // Same service uid - l_tx_in_output->header.ts_expires == a_tx_out_cond->header.ts_expires && // Same expires time - l_tx_in_output->tsd_size == a_tx_out_cond->tsd_size && // Same params size - memcmp(l_tx_in_output->tsd, a_tx_out_cond->tsd, l_tx_in_output->tsd_size) == 0 && // Same params itself - memcmp(&l_tx_in_output->subtype.srv_xchange, &a_tx_out_cond->subtype.srv_xchange, // Same subtype header - sizeof(a_tx_out_cond->subtype.srv_xchange)) == 0) { - l_sell_again_val = l_tx_in_output->header.value; // It is back to cond owner value - } - }break; - default: break; + byte_t *l_tx_item; size_t l_size; + TX_ITEM_ITER_TX(l_tx_item, l_size, a_tx_in) { + switch (*l_tx_item) { + case TX_ITEM_TYPE_OUT_EXT: { + dap_chain_tx_out_ext_t *l_tx_in_output = (dap_chain_tx_out_ext_t*)l_tx_item; + const char *l_out_token = l_tx_in_output->token; + const uint256_t l_out_value = l_tx_in_output->header.value; + dap_chain_addr_t l_out_addr = l_tx_in_output->addr; + // Out is with token to buy + if (!strcmp(l_out_token, l_buy_ticker) && + !memcmp(&l_out_addr, l_seller_addr, sizeof(l_out_addr)) && + SUM_256_256(l_buy_val, l_out_value, &l_buy_val)) { + log_it(L_WARNING, "Integer overflow for buyer value of exchange tx"); + return -5; + } + // Out is with token to fee + if (l_service_fee_used && !strcmp(l_out_token, l_service_ticker) && + !memcmp(&l_out_addr, &l_service_fee_addr, sizeof(l_out_addr)) && + SUM_256_256(l_fee_val, l_out_value, &l_fee_val)) { + log_it(L_WARNING, "Integer overflow for fee value of exchange tx"); + return -5; + } + } break; + case TX_ITEM_TYPE_OUT_COND: { + dap_chain_tx_out_cond_t *l_tx_in_output = (dap_chain_tx_out_cond_t*)l_tx_item; + if (l_tx_in_output->header.subtype == a_tx_out_cond->header.subtype && // Same subtype + l_tx_in_output->header.srv_uid.uint64 == a_tx_out_cond->header.srv_uid.uint64 && // Same service uid + l_tx_in_output->header.ts_expires == a_tx_out_cond->header.ts_expires && // Same expires time + l_tx_in_output->tsd_size == a_tx_out_cond->tsd_size && // Same params size + memcmp(l_tx_in_output->tsd, a_tx_out_cond->tsd, l_tx_in_output->tsd_size) == 0 && // Same params itself + memcmp(&l_tx_in_output->subtype.srv_xchange, &a_tx_out_cond->subtype.srv_xchange, // Same subtype header + sizeof(a_tx_out_cond->subtype.srv_xchange)) == 0) { + l_sell_again_val = l_tx_in_output->header.value; // It is back to cond owner value + } + } break; + default: + break; } - l_item_idx_start++; } /* Check the condition for rate verification success @@ -316,11 +318,28 @@ static int s_xchange_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_o * a_cond->subtype.srv_xchange.buy_value * (a_cond->header.value - new_cond->header.value) */ + uint256_t l_sell_val, l_buyer_val_expected; - if (compare256(l_sell_again_val, a_tx_out_cond->header.value) >= 0) + if (SUBTRACT_256_256(a_tx_out_cond->header.value, l_sell_again_val, &l_sell_val)) { + log_it(L_WARNING, "Integer overflow for resell value of exchange tx"); return -5; - SUBTRACT_256_256(a_tx_out_cond->header.value, l_sell_again_val, &l_sell_val); + } MULT_256_COIN(l_sell_val, a_tx_out_cond->subtype.srv_xchange.rate, &l_buyer_val_expected); + if (s_debug_more) { + const char *l_value_str; + dap_uint256_to_char(a_tx_out_cond->header.value, &l_value_str); + log_it(L_NOTICE, "Total sell %s %s from %s", l_value_str, l_sell_ticker, dap_hash_fast_to_str_static(&l_tx_in_cond->header.tx_prev_hash)); + dap_uint256_to_char(a_tx_out_cond->subtype.srv_xchange.rate, &l_value_str); + log_it(L_NOTICE, "Rate is %s", l_value_str); + dap_uint256_to_char(l_sell_again_val, &l_value_str); + log_it(L_NOTICE, "Resell %s %s", l_value_str, l_sell_ticker); + dap_uint256_to_char(l_buyer_val_expected, &l_value_str); + log_it(L_NOTICE, "Expect to buy %s %s", l_value_str, l_buy_ticker); + dap_uint256_to_char(l_buy_val, &l_value_str); + log_it(L_NOTICE, "Buy %s %s", l_value_str, l_buy_ticker); + dap_uint256_to_char(l_fee_val, &l_value_str); + log_it(L_NOTICE, "Service fee is %s %s", l_value_str, l_service_ticker); + } if (compare256(l_buyer_val_expected, l_buy_val) > 0) return -6; @@ -679,7 +698,7 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha return NULL; } const dap_chain_addr_t *l_seller_addr = &l_tx_out_cond->subtype.srv_xchange.seller_addr; - if (dap_chain_datum_tx_add_in_cond_item(&l_tx, &a_price->tx_hash, l_prev_cond_idx, 0)) { + if (1 != dap_chain_datum_tx_add_in_cond_item(&l_tx, &a_price->tx_hash, l_prev_cond_idx, 0)) { dap_chain_datum_tx_delete(l_tx); log_it(L_ERROR, "Can't add conditional input"); return NULL; @@ -867,14 +886,14 @@ uint64_t dap_chain_net_srv_xchange_get_order_completion_rate(dap_chain_net_t *a_ return 0; } - dap_hash_fast_t * l_last_tx_hash = dap_ledger_get_final_chain_tx_hash(a_net->pub.ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_price->tx_hash); - if(!l_last_tx_hash){ + dap_hash_fast_t l_last_tx_hash = dap_ledger_get_final_chain_tx_hash(a_net->pub.ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_price->tx_hash); + if ( dap_hash_fast_is_blank(&l_last_tx_hash) ){ log_it(L_ERROR, " Can't get last tx cond hash from order"); return 0; } - dap_chain_datum_tx_t * l_last_tx = dap_ledger_tx_find_by_hash(a_net->pub.ledger, l_last_tx_hash); - if(!l_last_tx_hash){ + dap_chain_datum_tx_t * l_last_tx = dap_ledger_tx_find_by_hash(a_net->pub.ledger, &l_last_tx_hash); + if(!l_last_tx){ log_it(L_ERROR, "Can't find last tx"); return 0; } @@ -924,14 +943,14 @@ dap_chain_net_srv_xchange_order_status_t dap_chain_net_srv_xchange_get_order_sta return XCHANGE_ORDER_STATUS_UNKNOWN; } - dap_hash_fast_t * l_last_tx_hash = dap_ledger_get_final_chain_tx_hash(a_net->pub.ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_price->tx_hash); - if(!l_last_tx_hash){ + dap_hash_fast_t l_last_tx_hash = dap_ledger_get_final_chain_tx_hash(a_net->pub.ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_price->tx_hash); + if ( dap_hash_fast_is_blank(&l_last_tx_hash) ) { log_it(L_ERROR, " Can't get last tx cond hash from order"); return XCHANGE_ORDER_STATUS_UNKNOWN; } - dap_chain_datum_tx_t * l_last_tx = dap_ledger_tx_find_by_hash(a_net->pub.ledger, l_last_tx_hash); - if(!l_last_tx_hash){ + dap_chain_datum_tx_t * l_last_tx = dap_ledger_tx_find_by_hash(a_net->pub.ledger, &l_last_tx_hash); + if (!l_last_tx) { log_it(L_ERROR, "Can't find last tx"); return XCHANGE_ORDER_STATUS_UNKNOWN; } @@ -1149,10 +1168,10 @@ dap_chain_net_srv_xchange_price_t *s_xchange_price_from_order(dap_chain_net_t *a l_price->creator_addr = l_out_cond->subtype.srv_xchange.seller_addr; if (!IS_ZERO_256(l_price->datoshi_buy)) { l_price->rate = l_out_cond->subtype.srv_xchange.rate; - dap_hash_fast_t *l_final_hash = dap_ledger_get_final_chain_tx_hash(a_net->pub.ledger, + dap_hash_fast_t l_final_hash = dap_ledger_get_final_chain_tx_hash(a_net->pub.ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_tx_hash); - if (l_final_hash) { - l_price->tx_hash = *l_final_hash; + if ( !dap_hash_fast_is_blank(&l_final_hash) ) { + l_price->tx_hash = l_final_hash; return l_price; } else { log_it(L_WARNING, "This order have no active conditional transaction"); @@ -1533,14 +1552,14 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, v dap_ledger_t * l_ledger = dap_ledger_by_net_name(l_net->pub.name); char *l_cp_rate; char* l_status_order = NULL; - dap_hash_fast_t * l_last_tx_hash = dap_ledger_get_final_chain_tx_hash(l_ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_price->tx_hash); - if(!l_last_tx_hash){ + dap_hash_fast_t l_last_tx_hash = dap_ledger_get_final_chain_tx_hash(l_ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_price->tx_hash); + if( dap_hash_fast_is_blank(&l_last_tx_hash) ){ dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't get last tx cond hash from order"); return -18; } - dap_chain_datum_tx_t * l_last_tx = dap_ledger_tx_find_by_hash(l_ledger, l_last_tx_hash); - if(!l_last_tx_hash){ + dap_chain_datum_tx_t * l_last_tx = dap_ledger_tx_find_by_hash(l_ledger, &l_last_tx_hash); + if (!l_last_tx){ dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't find last tx"); return -18; } @@ -1631,7 +1650,7 @@ static bool s_filter_tx_list(dap_chain_datum_t *a_datum, dap_chain_t *a_chain, v return true; // Find SRV_XCHANGE in_cond item int l_item_idx = 0; - dap_chain_tx_in_cond_t * l_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(l_datum_tx, &l_item_idx, TX_ITEM_TYPE_IN_COND , NULL); + dap_chain_tx_in_cond_t * l_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(l_datum_tx, &l_item_idx, NULL, TX_ITEM_TYPE_IN_COND , NULL); int l_prev_cond_idx = 0; dap_chain_datum_tx_t * l_prev_tx = l_in_cond ? dap_ledger_tx_find_by_hash(l_net->pub.ledger, &l_in_cond->header.tx_prev_hash) : NULL; dap_chain_tx_out_cond_t *l_out_prev_cond_item = l_prev_tx ? dap_chain_datum_tx_out_cond_get(l_prev_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, @@ -1651,7 +1670,7 @@ xchange_tx_type_t dap_chain_net_srv_xchange_tx_get_type (dap_ledger_t * a_ledger &l_cond_idx); // Find SRV_XCHANGE in_cond item int l_item_idx = 0; - byte_t *l_tx_item = dap_chain_datum_tx_item_get(a_tx, &l_item_idx, TX_ITEM_TYPE_IN_COND , NULL); + byte_t *l_tx_item = dap_chain_datum_tx_item_get(a_tx, &l_item_idx, NULL, TX_ITEM_TYPE_IN_COND , NULL); dap_chain_tx_in_cond_t * l_in_cond = l_tx_item ? (dap_chain_tx_in_cond_t *) l_tx_item : NULL; int l_prev_cond_idx = 0; dap_chain_datum_tx_t * l_prev_tx = l_in_cond ? dap_ledger_tx_find_by_hash(a_ledger, &l_in_cond->header.tx_prev_hash) : NULL; @@ -1673,7 +1692,7 @@ xchange_tx_type_t dap_chain_net_srv_xchange_tx_get_type (dap_ledger_t * a_ledger { dap_chain_datum_tx_t * l_prev_tx_temp = a_tx; byte_t *l_tx_item_temp = NULL; - while((l_tx_item_temp = dap_chain_datum_tx_item_get(l_prev_tx_temp, &l_item_idx, TX_ITEM_TYPE_IN_COND , NULL)) != NULL) + while((l_tx_item_temp = dap_chain_datum_tx_item_get(l_prev_tx_temp, &l_item_idx, NULL, TX_ITEM_TYPE_IN_COND , NULL)) != NULL) { dap_chain_tx_in_cond_t * l_in_cond_temp = (dap_chain_tx_in_cond_t *) l_tx_item_temp; l_prev_tx_temp = dap_ledger_tx_find_by_hash(a_ledger, &l_in_cond_temp->header.tx_prev_hash); @@ -1686,9 +1705,9 @@ xchange_tx_type_t dap_chain_net_srv_xchange_tx_get_type (dap_ledger_t * a_ledger if (!l_out_cond_item) { l_tx_type = TX_TYPE_UNDEFINED; } else { - dap_chain_tx_sig_t *l_tx_prev_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(l_prev_tx_temp, NULL, TX_ITEM_TYPE_SIG, NULL); + dap_chain_tx_sig_t *l_tx_prev_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(l_prev_tx_temp, NULL, NULL, TX_ITEM_TYPE_SIG, NULL); dap_sign_t *l_prev_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_tx_prev_sig); - dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_SIG, NULL); + dap_chain_tx_sig_t *l_tx_sig = (dap_chain_tx_sig_t *)dap_chain_datum_tx_item_get(a_tx, NULL, NULL, TX_ITEM_TYPE_SIG, NULL); dap_sign_t *l_sign = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)l_tx_sig); bool l_owner = false; @@ -1721,14 +1740,14 @@ static int s_tx_check_for_open_close(dap_chain_net_t * a_net, dap_chain_datum_tx dap_hash_fast_t l_tx_hash = {}; dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), &l_tx_hash); - dap_hash_fast_t * l_last_tx_hash = dap_ledger_get_final_chain_tx_hash(l_ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_tx_hash); - if(!l_last_tx_hash){ + dap_hash_fast_t l_last_tx_hash = dap_ledger_get_final_chain_tx_hash(l_ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_tx_hash); + if ( dap_hash_fast_is_blank(&l_last_tx_hash) ) { log_it(L_WARNING,"Can't get last tx cond hash from order"); return 0; } - dap_chain_datum_tx_t * l_last_tx = dap_ledger_tx_find_by_hash(l_ledger, l_last_tx_hash); - if(!l_last_tx_hash){ + dap_chain_datum_tx_t * l_last_tx = dap_ledger_tx_find_by_hash(l_ledger, &l_last_tx_hash); + if (!l_last_tx) { log_it(L_WARNING,"Can't find last tx"); return 0; } @@ -1806,7 +1825,7 @@ static bool s_string_append_tx_cond_info( dap_string_t * a_reply_str, } break; case TX_TYPE_EXCHANGE:{ dap_chain_tx_in_cond_t *l_in_cond - = (dap_chain_tx_in_cond_t*)dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_IN_COND , NULL); + = (dap_chain_tx_in_cond_t*)dap_chain_datum_tx_item_get(a_tx, NULL, NULL, TX_ITEM_TYPE_IN_COND , NULL); char l_tx_prev_cond_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE]; dap_hash_fast_to_str(&l_in_cond->header.tx_prev_hash, l_tx_prev_cond_hash_str, sizeof(l_tx_prev_cond_hash_str)); @@ -1856,7 +1875,7 @@ static bool s_string_append_tx_cond_info( dap_string_t * a_reply_str, dap_string_append_printf(a_reply_str, "\n Prev cond: %s", l_tx_prev_cond_hash_str); } break; case TX_TYPE_INVALIDATE:{ - dap_chain_tx_in_cond_t * l_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(a_tx, NULL, TX_ITEM_TYPE_IN_COND , NULL); + dap_chain_tx_in_cond_t * l_in_cond = (dap_chain_tx_in_cond_t *)dap_chain_datum_tx_item_get(a_tx, NULL, NULL, TX_ITEM_TYPE_IN_COND , NULL); char l_tx_prev_cond_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE]; dap_hash_fast_to_str(&l_in_cond->header.tx_prev_hash,l_tx_prev_cond_hash_str, sizeof(l_tx_prev_cond_hash_str)); @@ -1870,13 +1889,10 @@ static bool s_string_append_tx_cond_info( dap_string_t * a_reply_str, return false; int l_out_num = l_in_cond->header.tx_out_prev_idx; - dap_hash_fast_t l_order_hash = l_in_cond->header.tx_prev_hash; dap_chain_tx_out_cond_t *l_out_cond = dap_chain_datum_tx_out_cond_get(l_prev_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_out_num); - dap_hash_fast_t *l_order_hash_ptr = dap_ledger_get_first_chain_tx_hash(a_net->pub.ledger, a_tx, l_out_cond); - if (l_order_hash_ptr){ - l_order_hash = *l_order_hash_ptr; - DAP_DEL_Z(l_order_hash_ptr); - } + dap_hash_fast_t l_order_hash = dap_ledger_get_first_chain_tx_hash(a_net->pub.ledger, a_tx, l_out_cond); + if ( dap_hash_fast_is_blank(&l_order_hash) ) + l_order_hash = l_in_cond->header.tx_prev_hash; char *l_value_from_str = dap_chain_balance_to_coins(l_out_prev_cond_item->header.value); char *l_value_from_datoshi_str = dap_chain_balance_print(l_out_prev_cond_item->header.value); @@ -1941,13 +1957,11 @@ size_t l_tx_total; return 0; } -void s_tx_is_order_check (dap_chain_net_t* a_net, dap_chain_datum_tx_t *a_tx, dap_hash_fast_t *a_tx_hash, void *a_arg) +void s_tx_is_order_check(UNUSED_ARG dap_chain_net_t* a_net, dap_chain_datum_tx_t *a_tx, UNUSED_ARG dap_hash_fast_t *a_tx_hash, void *a_arg) { - UNUSED(a_net); - UNUSED(a_tx_hash); dap_list_t **l_tx_list_ptr = a_arg; - if (dap_chain_datum_tx_out_cond_get(a_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE , NULL) && - !dap_chain_datum_tx_items_get(a_tx, TX_ITEM_TYPE_IN_COND, NULL)) + if ( dap_chain_datum_tx_out_cond_get(a_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, NULL) && + !dap_chain_datum_tx_item_get(a_tx, NULL, NULL, TX_ITEM_TYPE_IN_COND, NULL)) *l_tx_list_ptr = dap_list_append(*l_tx_list_ptr, a_tx); } @@ -2086,14 +2100,14 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) dap_ledger_t * l_ledger = dap_ledger_by_net_name(l_net->pub.name); char *l_cp_rate; char* l_status_order = NULL; - dap_hash_fast_t * l_last_tx_hash = dap_ledger_get_final_chain_tx_hash(l_ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_price->tx_hash); - if(!l_last_tx_hash){ + dap_hash_fast_t l_last_tx_hash = dap_ledger_get_final_chain_tx_hash(l_ledger, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_price->tx_hash); + if ( dap_hash_fast_is_blank(&l_last_tx_hash) ) { log_it(L_WARNING,"Can't get last tx cond hash from order"); continue; } - dap_chain_datum_tx_t * l_last_tx = dap_ledger_tx_find_by_hash(l_ledger, l_last_tx_hash); - if(!l_last_tx_hash){ + dap_chain_datum_tx_t * l_last_tx = dap_ledger_tx_find_by_hash(l_ledger, &l_last_tx_hash); + if(!l_last_tx){ log_it(L_WARNING,"Can't find last tx"); continue; } @@ -2486,7 +2500,7 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, void **a_str_reply) NULL); if(!l_out_cond_item){ int l_item_idx = 0; - byte_t *l_tx_item = dap_chain_datum_tx_item_get(l_tx, &l_item_idx, TX_ITEM_TYPE_IN_COND , NULL); + byte_t *l_tx_item = dap_chain_datum_tx_item_get(l_tx, &l_item_idx, NULL, TX_ITEM_TYPE_IN_COND , NULL); dap_chain_tx_in_cond_t * l_in_cond = l_tx_item ? (dap_chain_tx_in_cond_t *) l_tx_item : NULL; int l_prev_cond_idx = 0; dap_chain_datum_tx_t * l_prev_tx = l_in_cond ? dap_ledger_tx_find_by_hash(l_net->pub.ledger, &l_in_cond->header.tx_prev_hash) : NULL; diff --git a/modules/type/blocks/dap_chain_cs_blocks.c b/modules/type/blocks/dap_chain_cs_blocks.c index ae29fe56a99637fb09d8defdd4bef8525bb3bb3f..17180d9a64676e2a41ebf7f06e577663ec8951b0 100644 --- a/modules/type/blocks/dap_chain_cs_blocks.c +++ b/modules/type/blocks/dap_chain_cs_blocks.c @@ -1155,7 +1155,10 @@ static int s_cli_blocks(int a_argc, char ** a_argv, void **a_str_reply) "Certificate \"%s\" doesn't contains private key", l_cert_name); return DAP_CHAIN_NODE_CLI_COM_BLOCK_CERT_ERR; } - + if (!l_fee_value_str) { + dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR, "Command 'block %s collect' requires parameter '-fee'", l_subcmd_str); + return DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR; + } l_fee_value = dap_chain_balance_scan(l_fee_value_str); if (!l_fee_value_str || IS_ZERO_256(l_fee_value)) { dap_json_rpc_error_add(DAP_CHAIN_NODE_CLI_COM_BLOCK_PARAM_ERR, "Command 'block %s collect' requires parameter '-fee' to be valid uint256", l_subcmd_str); @@ -2310,8 +2313,8 @@ static size_t s_callback_add_datums(dap_chain_t *a_chain, dap_chain_datum_t **a_ log_it(L_WARNING, "Empty datum"); /* How might it be? */ continue; } - if (l_blocks->block_new_size + l_datum_size > DAP_CHAIN_CS_BLOCKS_MAX_BLOCK_SIZE) { - log_it(L_DEBUG, "Maximum size exeeded, %zu > %d", l_blocks->block_new_size + l_datum_size, DAP_CHAIN_CS_BLOCKS_MAX_BLOCK_SIZE); + if (l_blocks->block_new_size + l_datum_size > DAP_CHAIN_ATOM_MAX_SIZE) { + log_it(L_DEBUG, "Maximum size exeeded, %zu > %d", l_blocks->block_new_size + l_datum_size, DAP_CHAIN_ATOM_MAX_SIZE); break; } if (!l_blocks->block_new) { diff --git a/modules/type/blocks/include/dap_chain_cs_blocks.h b/modules/type/blocks/include/dap_chain_cs_blocks.h index 69a25180ca834f2d526d4c402d0445f58b0d1f42..dd538ac6bcb08f874b82cd549d9cd93818ce7711 100644 --- a/modules/type/blocks/include/dap_chain_cs_blocks.h +++ b/modules/type/blocks/include/dap_chain_cs_blocks.h @@ -26,12 +26,6 @@ #include "dap_chain_block.h" #include "dap_chain_block_cache.h" -#ifdef DAP_TPS_TEST -#define DAP_CHAIN_CS_BLOCKS_MAX_BLOCK_SIZE (100 * 1024 * 1024) -#else -#define DAP_CHAIN_CS_BLOCKS_MAX_BLOCK_SIZE (256 * 1024) // 256 KB -#endif - #define DAP_FORK_MAX_DEPTH 100 #define DAP_REWARD_INIT_TIMESTAMP 1700870400UL // 25 Nov 2023 00:00:00 GMT diff --git a/modules/type/dag/dap_chain_cs_dag_event.c b/modules/type/dag/dap_chain_cs_dag_event.c index 8bce113cf5cc3f468f2f972d1f0875ba0929585c..8e4fc060129010fbf0010edf8a07953441c6aec9 100644 --- a/modules/type/dag/dap_chain_cs_dag_event.c +++ b/modules/type/dag/dap_chain_cs_dag_event.c @@ -100,16 +100,16 @@ dap_chain_cs_dag_event_t *dap_chain_cs_dag_event_new(dap_chain_id_t a_chain_id, * @param a_event * @return */ -size_t dap_chain_cs_dag_event_calc_size_excl_signs(dap_chain_cs_dag_event_t *a_event, size_t a_limit_size) +uint64_t dap_chain_cs_dag_event_calc_size_excl_signs(dap_chain_cs_dag_event_t *a_event, uint64_t a_limit_size) { dap_return_val_if_fail(a_event, 0); if (a_limit_size && a_limit_size < sizeof(a_event->header)) return 0; - size_t l_hashes_size = a_event->header.hash_count * sizeof(dap_chain_hash_fast_t); + uint32_t l_hashes_size = a_event->header.hash_count * sizeof(dap_chain_hash_fast_t); if (a_limit_size && a_limit_size < l_hashes_size + sizeof(a_event->header) + sizeof(dap_chain_datum_t)) return 0; - dap_chain_datum_t *l_datum = (dap_chain_datum_t*) (a_event->hashes_n_datum_n_signs + l_hashes_size); - size_t l_ret = dap_chain_datum_size(l_datum) + l_hashes_size + sizeof(a_event->header); + dap_chain_datum_t *l_datum = (dap_chain_datum_t *)(a_event->hashes_n_datum_n_signs + l_hashes_size); + uint64_t l_ret = dap_chain_datum_size(l_datum) + l_hashes_size + sizeof(a_event->header); if (a_limit_size && a_limit_size < l_ret) return 0; return l_ret; @@ -120,21 +120,28 @@ size_t dap_chain_cs_dag_event_calc_size_excl_signs(dap_chain_cs_dag_event_t *a_e * @param a_event * @return */ -size_t dap_chain_cs_dag_event_calc_size(dap_chain_cs_dag_event_t *a_event, size_t a_limit_size) +uint64_t dap_chain_cs_dag_event_calc_size(dap_chain_cs_dag_event_t *a_event, uint64_t a_limit_size) { dap_return_val_if_fail(a_event, 0); - size_t l_signs_offset = dap_chain_cs_dag_event_calc_size_excl_signs(a_event, a_limit_size); + uint64_t l_signs_offset = dap_chain_cs_dag_event_calc_size_excl_signs(a_event, a_limit_size); if (!l_signs_offset) return 0; byte_t *l_signs = (byte_t *)a_event + l_signs_offset; size_t l_signs_size = 0; for (uint16_t l_signs_passed = 0; l_signs_passed < a_event->header.signs_count; l_signs_passed++) { dap_sign_t *l_sign = (dap_sign_t *)(l_signs + l_signs_size); + if (l_signs_offset + l_signs_size + sizeof(dap_sign_t) <= l_signs_offset) + return 0; if (a_limit_size && a_limit_size < l_signs_offset + l_signs_size + sizeof(dap_sign_t)) return 0; - l_signs_size += dap_sign_get_size(l_sign); + uint64_t l_sign_size = dap_sign_get_size(l_sign); + if (!l_sign_size) + break; + if (l_signs_size + l_sign_size <= l_signs_size) + return 0; + l_signs_size += l_sign_size; } - size_t l_total_size = l_signs_offset + l_signs_size; + size_t l_total_size = l_signs_offset + l_signs_size <= l_signs_offset ? 0 : l_signs_offset + l_signs_size; return a_limit_size && l_total_size > a_limit_size ? 0 : l_total_size; } diff --git a/modules/type/dag/include/dap_chain_cs_dag_event.h b/modules/type/dag/include/dap_chain_cs_dag_event.h index 5f4d6a1c94255515bb77d0487764860e1457c3cb..4de1d9055b8eca61d05ca961d6fd6cfcd5a003cc 100644 --- a/modules/type/dag/include/dap_chain_cs_dag_event.h +++ b/modules/type/dag/include/dap_chain_cs_dag_event.h @@ -90,8 +90,8 @@ bool dap_chain_cs_dag_event_sign_exists(dap_chain_cs_dag_event_t *a_event, size_ bool dap_chain_cs_dag_event_round_sign_exists(dap_chain_cs_dag_event_round_item_t *a_round_item, dap_enc_key_t * a_key); dap_sign_t * dap_chain_cs_dag_event_get_sign( dap_chain_cs_dag_event_t * a_event, size_t a_event_size, uint16_t a_sign_number); -size_t dap_chain_cs_dag_event_calc_size_excl_signs(dap_chain_cs_dag_event_t *a_event, size_t a_limit_size); -size_t dap_chain_cs_dag_event_calc_size(dap_chain_cs_dag_event_t *a_event, size_t a_limit_size); +uint64_t dap_chain_cs_dag_event_calc_size_excl_signs(dap_chain_cs_dag_event_t *a_event, uint64_t a_limit_size); +uint64_t dap_chain_cs_dag_event_calc_size(dap_chain_cs_dag_event_t *a_event, uint64_t a_limit_size); /** diff --git a/modules/wallet/dap_chain_wallet.c b/modules/wallet/dap_chain_wallet.c index 25892281a3fab2a8418557a4eb05290c2a0c4b53..38986922299ee3aa5c5bd9cd36dcbe8da9f6e7f3 100644 --- a/modules/wallet/dap_chain_wallet.c +++ b/modules/wallet/dap_chain_wallet.c @@ -352,7 +352,7 @@ static char s_wallets_path[MAX_PATH]; const char* dap_chain_wallet_get_path(dap_config_t * a_config) { - char *l_cp = NULL; + const char *l_cp = NULL; if (!a_config) a_config = g_config; if ( s_wallets_path[0] ) /* Is the path to the wallet's store has been defined ? */