Skip to content
This repository was archived by the owner on Dec 26, 2022. It is now read-only.

Commit ccd7074

Browse files
authored
Merge pull request #363 from locke2833/reattach
Implement transaction reattachment related APIs
2 parents 0fee66a + 2f0bbfb commit ccd7074

File tree

18 files changed

+464
-48
lines changed

18 files changed

+464
-48
lines changed

README.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -156,7 +156,9 @@ For more information for MQTT connectivity of `tangle-accelerator`, you could re
156156
### Optional: Enable external database for transaction reattachment
157157
Transaction reattachment is an optional feature.
158158

159-
You can enable it in the build time by adding option : `--define db=enable`
159+
You can enable it in the build time by adding option : `--define db=enable`.
160+
161+
When enabling reattachment, every transaction issues from the `tangle-accelerator` API called `Send Transfer Message` will be stored in the specific ScyllaDB host and response a UUID string for each transfer message as the identifier. With a promoting process that monitors the status of storing transactions, persistent pending transactions will be reattached to the Tangle.
160162

161163
Transaction reattachment relies on ScyllDB, you need to install the dependency by following commands.
162164

accelerator/BUILD

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,13 +54,26 @@ cc_binary(
5454
"-pg",
5555
],
5656
"//conditions:default": ["-DNDEBUG"],
57+
}) + select({
58+
"//connectivity/mqtt:mqtt_enable": [
59+
"-DMQTT_ENABLE",
60+
],
61+
"//conditions:default": [],
62+
}) + select({
63+
"//storage:db_enable": ["-DDB_ENABLE"],
64+
"//conditions:default": [],
5765
}),
5866
deps = [
5967
":http",
6068
":ta_config",
6169
":ta_errors",
6270
"@entangled//utils/handles:signal",
63-
],
71+
] + select({
72+
"//connectivity/mqtt:mqtt_enable": [
73+
"//connectivity/mqtt:mqtt_utils",
74+
],
75+
"//conditions:default": [],
76+
}),
6477
)
6578

