From 79e299c258d7f20b55231549bd97624acd846dfb Mon Sep 17 00:00:00 2001 From: Yu Wei Wu Date: Tue, 2 Apr 2019 13:34:28 +0800 Subject: [PATCH 01/26] fix(pow): Fix bundle order of pow The bundle array order is actually increment from front to back. So if we should start with back to be trunk. --- utils/pow.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/utils/pow.c b/utils/pow.c index 373ad324..7915b4e6 100644 --- a/utils/pow.c +++ b/utils/pow.c @@ -43,9 +43,10 @@ status_t ta_pow(const bundle_transactions_t* bundle, iota_transaction_t* tx; flex_trit_t* ctrunk = (flex_trit_t*)calloc(FLEX_TRIT_SIZE_243, sizeof(flex_trit_t)); + flex_trit_t tx_trits[FLEX_TRIT_SIZE_8019]; size_t cur_idx = 0; - tx = (iota_transaction_t*)utarray_front(bundle); + tx = (iota_transaction_t*)utarray_back(bundle); if (tx == NULL) { ret = SC_TA_NULL; goto done; @@ -55,7 +56,6 @@ status_t ta_pow(const bundle_transactions_t* bundle, do { cur_idx--; - // set trunk, branch, and attachment timestamp transaction_set_trunk(tx, ctrunk); transaction_set_branch(tx, branch); @@ -63,7 +63,7 @@ status_t ta_pow(const bundle_transactions_t* bundle, transaction_set_attachment_timestamp_upper(tx, 3812798742493LL); transaction_set_attachment_timestamp_lower(tx, 0); - flex_trit_t* tx_trits = transaction_serialize(tx); + transaction_serialize_on_flex_trits(tx, tx_trits); if (tx_trits == NULL) { ret = SC_CCLIENT_INVALID_FLEX_TRITS; goto done; @@ -78,9 +78,10 @@ status_t ta_pow(const bundle_transactions_t* bundle, transaction_set_nonce(tx, nonce); free(ctrunk); + transaction_serialize_on_flex_trits(tx, tx_trits); ctrunk = iota_flex_digest(tx_trits, NUM_TRITS_SERIALIZED_TRANSACTION); + tx = (iota_transaction_t*)utarray_prev(bundle, tx); free(nonce); - free(tx_trits); } while (cur_idx != 0); done: From 1765061d6e5a95b48b0beb0c039ce6c2b1ddd5c6 Mon Sep 17 00:00:00 2001 From: YangHau Date: Fri, 29 Mar 2019 17:59:57 +0800 Subject: [PATCH 02/26] feat(mam): Implement api_mam_send_message() Implement `api_mam_send_message()` and related test, function. The function was implemented is `mam_send_bundle()` whose arg is bundle. --- accelerator/apis.c | 91 ++++++++++++++++++++++++++++++++++++++- accelerator/apis.h | 23 ++++++++++ accelerator/common_core.c | 27 +++++++++++- accelerator/common_core.h | 18 ++++++++ accelerator/config.c | 3 +- accelerator/config.h | 8 ++-- accelerator/errors.h | 2 + tests/driver.c | 31 +++++++++++++ tests/test_define.h | 21 +++++++++ 9 files changed, 218 insertions(+), 6 deletions(-) diff --git a/accelerator/apis.c b/accelerator/apis.c index 125ebf92..b055aba1 100644 --- a/accelerator/apis.c +++ b/accelerator/apis.c @@ -54,7 +54,7 @@ status_t api_get_tips_pair(const iota_config_t* const tangle, goto done; } - ret = cclient_get_txn_to_approve(service, tangle->depth, res); + ret = cclient_get_txn_to_approve(service, tangle->milestone_depth, res); if (ret) { goto done; } @@ -214,6 +214,95 @@ status_t api_receive_mam_message(const iota_client_service_t* const service, return ret; } +status_t api_mam_send_message(const iota_config_t* const tangle, + const iota_client_service_t* const service, + char const* const payload, + char** bundle_hash_result, + char** channel_id_result) { + status_t ret = SC_OK; + mam_api_t mam; + const bool last_packet = true; + bundle_transactions_t* bundle = NULL; + mam_psk_t_set_t psks = NULL; + bundle_transactions_new(&bundle); + tryte_t channel_id[MAM_CHANNEL_ID_SIZE]; + trit_t msg_id[MAM_MSG_ID_SIZE]; + + size_t payload_size = strlen(payload) * 2; + if ((payload_size == 0) || ((payload_size * 3) > SIZE_MAX)) { + return SC_MAM_OOM; + } + tryte_t* payload_trytes = (tryte_t*)malloc(payload_size * sizeof(tryte_t)); + if (!payload_trytes) { + return SC_MAM_OOM; + } + ascii_to_trytes(payload, payload_trytes); + + *bundle_hash_result = (tryte_t*)malloc(sizeof(tryte_t) * NUM_TRYTES_ADDRESS); + if (!(*bundle_hash_result)) { + return SC_MAM_OOM; + } + *channel_id_result = (tryte_t*)malloc(sizeof(tryte_t) * NUM_TRYTES_ADDRESS); + if (!(*channel_id_result)) { + return SC_MAM_OOM; + } + + // Creating MAM API + if (mam_api_init(&mam, (tryte_t*)SEED)) { + ret = SC_MAM_FAILED_INIT; + goto done; + } + + // Create mam channel + if (mam_channel_t_set_size(mam.channels) == 0) { + mam_api_create_channel(&mam, tangle->mss_depth, channel_id); + } else { + mam_channel_t* channel = &mam.channels->value; + trits_to_trytes(trits_begin(mam_channel_id(channel)), channel_id, + NUM_TRITS_ADDRESS); + } + + // Write header and packet + if (!mam_psk_t_set_contains(&psks, &psk)) { + if (mam_psk_t_set_add(&psks, &psk) != RC_OK) { + ret = SC_MAM_FAILED_WRITE; + goto done; + } + } + if (mam_api_bundle_write_header_on_channel(&mam, channel_id, psks, NULL, 0, + bundle, msg_id) != RC_OK) { + ret = SC_MAM_FAILED_WRITE; + goto done; + } + if (mam_api_bundle_write_packet(&mam, msg_id, payload_trytes, payload_size, 0, + last_packet, bundle) != RC_OK) { + ret = SC_MAM_FAILED_WRITE; + goto done; + } + memcpy(*channel_id_result, channel_id, sizeof(tryte_t) * NUM_TRYTES_ADDRESS); + + // Sending bundle + if (ta_send_bundle(tangle, service, bundle) != SC_OK) { + ret = SC_MAM_FAILED_RESPONSE; + goto done; + } + memcpy(*bundle_hash_result, + ((iota_transaction_t*)utarray_front(bundle))->essence.bundle, + sizeof(tryte_t) * NUM_TRYTES_ADDRESS); + +done: + // Destroying MAM API + if (ret != SC_MAM_FAILED_INIT) { + if (mam_api_destroy(&mam) != RC_OK) { + ret = SC_MAM_FAILED_DESTROYED; + } + } + free(payload_trytes); + mam_psk_t_set_free(&psks); + bundle_transactions_free(&bundle); + return ret; +} + status_t api_send_transfer(const iota_config_t* const tangle, const iota_client_service_t* const service, const char* const obj, char** json_result) { diff --git a/accelerator/apis.h b/accelerator/apis.h index c9be5fe2..105c63ec 100644 --- a/accelerator/apis.h +++ b/accelerator/apis.h @@ -92,6 +92,29 @@ status_t api_receive_mam_message(const iota_client_service_t* const service, const char* const bundle_hash, char** json_result); +/** + * @brief Send a MAM message with given Payload. + * + * Send a MAM message from given Payload(ascii message). + * There is no need to decode the ascii payload to tryte, since the + * api_mam_send_message() will take this job. + * + * @param[in] tangle IOTA API parameter configurations + * @param[in] service IRI node end point service + * @param[in] payload message to send undecoded ascii string. + * @param[out] bundle_hashes_result the bundle hash of sent message + * @param[out] channel_id_result the channel id the sent message to + * + * @return + * - SC_OK on success + * - non-zero on error + */ +status_t api_mam_send_message(const iota_config_t* const tangle, + const iota_client_service_t* const service, + char const* const payload, + char** bundle_hash_result, + char** channel_id_result); + /** * @brief Send transfer to tangle. * diff --git a/accelerator/common_core.c b/accelerator/common_core.c index 1cedbc68..2f2184a7 100644 --- a/accelerator/common_core.c +++ b/accelerator/common_core.c @@ -169,7 +169,8 @@ status_t ta_send_trytes(const iota_config_t* const tangle, } // get transaction to approve - ret = cclient_get_txn_to_approve(service, tangle->depth, get_txn_res); + ret = + cclient_get_txn_to_approve(service, tangle->milestone_depth, get_txn_res); if (ret) { goto done; } @@ -520,3 +521,27 @@ status_t ta_get_bundle(const iota_client_service_t* const service, find_transactions_req_free(&find_tx_req); return ret; } + +status_t ta_send_bundle(const iota_config_t* const tangle, + const iota_client_service_t* const service, + bundle_transactions_t* const bundle) { + Kerl kerl; + kerl_init(&kerl); + bundle_finalize(bundle, &kerl); + transaction_array_t* out_tx_objs = transaction_array_new(); + hash8019_array_p raw_trytes = hash8019_array_new(); + iota_transaction_t* curr_tx = NULL; + flex_trit_t trits_8019[FLEX_TRIT_SIZE_8019]; + + BUNDLE_FOREACH(bundle, curr_tx) { + transaction_serialize_on_flex_trits(curr_tx, trits_8019); + hash_array_push(raw_trytes, trits_8019); + } + + ta_send_trytes(tangle, service, raw_trytes); + + hash_array_free(raw_trytes); + transaction_array_free(out_tx_objs); + + return SC_OK; +} diff --git a/accelerator/common_core.h b/accelerator/common_core.h index c372272d..2e1259c6 100644 --- a/accelerator/common_core.h +++ b/accelerator/common_core.h @@ -195,6 +195,24 @@ status_t ta_get_bundle(const iota_client_service_t* const service, tryte_t const* const bundle_hash, bundle_transactions_t* const bundle); +/** + * @brief Send bundle object. + * + * Send the unpacked bundle which contains transactions. MAM functions should + * send message with this function. + * + * @param[in] service IRI node end point service + * @param[in] bundle bundle object to send + * @param[out] bundle Result containing bundle object in bundle_transactions_t + * + * @return + * - SC_OK on success + * - non-zero on error + */ +status_t ta_send_bundle(const iota_config_t* const tangle, + const iota_client_service_t* const service, + bundle_transactions_t* const bundle); + #ifdef __cplusplus } #endif diff --git a/accelerator/config.c b/accelerator/config.c index 97c78eaf..c4731961 100644 --- a/accelerator/config.c +++ b/accelerator/config.c @@ -23,7 +23,8 @@ status_t ta_config_init(ta_config_t* const info, iota_config_t* const tangle, info->thread_count = TA_THREAD_COUNT; log_info(logger_id, "Initializing IRI configuration\n"); - tangle->depth = DEPTH; + tangle->milestone_depth = MILESTONE_DEPTH; + tangle->mss_depth = MSS_DEPTH; tangle->mwm = MWM; tangle->seed = SEED; diff --git a/accelerator/config.h b/accelerator/config.h index 0348f7d9..e7cdbef6 100644 --- a/accelerator/config.h +++ b/accelerator/config.h @@ -23,7 +23,8 @@ extern "C" { #define TA_THREAD_COUNT 10 #define IRI_HOST "localhost" #define IRI_PORT 14265 -#define DEPTH 3 +#define MILESTONE_DEPTH 3 +#define MSS_DEPTH 4 #define MWM 14 #define SEED \ "AMRWQP9BUMJALJHBXUCHOD9HFFD9LGTGEAWMJWWXSDVOF9PI9YGJAPBQLQUOMNYEQCZPGCTHGV" \ @@ -45,8 +46,9 @@ typedef struct ta_info_s { /** struct type of iota configuration */ typedef struct ta_config_s { - uint8_t depth; /**< Depth of API argument */ - uint8_t mwm; /**< Minimum weight magnitude of API argument */ + uint8_t milestone_depth; /**< Depth of API argument */ + uint8_t mss_depth; /**< Depth of MSS layer merkle tree */ + uint8_t mwm; /**< Minimum weight magnitude of API argument */ /** Seed to generate address. This does not do any signature yet. */ const char* seed; } iota_config_t; diff --git a/accelerator/errors.h b/accelerator/errors.h index e191e750..74f572e2 100644 --- a/accelerator/errors.h +++ b/accelerator/errors.h @@ -103,6 +103,8 @@ typedef enum { /**< Error in mam destroy */ SC_MAM_NO_PAYLOAD = 0x07 | SC_MODULE_MAM | SC_SEVERITY_FATAL, /**< No payload or no chid */ + SC_MAM_FAILED_WRITE = 0x08 | SC_MODULE_MAM | SC_SEVERITY_FATAL, + /**< Failed to write */ } status_t; typedef enum { diff --git a/tests/driver.c b/tests/driver.c index c7e2183e..89a9d81d 100644 --- a/tests/driver.c +++ b/tests/driver.c @@ -138,6 +138,37 @@ void test_find_transactions_obj_by_tag(void) { printf("Average time of find_tx_obj_by_tag: %lf\n", sum / TEST_COUNT); } +void test_send_mam_message(void) { + double sum = 0; + status_t ret = SC_OK; + + char* bundle_hash_result; + char* channel_id_result; + + for (size_t count = 0; count < TEST_COUNT; count++) { + test_time_start(&start_time); + TEST_ASSERT_EQUAL_INT32( + SC_OK, + api_mam_send_message(&ta_core.tangle, &ta_core.service, TEST_PAYLOAD, + &bundle_hash_result, &channel_id_result)); + test_time_end(&start_time, &end_time, &sum); + + for (size_t i = 0; i < FLEX_TRIT_SIZE_243; i++) { + printf("%c", channel_id_result[i]); + } + printf("\n"); + printf("Bundle: "); + for (size_t i = 0; i < FLEX_TRIT_SIZE_243; i++) { + printf("%c", bundle_hash_result[i]); + } + printf("\n"); + + free(bundle_hash_result); + free(channel_id_result); + } + printf("Average time of receive_mam_message: %lf\n", sum / TEST_COUNT); +} + void test_receive_mam_message(void) { char* json_result; double sum = 0; diff --git a/tests/test_define.h b/tests/test_define.h index cd9995a2..ee12df5c 100644 --- a/tests/test_define.h +++ b/tests/test_define.h @@ -113,6 +113,27 @@ extern "C" { "WYEVIWJN9DF9SBQHBUWYUECD9KD9BQHQXHOGQDTVKKYBRQUFQYGOFOTHREGVSKSSEVXMFOEHWN" \ "KHLHDKQ" +#define TEST_PAYLOAD \ + "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer aliquam " \ + "velit ac placerat dignissim. Suspendisse interdum nisl velit, quis " \ + "consequat lacus gravida vitae. Mauris in faucibus eros. Phasellus " \ + "eleifend bibendum magna in iaculis. Nullam quis nibh posuere, efficitur " \ + "metus nec, cursus justo. Cras in eros velit. Suspendisse tempus a ipsum " \ + "et vehicula. Nulla sed ipsum porttitor, molestie enim ut, porttitor " \ + "neque. Aenean rutrum nunc eros, vitae ullamcorper neque pretium ut. Etiam " \ + "tempor libero sit amet fringilla eleifend. Maecenas varius nunc vel porta " \ + "bibendum. Vestibulum ultricies sagittis elit eu rutrum. Duis id orci at " \ + "eros vehicula suscipit a ac tortor. Morbi nulla nisi, laoreet vel leo " \ + "vel, dignissim convallis sem. Nunc id lacus consectetur, iaculis metus " \ + "ac, dictum erat. Curabitur eget erat eu eros hendrerit dapibus quis nec " \ + "diam. Sed vulputate velit a mi ullamcorper, ut vestibulum felis " \ + "tincidunt. Fusce et euismod elit. Phasellus augue turpis, efficitur a " \ + "augue ac, rutrum vehicula nisl. Morbi ullamcorper, dui non ultrices " \ + "consequat, odio felis aliquam dui, et mattis nibh purus vitae felis. " \ + "Pellentesque rhoncus diam enim, in porttitor turpis dignissim in. " \ + "Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere " \ + "cubilia Curae;" + #ifdef __cplusplus } #endif From 0d45c6f8c073a76e580f4940009a53350467f0a6 Mon Sep 17 00:00:00 2001 From: YangHau Date: Fri, 29 Mar 2019 15:29:28 +0800 Subject: [PATCH 03/26] refactor(driver): Change ASSERT function Use `TEST_ASSERT_EQUAL_INT32` instead of `TEST_ASSERT` --- tests/driver.c | 46 ++++++++++++++++++++++++++++------------------ 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/tests/driver.c b/tests/driver.c index 89a9d81d..495e6ad6 100644 --- a/tests/driver.c +++ b/tests/driver.c @@ -42,7 +42,8 @@ void test_generate_address(void) { for (size_t count = 0; count < TEST_COUNT; count++) { test_time_start(&start_time); - TEST_ASSERT_FALSE( + TEST_ASSERT_EQUAL_INT32( + SC_OK, api_generate_address(&ta_core.tangle, &ta_core.service, &json_result)); test_time_end(&start_time, &end_time, &sum); free(json_result); @@ -56,7 +57,8 @@ void test_get_tips_pair(void) { for (size_t count = 0; count < TEST_COUNT; count++) { test_time_start(&start_time); - TEST_ASSERT_FALSE( + TEST_ASSERT_EQUAL_INT32( + SC_OK, api_get_tips_pair(&ta_core.tangle, &ta_core.service, &json_result)); test_time_end(&start_time, &end_time, &sum); free(json_result); @@ -70,7 +72,8 @@ void test_get_tips(void) { for (size_t count = 0; count < TEST_COUNT; count++) { test_time_start(&start_time); - TEST_ASSERT_FALSE(api_get_tips(&ta_core.service, &json_result)); + TEST_ASSERT_EQUAL_INT32(SC_OK, + api_get_tips(&ta_core.service, &json_result)); test_time_end(&start_time, &end_time, &sum); free(json_result); } @@ -88,8 +91,9 @@ void test_send_transfer(void) { for (size_t count = 0; count < TEST_COUNT; count++) { test_time_start(&start_time); - TEST_ASSERT_FALSE(api_send_transfer(&ta_core.tangle, &ta_core.service, json, - &json_result)); + TEST_ASSERT_EQUAL_INT32( + SC_OK, api_send_transfer(&ta_core.tangle, &ta_core.service, json, + &json_result)); test_time_end(&start_time, &end_time, &sum); free(json_result); } @@ -102,8 +106,9 @@ void test_get_transaction_object(void) { for (size_t count = 0; count < TEST_COUNT; count++) { test_time_start(&start_time); - TEST_ASSERT_FALSE(api_get_transaction_object(&ta_core.service, TRYTES_81_3, - &json_result)); + TEST_ASSERT_EQUAL_INT32( + SC_OK, api_get_transaction_object(&ta_core.service, TRYTES_81_3, + &json_result)); test_time_end(&start_time, &end_time, &sum); free(json_result); } @@ -116,8 +121,10 @@ void test_find_transactions_by_tag(void) { for (size_t count = 0; count < TEST_COUNT; count++) { test_time_start(&start_time); - TEST_ASSERT_FALSE(api_find_transactions_by_tag(&ta_core.service, - FIND_TAG_MSG, &json_result)); + + TEST_ASSERT_EQUAL_INT32( + SC_OK, api_find_transactions_by_tag(&ta_core.service, FIND_TAG_MSG, + &json_result)); test_time_end(&start_time, &end_time, &sum); free(json_result); } @@ -130,8 +137,10 @@ void test_find_transactions_obj_by_tag(void) { for (size_t count = 0; count < TEST_COUNT; count++) { test_time_start(&start_time); - TEST_ASSERT_FALSE(api_find_transactions_obj_by_tag( - &ta_core.service, FIND_TAG_MSG, &json_result)); + + TEST_ASSERT_EQUAL_INT32( + SC_OK, api_find_transactions_obj_by_tag(&ta_core.service, FIND_TAG_MSG, + &json_result)); test_time_end(&start_time, &end_time, &sum); free(json_result); } @@ -140,7 +149,6 @@ void test_find_transactions_obj_by_tag(void) { void test_send_mam_message(void) { double sum = 0; - status_t ret = SC_OK; char* bundle_hash_result; char* channel_id_result; @@ -172,13 +180,14 @@ void test_send_mam_message(void) { void test_receive_mam_message(void) { char* json_result; double sum = 0; - status_t ret = SC_OK; + for (size_t count = 0; count < TEST_COUNT; count++) { - clock_gettime(CLOCK_REALTIME, &start_time); - ret = api_receive_mam_message(&ta_core.service, TEST_BUNDLE_HASH, - &json_result); - TEST_ASSERT_EQUAL_INT32(ret, SC_OK); - clock_gettime(CLOCK_REALTIME, &end_time); + test_time_start(&start_time); + + TEST_ASSERT_EQUAL_INT32( + SC_OK, api_receive_mam_message(&ta_core.service, TEST_BUNDLE_HASH, + &json_result)); + test_time_end(&start_time, &end_time, &sum); free(json_result); } printf("Average time of receive_mam_message: %lf\n", sum / TEST_COUNT); @@ -198,6 +207,7 @@ int main(void) { RUN_TEST(test_find_transactions_by_tag); RUN_TEST(test_find_transactions_obj_by_tag); RUN_TEST(test_receive_mam_message); + RUN_TEST(test_send_mam_message); ta_config_destroy(&ta_core.service); return UNITY_END(); } From 153727f69e0c68c50906ff021eede17b49cdc0f2 Mon Sep 17 00:00:00 2001 From: Yu Wei Wu Date: Thu, 4 Apr 2019 10:35:42 +0800 Subject: [PATCH 04/26] feat(api): Add send_mam_message API --- accelerator/server.cc | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/accelerator/server.cc b/accelerator/server.cc index 7ee9173b..69d4ae8e 100644 --- a/accelerator/server.cc +++ b/accelerator/server.cc @@ -79,6 +79,36 @@ int main(int, char const**) { res << json_result; }); + mux.handle("/mam") + .method(served::method::OPTIONS, + [&](served::response& res, const served::request& req) { + set_method_header(res, HTTP_METHOD_OPTIONS); + }) + .post([&](served::response& res, const served::request& req) { + status_t ret = SC_OK; + char* json_result; + char* chid_result; + + if (req.header("content-type").find("application/json") == + std::string::npos) { + cJSON* json_obj = cJSON_CreateObject(); + cJSON_AddStringToObject(json_obj, "message", + "Invalid request header"); + json_result = cJSON_PrintUnformatted(json_obj); + + res.set_status(SC_HTTP_BAD_REQUEST); + cJSON_Delete(json_obj); + } else { + api_mam_send_message(&ta_core.tangle, &ta_core.service, + req.body().c_str(), &json_result, &chid_result); + ret = set_response_content(ret, &json_result); + res.set_status(ret); + } + + set_method_header(res, HTTP_METHOD_POST); + res << json_result; + }); + /** * @method {get} /tag/:tag Find transactions by tag * From 9ddb155e9697c456da2b777763169b670289098b Mon Sep 17 00:00:00 2001 From: YangHau Date: Thu, 4 Apr 2019 16:04:31 +0800 Subject: [PATCH 05/26] feat(mam): Implement send_mam_req send_mam_req obj can simplify the arg of api_mam_send_message(). --- request/BUILD | 1 + request/request.h | 1 + request/ta_send_mam_req.c | 40 +++++++++++++++++++++++++++++++++++++++ request/ta_send_mam_req.h | 27 ++++++++++++++++++++++++++ 4 files changed, 69 insertions(+) create mode 100644 request/ta_send_mam_req.c create mode 100644 request/ta_send_mam_req.h diff --git a/request/BUILD b/request/BUILD index 61b29b06..35cfd629 100644 --- a/request/BUILD +++ b/request/BUILD @@ -10,5 +10,6 @@ cc_library( visibility = ["//visibility:public"], deps = [ "@entangled//cclient/types", + "//accelerator:ta_errors", ], ) diff --git a/request/request.h b/request/request.h index 19df9bde..0c8935d1 100644 --- a/request/request.h +++ b/request/request.h @@ -1,6 +1,7 @@ #ifndef REQUEST_REQUEST_H_ #define REQUEST_REQUEST_H_ +#include "request/ta_send_mam_req.h" #include "request/ta_send_transfer.h" /** diff --git a/request/ta_send_mam_req.c b/request/ta_send_mam_req.c new file mode 100644 index 00000000..a3f9d043 --- /dev/null +++ b/request/ta_send_mam_req.c @@ -0,0 +1,40 @@ +#include "ta_send_mam_req.h" + +send_mam_req_t* send_mam_req_new() { + send_mam_req_t* req = (send_mam_req_t*)malloc(sizeof(send_mam_req_t)); + if (req) { + req->payload_trytes = NULL; + } + + return req; +} + +status_t send_mam_req_set_payload(send_mam_req_t* req, const tryte_t* payload) { + status_t ret = SC_OK; + size_t payload_size = sizeof(payload) / sizeof(tryte_t); + + if ((!payload) || (payload_size == 0) || ((payload_size * 3) > SIZE_MAX)) { + return SC_MAM_OOM; + } + + req->payload_trytes = (tryte_t*)malloc(payload_size * sizeof(tryte_t)); + if (!req->payload_trytes) { + return SC_MAM_OOM; + } + memcpy(req->payload_trytes, payload, payload_size); + req->payload_trytes_size = payload_size; + + return ret; +} + +void send_mam_req_free(send_mam_req_t** req) { + if (!req || !(*req)) { + return; + } + if ((*req)->payload_trytes) { + free((*req)->payload_trytes); + (*req)->payload_trytes = NULL; + } + free(*req); + *req = NULL; +} diff --git a/request/ta_send_mam_req.h b/request/ta_send_mam_req.h new file mode 100644 index 00000000..41b77a90 --- /dev/null +++ b/request/ta_send_mam_req.h @@ -0,0 +1,27 @@ +#ifndef REQUEST_TA_SEND_MAM_REQ_H_ +#define REQUEST_TA_SEND_MAM_REQ_H_ + +#include +#include +#include +#include "accelerator/errors.h" +#include "cclient/types/types.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct send_mam_req_s { + tryte_t* payload_trytes; + size_t payload_trytes_size; +} send_mam_req_t; + +send_mam_req_t* send_mam_req_new(); +status_t send_mam_req_set_payload(send_mam_req_t* req, const tryte_t* payload); +void send_mam_req_free(send_mam_req_t** req); + +#ifdef __cplusplus +} +#endif + +#endif // REQUEST_TA_SEND_MAM_REQ_H_ From b9788d6991f03622c53cb55f03eeab6c32917154 Mon Sep 17 00:00:00 2001 From: YangHau Date: Sat, 6 Apr 2019 15:02:32 +0800 Subject: [PATCH 06/26] fix(mam): Remove useless send_mam_req inclusion --- request/ta_send_mam_req.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/request/ta_send_mam_req.h b/request/ta_send_mam_req.h index 41b77a90..c7597d9e 100644 --- a/request/ta_send_mam_req.h +++ b/request/ta_send_mam_req.h @@ -1,9 +1,6 @@ #ifndef REQUEST_TA_SEND_MAM_REQ_H_ #define REQUEST_TA_SEND_MAM_REQ_H_ -#include -#include -#include #include "accelerator/errors.h" #include "cclient/types/types.h" From b143777d210b9dc6882061d02e6c05a8d840e71e Mon Sep 17 00:00:00 2001 From: YangHau Date: Sat, 6 Apr 2019 14:35:14 +0800 Subject: [PATCH 07/26] feat(mam): Implement send_mam_res object --- accelerator/errors.h | 7 ++++ response/BUILD | 2 + response/response.h | 1 + response/ta_send_mam_res.c | 60 +++++++++++++++++++++++++++++ response/ta_send_mam_res.h | 79 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 149 insertions(+) create mode 100644 response/ta_send_mam_res.c create mode 100644 response/ta_send_mam_res.h diff --git a/accelerator/errors.h b/accelerator/errors.h index 74f572e2..d5e308d1 100644 --- a/accelerator/errors.h +++ b/accelerator/errors.h @@ -40,6 +40,7 @@ extern "C" { #define SC_MODULE_SERIALIZER (0x03 << SC_MODULE_SHIFT) #define SC_MODULE_CACHE (0x04 << SC_MODULE_SHIFT) #define SC_MODULE_MAM (0x05 << SC_MODULE_SHIFT) +#define SC_MODULE_RES (0x06 << SC_MODULE_SHIFT) /** @} */ /** @name serverity code */ @@ -105,6 +106,12 @@ typedef enum { /**< No payload or no chid */ SC_MAM_FAILED_WRITE = 0x08 | SC_MODULE_MAM | SC_SEVERITY_FATAL, /**< Failed to write */ + + // response module + SC_RES_OOM = 0x01 | SC_MODULE_RES | SC_SEVERITY_FATAL, + /**< Fail to create response object */ + SC_RES_NULL = 0x02 | SC_MODULE_RES | SC_SEVERITY_FATAL, + /**< NULL object in response */ } status_t; typedef enum { diff --git a/response/BUILD b/response/BUILD index 623b5ebe..ea097dba 100644 --- a/response/BUILD +++ b/response/BUILD @@ -10,5 +10,7 @@ cc_library( visibility = ["//visibility:public"], deps = [ "@entangled//cclient/types", + "@entangled//common/model:transaction", + "//accelerator:ta_errors", ], ) diff --git a/response/response.h b/response/response.h index d2344531..94ae4a95 100644 --- a/response/response.h +++ b/response/response.h @@ -6,6 +6,7 @@ #include "response/ta_generate_address.h" #include "response/ta_get_tips.h" #include "response/ta_get_transaction_object.h" +#include "response/ta_send_mam_res.h" #include "response/ta_send_transfer.h" /** diff --git a/response/ta_send_mam_res.c b/response/ta_send_mam_res.c new file mode 100644 index 00000000..14032b50 --- /dev/null +++ b/response/ta_send_mam_res.c @@ -0,0 +1,60 @@ +#include "ta_send_mam_res.h" + +send_mam_res_t* send_mam_res_new() { + send_mam_res_t* res = (send_mam_res_t*)malloc(sizeof(send_mam_res_t)); + if (res) { + res->bundle_hash = NULL; + res->channel_id = NULL; + } + + return res; +} + +status_t send_mam_res_set_bundle_hash(send_mam_res_t* res, + const tryte_t* bundle_hash) { + if (res->bundle_hash || !bundle_hash) { + return SC_RES_NULL; + } + + size_t bundle_hash_size = NUM_TRYTES_ADDRESS * sizeof(char); + res->bundle_hash = (char*)malloc(bundle_hash_size); + if (!res->bundle_hash) { + return SC_RES_OOM; + } + + memcpy(res->bundle_hash, bundle_hash, bundle_hash_size); + return SC_OK; +} + +status_t send_mam_res_set_channel_id(send_mam_res_t* res, + const tryte_t* channel_id) { + if (res->channel_id || !channel_id) { + return SC_RES_NULL; + } + + size_t channel_id_size = NUM_TRYTES_ADDRESS * sizeof(char); + res->channel_id = (char*)malloc(channel_id_size); + if (!res->channel_id) { + return SC_RES_OOM; + } + + memcpy(res->channel_id, channel_id, channel_id_size); + return SC_OK; +} + +void send_mam_res_free(send_mam_res_t** res) { + if (!res || !(*res)) { + return; + } + if ((*res)->bundle_hash) { + free((*res)->bundle_hash); + (*res)->bundle_hash = NULL; + } + if ((*res)->channel_id) { + free((*res)->channel_id); + (*res)->channel_id = NULL; + } + + free(*res); + *res = NULL; +} diff --git a/response/ta_send_mam_res.h b/response/ta_send_mam_res.h new file mode 100644 index 00000000..57b68f0d --- /dev/null +++ b/response/ta_send_mam_res.h @@ -0,0 +1,79 @@ +#ifndef RESPONSE_TA_SEND_MAM_RES_H_ +#define RESPONSE_TA_SEND_MAM_RES_H_ + +#include "accelerator/errors.h" +#include "common/model/transaction.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @file response/ta_send_mam_res.h + */ + +/** struct of ta_send_mam_res_t */ +typedef struct send_mam_res_s { + /** ascii string bundle hash */ + char* bundle_hash; + /** ascii string channel id */ + char* channel_id; +} send_mam_res_t; + +/** + * Allocate memory of send_mam_res_t + * + * @return + * - struct of send_mam_res_t on success + * - NULL on error + */ +send_mam_res_t* send_mam_res_new(); + +/** + * @brief Set the bundle_hash field of send_mam_res object. + * + * Receive a bundle hash tryte_t array which is 81 trytes long, + * and convert (instead of decoding) the received bundle hash to ascii string. + * After conversion, set the bundle_hash field of send_mam_res object. + * + * @param[in] res send_mam_res_t struct object + * @param[in] bundle_hash bundle hash decoded in trytes string + * + * @return + * - SC_OK on success + * - non-zero on error + */ +status_t send_mam_res_set_bundle_hash(send_mam_res_t* res, + const tryte_t* bundle_hash); + +/** + * @brief Set the channel_id field of send_mam_res object. + * + * Receive a channel id tryte_t array which is 81 trytes long, + * and convert (instead of decoding) the received channel id to ascii string. + * After conversion, set the channel_id field of send_mam_res object. + * + * @param[in] res send_mam_res_t struct object + * @param[in] channel_id channel id decoded in trytes string + * + * @return + * - SC_OK on success + * - non-zero on error + */ +status_t send_mam_res_set_channel_id(send_mam_res_t* res, + const tryte_t* channel_id); + +/** + * Free memory of send_mam_res_t + * + * @param req Data type of send_mam_res_t + * + * @return NULL + */ +void send_mam_res_free(send_mam_res_t** res); + +#ifdef __cplusplus +} +#endif + +#endif // RESPONSE_TA_SEND_MAM_RES_H_ From 53f23fec730f56387568e37f291d5c7dad155194 Mon Sep 17 00:00:00 2001 From: Yu Wei Wu Date: Tue, 9 Apr 2019 15:12:50 +0800 Subject: [PATCH 08/26] fix: Rename send mam request/response file names Rename send mam request/response file names to unify with others. --- request/BUILD | 2 +- request/request.h | 2 +- request/{ta_send_mam_req.c => ta_send_mam.c} | 2 +- request/{ta_send_mam_req.h => ta_send_mam.h} | 6 +++--- response/BUILD | 2 +- response/response.h | 2 +- response/{ta_send_mam_res.c => ta_send_mam.c} | 2 +- response/{ta_send_mam_res.h => ta_send_mam.h} | 6 +++--- 8 files changed, 12 insertions(+), 12 deletions(-) rename request/{ta_send_mam_req.c => ta_send_mam.c} (96%) rename request/{ta_send_mam_req.h => ta_send_mam.h} (79%) rename response/{ta_send_mam_res.c => ta_send_mam.c} (97%) rename response/{ta_send_mam_res.h => ta_send_mam.h} (94%) diff --git a/request/BUILD b/request/BUILD index 35cfd629..c4ace7fe 100644 --- a/request/BUILD +++ b/request/BUILD @@ -9,7 +9,7 @@ cc_library( include_prefix = "request", visibility = ["//visibility:public"], deps = [ - "@entangled//cclient/types", "//accelerator:ta_errors", + "@entangled//cclient/types", ], ) diff --git a/request/request.h b/request/request.h index 0c8935d1..6e7cc93e 100644 --- a/request/request.h +++ b/request/request.h @@ -1,7 +1,7 @@ #ifndef REQUEST_REQUEST_H_ #define REQUEST_REQUEST_H_ -#include "request/ta_send_mam_req.h" +#include "request/ta_send_mam.h" #include "request/ta_send_transfer.h" /** diff --git a/request/ta_send_mam_req.c b/request/ta_send_mam.c similarity index 96% rename from request/ta_send_mam_req.c rename to request/ta_send_mam.c index a3f9d043..641ef46b 100644 --- a/request/ta_send_mam_req.c +++ b/request/ta_send_mam.c @@ -1,4 +1,4 @@ -#include "ta_send_mam_req.h" +#include "ta_send_mam.h" send_mam_req_t* send_mam_req_new() { send_mam_req_t* req = (send_mam_req_t*)malloc(sizeof(send_mam_req_t)); diff --git a/request/ta_send_mam_req.h b/request/ta_send_mam.h similarity index 79% rename from request/ta_send_mam_req.h rename to request/ta_send_mam.h index c7597d9e..e3f6137a 100644 --- a/request/ta_send_mam_req.h +++ b/request/ta_send_mam.h @@ -1,5 +1,5 @@ -#ifndef REQUEST_TA_SEND_MAM_REQ_H_ -#define REQUEST_TA_SEND_MAM_REQ_H_ +#ifndef REQUEST_TA_SEND_MAM_H_ +#define REQUEST_TA_SEND_MAM_H_ #include "accelerator/errors.h" #include "cclient/types/types.h" @@ -21,4 +21,4 @@ void send_mam_req_free(send_mam_req_t** req); } #endif -#endif // REQUEST_TA_SEND_MAM_REQ_H_ +#endif // REQUEST_TA_SEND_MAM_H_ diff --git a/response/BUILD b/response/BUILD index ea097dba..c7ee8cff 100644 --- a/response/BUILD +++ b/response/BUILD @@ -9,8 +9,8 @@ cc_library( include_prefix = "response", visibility = ["//visibility:public"], deps = [ + "//accelerator:ta_errors", "@entangled//cclient/types", "@entangled//common/model:transaction", - "//accelerator:ta_errors", ], ) diff --git a/response/response.h b/response/response.h index 94ae4a95..733174b5 100644 --- a/response/response.h +++ b/response/response.h @@ -6,7 +6,7 @@ #include "response/ta_generate_address.h" #include "response/ta_get_tips.h" #include "response/ta_get_transaction_object.h" -#include "response/ta_send_mam_res.h" +#include "response/ta_send_mam.h" #include "response/ta_send_transfer.h" /** diff --git a/response/ta_send_mam_res.c b/response/ta_send_mam.c similarity index 97% rename from response/ta_send_mam_res.c rename to response/ta_send_mam.c index 14032b50..6e282541 100644 --- a/response/ta_send_mam_res.c +++ b/response/ta_send_mam.c @@ -1,4 +1,4 @@ -#include "ta_send_mam_res.h" +#include "ta_send_mam.h" send_mam_res_t* send_mam_res_new() { send_mam_res_t* res = (send_mam_res_t*)malloc(sizeof(send_mam_res_t)); diff --git a/response/ta_send_mam_res.h b/response/ta_send_mam.h similarity index 94% rename from response/ta_send_mam_res.h rename to response/ta_send_mam.h index 57b68f0d..4422b001 100644 --- a/response/ta_send_mam_res.h +++ b/response/ta_send_mam.h @@ -1,5 +1,5 @@ -#ifndef RESPONSE_TA_SEND_MAM_RES_H_ -#define RESPONSE_TA_SEND_MAM_RES_H_ +#ifndef RESPONSE_TA_SEND_MAM_H_ +#define RESPONSE_TA_SEND_MAM_H_ #include "accelerator/errors.h" #include "common/model/transaction.h" @@ -76,4 +76,4 @@ void send_mam_res_free(send_mam_res_t** res); } #endif -#endif // RESPONSE_TA_SEND_MAM_RES_H_ +#endif // RESPONSE_TA_SEND_MAM_H_ From 5270af8fa979ef81914a31b885459cda9dc1c492 Mon Sep 17 00:00:00 2001 From: YangHau Date: Mon, 8 Apr 2019 15:56:35 +0800 Subject: [PATCH 09/26] feat: Impl help instruction display Implement struct `ta_cli_argument_s` for saving information of instructions. `ta_cli_arg_value_t` is an enum for recognising the commands. And once calling the function `ta_usage()`, it will show all the currently available command. --- accelerator/BUILD | 6 +++++ accelerator/message.c | 18 +++++++++++++++ accelerator/message.h | 52 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) create mode 100644 accelerator/message.c create mode 100644 accelerator/message.h diff --git a/accelerator/BUILD b/accelerator/BUILD index e959d048..4d9539f0 100644 --- a/accelerator/BUILD +++ b/accelerator/BUILD @@ -68,3 +68,9 @@ cc_library( hdrs = ["errors.h"], visibility = ["//visibility:public"], ) + +cc_library( + name = "message", + srcs = ["message.c"], + hdrs = ["message.h"], +) diff --git a/accelerator/message.c b/accelerator/message.c new file mode 100644 index 00000000..ccc300be --- /dev/null +++ b/accelerator/message.c @@ -0,0 +1,18 @@ +#include "message.h" +#include "stdio.h" + +void ta_usage() { + printf("tangle-accelerator usage:\n"); + for (int i = 0; i < cli_cmd_num; i++) { + printf("--%-34s ", ta_cli_arguments_g[i].name); + printf(" "); + if (ta_cli_arguments_g[i].has_arg == REQUIRED_ARG) { + printf(" arg "); + } else if (ta_cli_arguments_g[i].has_arg == OPTIONAL_ARG) { + printf("[arg]"); + } else { + printf(" "); + } + printf(" %s \n", ta_cli_arguments_g[i].desc); + } +} diff --git a/accelerator/message.h b/accelerator/message.h new file mode 100644 index 00000000..e7af5e53 --- /dev/null +++ b/accelerator/message.h @@ -0,0 +1,52 @@ +#ifndef ACCELERATOR_MESSAGE_H_ +#define ACCELERATOR_MESSAGE_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum ta_cli_arg_value_e { + HELP_CLI, + + /** TA */ + TA_HOST_CLI, + TA_PORT_CLI, + TA_THREAD_COUNT_CLI, + TA_VERSION_CLI, + + /** IRI */ + IRI_HOST_CLI, + IRI_PORT_CLI, + + /** REDIS */ + REDIS_HOST_CLI, + REDIS_PORT_CLI, + + /** CONFIG */ + MILESTONE_DEPTH_CLI, + MWM_CLI, + SEED_CLI, +} ta_cli_arg_value_t; + +typedef enum ta_cli_arg_requirement_e { + NO_ARG, + REQUIRED_ARG, + OPTIONAL_ARG +} ta_cli_arg_requirement_t; + +static struct ta_cli_argument_s { + char* name; + int val; + char* desc; + ta_cli_arg_requirement_t has_arg; +} ta_cli_arguments_g[] = { + {"ta-help", HELP_CLI, "Show tangle-accelerator usage.", NO_ARG}}; + +static const int cli_cmd_num = + sizeof(ta_cli_arguments_g) / sizeof(struct ta_cli_argument_s); +void ta_usage(); +#ifdef __cplusplus +} +#endif + +#endif // ACCELERATOR_MESSAGE_H_ From ea3e119c3cd7ebca66ad85dc2ed88af89d41a0c3 Mon Sep 17 00:00:00 2001 From: Yu Wei Wu Date: Tue, 9 Apr 2019 16:33:17 +0800 Subject: [PATCH 10/26] feat(serialize): Add serializer for send mam message --- accelerator/BUILD | 1 - response/ta_send_mam.c | 34 +++++--------------------- response/ta_send_mam.h | 4 ++-- serializer/BUILD | 1 + serializer/serializer.c | 53 +++++++++++++++++++++++++++++++++++++++++ serializer/serializer.h | 25 +++++++++++++++++++ tests/driver.c | 24 ++++--------------- tests/test_serializer.c | 37 ++++++++++++++++++++++++++++ 8 files changed, 129 insertions(+), 50 deletions(-) diff --git a/accelerator/BUILD b/accelerator/BUILD index e959d048..7ac9c770 100644 --- a/accelerator/BUILD +++ b/accelerator/BUILD @@ -28,7 +28,6 @@ cc_library( ":ta_errors", "//serializer", "@entangled//common/trinary:trit_tryte", - "@entangled//common/trinary:tryte_ascii", "@entangled//mam/api", ], ) diff --git a/response/ta_send_mam.c b/response/ta_send_mam.c index 6e282541..630bbfe1 100644 --- a/response/ta_send_mam.c +++ b/response/ta_send_mam.c @@ -2,43 +2,29 @@ send_mam_res_t* send_mam_res_new() { send_mam_res_t* res = (send_mam_res_t*)malloc(sizeof(send_mam_res_t)); - if (res) { - res->bundle_hash = NULL; - res->channel_id = NULL; - } return res; } status_t send_mam_res_set_bundle_hash(send_mam_res_t* res, const tryte_t* bundle_hash) { - if (res->bundle_hash || !bundle_hash) { + if (!bundle_hash || !res) { return SC_RES_NULL; } - size_t bundle_hash_size = NUM_TRYTES_ADDRESS * sizeof(char); - res->bundle_hash = (char*)malloc(bundle_hash_size); - if (!res->bundle_hash) { - return SC_RES_OOM; - } - - memcpy(res->bundle_hash, bundle_hash, bundle_hash_size); + memcpy(res->bundle_hash, bundle_hash, NUM_TRYTES_HASH); + res->bundle_hash[NUM_TRYTES_HASH] = '\0'; return SC_OK; } status_t send_mam_res_set_channel_id(send_mam_res_t* res, const tryte_t* channel_id) { - if (res->channel_id || !channel_id) { + if (!channel_id || !res) { return SC_RES_NULL; } - size_t channel_id_size = NUM_TRYTES_ADDRESS * sizeof(char); - res->channel_id = (char*)malloc(channel_id_size); - if (!res->channel_id) { - return SC_RES_OOM; - } - - memcpy(res->channel_id, channel_id, channel_id_size); + memcpy(res->channel_id, channel_id, NUM_TRYTES_HASH); + res->channel_id[NUM_TRYTES_HASH] = '\0'; return SC_OK; } @@ -46,14 +32,6 @@ void send_mam_res_free(send_mam_res_t** res) { if (!res || !(*res)) { return; } - if ((*res)->bundle_hash) { - free((*res)->bundle_hash); - (*res)->bundle_hash = NULL; - } - if ((*res)->channel_id) { - free((*res)->channel_id); - (*res)->channel_id = NULL; - } free(*res); *res = NULL; diff --git a/response/ta_send_mam.h b/response/ta_send_mam.h index 4422b001..6d9d2683 100644 --- a/response/ta_send_mam.h +++ b/response/ta_send_mam.h @@ -15,9 +15,9 @@ extern "C" { /** struct of ta_send_mam_res_t */ typedef struct send_mam_res_s { /** ascii string bundle hash */ - char* bundle_hash; + char bundle_hash[NUM_TRYTES_HASH + 1]; /** ascii string channel id */ - char* channel_id; + char channel_id[NUM_TRYTES_HASH + 1]; } send_mam_res_t; /** diff --git a/serializer/BUILD b/serializer/BUILD index 1a82a61e..fb372cc6 100644 --- a/serializer/BUILD +++ b/serializer/BUILD @@ -11,5 +11,6 @@ cc_library( "//response", "@cJSON", "@entangled//cclient/types", + "@entangled//common/trinary:tryte_ascii", ], ) diff --git a/serializer/serializer.c b/serializer/serializer.c index fb38b94d..1b4fb172 100644 --- a/serializer/serializer.c +++ b/serializer/serializer.c @@ -407,3 +407,56 @@ status_t receive_mam_message_serialize(char** obj, const char** res) { cJSON_Delete(json_root); return ret; } + +status_t send_mam_res_serialize(char** obj, const send_mam_res_t* const res) { + status_t ret = SC_OK; + cJSON* json_root = cJSON_CreateObject(); + if (json_root == NULL) { + ret = SC_SERIALIZER_JSON_CREATE; + goto done; + } + + cJSON_AddStringToObject(json_root, "channel", res->channel_id); + + cJSON_AddStringToObject(json_root, "bundle_hash", res->bundle_hash); + + *obj = cJSON_PrintUnformatted(json_root); + if (*obj == NULL) { + ret = SC_SERIALIZER_JSON_PARSE; + goto done; + } + +done: + cJSON_Delete(json_root); + return ret; +} + +status_t send_mam_req_deserialize(const char* const obj, send_mam_req_t* req) { + if (obj == NULL) { + return SC_SERIALIZER_NULL; + } + cJSON* json_obj = cJSON_Parse(obj); + cJSON* json_result = NULL; + status_t ret = SC_OK; + + if (json_obj == NULL) { + ret = SC_SERIALIZER_JSON_PARSE; + goto done; + } + + json_result = cJSON_GetObjectItemCaseSensitive(json_obj, "message"); + if (json_result != NULL) { + size_t payload_size = strlen(json_result->valuestring) * 2; + tryte_t* payload_trytes = (tryte_t*)malloc(payload_size * sizeof(tryte_t)); + ascii_to_trytes(json_result->valuestring, payload_trytes); + + req->payload_trytes = payload_trytes; + req->payload_trytes_size = payload_size; + } else { + ret = SC_SERIALIZER_NULL; + } + +done: + cJSON_Delete(json_obj); + return ret; +} diff --git a/serializer/serializer.h b/serializer/serializer.h index bca7d18e..b9c2e4f0 100644 --- a/serializer/serializer.h +++ b/serializer/serializer.h @@ -6,6 +6,7 @@ #include "accelerator/errors.h" #include "cJSON.h" #include "cclient/types/types.h" +#include "common/trinary/tryte_ascii.h" #include "request/request.h" #include "response/response.h" @@ -122,6 +123,30 @@ status_t ta_find_transactions_obj_res_serialize( * - non-zero on error */ status_t receive_mam_message_serialize(char** obj, const char** res); + +/** + * @brief Serialze type of send_mam_res_t to JSON string + * + * @param[out] obj send mam response object in JSON + * @param[in] res Response data in type of send_mam_res_t + * + * @return + * - SC_OK on success + * - non-zero on error + */ +status_t send_mam_res_serialize(char** obj, const send_mam_res_t* const res); + +/** + * @brief Deserialze JSON string to type of send_mam_req_t + * + * @param[in] obj Input values in JSON + * @param[out] req Request data in type of send_mam_req_t + * + * @return + * - SC_OK on success + * - non-zero on error + */ +status_t send_mam_req_deserialize(const char* const obj, send_mam_req_t* req); #ifdef __cplusplus } #endif diff --git a/tests/driver.c b/tests/driver.c index 495e6ad6..ee94fb29 100644 --- a/tests/driver.c +++ b/tests/driver.c @@ -149,30 +149,16 @@ void test_find_transactions_obj_by_tag(void) { void test_send_mam_message(void) { double sum = 0; - - char* bundle_hash_result; - char* channel_id_result; + const char* json = "{\"message\":\"" TEST_PAYLOAD "\"}"; + char* json_result; for (size_t count = 0; count < TEST_COUNT; count++) { test_time_start(&start_time); TEST_ASSERT_EQUAL_INT32( - SC_OK, - api_mam_send_message(&ta_core.tangle, &ta_core.service, TEST_PAYLOAD, - &bundle_hash_result, &channel_id_result)); + SC_OK, api_mam_send_message(&ta_core.tangle, &ta_core.service, json, + &json_result)); test_time_end(&start_time, &end_time, &sum); - - for (size_t i = 0; i < FLEX_TRIT_SIZE_243; i++) { - printf("%c", channel_id_result[i]); - } - printf("\n"); - printf("Bundle: "); - for (size_t i = 0; i < FLEX_TRIT_SIZE_243; i++) { - printf("%c", bundle_hash_result[i]); - } - printf("\n"); - - free(bundle_hash_result); - free(channel_id_result); + free(json_result); } printf("Average time of receive_mam_message: %lf\n", sum / TEST_COUNT); } diff --git a/tests/test_serializer.c b/tests/test_serializer.c index 9a826e0e..780ef261 100644 --- a/tests/test_serializer.c +++ b/tests/test_serializer.c @@ -251,6 +251,41 @@ void test_serialize_ta_find_transactions_obj_by_tag(void) { transaction_free(txn); free(json_result); } + +void test_serialize_send_mam_message(void) { + const char* json = "{\"channel\":\"" TRYTES_81_1 + "\"," + "\"bundle_hash\":\"" TRYTES_81_2 "\"}"; + char* json_result; + send_mam_res_t* res = send_mam_res_new(); + + send_mam_res_set_bundle_hash(res, (tryte_t*)TRYTES_81_2); + send_mam_res_set_channel_id(res, (tryte_t*)TRYTES_81_1); + + send_mam_res_serialize(&json_result, res); + TEST_ASSERT_EQUAL_STRING(json, json_result); + + free(json_result); + send_mam_res_free(&res); +} + +void test_deserialize_send_mam_message(void) { + const char* json = "{\"message\":\"" TEST_PAYLOAD "\"}"; + send_mam_req_t* req = send_mam_req_new(); + + send_mam_req_deserialize(json, req); + + size_t payload_size = strlen(TEST_PAYLOAD) * 2; + tryte_t* payload_trytes = (tryte_t*)malloc(payload_size * sizeof(tryte_t)); + ascii_to_trytes(TEST_PAYLOAD, payload_trytes); + + TEST_ASSERT_EQUAL_UINT(payload_size, req->payload_trytes_size); + TEST_ASSERT_EQUAL_MEMORY(payload_trytes, req->payload_trytes, payload_size); + + free(payload_trytes); + send_mam_req_free(&req); +} + int main(void) { UNITY_BEGIN(); @@ -260,5 +295,7 @@ int main(void) { RUN_TEST(test_serialize_ta_get_transaction_object); RUN_TEST(test_serialize_ta_find_transactions_by_tag); RUN_TEST(test_serialize_ta_find_transactions_obj_by_tag); + RUN_TEST(test_serialize_send_mam_message); + RUN_TEST(test_deserialize_send_mam_message); return UNITY_END(); } From fea96de2c1efd63c7205ca25ed2af36ebffedcaa Mon Sep 17 00:00:00 2001 From: Yu Wei Wu Date: Tue, 9 Apr 2019 16:33:24 +0800 Subject: [PATCH 11/26] fead(api): Apply serializer to send mam api --- accelerator/apis.c | 43 ++++++++++++++++--------------------------- accelerator/apis.h | 8 ++------ accelerator/server.cc | 3 +-- 3 files changed, 19 insertions(+), 35 deletions(-) diff --git a/accelerator/apis.c b/accelerator/apis.c index 7a0a7c05..d6dfacf4 100644 --- a/accelerator/apis.c +++ b/accelerator/apis.c @@ -223,9 +223,7 @@ status_t api_receive_mam_message(const iota_client_service_t* const service, status_t api_mam_send_message(const iota_config_t* const tangle, const iota_client_service_t* const service, - char const* const payload, - char** bundle_hash_result, - char** channel_id_result) { + char const* const payload, char** json_result) { status_t ret = SC_OK; mam_api_t mam; const bool last_packet = true; @@ -234,24 +232,12 @@ status_t api_mam_send_message(const iota_config_t* const tangle, bundle_transactions_new(&bundle); tryte_t channel_id[MAM_CHANNEL_ID_SIZE]; trit_t msg_id[MAM_MSG_ID_SIZE]; + send_mam_req_t* req = send_mam_req_new(); + send_mam_res_t* res = send_mam_res_new(); - size_t payload_size = strlen(payload) * 2; - if ((payload_size == 0) || ((payload_size * 3) > SIZE_MAX)) { - return SC_MAM_OOM; - } - tryte_t* payload_trytes = (tryte_t*)malloc(payload_size * sizeof(tryte_t)); - if (!payload_trytes) { - return SC_MAM_OOM; - } - ascii_to_trytes(payload, payload_trytes); - - *bundle_hash_result = (tryte_t*)malloc(sizeof(tryte_t) * NUM_TRYTES_ADDRESS); - if (!(*bundle_hash_result)) { - return SC_MAM_OOM; - } - *channel_id_result = (tryte_t*)malloc(sizeof(tryte_t) * NUM_TRYTES_ADDRESS); - if (!(*channel_id_result)) { - return SC_MAM_OOM; + ret = send_mam_req_deserialize(payload, req); + if (ret) { + goto done; } // Creating MAM API @@ -281,21 +267,23 @@ status_t api_mam_send_message(const iota_config_t* const tangle, ret = SC_MAM_FAILED_WRITE; goto done; } - if (mam_api_bundle_write_packet(&mam, msg_id, payload_trytes, payload_size, 0, - last_packet, bundle) != RC_OK) { + if (mam_api_bundle_write_packet(&mam, msg_id, req->payload_trytes, + req->payload_trytes_size, 0, last_packet, + bundle) != RC_OK) { ret = SC_MAM_FAILED_WRITE; goto done; } - memcpy(*channel_id_result, channel_id, sizeof(tryte_t) * NUM_TRYTES_ADDRESS); + send_mam_res_set_channel_id(res, channel_id); // Sending bundle if (ta_send_bundle(tangle, service, bundle) != SC_OK) { ret = SC_MAM_FAILED_RESPONSE; goto done; } - memcpy(*bundle_hash_result, - ((iota_transaction_t*)utarray_front(bundle))->essence.bundle, - sizeof(tryte_t) * NUM_TRYTES_ADDRESS); + send_mam_res_set_bundle_hash( + res, transaction_bundle((iota_transaction_t*)utarray_front(bundle))); + + ret = send_mam_res_serialize(json_result, res); done: // Destroying MAM API @@ -304,9 +292,10 @@ status_t api_mam_send_message(const iota_config_t* const tangle, ret = SC_MAM_FAILED_DESTROYED; } } - free(payload_trytes); mam_psk_t_set_free(&psks); bundle_transactions_free(&bundle); + send_mam_req_free(&req); + send_mam_res_free(&res); return ret; } diff --git a/accelerator/apis.h b/accelerator/apis.h index 105c63ec..1585d215 100644 --- a/accelerator/apis.h +++ b/accelerator/apis.h @@ -5,7 +5,6 @@ #include "accelerator/errors.h" #include "cclient/types/types.h" #include "common/trinary/trit_tryte.h" -#include "common/trinary/tryte_ascii.h" #include "mam/api/api.h" #include "mam/mam/mam_channel_t_set.h" #include "serializer/serializer.h" @@ -102,8 +101,7 @@ status_t api_receive_mam_message(const iota_client_service_t* const service, * @param[in] tangle IOTA API parameter configurations * @param[in] service IRI node end point service * @param[in] payload message to send undecoded ascii string. - * @param[out] bundle_hashes_result the bundle hash of sent message - * @param[out] channel_id_result the channel id the sent message to + * @param[out] json_result Result containing channel id and bundle hash * * @return * - SC_OK on success @@ -111,9 +109,7 @@ status_t api_receive_mam_message(const iota_client_service_t* const service, */ status_t api_mam_send_message(const iota_config_t* const tangle, const iota_client_service_t* const service, - char const* const payload, - char** bundle_hash_result, - char** channel_id_result); + char const* const payload, char** json_result); /** * @brief Send transfer to tangle. diff --git a/accelerator/server.cc b/accelerator/server.cc index 69d4ae8e..1b01cecd 100644 --- a/accelerator/server.cc +++ b/accelerator/server.cc @@ -87,7 +87,6 @@ int main(int, char const**) { .post([&](served::response& res, const served::request& req) { status_t ret = SC_OK; char* json_result; - char* chid_result; if (req.header("content-type").find("application/json") == std::string::npos) { @@ -100,7 +99,7 @@ int main(int, char const**) { cJSON_Delete(json_obj); } else { api_mam_send_message(&ta_core.tangle, &ta_core.service, - req.body().c_str(), &json_result, &chid_result); + req.body().c_str(), &json_result); ret = set_response_content(ret, &json_result); res.set_status(ret); } From 6aecb05cb4df5f1ddd37904aa096d83d737ff9b0 Mon Sep 17 00:00:00 2001 From: jkrvivian Date: Wed, 10 Apr 2019 20:14:46 +0800 Subject: [PATCH 12/26] feat(conf): Implement CLI configuration interface --- accelerator/BUILD | 1 + accelerator/config.c | 120 ++++++++++++++++++++++++++++++++++++++++-- accelerator/config.h | 44 +++++++++++++++- accelerator/errors.h | 9 ++++ accelerator/message.h | 23 +++++--- accelerator/server.cc | 19 ++++++- tests/driver.c | 4 +- 7 files changed, 203 insertions(+), 17 deletions(-) diff --git a/accelerator/BUILD b/accelerator/BUILD index a7a36923..b955c49d 100644 --- a/accelerator/BUILD +++ b/accelerator/BUILD @@ -54,6 +54,7 @@ cc_library( hdrs = ["config.h"], visibility = ["//visibility:public"], deps = [ + ":message", ":ta_errors", "//utils:cache", "//utils:pow", diff --git a/accelerator/config.c b/accelerator/config.c index c4731961..36a03aa9 100644 --- a/accelerator/config.c +++ b/accelerator/config.c @@ -5,10 +5,74 @@ static logger_id_t logger_id; -status_t ta_config_init(ta_config_t* const info, iota_config_t* const tangle, - iota_client_service_t* const service) { +struct option* cli_build_options() { + struct option* long_options = + (struct option*)malloc(cli_cmd_num * sizeof(struct option)); + for (int i = 0; i < cli_cmd_num; ++i) { + long_options[i].name = ta_cli_arguments_g[i].name; + long_options[i].has_arg = ta_cli_arguments_g[i].has_arg; + long_options[i].flag = NULL; + long_options[i].val = ta_cli_arguments_g[i].val; + } + return long_options; +} + +status_t cli_config_set(ta_config_t* const info, iota_config_t* const tangle, + ta_cache_t* const cache, + iota_client_service_t* const service, int key, + char* const value) { + if (value == NULL || info == NULL || tangle == NULL || cache == NULL || + service == NULL) { + return SC_CONF_NULL; + } + switch (key) { + // TA configuration + case TA_HOST_CLI: + info->host = value; + break; + case TA_PORT_CLI: + info->port = value; + break; + case TA_THREAD_COUNT_CLI: + info->thread_count = atoi(value); + break; + + // IRI configuration + case IRI_HOST_CLI: + service->http.host = value; + break; + case IRI_PORT_CLI: + service->http.port = atoi(value); + break; + + // Cache configuration + case REDIS_HOST_CLI: + cache->host = value; + break; + case REDIS_PORT_CLI: + cache->port = atoi(value); + break; + + // Tangle configuration + case MILESTONE_DEPTH_CLI: + tangle->milestone_depth = atoi(value); + break; + case MWM_CLI: + tangle->mwm = atoi(value); + break; + case SEED_CLI: + tangle->seed = value; + break; + } + return SC_OK; +} + +status_t ta_config_default_init(ta_config_t* const info, + iota_config_t* const tangle, + ta_cache_t* const cache, + iota_client_service_t* const service) { status_t ret = SC_OK; - if (info == NULL || tangle == NULL || service == NULL) { + if (info == NULL || tangle == NULL || cache == NULL || service == NULL) { return SC_TA_NULL; } @@ -22,6 +86,10 @@ status_t ta_config_init(ta_config_t* const info, iota_config_t* const tangle, info->port = TA_PORT; info->thread_count = TA_THREAD_COUNT; + log_info(logger_id, "Initializing Redis information\n"); + cache->host = REDIS_HOST; + cache->port = REDIS_PORT; + log_info(logger_id, "Initializing IRI configuration\n"); tangle->milestone_depth = MILESTONE_DEPTH; tangle->mss_depth = MSS_DEPTH; @@ -36,6 +104,49 @@ status_t ta_config_init(ta_config_t* const info, iota_config_t* const tangle, service->http.port = IRI_PORT; service->http.api_version = 1; service->serializer_type = SR_JSON; + return ret; +} + +status_t ta_config_cli_init(ta_core_t* const conf, int argc, char** argv) { + int key = 0; + status_t ret = SC_OK; + struct option* long_options = cli_build_options(); + + while ((key = getopt_long(argc, argv, "hv", long_options, NULL)) != -1) { + switch (key) { + case ':': + ret = SC_CONF_MISSING_ARGUMENT; + break; + case '?': + ret = SC_CONF_UNKNOWN_OPTION; + break; + case 'h': + ta_usage(); + exit(EXIT_SUCCESS); + case 'v': + printf("%s\n", TA_VERSION); + exit(EXIT_SUCCESS); + default: + ret = cli_config_set(&conf->info, &conf->tangle, &conf->cache, + &conf->service, key, optarg); + break; + } + if (ret != SC_OK) { + break; + } + } + + free(long_options); + return ret; +} + +status_t ta_config_set(ta_cache_t* const cache, + iota_client_service_t* const service) { + status_t ret = SC_OK; + if (cache == NULL || service == NULL) { + return SC_TA_NULL; + } + if (iota_client_core_init(service)) { log_critical(logger_id, "Initializing IRI connection failed!\n"); ret = SC_TA_OOM; @@ -46,8 +157,7 @@ status_t ta_config_init(ta_config_t* const info, iota_config_t* const tangle, pow_init(); log_info(logger_id, "Initializing cache connection\n"); - cache_init(REDIS_HOST, REDIS_PORT); - + cache_init(cache->host, cache->port); return ret; } diff --git a/accelerator/config.h b/accelerator/config.h index e7cdbef6..e3ecf6b0 100644 --- a/accelerator/config.h +++ b/accelerator/config.h @@ -1,7 +1,10 @@ #ifndef ACCELERATOR_CONFIG_H_ #define ACCELERATOR_CONFIG_H_ +#include + #include "accelerator/errors.h" +#include "accelerator/message.h" #include "cclient/api/core/core_api.h" #include "cclient/api/extended/extended_api.h" #include "cclient/types/types.h" @@ -53,9 +56,16 @@ typedef struct ta_config_s { const char* seed; } iota_config_t; +/** struct type of accelerator cache */ +typedef struct ta_cache_s { + char* host; /**< Binding address of redis server */ + uint16_t port; /**< Binding port of redis server */ +} ta_cache_t; + /** struct type of accelerator core */ typedef struct ta_core_s { ta_config_t info; /**< accelerator configiuration structure */ + ta_cache_t cache; /**< redis configiuration structure */ iota_config_t tangle; /**< iota configuration structure */ iota_client_service_t service; /**< iota connection structure */ } ta_core_t; @@ -66,14 +76,44 @@ typedef struct ta_core_s { * * @param info[in] Tangle-accelerator configuration variables * @param tangle[in] iota configuration variables + * @param cache[in] redis configuration variables + * @param service[in] IRI connection configuration variables + * + * @return + * - SC_OK on success + * - non-zero on error + */ +status_t ta_config_default_init(ta_config_t* const info, + iota_config_t* const tangle, + ta_cache_t* const cache, + iota_client_service_t* const service); + +/** + * Initializes configurations with CLI values + * Should be called third + * + * @param ta_conf[in] All configuration variables + * @param argc[in] Number of argumentof CLI + * @param argv[in] Argument of CLI + * + * @return + * - SC_OK on success + * - non-zero on error + */ +status_t ta_config_cli_init(ta_core_t* const ta_conf, int argc, char** argv); + +/** + * Start services after configurations are set + * + * @param cache[in] Redis server configuration variables * @param service[in] IRI connection configuration variables * * @return * - SC_OK on success * - non-zero on error */ -status_t ta_config_init(ta_config_t* const info, iota_config_t* const tangle, - iota_client_service_t* const service); +status_t ta_config_set(ta_cache_t* const cache, + iota_client_service_t* const service); /** * Free memory of configuration variables diff --git a/accelerator/errors.h b/accelerator/errors.h index d5e308d1..38ca230d 100644 --- a/accelerator/errors.h +++ b/accelerator/errors.h @@ -41,6 +41,7 @@ extern "C" { #define SC_MODULE_CACHE (0x04 << SC_MODULE_SHIFT) #define SC_MODULE_MAM (0x05 << SC_MODULE_SHIFT) #define SC_MODULE_RES (0x06 << SC_MODULE_SHIFT) +#define SC_MODULE_CONF (0x07 << SC_MODULE_SHIFT) /** @} */ /** @name serverity code */ @@ -112,6 +113,14 @@ typedef enum { /**< Fail to create response object */ SC_RES_NULL = 0x02 | SC_MODULE_RES | SC_SEVERITY_FATAL, /**< NULL object in response */ + + // configuration module + SC_CONF_NULL = 0x02 | SC_MODULE_CONF | SC_SEVERITY_FATAL, + /**< NULL object in response */ + SC_CONF_MISSING_ARGUMENT = 0x04 | SC_MODULE_CONF | SC_SEVERITY_FATAL, + /**< No argument in CLI */ + SC_CONF_UNKNOWN_OPTION = 0x05 | SC_MODULE_CONF | SC_SEVERITY_FATAL, + /**< undefined option in CLI */ } status_t; typedef enum { diff --git a/accelerator/message.h b/accelerator/message.h index e7af5e53..7a387e33 100644 --- a/accelerator/message.h +++ b/accelerator/message.h @@ -6,13 +6,10 @@ extern "C" { #endif typedef enum ta_cli_arg_value_e { - HELP_CLI, - /** TA */ - TA_HOST_CLI, + TA_HOST_CLI = 127, TA_PORT_CLI, TA_THREAD_COUNT_CLI, - TA_VERSION_CLI, /** IRI */ IRI_HOST_CLI, @@ -35,12 +32,24 @@ typedef enum ta_cli_arg_requirement_e { } ta_cli_arg_requirement_t; static struct ta_cli_argument_s { - char* name; + char const* name; int val; - char* desc; + char const* desc; ta_cli_arg_requirement_t has_arg; } ta_cli_arguments_g[] = { - {"ta-help", HELP_CLI, "Show tangle-accelerator usage.", NO_ARG}}; + {"help", 'h', "Show tangle-accelerator usage", NO_ARG}, + {"version", 'v', "tangle-accelerator version", NO_ARG}, + {"ta_host", TA_HOST_CLI, "TA listening host", REQUIRED_ARG}, + {"ta_port", TA_PORT_CLI, "TA listening port", REQUIRED_ARG}, + {"ta_thread", TA_THREAD_COUNT_CLI, "TA executing thread", OPTIONAL_ARG}, + {"iri_host", IRI_HOST_CLI, "IRI listening host", REQUIRED_ARG}, + {"iri_port", IRI_PORT_CLI, "IRI listening port", REQUIRED_ARG}, + {"redis_host", REDIS_HOST_CLI, "Redis server listening host", REQUIRED_ARG}, + {"redis_port", REDIS_PORT_CLI, "Redis server listening port", REQUIRED_ARG}, + {"milestone_depth", MILESTONE_DEPTH_CLI, "IRI milestone depth", + OPTIONAL_ARG}, + {"mwm", MWM_CLI, "minimum weight magnitude", OPTIONAL_ARG}, + {"seed", SEED_CLI, "IOTA seed", OPTIONAL_ARG}}; static const int cli_cmd_num = sizeof(ta_cli_arguments_g) / sizeof(struct ta_cli_argument_s); diff --git a/accelerator/server.cc b/accelerator/server.cc index 1b01cecd..079ad931 100644 --- a/accelerator/server.cc +++ b/accelerator/server.cc @@ -50,7 +50,7 @@ status_t set_response_content(status_t ret, char** json_result) { return http_ret; } -int main(int, char const**) { +int main(int argc, char* argv[]) { served::multiplexer mux; mux.use_after(served::plugin::access_log); @@ -59,7 +59,22 @@ int main(int, char const**) { } logger_id = logger_helper_enable(MAIN_LOGGER_ID, LOGGER_DEBUG, true); - ta_config_init(&ta_core.info, &ta_core.tangle, &ta_core.service); + // Initialize configurations with default value + if (ta_config_default_init(&ta_core.info, &ta_core.tangle, &ta_core.cache, + &ta_core.service) != SC_OK) { + return EXIT_FAILURE; + } + + // Initialize configurations with CLI value + if (ta_config_cli_init(&ta_core, argc, argv) != SC_OK) { + return EXIT_FAILURE; + } + + if (ta_config_set(&ta_core.cache, &ta_core.service) != SC_OK) { + log_critical(logger_id, "[%s:%d] Configure failed %s.\n", __func__, + __LINE__, MAIN_LOGGER_ID); + return EXIT_FAILURE; + } mux.handle("/mam/{bundle:[A-Z9]{81}}") .method(served::method::OPTIONS, diff --git a/tests/driver.c b/tests/driver.c index ee94fb29..8425914e 100644 --- a/tests/driver.c +++ b/tests/driver.c @@ -182,7 +182,9 @@ void test_receive_mam_message(void) { int main(void) { UNITY_BEGIN(); - ta_config_init(&ta_core.info, &ta_core.tangle, &ta_core.service); + ta_config_default_init(&ta_core.info, &ta_core.tangle, &ta_core.cache, + &ta_core.service); + ta_config_set(&ta_core.cache, &ta_core.service); printf("Total samples for each API test: %d\n", TEST_COUNT); RUN_TEST(test_generate_address); From c8f238d7bf5cd29a936af28d3544bae6aae3727a Mon Sep 17 00:00:00 2001 From: YangHau Date: Wed, 17 Apr 2019 16:36:03 +0800 Subject: [PATCH 13/26] feat(serialize): Add send_mam_res_deserialize() Use send_mam_res_deserialize() to deserialize json_result which is answered from api_receive_mam_message(). --- serializer/serializer.c | 62 +++++++++++++++++++++++++++++++++++++---- serializer/serializer.h | 13 +++++++++ tests/test_serializer.c | 15 ++++++++++ 3 files changed, 84 insertions(+), 6 deletions(-) diff --git a/serializer/serializer.c b/serializer/serializer.c index 1b4fb172..facaad6b 100644 --- a/serializer/serializer.c +++ b/serializer/serializer.c @@ -6,9 +6,9 @@ void fill_tag(char* new_tag, char* old_tag, size_t tag_len) { sprintf(new_tag, "%s%*.*s", old_tag, pad_len, pad_len, nines); } -status_t ta_hash243_stack_to_json_array(hash243_stack_t stack, - cJSON* const json_root, - char const* const obj_name) { +static status_t ta_hash243_stack_to_json_array(hash243_stack_t stack, + cJSON* const json_root, + char const* const obj_name) { size_t array_count = 0; cJSON* array_obj = NULL; hash243_stack_entry_t* s_iter = NULL; @@ -41,9 +41,9 @@ status_t ta_hash243_stack_to_json_array(hash243_stack_t stack, return SC_OK; } -status_t ta_hash243_queue_to_json_array(hash243_queue_t queue, - cJSON* const json_root, - char const* const obj_name) { +static status_t ta_hash243_queue_to_json_array(hash243_queue_t queue, + cJSON* const json_root, + char const* const obj_name) { size_t array_count; cJSON* array_obj = NULL; hash243_queue_entry_t* q_iter = NULL; @@ -75,6 +75,25 @@ status_t ta_hash243_queue_to_json_array(hash243_queue_t queue, return SC_OK; } +static status_t ta_json_get_string(cJSON const* const json_obj, + char const* const obj_name, + char* const text) { + retcode_t ret = SC_OK; + + cJSON* json_value = cJSON_GetObjectItemCaseSensitive(json_obj, obj_name); + if (json_value == NULL) { + return RC_CCLIENT_JSON_KEY; + } + + if (cJSON_IsString(json_value) && (json_value->valuestring != NULL)) { + strcpy(text, json_value->valuestring); + } else { + return RC_CCLIENT_JSON_PARSE; + } + + return ret; +} + status_t iota_transaction_to_json_object(iota_transaction_t const* const txn, cJSON** txn_json) { if (txn == NULL) { @@ -431,6 +450,37 @@ status_t send_mam_res_serialize(char** obj, const send_mam_res_t* const res) { return ret; } +status_t send_mam_res_deserialize(const char* const obj, + send_mam_res_t* const res) { + if (obj == NULL) { + return SC_SERIALIZER_NULL; + } + cJSON* json_obj = cJSON_Parse(obj); + status_t ret = SC_OK; + tryte_t addr[NUM_TRYTES_ADDRESS + 1]; + + if (json_obj == NULL) { + ret = SC_SERIALIZER_JSON_PARSE; + goto done; + } + + if (ta_json_get_string(json_obj, "channel", (char*)addr) != SC_OK) { + ret = SC_SERIALIZER_NULL; + goto done; + } + send_mam_res_set_channel_id(res, addr); + + if (ta_json_get_string(json_obj, "bundle_hash", (char*)addr) != SC_OK) { + ret = SC_SERIALIZER_NULL; + goto done; + } + send_mam_res_set_bundle_hash(res, addr); + +done: + cJSON_Delete(json_obj); + return ret; +} + status_t send_mam_req_deserialize(const char* const obj, send_mam_req_t* req) { if (obj == NULL) { return SC_SERIALIZER_NULL; diff --git a/serializer/serializer.h b/serializer/serializer.h index b9c2e4f0..72f200bc 100644 --- a/serializer/serializer.h +++ b/serializer/serializer.h @@ -136,6 +136,19 @@ status_t receive_mam_message_serialize(char** obj, const char** res); */ status_t send_mam_res_serialize(char** obj, const send_mam_res_t* const res); +/** + * @brief Deserialze JSON string to type of send_mam_res_t + * + * @param[in] obj Input values in JSON + * @param[out] res Response data in type of send_mam_res_t + * + * @return + * - SC_OK on success + * - non-zero on error + */ +status_t send_mam_res_deserialize(const char* const obj, + send_mam_res_t* const res); + /** * @brief Deserialze JSON string to type of send_mam_req_t * diff --git a/tests/test_serializer.c b/tests/test_serializer.c index 780ef261..a58ad467 100644 --- a/tests/test_serializer.c +++ b/tests/test_serializer.c @@ -269,6 +269,20 @@ void test_serialize_send_mam_message(void) { send_mam_res_free(&res); } +void test_deserialize_send_mam_message_response(void) { + const char* json = "{\"channel\":\"" TRYTES_81_1 + "\"," + "\"bundle_hash\":\"" TRYTES_81_2 "\"}"; + send_mam_res_t* res = send_mam_res_new(); + + send_mam_res_deserialize(json, res); + + TEST_ASSERT_EQUAL_STRING(TRYTES_81_1, res->channel_id); + TEST_ASSERT_EQUAL_STRING(TRYTES_81_2, res->bundle_hash); + + send_mam_res_free(&res); +} + void test_deserialize_send_mam_message(void) { const char* json = "{\"message\":\"" TEST_PAYLOAD "\"}"; send_mam_req_t* req = send_mam_req_new(); @@ -296,6 +310,7 @@ int main(void) { RUN_TEST(test_serialize_ta_find_transactions_by_tag); RUN_TEST(test_serialize_ta_find_transactions_obj_by_tag); RUN_TEST(test_serialize_send_mam_message); + RUN_TEST(test_deserialize_send_mam_message_response); RUN_TEST(test_deserialize_send_mam_message); return UNITY_END(); } From 16cea5af37e096b34c5701857198346064f9b7ae Mon Sep 17 00:00:00 2001 From: YangHau Date: Wed, 17 Apr 2019 17:12:13 +0800 Subject: [PATCH 14/26] fix(driver): Redesign test driver In order to react to the situation that transactions' record will disapear, after snapshot (both global one and local one), the order of test in driver is redesigned. Send transaction APIs are ahead of recieve transaction APIs, and the infomation that are used in the recieve transaction APIs (i.e. tag, bundle hash) are come from send transaction APIs. --- accelerator/errors.h | 4 ++++ serializer/serializer.c | 9 ++++++--- tests/driver.c | 39 ++++++++++++++++++++++++++++++--------- 3 files changed, 40 insertions(+), 12 deletions(-) diff --git a/accelerator/errors.h b/accelerator/errors.h index 38ca230d..5888f619 100644 --- a/accelerator/errors.h +++ b/accelerator/errors.h @@ -75,6 +75,10 @@ typedef enum { /**< flex_trits conversion error */ SC_CCLIENT_HASH = 0x06 | SC_MODULE_CCLIENT | SC_SEVERITY_MAJOR, /**< hash container operation error */ + SC_CCLIENT_JSON_KEY = 0x07 | SC_MODULE_CCLIENT | SC_SEVERITY_MAJOR, + /**< JSON key not found */ + SC_CCLIENT_JSON_PARSE = 0x08 | SC_MODULE_CCLIENT | SC_SEVERITY_MAJOR, + /**< json parsing error, might the wrong format */ // Serializer module SC_SERIALIZER_JSON_CREATE = 0x01 | SC_MODULE_SERIALIZER | SC_SEVERITY_FATAL, diff --git a/serializer/serializer.c b/serializer/serializer.c index facaad6b..33d829e9 100644 --- a/serializer/serializer.c +++ b/serializer/serializer.c @@ -78,17 +78,20 @@ static status_t ta_hash243_queue_to_json_array(hash243_queue_t queue, static status_t ta_json_get_string(cJSON const* const json_obj, char const* const obj_name, char* const text) { - retcode_t ret = SC_OK; + status_t ret = SC_OK; + if (json_obj == NULL || obj_name == NULL || text == NULL) { + return SC_SERIALIZER_NULL; + } cJSON* json_value = cJSON_GetObjectItemCaseSensitive(json_obj, obj_name); if (json_value == NULL) { - return RC_CCLIENT_JSON_KEY; + return SC_CCLIENT_JSON_KEY; } if (cJSON_IsString(json_value) && (json_value->valuestring != NULL)) { strcpy(text, json_value->valuestring); } else { - return RC_CCLIENT_JSON_PARSE; + return SC_CCLIENT_JSON_PARSE; } return ret; diff --git a/tests/driver.c b/tests/driver.c index 8425914e..eba1789a 100644 --- a/tests/driver.c +++ b/tests/driver.c @@ -5,12 +5,23 @@ static ta_core_t ta_core; struct timespec start_time, end_time; +char driver_tag_msg[NUM_TRYTES_TAG]; +send_mam_res_t* res; + #if defined(ENABLE_STAT) #define TEST_COUNT 100 #else #define TEST_COUNT 1 #endif +static void gen_rand_tag(char* tag) { + const char tryte_alpahbet[] = "NOPQRSTUVWXYZ9ABCDEFGHIJKLM"; + + for (int i = 0; i < NUM_TRYTES_TAG; i++) { + tag[i] = tryte_alpahbet[rand() % 27]; + } +} + double diff_time(struct timespec start, struct timespec end) { struct timespec diff; if (end.tv_nsec - start.tv_nsec < 0) { @@ -81,14 +92,19 @@ void test_get_tips(void) { } void test_send_transfer(void) { - const char* json = + const char* pre_json = "{\"value\":100," - "\"message\":\"" TAG_MSG "\",\"tag\":\"" TAG_MSG - "\"," + "\"message\":\"" TAG_MSG + "\",\"tag\":\"%s\"," "\"address\":\"" TRYTES_81_1 "\"}"; char* json_result; double sum = 0; + gen_rand_tag(driver_tag_msg); + int json_len = strlen(pre_json); + char json[json_len + NUM_TRYTES_TAG]; + sprintf(json, pre_json, driver_tag_msg); + for (size_t count = 0; count < TEST_COUNT; count++) { test_time_start(&start_time); TEST_ASSERT_EQUAL_INT32( @@ -123,7 +139,7 @@ void test_find_transactions_by_tag(void) { test_time_start(&start_time); TEST_ASSERT_EQUAL_INT32( - SC_OK, api_find_transactions_by_tag(&ta_core.service, FIND_TAG_MSG, + 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); @@ -139,8 +155,8 @@ void test_find_transactions_obj_by_tag(void) { test_time_start(&start_time); TEST_ASSERT_EQUAL_INT32( - SC_OK, api_find_transactions_obj_by_tag(&ta_core.service, FIND_TAG_MSG, - &json_result)); + 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); } @@ -151,12 +167,15 @@ void test_send_mam_message(void) { double sum = 0; const char* json = "{\"message\":\"" TEST_PAYLOAD "\"}"; char* json_result; + res = send_mam_res_new(); for (size_t count = 0; count < TEST_COUNT; count++) { test_time_start(&start_time); TEST_ASSERT_EQUAL_INT32( SC_OK, api_mam_send_message(&ta_core.tangle, &ta_core.service, json, &json_result)); + send_mam_res_deserialize(json_result, res); + test_time_end(&start_time, &end_time, &sum); free(json_result); } @@ -171,8 +190,8 @@ void test_receive_mam_message(void) { test_time_start(&start_time); TEST_ASSERT_EQUAL_INT32( - SC_OK, api_receive_mam_message(&ta_core.service, TEST_BUNDLE_HASH, - &json_result)); + SC_OK, api_receive_mam_message(&ta_core.service, + (char*)res->bundle_hash, &json_result)); test_time_end(&start_time, &end_time, &sum); free(json_result); } @@ -180,6 +199,8 @@ void test_receive_mam_message(void) { } int main(void) { + srand(time(NULL)); + UNITY_BEGIN(); ta_config_default_init(&ta_core.info, &ta_core.tangle, &ta_core.cache, @@ -194,8 +215,8 @@ int main(void) { RUN_TEST(test_get_transaction_object); RUN_TEST(test_find_transactions_by_tag); RUN_TEST(test_find_transactions_obj_by_tag); - RUN_TEST(test_receive_mam_message); RUN_TEST(test_send_mam_message); + RUN_TEST(test_receive_mam_message); ta_config_destroy(&ta_core.service); return UNITY_END(); } From 8b04585bb1296feee43d0938327aad263d5e3860 Mon Sep 17 00:00:00 2001 From: Yu Wei Wu Date: Wed, 17 Apr 2019 10:18:58 +0800 Subject: [PATCH 15/26] fix(MAM): Remove psk for public message Pre-Shared Key is used for encrypt message. Remove psk so every messages can be public in MAM protocol. --- accelerator/apis.c | 34 +--------------------------------- 1 file changed, 1 insertion(+), 33 deletions(-) diff --git a/accelerator/apis.c b/accelerator/apis.c index d6dfacf4..dd00ad20 100644 --- a/accelerator/apis.c +++ b/accelerator/apis.c @@ -1,28 +1,5 @@ #include "apis.h" -// TODO: Generate actual pre shared keys -static mam_psk_t const psk = { - .id = {1, 0, -1, -1, 0, -1, -1, 0, 0, 1, -1, 0, 1, 0, 0, 1, 1, - 1, -1, 1, 1, 0, 1, 1, 0, 0, -1, 1, -1, -1, -1, -1, -1, -1, - -1, 1, -1, -1, 0, -1, -1, 1, 0, -1, -1, -1, 1, 1, 1, 0, 0, - -1, 1, -1, -1, -1, 0, -1, 1, -1, -1, -1, 1, 1, -1, 1, 0, 0, - 1, 1, 1, -1, -1, 0, 0, -1, -1, 1, 0, -1, 1}, - .key = {-1, 1, -1, -1, 1, -1, -1, 0, 0, 0, -1, -1, 1, 1, 1, -1, -1, - -1, 0, 0, 0, 0, -1, -1, 1, 1, 1, 0, -1, -1, -1, 0, 0, 0, - -1, -1, 1, -1, 0, 0, 1, 0, 0, -1, 1, 1, 0, -1, 0, 0, 1, - -1, 1, 0, 1, 0, 0, -1, 1, 1, -1, 1, 0, -1, 0, -1, 1, -1, - -1, -1, 0, -1, -1, 0, -1, -1, 0, 0, -1, -1, 1, -1, 0, 0, -1, - -1, -1, -1, 0, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, 1, 0, 1, - 0, 1, -1, 0, 0, 1, 0, 1, 0, 0, 1, 0, -1, 0, 1, 1, 0, - 0, -1, -1, 1, 1, 0, 0, 1, -1, 1, 1, 1, 0, 1, 1, 1, 0, - 0, -1, -1, -1, -1, 1, 1, 1, 0, 0, -1, 0, 1, -1, 1, 1, 1, - 0, 0, 1, -1, -1, 0, -1, 1, -1, 1, 0, 0, 1, -1, 0, 1, -1, - 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, -1, 1, -1, 1, 0, 1, 1, - 1, -1, 0, 0, -1, 1, 1, 0, -1, -1, 0, 0, -1, 1, 0, 1, -1, - 0, 0, -1, 1, -1, 1, 1, 1, -1, 0, 1, 1, 0, 0, -1, -1, -1, - 0, 0, 1, 0, 1, 0, -1, 1, -1, 0, 1, 0, -1, 1, 1, -1, -1, - 0, 0, -1, 0, -1}}; - status_t api_get_tips(const iota_client_service_t* const service, char** json_result) { status_t ret = SC_OK; @@ -178,7 +155,6 @@ status_t api_receive_mam_message(const iota_client_service_t* const service, } // Set first transaction's address as chid, if no `chid` specified - mam_psk_t_set_add(&mam.psks, &psk); iota_transaction_t* curr_tx = (iota_transaction_t*)utarray_eltptr(bundle, 0); none_chid_trytes = (tryte_t*)malloc(sizeof(tryte_t) * NUM_TRYTES_ADDRESS); flex_trits_to_trytes(none_chid_trytes, NUM_TRYTES_ADDRESS, @@ -228,7 +204,6 @@ status_t api_mam_send_message(const iota_config_t* const tangle, mam_api_t mam; const bool last_packet = true; bundle_transactions_t* bundle = NULL; - mam_psk_t_set_t psks = NULL; bundle_transactions_new(&bundle); tryte_t channel_id[MAM_CHANNEL_ID_SIZE]; trit_t msg_id[MAM_MSG_ID_SIZE]; @@ -256,13 +231,7 @@ status_t api_mam_send_message(const iota_config_t* const tangle, } // Write header and packet - if (!mam_psk_t_set_contains(&psks, &psk)) { - if (mam_psk_t_set_add(&psks, &psk) != RC_OK) { - ret = SC_MAM_FAILED_WRITE; - goto done; - } - } - if (mam_api_bundle_write_header_on_channel(&mam, channel_id, psks, NULL, 0, + if (mam_api_bundle_write_header_on_channel(&mam, channel_id, NULL, NULL, 0, bundle, msg_id) != RC_OK) { ret = SC_MAM_FAILED_WRITE; goto done; @@ -292,7 +261,6 @@ status_t api_mam_send_message(const iota_config_t* const tangle, ret = SC_MAM_FAILED_DESTROYED; } } - mam_psk_t_set_free(&psks); bundle_transactions_free(&bundle); send_mam_req_free(&req); send_mam_res_free(&res); From effd54bb5256ed726d747be174e539bfc55c6bce Mon Sep 17 00:00:00 2001 From: Yu Wei Wu Date: Thu, 18 Apr 2019 13:07:09 +0800 Subject: [PATCH 16/26] fix(api): Reorder send mam init for better memory free --- accelerator/apis.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/accelerator/apis.c b/accelerator/apis.c index dd00ad20..6c4bca6f 100644 --- a/accelerator/apis.c +++ b/accelerator/apis.c @@ -210,17 +210,17 @@ status_t api_mam_send_message(const iota_config_t* const tangle, send_mam_req_t* req = send_mam_req_new(); send_mam_res_t* res = send_mam_res_new(); - ret = send_mam_req_deserialize(payload, req); - if (ret) { - goto done; - } - // Creating MAM API if (mam_api_init(&mam, (tryte_t*)SEED)) { ret = SC_MAM_FAILED_INIT; goto done; } + ret = send_mam_req_deserialize(payload, req); + if (ret) { + goto done; + } + // Create mam channel if (mam_channel_t_set_size(mam.channels) == 0) { mam_api_create_channel(&mam, tangle->mss_depth, channel_id); From 6c378bab9ee1e075dcb216b7da806ca99bf34a89 Mon Sep 17 00:00:00 2001 From: Yu Wei Wu Date: Thu, 18 Apr 2019 13:07:17 +0800 Subject: [PATCH 17/26] fix(http): Return actual status value of send mam api --- accelerator/errors.h | 2 +- accelerator/server.cc | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/accelerator/errors.h b/accelerator/errors.h index 5888f619..48a86ddc 100644 --- a/accelerator/errors.h +++ b/accelerator/errors.h @@ -85,7 +85,7 @@ typedef enum { /**< Fail to create JSON object in serializer */ SC_SERIALIZER_NULL = 0x02 | SC_MODULE_SERIALIZER | SC_SEVERITY_FATAL, /**< NULL object in serializer */ - SC_SERIALIZER_JSON_PARSE = 0x07 | SC_MODULE_SERIALIZER | SC_SEVERITY_FATAL, + SC_SERIALIZER_JSON_PARSE = 0x03 | SC_MODULE_SERIALIZER | SC_SEVERITY_FATAL, /**< Fail to parse JSON object in serializer */ // Cache module diff --git a/accelerator/server.cc b/accelerator/server.cc index 079ad931..a3fbf107 100644 --- a/accelerator/server.cc +++ b/accelerator/server.cc @@ -113,8 +113,8 @@ int main(int argc, char* argv[]) { res.set_status(SC_HTTP_BAD_REQUEST); cJSON_Delete(json_obj); } else { - api_mam_send_message(&ta_core.tangle, &ta_core.service, - req.body().c_str(), &json_result); + ret = api_mam_send_message(&ta_core.tangle, &ta_core.service, + req.body().c_str(), &json_result); ret = set_response_content(ret, &json_result); res.set_status(ret); } From 0dae84d10a37e21d20e800594ad1ce14f4247f2a Mon Sep 17 00:00:00 2001 From: YangHau Date: Mon, 15 Apr 2019 11:42:56 +0800 Subject: [PATCH 18/26] feat: Add regression test Add regression test for following API: * mam_recv_msg * mam_send_msg the test of `mam_recv_msg()` is done with python module `requests` the test of `mam_send_msg()` is done with curl --- tests/regression/runner.py | 155 +++++++++++++++++++++++++++++++++++++ 1 file changed, 155 insertions(+) create mode 100644 tests/regression/runner.py diff --git a/tests/regression/runner.py b/tests/regression/runner.py new file mode 100644 index 00000000..1f3b3694 --- /dev/null +++ b/tests/regression/runner.py @@ -0,0 +1,155 @@ +# Run in Python3 +import json +import requests +import sys +import subprocess +import unittest + +if len(sys.argv) == 2: + raw_url = sys.argv[1] +else: + raw_url = "localhost:8000" +url = "http://" + raw_url +headers = {'content-type': 'application/json'} + +# Utils: +TIMEOUT = 100 # [sec] +MSG_STATUS_CODE_405 = "[405] Method Not Allowed" +CURL_EMPTY_REPLY = "000" + + +def is_addr_trytes(trytes): + tryte_alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ9" + if len(trytes) != 81: + return False + + for char in trytes: + if char not in tryte_alphabet: + return False + + return True + + +def API(get_query, get_data=None, post_data=None): + try: + if get_data is not None: + r = requests.get(str(url + get_query + get_data), timeout=TIMEOUT) + if r.status_code == 405: + response = MSG_STATUS_CODE_405 + else: + response = r.text + + elif post_data is not None: + command = "curl " + str( + url + get_query + ) + " -X POST -H 'Content-Type: application/json' -w \", %{http_code}\" -d '" + str( + post_data) + "'" + p = subprocess.Popen(command, + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE) + out, err = p.communicate() + # print("err = " + str(err)) + response = str(out.decode('ascii')) + else: + print("Wrong request method") + response = None + + except BaseException: + print(url, "Timeout!") + print('\n ' + repr(sys.exc_info())) + return None + if not response: + response = "" + return response + + +class Regression_Test(unittest.TestCase): + def test_mam_send_msg(self): + """ cmd + 0. English char only msg [success] + 1. ASCII symbols msg [success] + 2. Chinese msg [failed] curl response: "curl: (52) Empty reply from server" + 3. Japanese msg [failed] curl response: "curl: (52) Empty reply from server" + 4. Empty msg [failed] + 5. Non-JSON, plain text msg [failed] + 6. JSON msg with wrong key (not "message") [failed] + """ + test_cases = [ + "ToBeOrNotToBe", "I met my soulmate. She didnt", "當工程師好開心阿", + "今夜は月が綺麗ですね", "", "Non-JSON, plain text msg", + "JSON msg with wrong key" + ] + + pass_case = [0, 1] + for i in range(len(test_cases)): + if i not in pass_case: + test_cases[i].encode(encoding='utf-8') + + response = [] + for i in range(len(test_cases)): + print("testing case = " + str(test_cases[i])) + if i == 5: + post_data_json = test_cases[i] + elif i == 6: + post_data = {"notkey": test_cases[i]} + post_data_json = json.dumps(post_data) + else: + post_data = {"message": test_cases[i]} + post_data_json = json.dumps(post_data) + response.append(API("/mam/", post_data=post_data_json)) + + for i in range(len(response)): + if i in pass_case: + res_split = response[i].split(", ") + res_json = json.loads(res_split[0]) + self.assertTrue(is_addr_trytes(res_json["channel"])) + self.assertTrue(is_addr_trytes(res_json["bundle_hash"])) + else: + self.assertTrue(CURL_EMPTY_REPLY in response[i]) + + def test_mam_recv_msg(self): + """ cmd + 1. Correct exist MAMv2 msg [success] + 2. Empty msg [failed] empty parameter causes http error 405 + 3. Unicode msg [failed] {\"message\":\"Internal service error\"} + 4. Not existing bundle hash (address) + """ + test_cases = [ + "QBFXQETKSHDYPFUDO9ILVCAVQIXOHXKCECZYFLPBNVIX9JUXQZJE9URQEEUWPWYZOIACTCGZX9IDIODCA", + "", "生れてすみません" + ] + expect_cases = [ + "{\"message\":\"jjjjjjjjj\"}", MSG_STATUS_CODE_405, + MSG_STATUS_CODE_405 + ] + + response = [] + for t_case in test_cases: + print("testing case = " + t_case) + response.append(API("/mam/", get_data=t_case)) + + self.assertEqual(len(expect_cases), len(test_cases)) + for i in range(len(test_cases)): + self.assertTrue(expect_cases[i] in response[i]) + + +""" + API List + mam_recv_msg: GET + mam_send_msg: POST + Find transactions by tag + Get transaction object + Find transaction objects by tag + Get transaction object + Find transaction objects by tag + Fetch pair tips which base on GetTransactionToApprove + Fetch all tips + Generate an unused address + send transfer + Client bad request +""" + +# Run all the API Test here +if __name__ == '__main__': + unittest.main(argv=['first-arg-is-ignored'], exit=False) From 92c24867f59809a4f41848f24acde95604eccd66 Mon Sep 17 00:00:00 2001 From: YangHau Date: Fri, 19 Apr 2019 16:44:09 +0800 Subject: [PATCH 19/26] feat: Add MAM regression test time cost statistics The functions in class Time_Consumption() calculate how long does each API cost. Each API is called for 100 times, and then, calculate its average time costs and time cost variance. --- tests/regression/runner.py | 56 +++++++++++++++++++++++++++++++++++++- 1 file changed, 55 insertions(+), 1 deletion(-) diff --git a/tests/regression/runner.py b/tests/regression/runner.py index 1f3b3694..f0e01ce9 100644 --- a/tests/regression/runner.py +++ b/tests/regression/runner.py @@ -4,6 +4,8 @@ import sys import subprocess import unittest +import numpy as np +import time if len(sys.argv) == 2: raw_url = sys.argv[1] @@ -17,6 +19,50 @@ MSG_STATUS_CODE_405 = "[405] Method Not Allowed" CURL_EMPTY_REPLY = "000" +TIMES_TOTAL = 100 + + +def eval_stat(time_cost, func_name): + avg = np.average(time_cost) + var = np.var(time_cost) + print("Average Elapsed Time of " + str(func_name) + ":" + str(avg) + + " sec") + print("With the range +- " + str(2 * var) + + "sec, including 95% of API call time consumption") + + +class Time_Consumption(): + def test_mam_send_msg(self): + payload = "Who are we? Just a speck of dust within the galaxy?" + post_data = {"message": payload} + post_data_json = json.dumps(post_data) + + time_cost = [] + for i in range(TIMES_TOTAL): + start_time = time.time() + API("/mam/", post_data=post_data_json) + time_cost.append(time.time() - start_time) + + eval_stat(time_cost, "mam send message") + + def test_mam_recv_msg(self): + payload = "Who are we? Just a speck of dust within the galaxy?" + post_data = {"message": payload} + post_data_json = json.dumps(post_data) + response = API("/mam/", post_data=post_data_json) + + res_split = response.split(", ") + res_json = json.loads(res_split[0]) + bundle_hash = res_json["bundle_hash"] + + time_cost = [] + for i in range(TIMES_TOTAL): + start_time = time.time() + API("/mam/", get_data=bundle_hash) + time_cost.append(time.time() - start_time) + + eval_stat(time_cost, "mam recv message") + def is_addr_trytes(trytes): tryte_alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ9" @@ -49,7 +95,6 @@ def API(get_query, get_data=None, post_data=None): stdout=subprocess.PIPE, stderr=subprocess.PIPE) out, err = p.communicate() - # print("err = " + str(err)) response = str(out.decode('ascii')) else: print("Wrong request method") @@ -153,3 +198,12 @@ def test_mam_recv_msg(self): # Run all the API Test here if __name__ == '__main__': unittest.main(argv=['first-arg-is-ignored'], exit=False) + + # Run all the Time_Consumption() tests + f = Time_Consumption() + public_method_names = [ + method for method in dir(f) if callable(getattr(f, method)) + if not method.startswith('_') + ] # 'private' methods start from _ + for method in public_method_names: + getattr(f, method)() # call From ccb7a8b9b35c03e2b2157fd93f0c366e6910afaa Mon Sep 17 00:00:00 2001 From: Yu Wei Wu Date: Mon, 22 Apr 2019 10:31:28 +0800 Subject: [PATCH 20/26] feat(serialzer): Add message format in send transfer Allow send transfer in ASCII format message and set default to ascii. Current message format are trytes and ascii, so we check only "trytes" to differ than default. --- serializer/serializer.c | 27 ++++++++++++++++++++++----- tests/test_serializer.c | 1 + 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/serializer/serializer.c b/serializer/serializer.c index 33d829e9..23cf9876 100644 --- a/serializer/serializer.c +++ b/serializer/serializer.c @@ -243,6 +243,7 @@ status_t ta_send_transfer_req_deserialize(const char* const obj, cJSON* json_result = NULL; flex_trit_t tag_trits[NUM_TRITS_TAG], address_trits[NUM_TRITS_HASH]; int msg_len = 0, tag_len = 0; + bool raw_message = true; status_t ret = SC_OK; if (json_obj == NULL) { @@ -288,13 +289,29 @@ status_t ta_send_transfer_req_deserialize(const char* const obj, goto done; } + json_result = cJSON_GetObjectItemCaseSensitive(json_obj, "message_format"); + if (json_result != NULL) { + strncmp("trytes", json_result->valuestring, 6); + raw_message = false; + } + json_result = cJSON_GetObjectItemCaseSensitive(json_obj, "message"); if (json_result != NULL) { - msg_len = strlen(json_result->valuestring); - req->msg_len = msg_len * 3; - flex_trits_from_trytes(req->message, req->msg_len, - (const tryte_t*)json_result->valuestring, msg_len, - msg_len); + if (raw_message) { + msg_len = strlen(json_result->valuestring) * 2; + req->msg_len = msg_len * 3; + tryte_t trytes_buffer[msg_len]; + + ascii_to_trytes(json_result->valuestring, trytes_buffer); + flex_trits_from_trytes(req->message, req->msg_len, trytes_buffer, msg_len, + msg_len); + } else { + msg_len = strlen(json_result->valuestring); + req->msg_len = msg_len * 3; + flex_trits_from_trytes(req->message, req->msg_len, + (const tryte_t*)json_result->valuestring, msg_len, + msg_len); + } } else { // 'message' does not exists, set to DEFAULT_MSG req->msg_len = DEFAULT_MSG_LEN * 3; diff --git a/tests/test_serializer.c b/tests/test_serializer.c index a58ad467..836d8e0f 100644 --- a/tests/test_serializer.c +++ b/tests/test_serializer.c @@ -47,6 +47,7 @@ void test_serialize_ta_generate_address(void) { void test_deserialize_ta_send_transfer(void) { const char* json = "{\"value\":100," + "\"message_format\":\"trytes\"," "\"message\":\"" TAG_MSG "\",\"tag\":\"" TAG_MSG "\"," "\"address\":\"" TRYTES_81_1 "\"}"; From dccf8ece8f278225776b183cdf80937b687def90 Mon Sep 17 00:00:00 2001 From: Yu Wei Wu Date: Wed, 24 Apr 2019 10:48:54 +0800 Subject: [PATCH 21/26] fix(MAM): Add MAM save MAM API can be serialized and saved into files. This PR create a temporarily file to save MSS after first time. Send MAM message can be faster in second call and after in this way. --- accelerator/apis.c | 15 +++++++++++---- accelerator/config.c | 3 +++ accelerator/config.h | 2 ++ 3 files changed, 16 insertions(+), 4 deletions(-) diff --git a/accelerator/apis.c b/accelerator/apis.c index 6c4bca6f..737a1c44 100644 --- a/accelerator/apis.c +++ b/accelerator/apis.c @@ -201,6 +201,7 @@ status_t api_mam_send_message(const iota_config_t* const tangle, const iota_client_service_t* const service, char const* const payload, char** json_result) { status_t ret = SC_OK; + retcode_t rc = RC_OK; mam_api_t mam; const bool last_packet = true; bundle_transactions_t* bundle = NULL; @@ -210,8 +211,14 @@ status_t api_mam_send_message(const iota_config_t* const tangle, send_mam_req_t* req = send_mam_req_new(); send_mam_res_t* res = send_mam_res_new(); - // Creating MAM API - if (mam_api_init(&mam, (tryte_t*)SEED)) { + // Loading and creating MAM API + if ((rc = mam_api_load(tangle->mam_file, &mam)) == + RC_UTILS_FAILED_TO_OPEN_FILE) { + if (mam_api_init(&mam, (tryte_t*)SEED)) { + ret = SC_MAM_FAILED_INIT; + goto done; + } + } else if (rc != RC_OK) { ret = SC_MAM_FAILED_INIT; goto done; } @@ -255,9 +262,9 @@ status_t api_mam_send_message(const iota_config_t* const tangle, ret = send_mam_res_serialize(json_result, res); done: - // Destroying MAM API + // Save and destroying MAM API if (ret != SC_MAM_FAILED_INIT) { - if (mam_api_destroy(&mam) != RC_OK) { + if (mam_api_save(&mam, tangle->mam_file) || mam_api_destroy(&mam)) { ret = SC_MAM_FAILED_DESTROYED; } } diff --git a/accelerator/config.c b/accelerator/config.c index 36a03aa9..cf0bbe69 100644 --- a/accelerator/config.c +++ b/accelerator/config.c @@ -72,6 +72,7 @@ status_t ta_config_default_init(ta_config_t* const info, ta_cache_t* const cache, iota_client_service_t* const service) { status_t ret = SC_OK; + char mss_tmp[] = "/tmp/XXXXXX"; if (info == NULL || tangle == NULL || cache == NULL || service == NULL) { return SC_TA_NULL; } @@ -92,6 +93,8 @@ status_t ta_config_default_init(ta_config_t* const info, log_info(logger_id, "Initializing IRI configuration\n"); tangle->milestone_depth = MILESTONE_DEPTH; + mkstemp(mss_tmp); + strncpy(tangle->mam_file, mss_tmp, FSIZE); tangle->mss_depth = MSS_DEPTH; tangle->mwm = MWM; tangle->seed = SEED; diff --git a/accelerator/config.h b/accelerator/config.h index e3ecf6b0..18c0ac5a 100644 --- a/accelerator/config.h +++ b/accelerator/config.h @@ -27,6 +27,7 @@ extern "C" { #define IRI_HOST "localhost" #define IRI_PORT 14265 #define MILESTONE_DEPTH 3 +#define FSIZE 11 #define MSS_DEPTH 4 #define MWM 14 #define SEED \ @@ -50,6 +51,7 @@ typedef struct ta_info_s { /** struct type of iota configuration */ typedef struct ta_config_s { uint8_t milestone_depth; /**< Depth of API argument */ + char mam_file[FSIZE]; /** Save file for mam struct like MSS, skn... */ uint8_t mss_depth; /**< Depth of MSS layer merkle tree */ uint8_t mwm; /**< Minimum weight magnitude of API argument */ /** Seed to generate address. This does not do any signature yet. */ From b49d3379977bedbac09e61602ba388839ebc5565 Mon Sep 17 00:00:00 2001 From: YangHau Date: Tue, 23 Apr 2019 23:45:09 +0800 Subject: [PATCH 22/26] feat: Package code files coverage into .tar The bazel rule `pkg_coverage` can package the folder `coverage` into tar file, but it can't be called before run code coverage. The code coverage result `/coverage` is hidden from git. --- .gitignore | 2 ++ BUILD | 7 +++++++ 2 files changed, 9 insertions(+) create mode 100644 BUILD diff --git a/.gitignore b/.gitignore index f0dc5688..2ebf3424 100644 --- a/.gitignore +++ b/.gitignore @@ -76,6 +76,8 @@ bazel* cclient/bazel* cclient/cmake-* +coverage + # Atom conf .clang_complete diff --git a/BUILD b/BUILD new file mode 100644 index 00000000..3169206d --- /dev/null +++ b/BUILD @@ -0,0 +1,7 @@ +load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar") + +pkg_tar( + name = "pkg_coverage", + srcs = glob(["coverage/*"]), + package_dir = "./coverage" +) From 59bf7657127c8e8d30b1f568b9131762b8c5beb9 Mon Sep 17 00:00:00 2001 From: YangHau Date: Sat, 27 Apr 2019 23:34:08 +0800 Subject: [PATCH 23/26] fix(error) Fix error code wrong ordering --- accelerator/errors.h | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/accelerator/errors.h b/accelerator/errors.h index 48a86ddc..936c9871 100644 --- a/accelerator/errors.h +++ b/accelerator/errors.h @@ -67,17 +67,17 @@ typedef enum { // CClient module SC_CCLIENT_OOM = 0x01 | SC_MODULE_CCLIENT | SC_SEVERITY_FATAL, /**< Fail to create cclient object */ - SC_CCLIENT_NOT_FOUND = 0x03 | SC_MODULE_CCLIENT | SC_SEVERITY_FATAL, + SC_CCLIENT_NOT_FOUND = 0x02 | SC_MODULE_CCLIENT | SC_SEVERITY_FATAL, /**< Empty result from cclient */ - SC_CCLIENT_FAILED_RESPONSE = 0x04 | SC_MODULE_CCLIENT | SC_SEVERITY_FATAL, + SC_CCLIENT_FAILED_RESPONSE = 0x03 | SC_MODULE_CCLIENT | SC_SEVERITY_FATAL, /**< Error in cclient response */ - SC_CCLIENT_INVALID_FLEX_TRITS = 0x05 | SC_MODULE_CCLIENT | SC_SEVERITY_MAJOR, + SC_CCLIENT_INVALID_FLEX_TRITS = 0x04 | SC_MODULE_CCLIENT | SC_SEVERITY_MAJOR, /**< flex_trits conversion error */ - SC_CCLIENT_HASH = 0x06 | SC_MODULE_CCLIENT | SC_SEVERITY_MAJOR, + SC_CCLIENT_HASH = 0x05 | SC_MODULE_CCLIENT | SC_SEVERITY_MAJOR, /**< hash container operation error */ - SC_CCLIENT_JSON_KEY = 0x07 | SC_MODULE_CCLIENT | SC_SEVERITY_MAJOR, + SC_CCLIENT_JSON_KEY = 0x06 | SC_MODULE_CCLIENT | SC_SEVERITY_MAJOR, /**< JSON key not found */ - SC_CCLIENT_JSON_PARSE = 0x08 | SC_MODULE_CCLIENT | SC_SEVERITY_MAJOR, + SC_CCLIENT_JSON_PARSE = 0x07 | SC_MODULE_CCLIENT | SC_SEVERITY_MAJOR, /**< json parsing error, might the wrong format */ // Serializer module @@ -89,9 +89,9 @@ typedef enum { /**< Fail to parse JSON object in serializer */ // Cache module - SC_CACHE_NULL = 0x02 | SC_MODULE_CACHE | SC_SEVERITY_FATAL, + SC_CACHE_NULL = 0x01 | SC_MODULE_CACHE | SC_SEVERITY_FATAL, /**< NULL parameters in cache */ - SC_CACHE_FAILED_RESPONSE = 0x04 | SC_MODULE_CACHE | SC_SEVERITY_FATAL, + SC_CACHE_FAILED_RESPONSE = 0x02 | SC_MODULE_CACHE | SC_SEVERITY_FATAL, /**< Fail in cache operations */ // MAM module @@ -119,11 +119,11 @@ typedef enum { /**< NULL object in response */ // configuration module - SC_CONF_NULL = 0x02 | SC_MODULE_CONF | SC_SEVERITY_FATAL, + SC_CONF_NULL = 0x01 | SC_MODULE_CONF | SC_SEVERITY_FATAL, /**< NULL object in response */ - SC_CONF_MISSING_ARGUMENT = 0x04 | SC_MODULE_CONF | SC_SEVERITY_FATAL, + SC_CONF_MISSING_ARGUMENT = 0x02 | SC_MODULE_CONF | SC_SEVERITY_FATAL, /**< No argument in CLI */ - SC_CONF_UNKNOWN_OPTION = 0x05 | SC_MODULE_CONF | SC_SEVERITY_FATAL, + SC_CONF_UNKNOWN_OPTION = 0x03 | SC_MODULE_CONF | SC_SEVERITY_FATAL, /**< undefined option in CLI */ } status_t; From f6eb532f808b91060da3511161791f1453145a03 Mon Sep 17 00:00:00 2001 From: Yu Wei Wu Date: Mon, 29 Apr 2019 14:22:31 +0800 Subject: [PATCH 24/26] fix(bazel): Obey buildifier style --- BUILD | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BUILD b/BUILD index 3169206d..26a944d3 100644 --- a/BUILD +++ b/BUILD @@ -3,5 +3,5 @@ load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar") pkg_tar( name = "pkg_coverage", srcs = glob(["coverage/*"]), - package_dir = "./coverage" + package_dir = "./coverage", ) From 0e813949a22798b3e9abace9cebd2f3e0e8e4953 Mon Sep 17 00:00:00 2001 From: Yu Wei Wu Date: Mon, 29 Apr 2019 14:26:19 +0800 Subject: [PATCH 25/26] fix(README): Update README badges --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2a5cd048..7cd7b55e 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Tangle-accelerator -[![Build Status](https://badge.buildkite.com/46ec07b122bde13f984c241fe8b38e64698c5c0d816ee6c7e4.svg)](https://buildkite.com/dltcollab/dcurl-test) [![Gitter](https://img.shields.io/gitter/room/DLTcollab/tangle-accelerator.svg)](https://gitter.im/DLTcollab/tangle-accelerator) ![GitHub release](https://img.shields.io/github/release-pre/DLTcollab/tangle-accelerator.svg) +[![Build Status](https://badge.buildkite.com/0deb4c46f2f69363e4d326014843b92853733f243f379c70b5.svg)](https://buildkite.com/dltcollab/tangle-accelerator-test) [![Gitter](https://img.shields.io/gitter/room/DLTcollab/tangle-accelerator.svg)](https://gitter.im/DLTcollab/tangle-accelerator) [![GitHub release](https://img.shields.io/github/release-pre/DLTcollab/tangle-accelerator.svg)](https://github.com/DLTcollab/tangle-accelerator/releases) `Tangle-accelerator` is a caching proxy server for [IOTA](https://www.iota.org/), which can cache API requests and rewrite their responses as needed to be routed through full From bd083cd7a41dbd5ff2b8ef142047759d2a6e7b64 Mon Sep 17 00:00:00 2001 From: Yu Wei Wu Date: Mon, 29 Apr 2019 15:29:16 +0800 Subject: [PATCH 26/26] fix(config): Bump TA version --- accelerator/config.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/accelerator/config.h b/accelerator/config.h index 18c0ac5a..3c0df9b0 100644 --- a/accelerator/config.h +++ b/accelerator/config.h @@ -20,7 +20,7 @@ extern "C" { * @brief Configuration of tangle-accelerator */ -#define TA_VERSION "tangle-accelerator/0.3.0" +#define TA_VERSION "tangle-accelerator/0.5.0" #define TA_HOST "localhost" #define TA_PORT "8000" #define TA_THREAD_COUNT 10