From b075db0bb47cbb3fdfe2465ad086d14ca14babb8 Mon Sep 17 00:00:00 2001 From: YangHau Date: Sat, 27 Jul 2019 13:21:30 +0800 Subject: [PATCH] feat(API): Add tag related fetching APIs back For downward compability, tag-related fetching APIs are back. --- accelerator/apis.c | 68 +++++++++++++++++++++++++++++++++++++++ accelerator/apis.h | 36 +++++++++++++++++++++ accelerator/common_core.c | 40 +++++++++++------------ accelerator/common_core.h | 10 +++--- accelerator/server.cc | 40 +++++++++++++++++++++++ serializer/serializer.c | 34 ++++++++++++++++++-- tests/driver.c | 30 +++++++++++++++++ 7 files changed, 228 insertions(+), 30 deletions(-) diff --git a/accelerator/apis.c b/accelerator/apis.c index f9e45d06..202d2abb 100644 --- a/accelerator/apis.c +++ b/accelerator/apis.c @@ -181,11 +181,13 @@ status_t api_find_transaction_objects(const iota_client_service_t* const service ret = ta_find_transaction_objects_req_deserialize(obj, req); if (ret != SC_OK) { + log_error(apis_logger_id, "[%s:%d]\n", __func__, __LINE__); goto done; } ret = ta_find_transaction_objects(service, req, res); if (ret) { + log_error(apis_logger_id, "[%s:%d]\n", __func__, __LINE__); goto done; } @@ -197,6 +199,72 @@ status_t api_find_transaction_objects(const iota_client_service_t* const service return ret; } +status_t api_find_transactions_by_tag(const iota_client_service_t* const service, const char* const obj, + char** json_result) { + status_t ret = SC_OK; + flex_trit_t tag_trits[NUM_FLEX_TRITS_TAG]; + find_transactions_req_t* req = find_transactions_req_new(); + find_transactions_res_t* res = find_transactions_res_new(); + if (req == NULL || res == NULL) { + ret = SC_TA_OOM; + log_error(apis_logger_id, "[%s:%d]\n", __func__, __LINE__); + goto done; + } + + flex_trits_from_trytes(tag_trits, NUM_TRITS_TAG, (const tryte_t*)obj, NUM_TRYTES_TAG, NUM_TRYTES_TAG); + if (find_transactions_req_tag_add(req, tag_trits) != RC_OK) { + ret = SC_CCLIENT_INVALID_FLEX_TRITS; + log_error(apis_logger_id, "[%s:%d]\n", __func__, __LINE__); + goto done; + } + + if (iota_client_find_transactions(service, req, res) != RC_OK) { + ret = SC_CCLIENT_FAILED_RESPONSE; + log_error(apis_logger_id, "[%s:%d]\n", __func__, __LINE__); + goto done; + } + + ret = ta_find_transactions_res_serialize(json_result, (ta_find_transactions_res_t*)res); + +done: + find_transactions_req_free(&req); + find_transactions_res_free(&res); + return ret; +} + +status_t api_find_transactions_obj_by_tag(const iota_client_service_t* const service, const char* const obj, + char** json_result) { + status_t ret = SC_OK; + flex_trit_t tag_trits[NUM_FLEX_TRITS_TAG]; + find_transactions_req_t* req = find_transactions_req_new(); + transaction_array_t* res = transaction_array_new(); + if (req == NULL || res == NULL) { + ret = SC_TA_OOM; + log_error(apis_logger_id, "[%s:%d]\n", __func__, __LINE__); + goto done; + } + + flex_trits_from_trytes(tag_trits, NUM_TRITS_TAG, (const tryte_t*)obj, NUM_TRYTES_TAG, NUM_TRYTES_TAG); + if (find_transactions_req_tag_add(req, tag_trits) != RC_OK) { + ret = SC_CCLIENT_INVALID_FLEX_TRITS; + log_error(apis_logger_id, "[%s:%d]\n", __func__, __LINE__); + goto done; + } + + ret = ta_find_transactions_obj_by_tag(service, req, res); + if (ret) { + log_error(apis_logger_id, "[%s:%d]\n", __func__, __LINE__); + goto done; + } + + ret = ta_find_transaction_objects_res_serialize(json_result, res); + +done: + find_transactions_req_free(&req); + transaction_array_free(res); + return ret; +} + status_t api_receive_mam_message(const iota_client_service_t* const service, const char* const chid, char** json_result) { status_t ret = SC_OK; diff --git a/accelerator/apis.h b/accelerator/apis.h index d462735d..5fe229e4 100644 --- a/accelerator/apis.h +++ b/accelerator/apis.h @@ -178,6 +178,42 @@ status_t api_find_transactions(const iota_client_service_t* const service, const status_t api_find_transaction_objects(const iota_client_service_t* const service, const char* const obj, char** json_result); +/** + * @brief Return list of transaction hash with given tag hash. + * + * Retreive all transactions that have same given tag. The result is a list of + * transaction hash in json format. + * + * @param[in] service IRI node end point service + * @param[in] obj tag in trytes + * @param[out] json_result Result containing list of transaction hash in json + * format + * + * @return + * - SC_OK on success + * - non-zero on error + */ +status_t api_find_transactions_by_tag(const iota_client_service_t* const service, const char* const obj, + char** json_result); + +/** + * @brief Return list of transaction object with given tag hash. + * + * Retreive all transactions that have same given tag. The result is a list of + * transaction objects in json format. + * + * @param[in] service IRI node end point service + * @param[in] obj tag in trytes + * @param[out] json_result Result containing list of transaction object in json + * format + * + * @return + * - SC_OK on success + * - non-zero on error + */ +status_t api_find_transactions_obj_by_tag(const iota_client_service_t* const service, const char* const obj, + char** json_result); + /** * @brief Attach trytes to Tangle and return transaction hashes * diff --git a/accelerator/common_core.c b/accelerator/common_core.c index 34320232..e09e0198 100644 --- a/accelerator/common_core.c +++ b/accelerator/common_core.c @@ -282,43 +282,39 @@ status_t ta_send_transfer(const iota_config_t* const tangle, const iota_client_s return ret; } -status_t ta_find_transactions_by_tag(const iota_client_service_t* const service, const char* const req, - ta_find_transactions_res_t* res) { +status_t ta_find_transactions_obj_by_tag(const iota_client_service_t* const service, + const find_transactions_req_t* const req, transaction_array_t* res) { if (req == NULL || res == NULL) { - log_error(cc_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_TA_NULL"); + log_error(cc_logger_id, "[%s:%d]\n", __func__, __LINE__); return SC_TA_NULL; } status_t ret = SC_OK; - find_transactions_req_t* find_tx_req = find_transactions_req_new(); - find_transactions_res_t* find_tx_res = find_transactions_res_new(); - if (find_tx_req == NULL || find_tx_res == NULL) { - ret = SC_CCLIENT_OOM; - log_error(cc_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_CCLIENT_OOM"); + find_transactions_res_t* txn_res = find_transactions_res_new(); + ta_find_transaction_objects_req_t* obj_req = ta_find_transaction_objects_req_new(); + if (txn_res == NULL || obj_req == NULL) { + ret = SC_TA_OOM; goto done; } - flex_trit_t tag_trits[NUM_TRITS_TAG]; - flex_trits_from_trytes(tag_trits, NUM_TRITS_TAG, (const tryte_t*)req, NUM_TRYTES_TAG, NUM_TRYTES_TAG); - ret = hash81_queue_push(&find_tx_req->tags, tag_trits); - if (ret) { - ret = SC_CCLIENT_HASH; - log_error(cc_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_CCLIENT_HASH"); + // get transaction hash + if (iota_client_find_transactions(service, req, txn_res) != RC_OK) { + ret = SC_CCLIENT_FAILED_RESPONSE; + log_error(cc_logger_id, "[%s:%d]\n", __func__, __LINE__); goto done; } - ret = iota_client_find_transactions(service, find_tx_req, find_tx_res); + + hash243_queue_copy(&obj_req->hashes, txn_res->hashes, hash243_queue_count(txn_res->hashes)); + + ret = ta_find_transaction_objects(service, obj_req, res); if (ret) { - ret = SC_CCLIENT_FAILED_RESPONSE; - log_error(cc_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_CCLIENT_FAILED_RESPONSE"); + log_error(cc_logger_id, "[%s:%d]\n", __func__, __LINE__); goto done; } - res->hashes = find_tx_res->hashes; - find_tx_res->hashes = NULL; - done: - find_transactions_req_free(&find_tx_req); - find_transactions_res_free(&find_tx_res); + find_transactions_res_free(&txn_res); + ta_find_transaction_objects_req_free(&obj_req); return ret; } diff --git a/accelerator/common_core.h b/accelerator/common_core.h index 746693ad..542aed51 100644 --- a/accelerator/common_core.h +++ b/accelerator/common_core.h @@ -143,16 +143,16 @@ status_t ta_find_transactions_by_tag(const iota_client_service_t* const service, * transaction objects in ta_find_transactions_obj_res_t. * * @param[in] service IRI node end point service - * @param[in] req tag in trytes - * @param[out] res Result containing list of transaction object in - * ta_find_transactions_obj_res_t + * @param[in] req find_transactions_req_t object which contains tags + * @param[out] res Result containing list of transaction objects in + * transaction_array_t * * @return * - SC_OK on success * - non-zero on error */ -status_t ta_find_transactions_obj_by_tag(const iota_client_service_t* const service, const char* const req, - ta_find_transactions_obj_res_t* res); +status_t ta_find_transactions_obj_by_tag(const iota_client_service_t* const service, + const find_transactions_req_t* const req, transaction_array_t* res); /** * @brief Return transaction object with given transaction hashes. diff --git a/accelerator/server.cc b/accelerator/server.cc index 129fb539..f1922056 100644 --- a/accelerator/server.cc +++ b/accelerator/server.cc @@ -260,6 +260,46 @@ int main(int argc, char* argv[]) { res << json_result; }); + /** + * @method {get} /tag//hashes Find transaction hash with tag + * + * @return {String} hash of address hashes + */ + mux.handle("/tag/{tag:[A-Z9]{27}}/hashes") + .method(served::method::OPTIONS, + [&](served::response& res, const served::request& req) { set_method_header(res, HTTP_METHOD_OPTIONS); }) + .get([&](served::response& res, const served::request& req) { + status_t ret = SC_OK; + char* json_result; + + ret = api_find_transactions_by_tag(&ta_core.service, req.params["tag"].c_str(), &json_result); + ret = set_response_content(ret, &json_result); + set_method_header(res, HTTP_METHOD_GET); + res.set_status(ret); + res << json_result; + }); + + /** + * @method {get} /tag/:tag Find transaction objects by tag + * + * @param {String} tag Must be 27 trytes long + * + * @return {String[]} transactions List of transaction objects + */ + mux.handle("/tag/{tag:[A-Z9]{27}}") + .method(served::method::OPTIONS, + [&](served::response& res, const served::request& req) { set_method_header(res, HTTP_METHOD_OPTIONS); }) + .get([&](served::response& res, const served::request& req) { + status_t ret = SC_OK; + char* json_result; + + ret = api_find_transactions_obj_by_tag(&ta_core.service, req.params["tag"].c_str(), &json_result); + ret = set_response_content(ret, &json_result); + set_method_header(res, HTTP_METHOD_GET); + res.set_status(ret); + res << json_result; + }); + /** * @method {post} /transaction send transfer * diff --git a/serializer/serializer.c b/serializer/serializer.c index 29b0718b..99b5f369 100644 --- a/serializer/serializer.c +++ b/serializer/serializer.c @@ -50,6 +50,35 @@ static status_t ta_hash243_stack_to_json_array(hash243_stack_t stack, cJSON* jso return SC_OK; } +static status_t ta_json_array_to_hash243_queue(cJSON const* const obj, char const* const obj_name, + hash243_queue_t* queue) { + status_t ret_code = SC_OK; + flex_trit_t hash[FLEX_TRIT_SIZE_243] = {}; + cJSON* json_item = cJSON_GetObjectItemCaseSensitive(obj, obj_name); + if (!json_item) { + log_error(seri_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_SERIALIZER_NULL"); + return SC_SERIALIZER_NULL; + } + + if (cJSON_IsArray(json_item)) { + cJSON* current_obj = NULL; + cJSON_ArrayForEach(current_obj, json_item) { + if (current_obj->valuestring != NULL) { + flex_trits_from_trytes(hash, NUM_TRITS_HASH, (tryte_t const*)current_obj->valuestring, NUM_TRYTES_HASH, + NUM_TRYTES_HASH); + if (hash243_queue_push(queue, hash) != RC_OK) { + log_error(seri_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_SERIALIZER_JSON_PARSE"); + return SC_SERIALIZER_JSON_PARSE; + } + } + } + } else { + log_error(seri_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_SERIALIZER_JSON_PARSE"); + return SC_SERIALIZER_JSON_PARSE; + } + return ret_code; +} + static status_t ta_hash243_queue_to_json_array(hash243_queue_t queue, cJSON* const json_root) { size_t array_count; hash243_queue_entry_t* q_iter = NULL; @@ -242,7 +271,6 @@ static status_t transaction_array_to_json_array(cJSON* json_root, const transact cJSON* txn_obj = NULL; TX_OBJS_FOREACH(txn_array, txn) { - txn_obj = NULL; ret = iota_transaction_to_json_object(txn, &txn_obj); if (ret != SC_OK) { return ret; @@ -445,8 +473,8 @@ status_t ta_find_transaction_objects_req_deserialize(const char* const obj, return SC_SERIALIZER_JSON_PARSE; } - if (json_array_to_hash243_queue(json_obj, "hashes", &req->hashes) != RC_OK) { - ret = SC_SERIALIZER_JSON_PARSE; + ret = ta_json_array_to_hash243_queue(json_obj, "hashes", &req->hashes); + if (ret != SC_OK) { log_error(seri_logger_id, "[%s:%d:%s]\n", __func__, __LINE__, "SC_SERIALIZER_JSON_PARSE"); } diff --git a/tests/driver.c b/tests/driver.c index 88a3ac10..4e63675c 100644 --- a/tests/driver.c +++ b/tests/driver.c @@ -157,6 +157,34 @@ void test_find_transaction_objects(void) { printf("Average time of find_transaction_objects: %lf\n", sum / TEST_COUNT); } +void test_find_transactions_by_tag(void) { + char* json_result; + double sum = 0; + + for (size_t count = 0; count < TEST_COUNT; count++) { + test_time_start(&start_time); + + TEST_ASSERT_EQUAL_INT32(SC_OK, api_find_transactions_by_tag(&ta_core.service, driver_tag_msg, &json_result)); + test_time_end(&start_time, &end_time, &sum); + free(json_result); + } + printf("Average time of find_transactions_by_tag: %lf\n", sum / TEST_COUNT); +} + +void test_find_transactions_obj_by_tag(void) { + char* json_result; + double sum = 0; + + for (size_t count = 0; count < TEST_COUNT; count++) { + test_time_start(&start_time); + + TEST_ASSERT_EQUAL_INT32(SC_OK, api_find_transactions_obj_by_tag(&ta_core.service, driver_tag_msg, &json_result)); + test_time_end(&start_time, &end_time, &sum); + free(json_result); + } + printf("Average time of find_tx_obj_by_tag: %lf\n", sum / TEST_COUNT); +} + void test_send_mam_message(void) { double sum = 0; const char* json = "{\"message\":\"" TEST_PAYLOAD "\"}"; @@ -206,6 +234,8 @@ int main(void) { RUN_TEST(test_find_transactions); RUN_TEST(test_send_mam_message); RUN_TEST(test_receive_mam_message); + RUN_TEST(test_find_transactions_by_tag); + RUN_TEST(test_find_transactions_obj_by_tag); ta_config_destroy(&ta_core.service); return UNITY_END(); }