6679
cc_image(
@@ -81,6 +94,15 @@ cc_library(
8194
name = "apis",
8295
srcs = ["apis.c"],
8396
hdrs = ["apis.h"],
97+
copts = select({
98+
"//connectivity/mqtt:mqtt_enable": [
99+
"-DMQTT_ENABLE",
100+
],
101+
"//conditions:default": [],
102+
}) + select({
103+
"//storage:db_enable": ["-DDB_ENABLE"],
104+
"//conditions:default": [],
105+
}),
84106
linkopts = ["-lpthread"],
85107
visibility = ["//visibility:public"],
86108
deps = [
@@ -114,6 +136,15 @@ cc_library(
114136
name = "http",
115137
srcs = ["http.c"],
116138
hdrs = ["http.h"],
139+
copts = select({
140+
"//connectivity/mqtt:mqtt_enable": [
141+
"-DMQTT_ENABLE",
142+
],
143+
"//conditions:default": [],
144+
}) + select({
145+
"//storage:db_enable": ["-DDB_ENABLE"],
146+
"//conditions:default": [],
147+
}),
117148
visibility = ["//visibility:public"],
118149
deps = [
119150
":apis",
@@ -128,6 +159,10 @@ cc_library(
128159
name = "common_core",
129160
srcs = ["common_core.c"],
130161
hdrs = ["common_core.h"],
162+
copts = select({
163+
"//storage:db_enable": ["-DDB_ENABLE"],
164+
"//conditions:default": [],
165+
}),
131166
visibility = ["//visibility:public"],
132167
deps = [
133168
":ta_config",

accelerator/apis.c

Lines changed: 99 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -500,8 +500,7 @@ status_t api_mam_send_message(const iota_config_t* const iconf, const iota_clien
500500
return ret;
501501
}
502502

503-
status_t api_send_transfer(const iota_config_t* const iconf, const iota_client_service_t* const service,
504-
const char* const obj, char** json_result) {
503+
status_t api_send_transfer(const ta_core_t* const core, const char* const obj, char** json_result) {
505504
status_t ret = SC_OK;
506505
ta_send_transfer_req_t* req = ta_send_transfer_req_new();
507506
ta_send_transfer_res_t* res = ta_send_transfer_res_new();
@@ -521,26 +520,31 @@ status_t api_send_transfer(const iota_config_t* const iconf, const iota_client_s
521520
goto done;
522521
}
523522

524-
ret = ta_send_transfer(iconf, service, req, res);
523+
ret = ta_send_transfer(&core->iota_conf, &core->iota_service, req, res);
525524
if (ret) {
526525
lock_handle_unlock(&cjson_lock);
527526
goto done;
528527
}
529528
lock_handle_unlock(&cjson_lock);
530-
531529
// return transaction object
532530
hash243_queue_push(&txn_obj_req->hashes, hash243_queue_peek(res->hash));
533531

534532
lock_handle_lock(&cjson_lock);
535-
ret = ta_find_transaction_objects(service, txn_obj_req, res_txn_array);
533+
ret = ta_find_transaction_objects(&core->iota_service, txn_obj_req, res_txn_array);
536534
if (ret) {
537535
lock_handle_unlock(&cjson_lock);
538536
goto done;
539537
}
540538
lock_handle_unlock(&cjson_lock);
541-
542-
ret = ta_send_transfer_res_serialize(res_txn_array, json_result);
543-
539+
res->txn_array = res_txn_array;
540+
#ifdef DB_ENABLE
541+
ret = db_insert_tx_into_identity(&core->db_service, res->hash, PENDING_TXN, res->uuid_string);
542+
if (ret != SC_OK) {
543+
ta_log_error("fail to insert new pending transaction for reattachement\n");
544+
goto done;
545+
}
546+
#endif
547+
ret = ta_send_transfer_res_serialize(res, json_result);
544548
done:
545549
ta_send_transfer_req_free(&req);
546550
ta_send_transfer_res_free(&res);
@@ -580,3 +584,90 @@ status_t api_send_trytes(const iota_config_t* const iconf, const iota_client_ser
580584
hash_array_free(trytes);
581585
return ret;
582586
}
587+
588+
#ifdef DB_ENABLE
589+
status_t api_find_transactions_by_id(const iota_client_service_t* const iota_service,
590+
const db_client_service_t* const db_service, const char* const obj,
591+
char** json_result) {
592+
if (obj == NULL) {
593+
ta_log_error("Invalid NULL pointer to uuid string\n");
594+
return SC_TA_NULL;
595+
}
596+
status_t ret = SC_OK;
597+
ta_log_info("find transaction by uuid string: %s\n", obj);
598+
db_identity_array_t* db_identity_array = db_identity_array_new();
599+
ret = db_get_identity_objs_by_uuid_string(db_service, obj, db_identity_array);
600+
if (ret != SC_OK) {
601+
ta_log_error("fail to find transaction by uuid string\n");
602+
goto exit;
603+
}
604+
605+
db_identity_t* itr = (db_identity_t*)utarray_front(db_identity_array);
606+
if (itr != NULL) {
607+
ret = api_find_transaction_object_single(iota_service, (const char* const)db_ret_identity_hash(itr), json_result);
608+
} else {
609+
ta_log_error("No corresponding transaction found by uuid string : %s\n", obj);
610+
ret = SC_TA_WRONG_REQUEST_OBJ;
611+
}
612+
613+
exit:
614+
db_identity_array_free(&db_identity_array);
615+
return ret;
616+
}
617+
618+
status_t api_get_identity_info_by_hash(const db_client_service_t* const db_service, const char* const obj,
619+
char** json_result) {
620+
if (obj == NULL) {
621+
ta_log_error("Invalid NULL pointer to uuid string\n");
622+
return SC_TA_NULL;
623+
}
624+
status_t ret = SC_OK;
625+
ta_log_info("get identity info by hash : %s\n", obj);
626+
db_identity_array_t* db_identity_array = db_identity_array_new();
627+
ret = db_get_identity_objs_by_hash(db_service, (const cass_byte_t*)obj, db_identity_array);
628+
if (ret != SC_OK) {
629+
ta_log_error("fail to get identity objs by transaction hash\n");
630+
goto exit;
631+
}
632+
633+
db_identity_t* itr = (db_identity_t*)utarray_front(db_identity_array);
634+
if (itr != NULL) {
635+
ret = db_identity_serialize(json_result, itr);
636+
} else {
637+
ta_log_error("No corresponding identity info found by hash : %s\n", obj);
638+
ret = SC_TA_WRONG_REQUEST_OBJ;
639+
}
640+
exit:
641+
db_identity_array_free(&db_identity_array);
642+
return ret;
643+
}
644+
645+
status_t api_get_identity_info_by_id(const db_client_service_t* const db_service, const char* const obj,
646+
char** json_result) {
647+
if (obj == NULL) {
648+
ta_log_error("Invalid NULL pointer to uuid string\n");
649+
return SC_TA_NULL;
650+
}
651+
652+
status_t ret = SC_OK;
653+
ta_log_info("get identity info by uuid string : %s\n", obj);
654+
db_identity_array_t* db_identity_array = db_identity_array_new();
655+
ret = db_get_identity_objs_by_uuid_string(db_service, obj, db_identity_array);
656+
if (ret != SC_OK) {
657+
ta_log_error("fail to get identity objs by uuid string\n");
658+
goto exit;
659+
}
660+
661+
db_identity_t* itr = (db_identity_t*)utarray_front(db_identity_array);
662+
if (itr != NULL) {
663+
ret = db_identity_serialize(json_result, itr);
664+
} else {
665+
ta_log_error("No corresponding identity info found by uuid string : %s\n", obj);
666+
ret = SC_TA_WRONG_REQUEST_OBJ;
667+
}
668+
669+
exit:
670+
db_identity_array_free(&db_identity_array);
671+
return ret;
672+
}
673+
#endif

accelerator/apis.h

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,17 +167,15 @@ status_t api_mam_send_message(const iota_config_t* const iconf, const iota_clien
167167
* fields include address, value, tag, and message. This API would also try to
168168
* find the transactions after bundle sent.
169169
*
170-
* @param[in] iconf IOTA API parameter configurations
171-
* @param[in] service IRI node end point service
170+
* @param core[in] Pointer to Tangle-accelerator core configuration structure
172171
* @param[in] obj Input data in JSON
173172
* @param[out] json_result Result containing transaction objects in json format
174173
*
175174
* @return
176175
* - SC_OK on success
177176
* - non-zero on error
178177
*/
179-
status_t api_send_transfer(const iota_config_t* const iconf, const iota_client_service_t* const service,
180-
const char* const obj, char** json_result);
178+
status_t api_send_transfer(const ta_core_t* const core, const char* const obj, char** json_result);
181179

182180
/**
183181
* @brief Return transaction object with given single transaction hash.
@@ -268,6 +266,54 @@ status_t api_find_transactions_obj_by_tag(const iota_client_service_t* const ser
268266
*/
269267
status_t api_send_trytes(const iota_config_t* const iconf, const iota_client_service_t* const service,
270268
const char* const obj, char** json_result);
269+
#ifdef DB_ENABLE
270+
/**
271+
* @brief Return transaction object with given single identity number.
272+
*
273+
* Explore transaction hash information with given single identity number. This would
274+
* return whole transaction object details in json format instead of raw trytes.
275+
*
276+
* @param[in] iota_service IRI node end point service
277+
* @param[in] db_service db client service
278+
* @param[in] obj identity number
279+
* @param[out] json_result Result containing the only one transaction object in json format
280+
*
281+
* @return
282+
* - SC_OK on success
283+
* - non-zero on error
284+
*/
285+
status_t api_find_transactions_by_id(const iota_client_service_t* const iota_service,
286+
const db_client_service_t* const db_service, const char* const obj,
287+
char** json_result);
288+
289+
/**
290+
* @brief Return db identity object with given single transaction hash.
291+
*
292+
* @param[in] db_service db client service
293+
* @param[in] obj transaction hash
294+
* @param[out] json_result Result containing the only one db identity object in json format
295+
*
296+
* @return
297+
* - SC_OK on success
298+
* - non-zero on error
299+
*/
300+
status_t api_get_identity_info_by_hash(const db_client_service_t* const db_service, const char* const obj,
301+
char** json_result);
302+
303+
/**
304+
* @brief Return db identity object with given single transaction id.
305+
*
306+
* @param[in] db_service db client service
307+
* @param[in] obj transaction id
308+
* @param[out] json_result Result containing the only one db identity object in json format
309+
*
310+
* @return
311+
* - SC_OK on success
312+
* - non-zero on error
313+
*/
314+
status_t api_get_identity_info_by_id(const db_client_service_t* const db_service, const char* const obj,
315+
char** json_result);
316+
#endif
271317

272318
#ifdef __cplusplus
273319
}

accelerator/config.c

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,7 @@ static status_t cli_core_set(ta_core_t* const core, int key, char* const value)
7878
#ifdef DB_ENABLE
7979
// DB configuration
8080
case DB_HOST_CLI:
81+
free(db_service->host);
8182
db_service->host = strdup(value);
8283
break;
8384
#endif
@@ -337,7 +338,7 @@ status_t ta_core_set(ta_core_t* core) {
337338
cache_init(cache->cache_state, cache->host, cache->port);
338339
#ifdef DB_ENABLE
339340
ta_log_info("Initializing db client service\n");
340-
if ((ret = db_client_service_init(db_service)) != SC_OK) {
341+
if ((ret = db_client_service_init(db_service, DB_USAGE_REATTACH)) != SC_OK) {
341342
ta_log_error("Initializing DB connection failed\n");
342343
}
343344
#endif
@@ -347,20 +348,14 @@ status_t ta_core_set(ta_core_t* core) {
347348
}
348349

349350
void ta_core_destroy(ta_core_t* const core) {
350-
iota_client_service_t* const iota_service = &core->iota_service;
351-
#ifdef DB_ENABLE
352-
db_client_service_t* const db_service = &core->db_service;
353-
#endif
354-
355351
ta_log_info("Destroying IRI connection\n");
356352
iota_client_extended_destroy();
357-
iota_client_core_destroy(iota_service);
353+
iota_client_core_destroy(&core->iota_service);
358354
#ifdef DB_ENABLE
359-
if (db_service->enabled) {
360-
ta_log_info("Destroying DB connection\n");
361-
db_client_service_free(db_service);
362-
}
355+
ta_log_info("Destroying DB connection\n");
356+
db_client_service_free(&core->db_service);
363357
#endif
358+
364359
pow_destroy();
365360
cache_stop();
366361
logger_helper_release(logger_id);

0 commit comments

Comments
 (0)