diff --git a/modules/chain/dap_chain_tx.c b/modules/chain/dap_chain_tx.c index d895ad60705cb8032b36d5f266b9500dad4bc897..6e4fb145d2c0f18416f8add80e541c0340a97266 100644 --- a/modules/chain/dap_chain_tx.c +++ b/modules/chain/dap_chain_tx.c @@ -79,9 +79,9 @@ dap_chain_tx_t* dap_chain_tx_dup(dap_chain_tx_t * a_tx) * @param a_tx_hh * @param a_tx */ -void dap_chain_tx_hh_add (dap_chain_tx_t * a_tx_hh, dap_chain_tx_t * a_tx) +void dap_chain_tx_hh_add (dap_chain_tx_t ** a_tx_hh, dap_chain_tx_t * a_tx) { - HASH_ADD(hh,a_tx_hh,hash, sizeof(a_tx->hash),a_tx); + HASH_ADD(hh,*a_tx_hh,hash, sizeof(a_tx->hash),a_tx); } void dap_chain_tx_hh_free (dap_chain_tx_t * a_tx_hh) diff --git a/modules/chain/include/dap_chain_tx.h b/modules/chain/include/dap_chain_tx.h index fbae57c57cf1bf10389fd5224e63fb006e8aa3c7..4fc657eb358d8e28319d71d437a02b88ee5f2e07 100644 --- a/modules/chain/include/dap_chain_tx.h +++ b/modules/chain/include/dap_chain_tx.h @@ -66,7 +66,7 @@ typedef struct dap_chain_tx } dap_chain_tx_t; dap_chain_tx_t * dap_chain_tx_wrap_packed(dap_chain_datum_tx_t * a_tx_packed); -void dap_chain_tx_hh_add (dap_chain_tx_t * a_tx_hh, dap_chain_tx_t * a_tx); +void dap_chain_tx_hh_add (dap_chain_tx_t ** a_tx_hh, dap_chain_tx_t * a_tx); /** * @brief Find tx in hashtable by its datum_tx hash 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 2c6ffd5ea1bd2bd5dbccac73442a4207583677fb..20bb4a14690cd4ee3c00fdc32caa2c97a4a5abd2 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 @@ -249,14 +249,14 @@ static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_ l_srv->callbacks.response_error(l_srv, 0, NULL, &l_err, sizeof(l_err)); return; } - + bool l_check_role = dap_chain_net_get_role(l_net).enums > NODE_ROLE_MASTER; // check role if ( ! l_srv || l_check_role) // Service not found l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_NOT_FOUND; if ( l_err.code || !l_srv_session){ debug_if( - l_check_role, L_ERROR, + l_check_role, L_ERROR, "You can't provide service with ID %lu in net %s. Node role should be not lower than master\n", l_srv->uid.uint64, l_net->pub.name ); @@ -289,7 +289,7 @@ static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_ dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err)); if (l_srv && l_srv->callbacks.response_error) l_srv->callbacks.response_error(l_srv, 0, NULL, &l_err, sizeof(l_err)); - DAP_DEL_Z(l_usage); + dap_chain_net_srv_usage_delete(l_srv_session); return; } l_usage->client->stream_worker = a_ch->stream_worker; @@ -303,10 +303,24 @@ static void s_service_start(dap_stream_ch_t* a_ch , dap_stream_ch_chain_net_srv_ l_usage->client_pkey_hash = a_request->hdr.client_pkey_hash; - if (l_srv->pricelist){ + if (l_srv->pricelist || !dap_hash_fast_is_blank(&a_request->hdr.order_hash)){ // not free service log_it( L_INFO, "Valid pricelist is founded. Start service in pay mode."); + if (dap_chain_net_get_state(l_net) == NET_STATE_OFFLINE) { + log_it(L_ERROR, "Can't start service because net %s is offline.", l_net->pub.name); + l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_IS_OFFLINE; + if(a_ch) + dap_stream_ch_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR, &l_err, sizeof (l_err)); + if (l_srv && l_srv->callbacks.response_error) + l_srv->callbacks.response_error(l_srv, 0, NULL, &l_err, sizeof(l_err)); + dap_chain_net_srv_usage_delete(l_srv_session); + return; + } + + if (!dap_hash_fast_is_blank(&a_request->hdr.order_hash)) + l_usage->static_order_hash = a_request->hdr.order_hash; + dap_chain_net_srv_grace_t *l_grace = DAP_NEW_Z(dap_chain_net_srv_grace_t); if (!l_grace) { log_it(L_CRITICAL, "Memory allocation error"); @@ -414,21 +428,51 @@ static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace) } a_grace->usage->is_grace = true; + if (a_grace->usage->receipt){ // If it is repeated grace - DL_FOREACH(a_grace->usage->service->pricelist, l_price) { - switch (l_price->units_uid.enm) { - case SERV_UNIT_MB: - case SERV_UNIT_SEC: - case SERV_UNIT_DAY: - case SERV_UNIT_KB: - case SERV_UNIT_B: - log_it(L_MSG, "Proper unit type %s found among available prices", - dap_chain_srv_unit_enum_to_str(l_price->units_uid.enm)); - break; - default: - continue; + if (dap_hash_fast_is_blank(&a_grace->usage->static_order_hash)){ + log_it(L_MSG, "Get price from list."); + DL_FOREACH(a_grace->usage->service->pricelist, l_price) { + switch (l_price->units_uid.enm) { + case SERV_UNIT_MB: + case SERV_UNIT_SEC: + case SERV_UNIT_DAY: + case SERV_UNIT_KB: + case SERV_UNIT_B: + log_it(L_MSG, "Proper unit type %s found among available prices", + dap_chain_srv_unit_enum_to_str(l_price->units_uid.enm)); + break; + default: + continue; + } + break; // proper price found, thus we exit from the loop + } + + if (!l_price) { + log_it(L_ERROR, "Price with proper unit type not found, check available orders and/or pricelists"); + l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_CANT_ADD_USAGE; + s_grace_error(a_grace, l_err); + return; + } + a_grace->usage->price = l_price; + } else { + char *l_order_hash_str = dap_chain_hash_fast_to_str_new(&a_grace->usage->static_order_hash); + log_it(L_MSG, "Get price from order %s.", l_order_hash_str); + DAP_DELETE(l_order_hash_str); + if ((l_price = dap_chain_net_srv_get_price_from_order(a_grace->usage->service, "srv_vpn", &a_grace->usage->static_order_hash))){ + switch (l_price->units_uid.enm) { + case SERV_UNIT_MB: + case SERV_UNIT_SEC: + case SERV_UNIT_DAY: + case SERV_UNIT_KB: + case SERV_UNIT_B: + log_it(L_MSG, "Proper unit type %s found among available prices", + dap_chain_srv_unit_enum_to_str(l_price->units_uid.enm)); + a_grace->usage->price = l_price; + default: + DAP_DEL_Z(l_price); + } } - break; // proper price found, thus we exit from the loop } if (!l_price) { @@ -437,7 +481,6 @@ static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace) s_grace_error(a_grace, l_err); return; } - a_grace->usage->price = l_price; usages_in_grace_t *l_item = DAP_NEW_Z_SIZE(usages_in_grace_t, sizeof(usages_in_grace_t)); if (!l_item) { log_it(L_CRITICAL, "Memory allocation error"); @@ -499,6 +542,13 @@ static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace) } } else { // Start service in normal pay mode + if (dap_chain_net_get_state(l_net) == NET_STATE_OFFLINE) { + log_it(L_ERROR, "Can't pay service because net %s is offline.", l_net->pub.name); + l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_IS_OFFLINE; + s_grace_error(a_grace, l_err); + return; + } + a_grace->usage->tx_cond = l_tx; l_tx_out_cond = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY, NULL ); @@ -530,43 +580,92 @@ static void s_grace_period_start(dap_chain_net_srv_grace_t *a_grace) } dap_stpcpy(a_grace->usage->token_ticker, l_ticker); - dap_chain_net_srv_price_t *l_price_tmp; - DL_FOREACH(a_grace->usage->service->pricelist, l_price_tmp) { - if (!l_price_tmp){ - continue; - } - if (l_price_tmp->net->pub.id.uint64 != a_grace->usage->net->pub.id.uint64){ - log_it( L_WARNING, "Pricelist is not set for net %s", a_grace->usage->net->pub.name); - continue; - } + if (dap_hash_fast_is_blank(&a_grace->usage->static_order_hash)){ + dap_chain_net_srv_price_t *l_price_tmp; + DL_FOREACH(a_grace->usage->service->pricelist, l_price_tmp) { + if (!l_price_tmp){ + continue; + } - if (dap_strcmp(l_price_tmp->token, l_ticker) != 0){ - log_it( L_WARNING, "Token ticker in the pricelist and tx do not match"); - continue; - } + if (l_price_tmp->net->pub.id.uint64 != a_grace->usage->net->pub.id.uint64){ + log_it( L_WARNING, "Pricelist is not for net %s.", a_grace->usage->net->pub.name); + continue; + } - if (l_price_tmp->units_uid.enm != l_tx_out_cond->subtype.srv_pay.unit.enm){ - log_it( L_WARNING, "Unit ID in the pricelist and tx do not match"); - continue; - } + if (dap_strcmp(l_price_tmp->token, l_ticker) != 0){ + log_it( L_WARNING, "Token ticker in the pricelist and tx do not match"); + continue; + } - uint256_t l_unit_price = {}; - if (l_price_tmp->units != 0){ - DIV_256(l_price_tmp->value_datoshi, GET_256_FROM_64(l_price_tmp->units), &l_unit_price); - } else { - log_it( L_WARNING, "Units in pricelist is zero. "); - continue; + if (l_price_tmp->units_uid.enm != l_tx_out_cond->subtype.srv_pay.unit.enm){ + log_it( L_WARNING, "Unit ID in the pricelist and tx do not match"); + continue; + } + + uint256_t l_unit_price = {}; + if (l_price_tmp->units != 0){ + DIV_256(l_price_tmp->value_datoshi, GET_256_FROM_64(l_price_tmp->units), &l_unit_price); + } else { + log_it( L_WARNING, "Units in pricelist is zero. "); + continue; + } + + if(IS_ZERO_256(l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) || + compare256(l_unit_price, l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) <= 0){ + l_price = l_price_tmp; + break; + } else { + log_it( L_WARNING, "Unit price in pricelist is greater than max allowable."); + } } + } else { + char *l_order_hash_str = dap_chain_hash_fast_to_str_new(&a_grace->usage->static_order_hash); + log_it(L_MSG, "Get price from order %s.", l_order_hash_str); + DAP_DELETE(l_order_hash_str); + if ((l_price = dap_chain_net_srv_get_price_from_order(a_grace->usage->service, "srv_vpn", &a_grace->usage->static_order_hash))){ + if (l_price->net->pub.id.uint64 != a_grace->usage->net->pub.id.uint64){ + log_it( L_WARNING, "Pricelist is not for net %s.", a_grace->usage->net->pub.name); + 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; + } - if(IS_ZERO_256(l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) || - compare256(l_unit_price, l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) <= 0){ - l_price = l_price_tmp; - break; - } else { - log_it( L_WARNING, "Unit price in pricelist is greater than max allowable."); + if (dap_strcmp(l_price->token, l_ticker) != 0){ + log_it( L_WARNING, "Token ticker in the pricelist and tx do not match"); + 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; + } + + if (l_price->units_uid.enm != l_tx_out_cond->subtype.srv_pay.unit.enm){ + log_it( L_WARNING, "Unit ID in the pricelist and tx do not match"); + 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; + } + + uint256_t l_unit_price = {}; + if (l_price->units != 0){ + DIV_256(l_price->value_datoshi, GET_256_FROM_64(l_price->units), &l_unit_price); + } else { + log_it( L_WARNING, "Units in pricelist is zero. "); + 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; + } + + if(IS_ZERO_256(l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) || + compare256(l_unit_price, l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) <= 0){ + } else { + log_it( L_WARNING, "Unit price in pricelist is greater than max allowable."); + 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; + } } } + 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 ); @@ -714,6 +813,13 @@ static bool s_grace_period_finish(usages_in_grace_t *a_grace_item) s_grace_error(l_grace, l_err); RET_WITH_DEL_A_GRACE; } else { // Start service in normal pay mode + if (dap_chain_net_get_state(l_net) == NET_STATE_OFFLINE) { + log_it(L_ERROR, "Can't pay service because net %s is offline.", l_net->pub.name); + l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_IS_OFFLINE; + s_grace_error(l_grace, l_err); + RET_WITH_DEL_A_GRACE; + } + log_it(L_INFO, "Tx is found in ledger."); l_grace->usage->tx_cond = l_tx; @@ -740,43 +846,91 @@ static bool s_grace_period_finish(usages_in_grace_t *a_grace_item) l_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(l_ledger, &l_grace->usage->tx_cond_hash); dap_stpcpy(l_grace->usage->token_ticker, l_ticker); - dap_chain_net_srv_price_t *l_price_tmp; - DL_FOREACH(l_grace->usage->service->pricelist, l_price_tmp) { - if (!l_price_tmp){ - continue; - } + if (dap_hash_fast_is_blank(&l_grace->usage->static_order_hash)){ + dap_chain_net_srv_price_t *l_price_tmp; + DL_FOREACH(l_grace->usage->service->pricelist, l_price_tmp) { + if (!l_price_tmp){ + continue; + } - if (l_price_tmp->net->pub.id.uint64 != l_grace->usage->net->pub.id.uint64){ - log_it( L_WARNING, "Pricelist is not set for net %s", l_grace->usage->net->pub.name); - continue; - } + if (l_price_tmp->net->pub.id.uint64 != l_grace->usage->net->pub.id.uint64){ + log_it( L_WARNING, "Pricelist is not for net %s.", l_grace->usage->net->pub.name); + continue; + } - if (dap_strcmp(l_price_tmp->token, l_ticker) != 0){ - log_it( L_WARNING, "Token ticker in the pricelist and tx do not match"); - continue; - } + if (dap_strcmp(l_price_tmp->token, l_ticker) != 0){ + log_it( L_WARNING, "Token ticker in the pricelist and tx do not match"); + continue; + } - if (l_price_tmp->units_uid.enm != l_tx_out_cond->subtype.srv_pay.unit.enm){ - log_it( L_WARNING, "Unit ID in the pricelist and tx do not match"); - continue; - } + if (l_price_tmp->units_uid.enm != l_tx_out_cond->subtype.srv_pay.unit.enm){ + log_it( L_WARNING, "Unit ID in the pricelist and tx do not match"); + continue; + } - uint256_t l_unit_price = {}; - if (l_price_tmp->units != 0){ - DIV_256(l_price_tmp->value_datoshi, GET_256_FROM_64(l_price_tmp->units), &l_unit_price); - } else { - log_it( L_WARNING, "Units in pricelist is zero. "); - continue; + uint256_t l_unit_price = {}; + if (l_price_tmp->units != 0){ + DIV_256(l_price_tmp->value_datoshi, GET_256_FROM_64(l_price_tmp->units), &l_unit_price); + } else { + log_it( L_WARNING, "Units in pricelist is zero. "); + continue; + } + + if(IS_ZERO_256(l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) || + compare256(l_unit_price, l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) <= 0){ + l_price = l_price_tmp; + break; + } else { + log_it( L_WARNING, "Unit price in pricelist is greater than max allowable."); + } } + } else { + char *l_order_hash_str = dap_chain_hash_fast_to_str_new(&l_grace->usage->static_order_hash); + log_it(L_MSG, "Get price from order %s.", l_order_hash_str); + DAP_DELETE(l_order_hash_str); + if ((l_price = dap_chain_net_srv_get_price_from_order(l_grace->usage->service, "srv_vpn", &l_grace->usage->static_order_hash))){ + if (l_price->net->pub.id.uint64 != l_grace->usage->net->pub.id.uint64){ + log_it( L_WARNING, "Pricelist is not for net %s.", l_grace->usage->net->pub.name); + l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; + s_grace_error(l_grace, l_err); + RET_WITH_DEL_A_GRACE; + } - if(IS_ZERO_256(l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) || - compare256(l_unit_price, l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) <= 0){ - l_price = l_price_tmp; - break; - } else { - log_it( L_WARNING, "Unit price in pricelist is greater than max allowable."); + if (dap_strcmp(l_price->token, l_ticker) != 0){ + log_it( L_WARNING, "Token ticker in the pricelist and tx do not match"); + l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; + s_grace_error(l_grace, l_err); + RET_WITH_DEL_A_GRACE; + } + + if (l_price->units_uid.enm != l_tx_out_cond->subtype.srv_pay.unit.enm){ + log_it( L_WARNING, "Unit ID in the pricelist and tx do not match"); + l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; + s_grace_error(l_grace, l_err); + RET_WITH_DEL_A_GRACE; + } + + uint256_t l_unit_price = {}; + if (l_price->units != 0){ + DIV_256(l_price->value_datoshi, GET_256_FROM_64(l_price->units), &l_unit_price); + } else { + log_it( L_WARNING, "Units in pricelist is zero. "); + l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; + s_grace_error(l_grace, l_err); + RET_WITH_DEL_A_GRACE; + } + + if(IS_ZERO_256(l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) || + compare256(l_unit_price, l_tx_out_cond->subtype.srv_pay.unit_price_max_datoshi) <= 0){ + } else { + log_it( L_WARNING, "Unit price in pricelist is greater than max allowable."); + l_err.code =DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_ACCEPT_TOKEN; + s_grace_error(l_grace, l_err); + RET_WITH_DEL_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 ); @@ -1039,7 +1193,7 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) } l_request->err_code = 0; - strncpy(l_request->ip_send, a_ch->stream->esocket->remote_addr_str, INET_ADDRSTRLEN - 1); + strncpy(l_request->ip_send, a_ch->stream->esocket->hostaddr, INET_ADDRSTRLEN - 1); l_request->ip_send[INET_ADDRSTRLEN - 1] = '\0'; // Compiler warning escape l_request->recv_time2 = dap_nanotime_now(); @@ -1063,6 +1217,13 @@ void s_stream_ch_packet_in(dap_stream_ch_t* a_ch , void* a_arg) case DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_SIGN_RESPONSE: { // Check receipt sign and make tx if success dap_chain_net_srv_usage_t * l_usage = l_srv_session->usage_active; + + if (dap_chain_net_get_state(l_usage->net) == NET_STATE_OFFLINE) { + log_it(L_ERROR, "Can't pay service because net %s is offline.", l_usage->net->pub.name); + l_err.code = DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_IS_OFFLINE; + break; + } + if (l_ch_pkt->hdr.data_size < sizeof(dap_chain_receipt_info_t)) { log_it(L_ERROR, "Wrong sign response size, %u when expected at least %zu with smth", l_ch_pkt->hdr.data_size, sizeof(dap_chain_receipt_info_t)); diff --git a/modules/channel/chain-voting/dap_stream_ch_chain_voting.c b/modules/channel/chain-voting/dap_stream_ch_chain_voting.c index 114aba6dd340bd82e6717899ab96655208e2de3f..8e683aeb087db0b3bd3050210f48d36e628c0b31 100644 --- a/modules/channel/chain-voting/dap_stream_ch_chain_voting.c +++ b/modules/channel/chain-voting/dap_stream_ch_chain_voting.c @@ -31,6 +31,7 @@ static struct voting_node_client_list *s_node_client_list = NULL; static size_t s_pkt_in_callback_count = 0; static struct voting_pkt_in_callback s_pkt_in_callback[16] = {}; +static pthread_rwlock_t s_node_client_list_lock; static void s_stream_ch_new(dap_stream_ch_t *a_ch, void *a_arg); static void s_stream_ch_delete(dap_stream_ch_t *a_ch, void *a_arg); @@ -40,6 +41,7 @@ int dap_stream_ch_chain_voting_init() { log_it(L_NOTICE, "Chains voting channel initialized"); + pthread_rwlock_init(&s_node_client_list_lock, NULL); dap_stream_ch_proc_add(DAP_STREAM_CH_ID_VOTING, s_stream_ch_new, s_stream_ch_delete, @@ -82,7 +84,9 @@ void dap_stream_ch_chain_voting_message_write(dap_chain_net_t *a_net, dap_chain_ size_t l_voting_pkt_size = sizeof(*a_voting_pkt) + a_voting_pkt->hdr.data_size; struct voting_node_client_list *l_node_client_item = NULL; if (a_remote_node_addr->uint64 != dap_chain_net_get_cur_addr_int(a_net)) { + pthread_rwlock_rdlock(&s_node_client_list_lock); HASH_FIND(hh, s_node_client_list, a_remote_node_addr, sizeof(dap_chain_node_addr_t), l_node_client_item); + pthread_rwlock_unlock(&s_node_client_list_lock); if (!l_node_client_item) { size_t node_info_size = 0; char *l_key = dap_chain_node_addr_to_hash_str(a_remote_node_addr); @@ -111,7 +115,9 @@ void dap_stream_ch_chain_voting_message_write(dap_chain_net_t *a_net, dap_chain_ l_node_client_item->node_addr = *a_remote_node_addr; l_node_client_item->node_info = l_node_info; l_node_client_item->node_client = l_node_client; + pthread_rwlock_wrlock(&s_node_client_list_lock); HASH_ADD(hh, s_node_client_list, node_addr, sizeof(dap_chain_node_addr_t), l_node_client_item); + pthread_rwlock_unlock(&s_node_client_list_lock); } if (!l_node_client_item->node_client) { log_it(L_ERROR, "NULL node_client in item of voting channel"); @@ -136,6 +142,21 @@ void dap_stream_ch_chain_voting_deinit() } } +void dap_stream_ch_chain_voting_close_all_clients(dap_chain_net_id_t a_net_id) +{ + struct voting_node_client_list *l_node_info_item, *l_node_info_tmp; + pthread_rwlock_wrlock(&s_node_client_list_lock); + HASH_ITER(hh, s_node_client_list, l_node_info_item, l_node_info_tmp) { + // Clang bug at this, l_node_info_item should change at every loop cycle + if (l_node_info_item->node_client->net->pub.id.uint64 == a_net_id.uint64){ + HASH_DEL(s_node_client_list, l_node_info_item); + dap_chain_node_client_close_mt(l_node_info_item->node_client); + DAP_DELETE(l_node_info_item); + } + } + pthread_rwlock_unlock(&s_node_client_list_lock); +} + static void s_stream_ch_new(dap_stream_ch_t *a_ch, void *a_arg) { UNUSED(a_arg); @@ -163,6 +184,18 @@ static void s_stream_ch_packet_in(dap_stream_ch_t *a_ch, void *a_arg) } dap_stream_ch_chain_voting_pkt_t *l_voting_pkt = (dap_stream_ch_chain_voting_pkt_t *)l_ch_pkt->data; + dap_chain_net_t *l_net = dap_chain_net_by_id(l_voting_pkt->hdr.net_id); + + if (!l_net) + return; + if (dap_chain_net_get_state(l_net) == NET_STATE_OFFLINE) { + log_it(L_ERROR, "Reject packet because net %s is offline", l_net->pub.name); + dap_stream_ch_chain_voting_pkt_write_unsafe(a_ch, DAP_STREAM_CH_CHAIN_VOTING_PKT_TYPE_ERROR, l_voting_pkt->hdr.net_id.uint64, + &l_voting_pkt->hdr.sender_node_addr, &l_voting_pkt->hdr.receiver_node_addr, NULL, 0); + a_ch->stream->esocket->flags |= DAP_SOCK_SIGNAL_CLOSE; + return; + } + dap_proc_thread_callback_add(dap_proc_thread_get(a_ch->stream_worker->worker->id), s_callback_pkt_in_call_all, DAP_DUP_SIZE(l_voting_pkt, l_voting_pkt_size)); dap_stream_ch_chain_voting_t *l_ch_chain_voting = DAP_STREAM_CH_CHAIN_VOTING(a_ch); diff --git a/modules/channel/chain-voting/include/dap_stream_ch_chain_voting.h b/modules/channel/chain-voting/include/dap_stream_ch_chain_voting.h index bc8c16913a29449521966fb1b704e5d7322b4028..f55f67014b3fbedfd086279a0d3032c471ecf504 100644 --- a/modules/channel/chain-voting/include/dap_stream_ch_chain_voting.h +++ b/modules/channel/chain-voting/include/dap_stream_ch_chain_voting.h @@ -10,6 +10,7 @@ #define DAP_STREAM_CH_CHAIN_VOTING_PKT_TYPE_DATA 0x01 #define DAP_STREAM_CH_CHAIN_VOTING_PKT_TYPE_TEST 0x02 +#define DAP_STREAM_CH_CHAIN_VOTING_PKT_TYPE_ERROR 0xFF #define DAP_STREAM_CH_ID_VOTING 'V' @@ -64,5 +65,5 @@ size_t dap_stream_ch_chain_voting_pkt_write_unsafe(dap_stream_ch_t *a_ch, uint8_ int dap_stream_ch_chain_voting_init(); void dap_stream_ch_chain_voting_deinit(); - +void dap_stream_ch_chain_voting_close_all_clients(dap_chain_net_id_t a_net_id); void dap_stream_ch_voting_queue_clear(); diff --git a/modules/common/dap_chain_datum.c b/modules/common/dap_chain_datum.c index dafae10e2933d5c059d56f1fdc450bdd56fcaaf1..dc3cae2a857ae95d56fce7799411650f8d44f0cb 100644 --- a/modules/common/dap_chain_datum.c +++ b/modules/common/dap_chain_datum.c @@ -503,17 +503,15 @@ bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum, DAP_DELETE(l_hash_str); } break; case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE: { - char *l_value_str = dap_chain_balance_print(((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_value); - char *l_coins_str = dap_chain_balance_to_coins(((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_value); +// char *l_value_str = dap_chain_balance_print(((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_value); + char *l_rate_str = dap_chain_balance_to_coins(((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.rate); dap_string_append_printf(a_str_out, "\t\t\t net id: 0x%016"DAP_UINT64_FORMAT_x"\n" "\t\t\t buy_token: %s\n" - "\t\t\t buy_value: %s (%s)\n", + "\t\t\t rate: %s (%s)\n", ((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_net_id.uint64, ((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_token, - l_coins_str, - l_value_str); - DAP_DELETE(l_value_str); - DAP_DELETE(l_coins_str); + l_rate_str); + DAP_DELETE(l_rate_str); } break; case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK: { dap_time_t l_ts_exp = ((dap_chain_tx_out_cond_t*)item)->subtype.srv_stake_lock.time_unlock; diff --git a/modules/common/dap_chain_datum_tx_items.c b/modules/common/dap_chain_datum_tx_items.c index 64e09ba41a5304fa982667ef72dc667f4388616f..233099e58e35ec55510c9a6e6f2f50eb6baec61b 100644 --- a/modules/common/dap_chain_datum_tx_items.c +++ b/modules/common/dap_chain_datum_tx_items.c @@ -504,13 +504,13 @@ json_object *dap_chain_datum_tx_item_out_cond_srv_pay_to_json(dap_chain_tx_out_c dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_xchange(dap_chain_net_srv_uid_t a_srv_uid, dap_chain_net_id_t a_sell_net_id, uint256_t a_value_sell, dap_chain_net_id_t a_buy_net_id, - const char *a_token, uint256_t a_value_buy, + const char *a_token, uint256_t a_value_rate, const dap_chain_addr_t *a_seller_addr, const void *a_params, uint32_t a_params_size) { if (!a_token) return NULL; - if (IS_ZERO_256(a_value_sell) || IS_ZERO_256(a_value_buy)) + if (IS_ZERO_256(a_value_sell) || IS_ZERO_256(a_value_rate)) return NULL; dap_chain_tx_out_cond_t *l_item = DAP_NEW_Z_SIZE(dap_chain_tx_out_cond_t, sizeof(dap_chain_tx_out_cond_t) + a_params_size); l_item->header.item_type = TX_ITEM_TYPE_OUT_COND; @@ -520,7 +520,7 @@ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_xchange(dap l_item->subtype.srv_xchange.buy_net_id = a_buy_net_id; l_item->subtype.srv_xchange.sell_net_id = a_sell_net_id; strncpy(l_item->subtype.srv_xchange.buy_token, a_token, DAP_CHAIN_TICKER_SIZE_MAX - 1); - l_item->subtype.srv_xchange.buy_value = a_value_buy; + l_item->subtype.srv_xchange.rate = a_value_rate; l_item->subtype.srv_xchange.seller_addr = *a_seller_addr; l_item->tsd_size = a_params_size; if (a_params_size) { @@ -539,12 +539,12 @@ json_object* dap_chain_datum_tx_item_out_cond_srv_xchange_to_json(dap_chain_tx_o json_object *l_obj_buy_net_id = dap_chain_net_id_to_json(a_srv_xchange->subtype.srv_xchange.buy_net_id); json_object *l_obj_sell_net_id = dap_chain_net_id_to_json(a_srv_xchange->subtype.srv_xchange.sell_net_id); json_object *l_obj_buy_token = json_object_new_string(a_srv_xchange->subtype.srv_xchange.buy_token); - char *l_value_buy = dap_chain_balance_print(a_srv_xchange->subtype.srv_xchange.buy_value); - json_object *l_obj_value_buy = json_object_new_string(l_value_buy); - DAP_DELETE(l_value_buy); + char *l_value_rate = dap_chain_balance_print(a_srv_xchange->subtype.srv_xchange.rate); + json_object *l_obj_value_rate = json_object_new_string(l_value_rate); + DAP_DELETE(l_value_rate); json_object *l_obj_seller_addr = dap_chain_addr_to_json(&a_srv_xchange->subtype.srv_xchange.seller_addr); json_object_object_add(l_object, "value", l_obj_value); - json_object_object_add(l_object, "valueBuy", l_obj_value_buy); + json_object_object_add(l_object, "valueRate", l_obj_value_rate); json_object_object_add(l_object, "srvUID", l_obj_srv_uid); json_object_object_add(l_object, "buyNetId", l_obj_buy_net_id); json_object_object_add(l_object, "sellNetId", l_obj_sell_net_id); diff --git a/modules/common/include/dap_chain_datum_tx_items.h b/modules/common/include/dap_chain_datum_tx_items.h index 13a728fbc469102b4cab01da8c047e3cb2ba3354..d9815983dd2a89639e56d980767721fdbdb5b395 100644 --- a/modules/common/include/dap_chain_datum_tx_items.h +++ b/modules/common/include/dap_chain_datum_tx_items.h @@ -177,7 +177,7 @@ json_object *dap_chain_datum_tx_item_out_cond_srv_pay_to_json(dap_chain_tx_out_c */ dap_chain_tx_out_cond_t *dap_chain_datum_tx_item_out_cond_create_srv_xchange(dap_chain_net_srv_uid_t a_srv_uid, dap_chain_net_id_t a_sell_net_id, uint256_t a_value_sell, dap_chain_net_id_t a_buy_net_id, - const char *a_token, uint256_t a_value_buy, const dap_chain_addr_t *a_seller_addr, + const char *a_token, uint256_t a_value_rate, const dap_chain_addr_t *a_seller_addr, const void *a_params, uint32_t a_params_size); json_object* dap_chain_datum_tx_item_out_cond_srv_xchange_to_json(dap_chain_tx_out_cond_t* a_srv_xchange); diff --git a/modules/common/include/dap_chain_datum_tx_out_cond.h b/modules/common/include/dap_chain_datum_tx_out_cond.h index 5bce661a7e0c06a61fd4f86a6fab3bef6e6a5e6d..0348c717a26930031648b9f4cd109a728567673d 100644 --- a/modules/common/include/dap_chain_datum_tx_out_cond.h +++ b/modules/common/include/dap_chain_datum_tx_out_cond.h @@ -98,7 +98,7 @@ typedef struct dap_chain_tx_out_cond { // Chain network to change to dap_chain_net_id_t buy_net_id; // Total amount of datoshi to change to - uint256_t buy_value; + uint256_t rate; // Token ticker to change to char buy_token[DAP_CHAIN_TICKER_SIZE_MAX]; // Seller address diff --git a/modules/consensus/esbocs/dap_chain_cs_esbocs.c b/modules/consensus/esbocs/dap_chain_cs_esbocs.c index abe85906fa54f48572d2c24e121c2206e12bde44..fae28da6293526912b0d667e121e5caed7adb728 100644 --- a/modules/consensus/esbocs/dap_chain_cs_esbocs.c +++ b/modules/consensus/esbocs/dap_chain_cs_esbocs.c @@ -429,6 +429,31 @@ bool dap_chain_esbocs_started() return s_session_items; } +void dap_chain_esbocs_stop_timer(dap_chain_net_id_t a_net_id) +{ + dap_chain_esbocs_session_t *l_session; + DL_FOREACH(s_session_items, l_session) { + if (l_session->chain->net_id.uint64 == a_net_id.uint64 && + l_session->cs_timer){ + log_it(L_INFO, "Stop consensus timer for net: %s, chain: %s", dap_chain_net_by_id(a_net_id)->pub.name, l_session->chain->name); + dap_timerfd_delete_mt(l_session->cs_timer->worker, l_session->cs_timer->esocket_uuid); + l_session->cs_timer = NULL; + } + } + dap_stream_ch_chain_voting_close_all_clients(a_net_id); +} + +void dap_chain_esbocs_start_timer(dap_chain_net_id_t a_net_id) +{ + dap_chain_esbocs_session_t *l_session; + DL_FOREACH(s_session_items, l_session) { + if (l_session->chain->net_id.uint64 == a_net_id.uint64){ + log_it(L_INFO, "Start consensus timer for net: %s, chain: %s", dap_chain_net_by_id(a_net_id)->pub.name, l_session->chain->name); + l_session->cs_timer = dap_timerfd_start(1000, s_session_timer, l_session); + } + } +} + static uint256_t s_callback_get_minimum_fee(dap_chain_t *a_chain) { dap_chain_cs_blocks_t *l_blocks = DAP_CHAIN_CS_BLOCKS(a_chain); diff --git a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h index f680c1b6958951c9224f61f36394fa91a98c2988..fb23fe97a9617a75ef0185b5041f14f6a035fa8b 100644 --- a/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h +++ b/modules/consensus/esbocs/include/dap_chain_cs_esbocs.h @@ -209,3 +209,6 @@ typedef struct dap_chain_esbocs_session { int dap_chain_cs_esbocs_init(); void dap_chain_cs_esbocs_deinit(void); bool dap_chain_esbocs_started(); + +void dap_chain_esbocs_stop_timer(dap_chain_net_id_t a_net_id); +void dap_chain_esbocs_start_timer(dap_chain_net_id_t a_net_id); diff --git a/modules/net/CMakeLists.txt b/modules/net/CMakeLists.txt index 533ef70d5b997302fc923fb460b8ebec09db1daa..bc27aa577a109f6f19686661fde8901bada25d4d 100644 --- a/modules/net/CMakeLists.txt +++ b/modules/net/CMakeLists.txt @@ -30,7 +30,7 @@ add_library(${PROJECT_NAME} STATIC ${DAP_CHAIN_NET_SRCS} ${DAP_CHAIN_NET_HEADERS target_link_libraries(${PROJECT_NAME} dap_core dap_crypto dap_client dap_io dap_notify_srv dap_cli_server dap_chain dap_chain_wallet dap_chain_net_srv dap_chain_mempool dap_global_db dap_chain_net_srv_xchange dap_chain_cs_none - dap_stream_ch_chain_net dap_stream_ch_chain_voting) + dap_stream_ch_chain_net dap_stream_ch_chain_voting dap_chain_cs_esbocs) if(LINUX) target_link_libraries(${PROJECT_NAME} resolv) endif() diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index e491970c19f5546474418865d3b909786b52d916..88481d80d146c38829c75a660a81645b6d3664e3 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -117,6 +117,7 @@ #include "dap_chain_net_srv_stake_pos_delegate.h" #include "dap_chain_net_srv_xchange.h" #include "dap_chain_node_net_ban_list.h" +#include "dap_chain_cs_esbocs.h" #include <stdio.h> #include <sys/types.h> @@ -372,8 +373,14 @@ int dap_chain_net_state_go_to(dap_chain_net_t * a_net, dap_chain_net_state_t a_n } PVT(a_net)->state_target = a_new_state; //PVT(a_net)->flags |= F_DAP_CHAIN_NET_SYNC_FROM_ZERO; // TODO set this flag according to -mode argument from command line - if (a_new_state == NET_STATE_OFFLINE) + if(a_new_state == NET_STATE_ONLINE) + dap_chain_esbocs_start_timer(a_net->pub.id); + + if (a_new_state == NET_STATE_OFFLINE){ + dap_chain_esbocs_stop_timer(a_net->pub.id); return 0; + } + return dap_proc_thread_callback_add(NULL, s_net_states_proc, a_net); } diff --git a/modules/net/dap_chain_net_tx.c b/modules/net/dap_chain_net_tx.c index 9f983be66b01e70a7d89a74304cc092ef8ab8d1a..55b8824e4471b74a758bd2e57f25215ed194bc72 100644 --- a/modules/net/dap_chain_net_tx.c +++ b/modules/net/dap_chain_net_tx.c @@ -291,7 +291,7 @@ static void s_get_tx_cond_chain_callback(dap_chain_net_t* a_net, dap_chain_datum if( l_args->ret ){ int l_item_idx = 0; byte_t *l_tx_item; - + dap_hash_fast_t * l_tx_hash = dap_chain_node_datum_tx_calc_hash(a_tx); // 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){ dap_chain_tx_in_cond_t * l_in_cond = (dap_chain_tx_in_cond_t *) l_tx_item; @@ -299,9 +299,21 @@ static void s_get_tx_cond_chain_callback(dap_chain_net_t* a_net, dap_chain_datum (uint32_t)l_args->tx_last_cond_idx == l_in_cond->header.tx_out_prev_idx ){ // Found output // We're the next tx in tx cond chain l_args->ret = dap_list_append(l_args->ret, a_tx); + // Check cond output and update tx last hash and index + dap_chain_tx_out_cond_t * l_out_cond = NULL; + int l_out_item_idx = 0; + if (l_out_cond = dap_chain_datum_tx_out_cond_get(a_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_out_item_idx)){ + if ( l_out_cond->header.srv_uid.uint64 == l_args->srv_uid.uint64 ){ // We found output with target service uuid + l_args->tx_last = a_tx; // Record current transaction as the last in tx chain + memcpy(&l_args->tx_last_hash, l_tx_hash, sizeof(*l_tx_hash)); // Record current hash + l_args->tx_last_cond_idx = l_out_item_idx; + } + } + break; } l_item_idx++; } + DAP_DELETE(l_tx_hash); }else if(a_tx){ dap_hash_fast_t * l_tx_hash = dap_chain_node_datum_tx_calc_hash(a_tx); if (!l_tx_hash) { @@ -311,11 +323,10 @@ static void s_get_tx_cond_chain_callback(dap_chain_net_t* a_net, dap_chain_datum if (dap_hash_fast_compare(l_tx_hash,l_args->tx_begin_hash)) { // Found condition int l_item_idx = 0; - byte_t *l_tx_item; // Get items from transaction - while ((l_tx_item = dap_chain_datum_tx_item_get(a_tx, &l_item_idx, TX_ITEM_TYPE_OUT_COND , NULL)) != NULL){ - dap_chain_tx_out_cond_t * l_out_cond = (dap_chain_tx_out_cond_t *) l_tx_item; + dap_chain_tx_out_cond_t * l_out_cond = NULL; + while (l_out_cond = dap_chain_datum_tx_out_cond_get(a_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_item_idx)){ if ( l_out_cond->header.srv_uid.uint64 == l_args->srv_uid.uint64 ){ // We found output with target service uuid l_args->tx_last = a_tx; // Record current transaction as the last in tx chain memcpy(&l_args->tx_last_hash, l_tx_hash, sizeof(*l_tx_hash)); // Record current hash @@ -385,8 +396,8 @@ static void s_get_tx_cond_all_for_addr_callback(dap_chain_net_t* a_net, dap_chai 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( l_tx ){ // Its input thats closing output for target address - we note it +// 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_chain_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, &l_tx->hash); } @@ -395,8 +406,8 @@ static void s_get_tx_cond_all_for_addr_callback(dap_chain_net_t* a_net, dap_chai 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( l_tx ){ // Its input thats closing conditioned tx related with target address, collect it +// 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; @@ -407,6 +418,7 @@ static void s_get_tx_cond_all_for_addr_callback(dap_chain_net_t* a_net, dap_chai } // 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:{ @@ -415,7 +427,7 @@ static void s_get_tx_cond_all_for_addr_callback(dap_chain_net_t* a_net, dap_chai 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); + dap_chain_tx_hh_add(&l_args->tx_all_hh, l_tx); l_tx_for_addr = true; } }break; @@ -425,7 +437,7 @@ static void s_get_tx_cond_all_for_addr_callback(dap_chain_net_t* a_net, dap_chai 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); + dap_chain_tx_hh_add(&l_args->tx_all_hh, l_tx); l_tx_for_addr = true; } }break; diff --git a/modules/net/dap_chain_node_client.c b/modules/net/dap_chain_node_client.c index bca24578358ed8ce00644532da641e3cefc604e7..98afec04ffcb5401c46382aa0839b25529bdf52b 100644 --- a/modules/net/dap_chain_node_client.c +++ b/modules/net/dap_chain_node_client.c @@ -64,6 +64,7 @@ #include "dap_stream_ch_chain.h" #include "dap_stream_ch_chain_pkt.h" #include "dap_stream_ch_chain_net.h" +#include "dap_stream_ch_proc.h" #include "dap_stream_ch_chain_net_pkt.h" #include "dap_stream_ch_chain_net_srv.h" #include "dap_stream_ch_chain_voting.h" diff --git a/modules/net/srv/dap_chain_net_srv_order.c b/modules/net/srv/dap_chain_net_srv_order.c index 810d334befdd7969e66fd389f8d7cf344d571378..07c316c94b588942b4bccc98d475340046e00799 100644 --- a/modules/net/srv/dap_chain_net_srv_order.c +++ b/modules/net/srv/dap_chain_net_srv_order.c @@ -550,6 +550,8 @@ void dap_chain_net_srv_order_dump_to_string(dap_chain_net_srv_order_t *a_order,d DAP_DELETE(l_balance); if( a_order->price_unit.uint32 ) dap_string_append_printf(a_str_out, " price_unit: %s\n", dap_chain_net_srv_price_unit_uid_to_str(a_order->price_unit) ); + if(a_order->price_ticker) + dap_string_append_printf(a_str_out, " price_token: %s\n", a_order->price_ticker); if ( a_order->node_addr.uint64) dap_string_append_printf(a_str_out, " node_addr: "NODE_ADDR_FP_STR"\n", NODE_ADDR_FP_ARGS_S(a_order->node_addr) ); diff --git a/modules/net/srv/include/dap_chain_net_srv.h b/modules/net/srv/include/dap_chain_net_srv.h index d8f6a3b43d61f9fcf5d057862ba19122a61800df..feb61aeb697529160a37fd65065774b584fec18e 100755 --- a/modules/net/srv/include/dap_chain_net_srv.h +++ b/modules/net/srv/include/dap_chain_net_srv.h @@ -104,6 +104,7 @@ typedef struct dap_chain_net_srv_price #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_SERVICE_IN_CLIENT_MODE 0x00000102 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_NOT_FOUND 0x00000200 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_NO_LEDGER 0x00000201 +#define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_NETWORK_IS_OFFLINE 0x00000202 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_CANT_ADD_USAGE 0x00000300 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NOT_FOUND 0x00000400 #define DAP_STREAM_CH_CHAIN_NET_SRV_PKT_TYPE_RESPONSE_ERROR_CODE_TX_COND_NO_COND_OUT 0x00000401 diff --git a/modules/service/vpn/dap_chain_net_srv_vpn.c b/modules/service/vpn/dap_chain_net_srv_vpn.c index ad2d44767bb9e6123bd0b088754873dc35dd49f3..11f6558f8f12e62cee4c1e800b2d34d3974f7157 100644 --- a/modules/service/vpn/dap_chain_net_srv_vpn.c +++ b/modules/service/vpn/dap_chain_net_srv_vpn.c @@ -82,7 +82,6 @@ typedef struct iphdr dap_os_iphdr_t; #include "dap_strfuncs.h" #include "dap_config.h" -#include "dap_context.h" #include "dap_events_socket.h" #include "dap_http_client.h" @@ -313,6 +312,10 @@ static bool s_tun_client_send_data(dap_chain_net_srv_ch_vpn_info_t * l_ch_vpn_in DAP_DEL_Z(l_pkt_out); return false; } + /* + dap_stream_worker_t *l_stream_worker = (dap_stream_worker_t *)dap_worker_get_current()->_inheritor; + s_tun_client_send_data_inter(l_stream_worker->queue_ch_io_input[l_ch_vpn_info->worker->id], l_ch_vpn_info->ch_vpn, l_pkt_out); + */ if(s_debug_more){ #ifdef DAP_OS_LINUX struct in_addr l_in_daddr = { .s_addr = ((dap_os_iphdr_t*)l_pkt_out->data)->daddr }; @@ -373,7 +376,7 @@ static void s_tun_recv_msg_callback(dap_events_socket_t * a_esocket_queue, void switch (l_msg->type) { case TUN_SOCKET_MSG_ESOCKET_REASSIGNED: { assert(l_msg->esocket_reassigment.worker_id < s_tun_sockets_count); - dap_chain_net_srv_vpn_tun_socket_t* l_tun_sock = s_tun_sockets[a_esocket_queue->worker->id]; + dap_chain_net_srv_vpn_tun_socket_t* l_tun_sock = s_tun_sockets[a_esocket_queue->context->worker->id]; assert(l_tun_sock); dap_chain_net_srv_ch_vpn_info_t* l_info = NULL; HASH_FIND(hh, l_tun_sock->clients, &l_msg->esocket_reassigment.addr, sizeof(l_msg->esocket_reassigment.addr), l_info); @@ -381,11 +384,11 @@ static void s_tun_recv_msg_callback(dap_events_socket_t * a_esocket_queue, void l_info->worker = dap_events_worker_get(l_msg->esocket_reassigment.worker_id); l_info->queue_msg = s_tun_sockets_queue_msg[l_msg->esocket_reassigment.worker_id]; l_info->is_reassigned_once = true; - l_info->is_on_this_worker = (a_esocket_queue->worker->id == l_msg->esocket_reassigment.worker_id); + l_info->is_on_this_worker = (a_esocket_queue->context->worker->id == l_msg->esocket_reassigment.worker_id); if (s_debug_more) { char l_addrbuf[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &l_msg->esocket_reassigment.addr, l_addrbuf, sizeof(l_addrbuf)); - log_it(L_INFO, "Tun:%u message: addr %s reassign on worker #%u", a_esocket_queue->worker->id, + log_it(L_INFO, "Tun:%u message: addr %s reassign on worker #%u", a_esocket_queue->context->worker->id, l_addrbuf, l_msg->esocket_reassigment.worker_id); } } @@ -393,13 +396,13 @@ static void s_tun_recv_msg_callback(dap_events_socket_t * a_esocket_queue, void char l_addrbuf[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &l_msg->esocket_reassigment.addr, l_addrbuf, sizeof(l_addrbuf)); log_it(L_INFO, "Reassigment message for address %s on worker %u comes but no such address was found on tun socket %u", - l_addrbuf, l_msg->esocket_reassigment.worker_id, a_esocket_queue->worker->id); + l_addrbuf, l_msg->esocket_reassigment.worker_id, a_esocket_queue->context->worker->id); } } break; /* l_msg->type == TUN_SOCKET_MSG_ESOCKET_REASSIGNED */ case TUN_SOCKET_MSG_IP_ASSIGNED:{ assert(l_msg->ip_assigment.worker_id < s_tun_sockets_count); - dap_chain_net_srv_vpn_tun_socket_t * l_tun_sock = s_tun_sockets[a_esocket_queue->worker->id]; + dap_chain_net_srv_vpn_tun_socket_t * l_tun_sock = s_tun_sockets[a_esocket_queue->context->worker->id]; assert(l_tun_sock); dap_chain_net_srv_ch_vpn_info_t * l_new_info = NULL; @@ -420,7 +423,7 @@ static void s_tun_recv_msg_callback(dap_events_socket_t * a_esocket_queue, void l_new_info->queue_msg = s_tun_sockets_queue_msg[l_msg->ip_assigment.worker_id]; l_new_info->usage_id = l_msg->ip_assigment.usage_id; l_new_info->is_reassigned_once = l_msg->is_reassigned_once; - l_new_info->is_on_this_worker = (l_msg->ip_assigment.worker_id == a_esocket_queue->worker->id); + l_new_info->is_on_this_worker = (l_msg->ip_assigment.worker_id == a_esocket_queue->context->worker->id); l_new_info->esocket = l_msg->esocket; l_new_info->esocket_uuid = l_msg->esocket_uuid; l_new_info->worker = dap_events_worker_get(l_msg->ip_assigment.worker_id); @@ -428,7 +431,7 @@ static void s_tun_recv_msg_callback(dap_events_socket_t * a_esocket_queue, void if (dap_log_level_get() <= L_INFO) { char l_addrbuf[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &l_msg->ip_assigment.addr, l_addrbuf, sizeof(l_addrbuf)); - log_it(L_DEBUG, "Tun:%u message: addr %s assigned for worker #%u on tun #u", a_esocket_queue->worker->id, + log_it(L_DEBUG, "Tun:%u message: addr %s assigned for worker #%u on tun #u", a_esocket_queue->context->worker->id, l_addrbuf, l_msg->ip_assigment.worker_id); } } @@ -436,7 +439,7 @@ static void s_tun_recv_msg_callback(dap_events_socket_t * a_esocket_queue, void case TUN_SOCKET_MSG_IP_UNASSIGNED:{ assert(l_msg->ip_unassigment.worker_id < s_tun_sockets_count); - dap_chain_net_srv_vpn_tun_socket_t *l_tun_sock = s_tun_sockets[a_esocket_queue->worker->id]; + dap_chain_net_srv_vpn_tun_socket_t *l_tun_sock = s_tun_sockets[a_esocket_queue->context->worker->id]; assert(l_tun_sock); dap_chain_net_srv_ch_vpn_info_t *l_new_info = NULL; @@ -457,18 +460,18 @@ static void s_tun_recv_msg_callback(dap_events_socket_t * a_esocket_queue, void }break; /* l_msg->type == TUN_SOCKET_MSG_IP_UNASSIGNED */ case TUN_SOCKET_MSG_CH_VPN_SEND: { - if (dap_context_find(a_esocket_queue->worker->context, l_msg->esocket_uuid) == l_msg->esocket) { + if (dap_context_find(a_esocket_queue->context->worker->context, l_msg->esocket_uuid) == l_msg->esocket) { s_tun_client_send_data_unsafe(l_msg->ch_vpn, l_msg->ch_vpn_send.pkt); if (s_debug_more) { char l_addrbuf[INET_ADDRSTRLEN]; inet_ntop(AF_INET, &l_msg->ip_assigment.addr, l_addrbuf, sizeof(l_addrbuf)); log_it(L_DEBUG, "Tun:%u message: send %u bytes for ch vpn protocol", - a_esocket_queue->worker->id, l_msg->ch_vpn_send.pkt->header.op_data.data_size); + a_esocket_queue->context->worker->id, l_msg->ch_vpn_send.pkt->header.op_data.data_size); } } else { log_it(L_ERROR, "MSG: No esocket %p on worker #%u, lost %d data", - l_msg->esocket, a_esocket_queue->worker->id, l_msg->ch_vpn_send.pkt->header.op_data.data_size); + l_msg->esocket, a_esocket_queue->context->worker->id, l_msg->ch_vpn_send.pkt->header.op_data.data_size); } DAP_DELETE(l_msg->ch_vpn_send.pkt); } break; /* l_msg->type == TUN_SOCKET_MSG_CH_VPN_SEND */ @@ -1195,7 +1198,7 @@ static void s_ch_vpn_esocket_unassigned(dap_events_socket_t* a_es, dap_worker_t //dap_chain_net_srv_ch_vpn_info_t * l_info = NULL; // HASH_FIND(hh,l_tun_sock->clients,&l_ch_vpn->addr_ipv4 , sizeof (l_ch_vpn->addr_ipv4), l_info); - s_tun_send_msg_esocket_reassigned_all_inter(a_es->worker->id, l_ch_vpn, l_ch_vpn->ch->stream->esocket, + s_tun_send_msg_esocket_reassigned_all_inter(a_es->context->worker->id, l_ch_vpn, l_ch_vpn->ch->stream->esocket, l_ch_vpn->ch->stream->esocket_uuid, l_ch_vpn->addr_ipv4); } @@ -1249,7 +1252,9 @@ static void s_ch_vpn_delete(dap_stream_ch_t* a_ch, void* arg) usage_client_t * l_usage_client = NULL; dap_chain_net_srv_stream_session_t *l_srv_session = DAP_CHAIN_NET_SRV_STREAM_SESSION(l_ch_vpn->ch->stream->session); - dap_timerfd_delete_mt(l_srv_session->usage_active->client->stream_worker->worker, l_srv_session->usage_active->timer_es_uuid); + if (l_srv_session && l_srv_session->usage_active && + l_srv_session->usage_active->client && l_srv_session->usage_active->client->stream_worker) + dap_timerfd_delete_mt(l_srv_session->usage_active->client->stream_worker->worker, l_srv_session->usage_active->timer_es_uuid); bool l_is_unleased = false; if ( l_ch_vpn->addr_ipv4.s_addr ){ // if leased address @@ -1339,10 +1344,12 @@ static void s_update_limits(dap_stream_ch_t * a_ch , if( a_srv_session->limits_ts <= 0 && !a_usage->is_grace){ log_it(L_INFO, "Limits by timestamp are over. Switch to the next receipt"); - dap_sign_t * l_receipt_sign = dap_chain_datum_tx_receipt_sign_get( a_usage->receipt_next, a_usage->receipt_next->size, 1); - if ( ! l_receipt_sign ){ - log_it(L_WARNING, "Next receipt does not have client's sign. Delete it."); - DAP_DEL_Z(a_usage->receipt_next); + if (a_usage->receipt_next){ + dap_sign_t * l_receipt_sign = dap_chain_datum_tx_receipt_sign_get( a_usage->receipt_next, a_usage->receipt_next->size, 1); + if ( ! l_receipt_sign ){ + log_it(L_WARNING, "Next receipt does not have client's sign. Delete it."); + DAP_DEL_Z(a_usage->receipt_next); + } } DAP_DEL_Z(a_usage->receipt); a_usage->receipt = a_usage->receipt_next; @@ -1401,11 +1408,12 @@ static void s_update_limits(dap_stream_ch_t * a_ch , if (a_srv_session->limits_bytes <= 0 && !a_usage->is_grace){ log_it(L_INFO, "Limits by traffic is over. Switch to the next receipt"); - // get a second signature - from the client (first sign in server, second sign in client) - dap_sign_t * l_receipt_sign = dap_chain_datum_tx_receipt_sign_get( a_usage->receipt_next, a_usage->receipt_next->size, 1); - if ( ! l_receipt_sign ){ - log_it(L_WARNING, "Next receipt does not have client's sign. Delete it."); - DAP_DEL_Z(a_usage->receipt_next); + if (a_usage->receipt_next){ + dap_sign_t * l_receipt_sign = dap_chain_datum_tx_receipt_sign_get( a_usage->receipt_next, a_usage->receipt_next->size, 1); + if ( ! l_receipt_sign ){ + log_it(L_WARNING, "Next receipt does not have client's sign. Delete it."); + DAP_DEL_Z(a_usage->receipt_next); + } } DAP_DEL_Z(a_usage->receipt); a_usage->receipt = a_usage->receipt_next; @@ -1843,9 +1851,9 @@ static void s_ch_packet_out(dap_stream_ch_t* a_ch, void* a_arg) static void s_es_tun_delete(dap_events_socket_t * a_es, void * arg) { (void) arg; - if (a_es->worker) { - s_tun_sockets[a_es->worker->id] = NULL; - dap_events_socket_remove_and_delete_unsafe(s_tun_sockets_queue_msg[a_es->worker->id],false); + if (a_es->context->worker) { + s_tun_sockets[a_es->context->worker->id] = NULL; + dap_events_socket_remove_and_delete_unsafe(s_tun_sockets_queue_msg[a_es->context->worker->id],false); log_it(L_NOTICE,"Destroyed TUN event socket"); } } @@ -1965,11 +1973,11 @@ static void s_es_tun_read(dap_events_socket_t * a_es, void * arg) } if (l_vpn_info) { if ( !l_vpn_info->is_on_this_worker && !l_vpn_info->is_reassigned_once && s_raw_server->auto_cpu_reassignment) { - log_it(L_NOTICE, "Reassigning from worker %u to %u", l_vpn_info->worker->id, a_es->worker->id); + log_it(L_NOTICE, "Reassigning from worker %u to %u", l_vpn_info->worker->id, a_es->context->worker->id); l_vpn_info->is_reassigned_once = true; - s_tun_send_msg_esocket_reassigned_all_inter(a_es->worker->id, l_vpn_info->ch_vpn, l_vpn_info->esocket, l_vpn_info->esocket_uuid, + s_tun_send_msg_esocket_reassigned_all_inter(a_es->context->worker->id, l_vpn_info->ch_vpn, l_vpn_info->esocket, l_vpn_info->esocket_uuid, l_vpn_info->addr_ipv4); - dap_events_socket_reassign_between_workers_mt(l_vpn_info->worker, l_vpn_info->esocket, a_es->worker); + dap_events_socket_reassign_between_workers_mt(l_vpn_info->worker, l_vpn_info->esocket, a_es->context->worker); } s_tun_client_send_data(l_vpn_info, a_es->buf_in, l_buf_in_size); } else if(s_debug_more) { @@ -2003,7 +2011,7 @@ static void s_es_tun_new(dap_events_socket_t * a_es, void * arg) (void) arg; dap_chain_net_srv_vpn_tun_socket_t * l_tun_socket = DAP_NEW_Z(dap_chain_net_srv_vpn_tun_socket_t); if ( l_tun_socket ){ - dap_worker_t * l_worker = l_tun_socket->worker = a_es->worker; + dap_worker_t * l_worker = l_tun_socket->worker = a_es->context->worker; uint32_t l_worker_id = l_tun_socket->worker_id = l_worker->id; l_tun_socket->es = a_es; diff --git a/modules/service/xchange/dap_chain_net_srv_xchange.c b/modules/service/xchange/dap_chain_net_srv_xchange.c index 9fcd359d8f2aa7ac083ffc10136b6946889c2f8b..41c4e2dedc754fb4e699191636353d7a47251518 100644 --- a/modules/service/xchange/dap_chain_net_srv_xchange.c +++ b/modules/service/xchange/dap_chain_net_srv_xchange.c @@ -50,6 +50,10 @@ #define LOG_TAG "dap_chain_net_srv_xchange" +typedef struct order_find_list{ + dap_list_t *tx_list; +}order_find_list_t; + static dap_chain_net_srv_fee_item_t *s_service_fees = NULL; // Governance statements for networks static pthread_rwlock_t s_service_fees_rwlock = PTHREAD_RWLOCK_INITIALIZER; @@ -86,9 +90,6 @@ int dap_chain_net_srv_xchange_init() "\tCreate a new order and tx with specified amount of datoshi to exchange with specified rate (buy / sell)\n" "srv_xchange order remove -net <net_name> -order <order_hash> -w <wallet_name>\n" "\tRemove order with specified order hash in specified net name\n" - "srv_xchange order update -net <net_name> -order <order_hash> -w <wallet_name> [-token_sell <token_ticker>] " - "[-net_buy <net_name>] [-token_buy <token_ticker>] [-coins <value>] [-rate <value>]\n" - "\tUpdate order with specified order hash in specified net name\n" "srv_xchange order history -net <net_name> {-order <order_hash> | -addr <wallet_addr>}" "\tShows transaction history for the selected order\n" "srv_xchange order status -net <net_name> -order <order_hash>" @@ -237,7 +238,8 @@ static bool s_xchange_verificator_callback(dap_ledger_t *a_ledger, dap_chain_tx_ return false; SUBTRACT_256_256(a_tx_out_cond->header.value, l_sell_again_val, &l_sell_val); MULT_256_256(a_tx_out_cond->header.value, l_buy_val, &l_seller_mul); - MULT_256_256(a_tx_out_cond->subtype.srv_xchange.buy_value, l_sell_val, &l_buyer_mul); + +// MULT_256_256(a_tx_out_cond->subtype.srv_xchange.buy_value, l_sell_val, &l_buyer_mul); if (compare256(l_seller_mul, l_buyer_mul) < 0) return false; @@ -496,7 +498,7 @@ static dap_chain_datum_tx_t *s_xchange_tx_create_exchange(dap_chain_net_srv_xcha bool l_pay_with_native = !dap_strcmp(a_price->token_buy, l_native_ticker); // find the transactions from which to take away coins uint256_t l_value_transfer, // how many coins to transfer - l_value_need = a_price->datoshi_buy, + l_value_need = a_datoshi_buy, //a_price->datoshi_buy, l_net_fee, l_service_fee, l_total_fee = a_datoshi_fee, @@ -894,6 +896,7 @@ char *s_xchange_order_create(dap_chain_net_srv_xchange_price_t *a_price, dap_cha dap_chain_hash_fast_t l_tx_hash = {}; dap_hash_fast(a_tx, dap_chain_datum_tx_get_size(a_tx), &l_tx_hash); a_price->tx_hash = l_tx_hash; + dap_chain_node_addr_t *l_node_addr = dap_chain_net_get_cur_addr(a_price->net); dap_chain_net_srv_price_unit_uid_t l_unit = { .uint32 = SERV_UNIT_UNDEFINED}; dap_chain_net_srv_uid_t l_uid = { .uint64 = DAP_CHAIN_NET_SRV_XCHANGE_ID }; uint256_t l_datoshi_buy = uint256_0; @@ -902,7 +905,7 @@ char *s_xchange_order_create(dap_chain_net_srv_xchange_price_t *a_price, dap_cha l_ext.datoshi_buy = l_datoshi_buy; strncpy(l_ext.token_buy, a_price->token_buy, DAP_CHAIN_TICKER_SIZE_MAX); uint32_t l_ext_size = sizeof(dap_srv_xchange_order_ext_t); - char *l_order_hash_str = dap_chain_net_srv_order_create(a_price->net, SERV_DIR_SELL, l_uid, g_node_addr, + char *l_order_hash_str = dap_chain_net_srv_order_create(a_price->net, SERV_DIR_SELL, l_uid, *l_node_addr, l_tx_hash, &a_price->datoshi_sell, l_unit, a_price->token_sell, 0, (uint8_t *)&l_ext, l_ext_size, 0, NULL, 0, a_price->wallet_key); return l_order_hash_str; @@ -914,7 +917,7 @@ char *s_xchange_order_create(dap_chain_net_srv_xchange_price_t *a_price, dap_cha * @param a_order * @return */ -dap_chain_net_srv_xchange_price_t *s_xchange_price_from_order(dap_chain_net_t *a_net, dap_chain_net_srv_order_t *a_order, bool a_ret_is_invalid) +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, bool a_ret_is_invalid) { if (!a_net || !a_order) return NULL; @@ -923,16 +926,24 @@ dap_chain_net_srv_xchange_price_t *s_xchange_price_from_order(dap_chain_net_t *a log_it(L_CRITICAL, "Memory allocation error"); return NULL; } - dap_srv_xchange_order_ext_t *l_ext = (dap_srv_xchange_order_ext_t *)a_order->ext_n_sign; - strcpy(l_price->token_buy, l_ext->token_buy); - l_price->datoshi_buy = l_ext->datoshi_buy; - strcpy(l_price->token_sell, a_order->price_ticker); - l_price->datoshi_sell = a_order->price; + + dap_chain_tx_out_cond_t *l_out_cond = dap_chain_datum_tx_out_cond_get(a_order, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE , NULL); + + strcpy(l_price->token_buy, l_out_cond->subtype.srv_xchange.buy_token); + MULT_256_256(l_out_cond->header.value, l_out_cond->subtype.srv_xchange.rate, &l_price->datoshi_buy); + + dap_hash_fast_t l_tx_hash = {}; + dap_hash_fast(a_order, dap_chain_datum_tx_get_size(a_order), &l_tx_hash); + const char *l_token_sell = dap_chain_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, &l_tx_hash); + strcpy(l_price->token_sell, l_token_sell); + + + l_price->datoshi_sell = l_out_cond->header.value; l_price->net = a_net; if (!IS_ZERO_256(l_price->datoshi_buy)) { - DIV_256_COIN(l_price->datoshi_buy, l_price->datoshi_sell, &l_price->rate); + l_price->rate = l_out_cond->subtype.srv_xchange.rate; dap_hash_fast_t *l_final_hash = dap_chain_ledger_get_final_chain_tx_hash(a_net->pub.ledger, - DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &a_order->tx_cond_hash); + DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_tx_hash); if (l_final_hash) { l_price->tx_hash = *l_final_hash; return l_price; @@ -970,9 +981,6 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c else if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, MIN(a_argc, a_arg_index + 1), "remove", NULL)) { l_cmd_num = CMD_REMOVE; } - else if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, MIN(a_argc, a_arg_index + 1), "update", NULL)) { - l_cmd_num = CMD_UPDATE; - } else if(dap_cli_server_cmd_find_option_val(a_argv, a_arg_index, MIN(a_argc, a_arg_index + 1), "history", NULL)) { l_cmd_num = CMD_HISTORY; } @@ -1104,28 +1112,45 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c dap_chain_wallet_close(l_wallet); return -14; } - // Create the order & put it to GDB - l_price->wallet_key = dap_chain_wallet_get_key(l_wallet, 0); - char *l_order_hash_str = s_xchange_order_create(l_price, l_tx); - dap_chain_wallet_close(l_wallet); - if (l_order_hash_str) { - dap_chain_hash_fast_from_str(l_order_hash_str, &l_price->order_hash); - if(!s_xchange_tx_put(l_tx, l_net)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't put transaction to mempool", l_sign_str); - dap_chain_net_srv_order_delete_by_hash_str_sync(l_net, l_order_hash_str); - DAP_DELETE(l_order_hash_str); - DAP_DELETE(l_price->wallet_str); - DAP_DELETE(l_price); - return -15; - } - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nSuccessfully created order %s", l_sign_str, l_order_hash_str); - DAP_DELETE(l_order_hash_str); - } else { - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't compose the order", l_sign_str); + dap_hash_fast_t l_tx_hash ={}; + dap_hash_fast(l_tx, dap_chain_datum_tx_get_size(l_tx), &l_tx_hash); + if(!s_xchange_tx_put(l_tx, l_net)) { + dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't put transaction to mempool", l_sign_str); DAP_DELETE(l_price->wallet_str); DAP_DELETE(l_price); - return -18; + return -15; } + // To avoid confusion, the term "order" will apply to the original conditional exchange offer transactions. + char *l_tx_hash_str = dap_hash_fast_str_new(&l_tx_hash, sizeof(l_tx_hash)); + dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nSuccessfully created order %s", l_sign_str, l_tx_hash_str); + DAP_DELETE(l_tx_hash_str); + + // Note: Orders are transferred to conditional transactions, but it is necessary to leave + // the possibility of subsequent improvements with standard orders, so the next block of + // code will be commented out until better times. + + // Create the order & put it to GDB +// l_price->wallet_key = dap_chain_wallet_get_key(l_wallet, 0); +// char *l_order_hash_str = s_xchange_order_create(l_price, l_tx); +// dap_chain_wallet_close(l_wallet); +// if (l_order_hash_str) { +// dap_chain_hash_fast_from_str(l_order_hash_str, &l_price->order_hash); +// if(!s_xchange_tx_put(l_tx, l_net)) { +// dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't put transaction to mempool", l_sign_str); +// dap_chain_net_srv_order_delete_by_hash_str_sync(l_net, l_order_hash_str); +// DAP_DELETE(l_order_hash_str); +// DAP_DELETE(l_price->wallet_str); +// DAP_DELETE(l_price); +// return -15; +// } +// dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nSuccessfully created order %s", l_sign_str, l_order_hash_str); +// DAP_DELETE(l_order_hash_str); +// } else { +// dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't compose the order", l_sign_str); +// DAP_DELETE(l_price->wallet_str); +// DAP_DELETE(l_price); +// return -18; +// } } break; case CMD_HISTORY:{ @@ -1150,40 +1175,48 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c dap_cli_server_cmd_set_reply_text(a_str_reply, "Command 'order history' requires parameter -order or -addr" ); return -12; } + if(l_addr_hash_str){ dap_chain_addr_t *l_addr = dap_chain_addr_from_str(l_addr_hash_str); if (!l_addr) { dap_cli_server_cmd_set_reply_text(a_str_reply, "Incorrect chain address"); return -14; } - if (dap_chain_addr_check_sum(l_addr)) { + if (dap_chain_addr_check_sum(l_addr) != 1 ) { dap_cli_server_cmd_set_reply_text(a_str_reply, "Incorrect chain address"); return -15; } dap_list_t *l_tx_list = dap_chain_net_get_tx_cond_all_for_addr(l_net,l_addr, c_dap_chain_net_srv_xchange_uid ); dap_string_t * l_str_reply = dap_string_new(""); - while(l_tx_list ){ - dap_chain_datum_tx_t * l_tx_cur = (dap_chain_datum_tx_t*) l_tx_list->data; - s_string_append_tx_cond_info(l_str_reply, l_net, l_tx_cur ); - //INFINITE LOOP ???? - + if (l_tx_list){ + dap_list_t *l_tx_list_temp = l_tx_list; + while(l_tx_list_temp ){ + dap_chain_datum_tx_t * l_tx_cur = (dap_chain_datum_tx_t*) l_tx_list_temp->data; + s_string_append_tx_cond_info(l_str_reply, l_net, l_tx_cur ); + l_tx_list_temp = l_tx_list_temp->next; + } + dap_list_free(l_tx_list); + *a_str_reply = dap_string_free(l_str_reply, false); + }else{ + dap_cli_server_cmd_set_reply_text(a_str_reply, "No history"); } - dap_list_free(l_tx_list); - *a_str_reply = dap_string_free(l_str_reply, false); DAP_DELETE(l_addr); } - if(l_order_hash_str){ - dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str); - if (!l_order) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified order not found"); - return -13; - } - dap_chain_datum_tx_t * l_tx = dap_chain_net_get_tx_by_hash(l_net,&l_order->tx_cond_hash, TX_SEARCH_TYPE_NET); + if(l_order_hash_str){ +// dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str); +// if (!l_order) { +// dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified order not found"); +// return -13; +// } + + dap_hash_fast_t l_order_tx_hash = {}; + dap_chain_hash_fast_from_str(l_order_hash_str, &l_order_tx_hash); + dap_chain_datum_tx_t * l_tx = dap_chain_net_get_tx_by_hash(l_net, &l_order_tx_hash, TX_SEARCH_TYPE_NET); if( l_tx){ int l_rc = s_tx_check_for_open_close(l_net,l_tx); - char *l_tx_hash = dap_chain_hash_fast_to_str_new(&l_order->tx_cond_hash); + char *l_tx_hash = dap_chain_hash_fast_to_str_new(&l_order_tx_hash); if(l_rc == 0){ dap_cli_server_cmd_set_reply_text(a_str_reply, "WRONG TX %s", l_tx_hash); }else if(l_rc == 1){ @@ -1192,13 +1225,12 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c *a_str_reply = dap_string_free(l_str_reply, false); }else if(l_rc == 2){ dap_string_t * l_str_reply = dap_string_new(""); - dap_list_t *l_tx_list = dap_chain_net_get_tx_cond_chain(l_net,&l_order->tx_cond_hash, c_dap_chain_net_srv_xchange_uid ); - while(l_tx_list ){ - dap_chain_datum_tx_t * l_tx_cur = (dap_chain_datum_tx_t*) l_tx_list->data; + dap_list_t *l_tx_list = dap_chain_net_get_tx_cond_chain(l_net, &l_order_tx_hash, c_dap_chain_net_srv_xchange_uid ); + dap_list_t *l_tx_list_temp = l_tx_list; + while(l_tx_list_temp ){ + dap_chain_datum_tx_t * l_tx_cur = (dap_chain_datum_tx_t*) l_tx_list_temp->data; s_string_append_tx_cond_info(l_str_reply, l_net, l_tx_cur ); - - //INFINITE LOOP ???? - + l_tx_list_temp = l_tx_list_temp->next; } dap_list_free(l_tx_list); *a_str_reply = dap_string_free(l_str_reply, false); @@ -1212,7 +1244,7 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c } break; case CMD_REMOVE: - case CMD_UPDATE: { + { const char * l_order_hash_str = NULL; dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-net", &l_net_str); if (!l_net_str) { @@ -1245,12 +1277,16 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c l_cmd_num == CMD_REMOVE ? "remove" : "update"); return -12; } - dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str); - if (!l_order) { +// dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str); + + dap_hash_fast_t l_tx_hash = {}; + dap_chain_hash_fast_from_str(l_order_hash_str, &l_tx_hash); + dap_chain_datum_tx_t *l_cond_tx = dap_chain_ledger_tx_find_by_hash(l_net->pub.ledger, &l_tx_hash); + if (!l_cond_tx) { dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nSpecified order not found", l_sign_str); return -13; } - dap_chain_net_srv_xchange_price_t *l_price = s_xchange_price_from_order(l_net, l_order, false); + dap_chain_net_srv_xchange_price_t *l_price = s_xchange_price_from_order(l_net, l_cond_tx, false); if (!l_price) { dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't create price object from order", l_sign_str); return -13; @@ -1269,102 +1305,11 @@ static int s_cli_srv_xchange_order(int a_argc, char **a_argv, int a_arg_index, c DAP_DELETE(l_tx_hash_str); } } - if (dap_chain_net_srv_order_delete_by_hash_str_sync(l_net, l_order_hash_str)) { - dap_string_append_printf(l_str_reply, "Can't remove order %s\n", l_order_hash_str); - } else { - dap_string_append_printf(l_str_reply, "Remove order %s\n", l_order_hash_str); - } DAP_DELETE(l_price); if (!l_str_reply->len) { dap_string_append(l_str_reply, "Price successfully removed"); } *a_str_reply = dap_string_free(l_str_reply, false); - } else { // CMD_UPDATE - const char *l_val_sell_str = NULL, *l_val_rate_str = NULL, *l_wallet_str = NULL, *l_new_wallet_str = NULL; - uint256_t l_datoshi_sell = {}; - uint256_t l_rate = uint256_0; - dap_chain_wallet_t *l_wallet = NULL; - dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-coins", &l_val_sell_str); - if (l_val_sell_str) { - l_datoshi_sell = dap_chain_balance_scan(l_val_sell_str); - if (IS_ZERO_256(l_datoshi_sell)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Format -coins <unsigned long long>"); - return -9; - } - } - dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-rate", &l_val_rate_str); - if (l_val_rate_str) { - l_rate = dap_chain_coins_to_balance(l_val_rate_str); - if (IS_ZERO_256(l_rate)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Format -rate <long double> = sell / buy"); - return -9; - } - } - dap_cli_server_cmd_find_option_val(a_argv, l_arg_index, a_argc, "-w", &l_new_wallet_str); - l_wallet_str = l_new_wallet_str ? l_new_wallet_str : l_price->wallet_str; - l_wallet = dap_chain_wallet_open(l_wallet_str, dap_chain_wallet_get_path(g_config)); - if (!l_wallet) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "Specified wallet not found"); - return -11; - } else { - l_sign_str = dap_chain_wallet_check_bliss_sign(l_wallet); - } - if (!l_val_sell_str && !l_val_rate_str && !l_wallet_str) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "At least one of updating parameters is mandatory"); - return -13; - } - uint256_t l_value = dap_chain_wallet_get_balance(l_wallet, l_net->pub.id, l_token_sell_str); - if (!IS_ZERO_256(l_datoshi_sell) && compare256(l_value, l_datoshi_sell) == -1) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nNot enough cash in specified wallet", l_sign_str); - dap_chain_wallet_close(l_wallet); - return -12; - } - if (l_val_sell_str) { - l_price->datoshi_sell = l_datoshi_sell; - } - if (l_val_rate_str) { - l_price->rate = l_rate; - } - // Update the transaction - dap_chain_datum_tx_t *l_tx = s_xchange_tx_create_request(l_price, l_wallet); - if (l_new_wallet_str) { - dap_chain_wallet_close(l_wallet); - l_wallet = dap_chain_wallet_open(l_price->wallet_str, dap_chain_wallet_get_path(g_config)); - DAP_DELETE(l_price->wallet_str); - l_price->wallet_str = dap_strdup(l_new_wallet_str); - } - if (!l_tx) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't compose the conditional transaction", l_sign_str); - return -14; - } - bool l_ret = s_xchange_tx_invalidate(l_price, l_wallet); // may be changed to old price later - dap_chain_wallet_close(l_wallet); - if (!l_ret) { - char *l_tx_hash_str = dap_chain_hash_fast_to_str_new(&l_price->tx_hash); - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't invalidate transaction %s\n", l_sign_str, l_tx_hash_str); - DAP_DELETE(l_tx_hash_str); - return -17; - } - // Update the order - dap_chain_net_srv_order_delete_by_hash_str_sync(l_price->net, l_order_hash_str); - DAP_DELETE(l_order_hash_str); - l_order_hash_str = s_xchange_order_create(l_price, l_tx); - if (l_order_hash_str) { - dap_chain_hash_fast_from_str(l_order_hash_str, &l_price->order_hash); - if(!s_xchange_tx_put(l_tx, l_net)) { - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't put transaction to mempool", l_sign_str); - dap_chain_net_srv_order_delete_by_hash_str_sync(l_net, l_order_hash_str); - DAP_DELETE(l_order_hash_str); - return -15; - } - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nSuccessfully created order %s", l_sign_str, l_order_hash_str); - DAP_DELETE(l_order_hash_str); - } else { - dap_cli_server_cmd_set_reply_text(a_str_reply, "%s\nCan't compose the order", l_sign_str); - DAP_DELETE(l_price->wallet_str); - DAP_DELETE(l_price); - return -18; - } } } break; @@ -1491,9 +1436,9 @@ static int s_tx_check_for_open_close(dap_chain_net_t * a_net, dap_chain_datum_tx &l_cond_idx); if (l_out_cond_item) { if(dap_chain_ledger_tx_hash_is_used_out_item(a_net->pub.ledger, &l_tx_hash, l_cond_idx, NULL)) - return 1; // If its SRV_XCHANGE and spent its closed + return 2; // If its SRV_XCHANGE and spent its closed else - return 2; // If its SRV_XCHANGE and not spent its open + return 1; // If its SRV_XCHANGE and not spent its open } return 0; } @@ -1519,9 +1464,6 @@ static void s_string_append_tx_cond_info( dap_string_t * a_reply_str, dap_chain_ const char * l_tx_input_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash( a_net->pub.ledger, &l_tx_hash); - - - // Find SRV_XCHANGE out_cond item int l_cond_idx = 0; dap_chain_tx_out_cond_t *l_out_cond_item = dap_chain_datum_tx_out_cond_get(a_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, @@ -1532,17 +1474,23 @@ static void s_string_append_tx_cond_info( dap_string_t * a_reply_str, dap_chain_ bool l_is_closed = dap_chain_ledger_tx_hash_is_used_out_item(a_net->pub.ledger, &l_tx_hash, l_cond_idx, NULL); uint256_t l_value_from = l_out_cond_item->header.value; - uint256_t l_value_to = l_out_cond_item->subtype.srv_xchange.buy_value; - char *l_value_to_str = dap_chain_balance_to_coins(l_value_to); + uint256_t l_rate = l_out_cond_item->subtype.srv_xchange.rate; + char *l_rate_str = dap_chain_balance_to_coins(l_rate); char *l_value_from_str = dap_chain_balance_to_coins(l_value_from); dap_string_append_printf(a_reply_str, "Hash: %s", l_tx_hash_str); dap_string_append_printf(a_reply_str, " Status: %s", l_is_closed ? "closed" : "open"); dap_string_append_printf(a_reply_str, " From: %s %s", l_value_from_str, l_tx_input_ticker); - dap_string_append_printf(a_reply_str, " To: %s %s", l_value_to_str, l_out_cond_item->subtype.srv_xchange.buy_token); + dap_string_append_printf(a_reply_str, " Rate: %s Buy token: %s", l_rate_str, l_out_cond_item->subtype.srv_xchange.buy_token); DAP_DELETE(l_value_from_str); - DAP_DELETE(l_value_to_str); + DAP_DELETE(l_rate_str); + l_is_cond_out = true; + } + else { + dap_string_append_printf(a_reply_str, "Hash: %s", l_tx_hash_str); + dap_string_append_printf(a_reply_str, " Status: closed"); + dap_string_append_printf(a_reply_str, " Order is used out"); l_is_cond_out = true; } if(l_is_cond_out){ @@ -1638,19 +1586,19 @@ dap_chain_tx_out_cond_t *l_out_cond_item; const char *l_tx_input_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash(a_net->pub.ledger, &l_hash); - uint256_t l_value_to = l_out_cond_item->subtype.srv_xchange.buy_value; + uint256_t l_rate = l_out_cond_item->subtype.srv_xchange.rate; uint256_t l_tx_input_values = dap_chain_net_get_tx_total_value(a_net, l_datum_tx); char *l_tx_input_values_str = dap_chain_balance_to_coins(l_tx_input_values); char *l_value_from_str = dap_chain_balance_to_coins(l_tx_input_values); - char *l_value_to_str = dap_chain_balance_to_coins(l_value_to); + char *l_rate_str = dap_chain_balance_to_coins(l_rate); dap_string_append_printf(l_reply_str, " Status: %s,", l_rc ? "closed" : "open"); dap_string_append_printf(l_reply_str, " From: %s %s,", l_tx_input_values_str, l_tx_input_ticker); - dap_string_append_printf(l_reply_str, " To: %s %s\n", l_value_to_str, l_out_cond_item->subtype.srv_xchange.buy_token); + dap_string_append_printf(l_reply_str, " Rate: %s Buy token: %s\n", l_rate_str, l_out_cond_item->subtype.srv_xchange.buy_token); DAP_DELETE(l_value_from_str); - DAP_DELETE(l_value_to_str); + DAP_DELETE(l_rate_str); dap_string_append(l_reply_str, "\n"); } @@ -1662,7 +1610,19 @@ dap_chain_tx_out_cond_t *l_out_cond_item; } +void s_tx_is_order_check (dap_chain_net_t* a_net, dap_chain_datum_tx_t *a_tx, void *a_arg) +{ + UNUSED(a_net); + + order_find_list_t *l_arg = (order_find_list_t*)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)) + { + l_arg->tx_list = dap_list_append(l_arg->tx_list, a_tx); + } + +} static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) { @@ -1710,25 +1670,36 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) return -3; } - char * l_gdb_group_str = dap_chain_net_srv_order_get_gdb_group(l_net); +// char * l_gdb_group_str = dap_chain_net_srv_order_get_gdb_group(l_net); - size_t l_orders_count = 0; - dap_global_db_obj_t * l_orders = dap_global_db_get_all_sync(l_gdb_group_str, &l_orders_count); - dap_chain_net_srv_xchange_price_t *l_price; +// size_t l_orders_count = 0; +// dap_global_db_obj_t * l_orders = dap_global_db_get_all_sync(l_gdb_group_str, &l_orders_count); +// dap_chain_net_srv_xchange_price_t *l_price; dap_string_t *l_reply_str = dap_string_new(""); + // Iterate blockchain, find txs with xchange cond out and without cond input + order_find_list_t l_arg = {}; + dap_chain_net_get_tx_all(l_net,TX_SEARCH_TYPE_NET, s_tx_is_order_check, &l_arg); - for (size_t i = 0; i < l_orders_count; i++) - { - dap_chain_net_srv_order_t *l_order = (dap_chain_net_srv_order_t *)l_orders[i].value; - if (l_order->srv_uid.uint64 != DAP_CHAIN_NET_SRV_XCHANGE_ID) + // Print all txs + dap_list_t *l_temp = l_arg.tx_list; + while(l_temp) + { +// dap_chain_net_srv_order_t *l_order = (dap_chain_net_srv_order_t *)l_orders[i].value; + dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)l_temp->data; + dap_chain_tx_out_cond_t *l_out_cond = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE , NULL); + if (!l_out_cond || l_out_cond->header.srv_uid.uint64 != DAP_CHAIN_NET_SRV_XCHANGE_ID){ + l_temp = l_temp->next; continue; + } // TODO add filters to list (tokens, network, etc.) - l_price = s_xchange_price_from_order(l_net, l_order, true); + dap_chain_net_srv_xchange_price_t * l_price = NULL; + l_price = s_xchange_price_from_order(l_net, l_tx, true); if( !l_price ){ log_it(L_WARNING,"Can't create price from order"); + l_temp = l_temp->next; continue; } @@ -1743,7 +1714,11 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) MULT_256_COIN(l_price->datoshi_sell, l_price->rate, &l_datoshi_buy); /* sell/buy computation */ - dap_string_append_printf(l_reply_str, "orderHash: %s (%s) tokSel: %s, net: %s, tokBuy: %s, sell: %s (%s), buy: %s (%s) buy/sell: %s\n", l_orders[i].key, + dap_hash_fast_t l_tx_hash = {}; + dap_hash_fast(l_tx, dap_chain_datum_tx_get_size(l_tx), &l_tx_hash); + char *l_tx_hash_str = dap_chain_hash_fast_to_str_new(&l_tx_hash); + + dap_string_append_printf(l_reply_str, "orderHash: %s (%s) tokSel: %s, net: %s, tokBuy: %s, sell: %s (%s), buy: %s (%s) buy/sell: %s\n", l_tx_hash_str, l_status_order, l_price->token_sell, l_price->net->pub.name, l_price->token_buy, l_cp_sell_coins = dap_chain_balance_to_coins(l_price->datoshi_sell), @@ -1752,15 +1727,18 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) l_cp_buy_datoshi = dap_chain_balance_print(l_datoshi_buy), l_cp_rate = dap_chain_balance_to_coins(l_price->rate)); + DAP_DEL_Z(l_tx_hash_str); DAP_DEL_Z(l_cp_buy_coins); DAP_DEL_Z(l_cp_buy_datoshi); DAP_DEL_Z(l_cp_sell_coins); DAP_DEL_Z(l_cp_sell_datoshi); DAP_DEL_Z(l_cp_rate); DAP_DEL_Z(l_price); + l_temp = l_temp->next; } - dap_global_db_objs_delete(l_orders, l_orders_count); - DAP_DELETE( l_gdb_group_str); +// dap_global_db_objs_delete(l_orders, l_orders_count); +// DAP_DELETE( l_gdb_group_str); + dap_list_free(l_arg.tx_list); if (!l_reply_str->len) { dap_string_append(l_reply_str, "No orders found"); } @@ -1816,9 +1794,13 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) dap_cli_server_cmd_set_reply_text(a_str_reply, "Format -fee <unsigned int256>"); return -9; } - dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str); - if (l_order) { - dap_chain_net_srv_xchange_price_t *l_price = s_xchange_price_from_order(l_net, l_order, false); +// dap_chain_net_srv_order_t *l_order = dap_chain_net_srv_order_find_by_hash_str(l_net, l_order_hash_str); + dap_hash_fast_t l_tx_hash = {}; + dap_chain_hash_fast_from_str(l_order_hash_str, &l_tx_hash); + dap_chain_datum_tx_t *l_cond_tx = dap_chain_ledger_tx_find_by_hash(l_net->pub.ledger, &l_tx_hash); + + if (l_cond_tx) { + dap_chain_net_srv_xchange_price_t *l_price = s_xchange_price_from_order(l_net, l_cond_tx, false); if(!l_price){ dap_cli_server_cmd_set_reply_text(a_str_reply, "Can't create price from order"); return -13; @@ -1830,7 +1812,6 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) dap_hash_fast_is_blank(&l_price->order_hash)) dap_chain_net_srv_order_delete_by_hash_str_sync(l_price->net, l_order_hash_str); DAP_DELETE(l_price); - DAP_DELETE(l_order); dap_cli_server_cmd_set_reply_text(a_str_reply, l_tx ? "Exchange transaction has done" : "Exchange transaction error"); } else { @@ -1959,8 +1940,8 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) &l_prev_cond_idx); if (l_out_cond_item) { uint256_t l_value_from = l_out_cond_item->header.value; - uint256_t l_value_to = l_out_cond_item->subtype.srv_xchange.buy_value; - char *l_value_to_str = dap_chain_balance_to_coins(l_value_to); + uint256_t l_rate = l_out_cond_item->subtype.srv_xchange.rate; + char *l_rate_str = dap_chain_balance_to_coins(l_rate); char *l_value_from_str = dap_chain_balance_to_coins(l_value_from); l_rc = dap_chain_ledger_tx_hash_is_used_out_item(l_net->pub.ledger, &l_tx_hash, l_prev_cond_idx, NULL); @@ -1974,10 +1955,10 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) dap_string_append_printf(l_reply_str, "Hash: %s,", l_hash_str); dap_string_append_printf(l_reply_str, " Status: %s,", l_rc ? "closed" : "open"); dap_string_append_printf(l_reply_str, " From: %s %s,", l_value_from_str, l_tx_input_ticker); - dap_string_append_printf(l_reply_str, " To: %s %s\n", l_value_to_str, l_out_cond_item->subtype.srv_xchange.buy_token); + dap_string_append_printf(l_reply_str, " Rate: %s Buy token: %s\n", l_rate_str, l_out_cond_item->subtype.srv_xchange.buy_token); DAP_DELETE(l_value_from_str); - DAP_DELETE(l_value_to_str); + DAP_DELETE(l_rate_str); } l_datum_list = dap_list_next(l_datum_list); @@ -2068,51 +2049,22 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) if(l_tx){ dap_hash_fast_t * l_tx_hash = dap_chain_node_datum_tx_calc_hash(l_tx); - // Get input token ticker - const char * l_tx_input_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash( - l_net->pub.ledger, l_tx_hash); - - int l_direction = 0; // 1 - from/to, -1 - to/from - // Compare with token_from and token_to - if(dap_strcmp(l_tx_input_ticker, l_token_from_str) == 0) - l_direction = 1; - else if (dap_strcmp(l_tx_input_ticker, l_token_to_str) == 0) - l_direction = -1; - else { - l_cur = dap_list_next(l_cur); - DAP_DEL_Z(l_tx_hash); - continue; - } int l_cond_idx = 0; dap_chain_tx_out_cond_t *l_out_cond_item = dap_chain_datum_tx_out_cond_get(l_tx, DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE, &l_cond_idx); if (l_out_cond_item && dap_chain_ledger_tx_hash_is_used_out_item(l_net->pub.ledger, l_tx_hash, l_cond_idx, NULL)) { uint256_t l_value_sell = l_out_cond_item->header.value; - uint256_t l_value_buy = l_out_cond_item->subtype.srv_xchange.buy_value; - if( l_direction == 1){ + l_rate = l_out_cond_item->subtype.srv_xchange.rate; if (!IS_ZERO_256(l_value_sell)) { - DIV_256_COIN(l_value_buy, l_value_sell, &l_rate); if(SUM_256_256(l_rate, l_total_rates, &l_total_rates )!= 0) log_it(L_ERROR, "Overflow on avarage price calculation (summing)"); INCR_256(&l_total_rates_count); }else{ log_it(L_ERROR, "Sell value is 0 in avarage price calculation (summing)"); } - }else if (l_direction == -1){ - if (!IS_ZERO_256(l_value_buy)) { - DIV_256_COIN(l_value_sell, l_value_buy, &l_rate); - if(SUM_256_256(l_rate, l_total_rates, &l_total_rates )!= 0) - log_it(L_ERROR, "Overflow on avarage price calculation (summing)"); - INCR_256(&l_total_rates_count); - }else{ - log_it(L_ERROR, "Buy value is 0 in avarage price calculation (summing)"); - } - }else{ - log_it(L_ERROR,"Wrong direction, not buy nor send (%d)",l_direction); - } + DAP_DEL_Z(l_tx_hash); } - DAP_DEL_Z(l_tx_hash); } l_cur = dap_list_next(l_cur); } @@ -2121,9 +2073,6 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) if (!IS_ZERO_256(l_total_rates_count)) DIV_256(l_total_rates,l_total_rates_count,&l_rate_average); - if (!IS_ZERO_256(l_total_rates_count)) - DIV_256(l_total_rates,l_total_rates_count,&l_rate_average); - char *l_rate_average_str = dap_chain_balance_to_coins(l_rate_average); char *l_last_rate_str = dap_chain_balance_to_coins(l_rate); dap_string_append_printf(l_reply_str,"Average price: %s Last price: %s", l_rate_average_str, l_last_rate_str); @@ -2149,16 +2098,6 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) const char * l_tx_input_ticker = dap_chain_ledger_tx_get_token_ticker_by_hash( l_net->pub.ledger, l_tx_hash); - int l_direction = 0; // 1 - from/to, -1 - to/from - // Compare with token_from and token_to - if(dap_strcmp(l_tx_input_ticker, l_token_from_str) == 0) - l_direction = 1; - else if (dap_strcmp(l_tx_input_ticker, l_token_to_str) == 0) - l_direction = -1; - else { - continue; - } - // Check if output is spent dap_chain_tx_out_cond_t *l_out_cond_item = l_cur->out_cond; if(l_out_cond_item && l_cur->tx_next) { @@ -2169,30 +2108,30 @@ static int s_cli_srv_xchange(int a_argc, char **a_argv, char **a_str_reply) DAP_DEL_Z(l_tx_hash_str); // Print tx_created - char l_tx_ts_str[92] = {}; /* Convert ts to Sat May 17 01:17:08 2014 */ - dap_time_to_str_rfc822(l_tx_ts_str, 92, l_tx->header.ts_created); + char l_tx_ts_str[92] = {0}; + struct tm l_tm={0}; /* Convert ts to Sat May 17 01:17:08 2014 */ + uint64_t l_ts = l_tx->header.ts_created; // We take the next tx in chain to print close time, not the open one + if ( (localtime_r((time_t *) &l_ts, &l_tm )) ) + asctime_r (&l_tm, l_tx_ts_str); + dap_string_append_printf(l_reply_str,"\tts_created: %s", l_tx_ts_str); + // Print tx_closed memset(l_tx_ts_str,0,sizeof(l_tx_ts_str)); - dap_time_to_str_rfc822(l_tx_ts_str, 92, l_cur->tx_next->header.ts_created); + memset(&l_tm,0,sizeof(l_tm)); /* Convert ts to Sat May 17 01:17:08 2014 */ + l_ts = l_cur->tx_next->header.ts_created; // We take the next tx in chain to print close time, not the open one + if ( (localtime_r((time_t *) &l_ts, &l_tm )) ) + asctime_r (&l_tm, l_tx_ts_str); + dap_string_append_printf(l_reply_str,"\tts_closed: %s", l_tx_ts_str); + // Print value_from/value_to + uint256_t l_value_from = l_out_cond_item->header.value; - uint256_t l_value_to = l_out_cond_item->subtype.srv_xchange.buy_value; - uint256_t l_rate = {}; - if( l_direction == 1){ - if(compare256(l_value_from, uint256_0) != 0){ - DIV_256_COIN(l_value_to, l_value_from, &l_rate); - }else - log_it(L_ERROR,"Value_from is zero, can't calc rate"); - }else if(l_direction == -1){ - if(compare256(l_value_to, uint256_0) != 0){ - DIV_256_COIN(l_value_from, l_value_to, &l_rate); - }else - log_it(L_ERROR,"Value_tois zero, can't calc rate"); - }else{ - log_it(L_ERROR,"Wrong direction, not buy nor send (%d)",l_direction); - } + uint256_t l_rate = l_out_cond_item->subtype.srv_xchange.rate; + uint256_t l_value_to = {}; + MULT_256_COIN(l_value_from, l_rate, &l_value_to); + char * l_value_from_str = dap_chain_balance_to_coins(l_value_from); char * l_value_to_str = dap_chain_balance_to_coins(l_value_to); char *l_rate_str = dap_chain_balance_to_coins(l_rate);