From 086dbc2e803c4056d960156f3e89e7276b7ca3a1 Mon Sep 17 00:00:00 2001 From: marktwtn Date: Thu, 3 Oct 2019 21:35:56 +0800 Subject: [PATCH 01/22] refactor: Change log function for unification with entangled The original ddprintf() function name is changed to the similar function log_debug() in entangled. The implementation is unchanged since the dcurl does not integrate with the logger project used by entangled. Currently dcurl has its own implementation. For unification, the logger_id_t logger_id parameter of log_debug() is added and assigned with 0. And there is a new log function log_info() for release mode. Close #180. --- src/common.h | 19 +++++++++++- src/implcontext.c | 5 ++-- src/remote_common.c | 65 ++++++++++++++++++++++-------------------- src/remote_interface.c | 11 +++---- src/remote_worker.c | 21 +++++++------- tests/test-pow.c | 13 +++++---- 6 files changed, 79 insertions(+), 55 deletions(-) diff --git a/src/common.h b/src/common.h index 9288133..d4e8ecf 100644 --- a/src/common.h +++ b/src/common.h @@ -20,7 +20,13 @@ double diff_in_second(struct timespec t1, struct timespec t2); -static inline void ddprintf(const char *format, ...) +/* Copy from logger project: + * https://bitbucket.org/embear/logger/src/abef6b0a6c991545a3d3fecfbc39d2b0448fb85a/include/logger.h#lines-199*/ +typedef int16_t logger_id_t; + +static inline void log_debug(logger_id_t const logger_id, + const char *format, + ...) { #if defined(ENABLE_DEBUG) va_list ap; @@ -31,6 +37,17 @@ static inline void ddprintf(const char *format, ...) #endif } +static inline void log_info(logger_id_t const logger_id, + const char *format, + ...) +{ + va_list ap; + va_start(ap, format); + vprintf(format, ap); + va_end(ap); + fflush(stdout); +} + typedef struct _pow_info PoW_Info; struct _pow_info { diff --git a/src/implcontext.c b/src/implcontext.c index 999bac3..ac251a4 100644 --- a/src/implcontext.c +++ b/src/implcontext.c @@ -23,8 +23,9 @@ bool initializeImplContext(ImplContext *impl_ctx) { bool res = impl_ctx->initialize(impl_ctx); if (res) { - ddprintf(MSG_PREFIX "Implementation %s is initialized successfully\n", - impl_ctx->description); + log_debug(0, + MSG_PREFIX "Implementation %s is initialized successfully\n", + impl_ctx->description); } return res; } diff --git a/src/remote_common.c b/src/remote_common.c index f5178d2..49c0fef 100644 --- a/src/remote_common.c +++ b/src/remote_common.c @@ -19,11 +19,11 @@ bool die_on_amqp_error(amqp_rpc_reply_t x, char const *context) return true; case AMQP_RESPONSE_NONE: - ddprintf("%s: missing RPC reply type!\n", context); + log_debug(0, "%s: missing RPC reply type!\n", context); break; case AMQP_RESPONSE_LIBRARY_EXCEPTION: - ddprintf("%s: %s\n", context, amqp_error_string2(x.library_error)); + log_debug(0, "%s: %s\n", context, amqp_error_string2(x.library_error)); break; case AMQP_RESPONSE_SERVER_EXCEPTION: @@ -31,21 +31,21 @@ bool die_on_amqp_error(amqp_rpc_reply_t x, char const *context) case AMQP_CONNECTION_CLOSE_METHOD: { amqp_connection_close_t *m = (amqp_connection_close_t *) x.reply.decoded; - ddprintf("%s: server connection error %u, message: %.*s\n", - context, m->reply_code, (int) m->reply_text.len, - (char *) m->reply_text.bytes); + log_debug(0, "%s: server connection error %u, message: %.*s\n", + context, m->reply_code, (int) m->reply_text.len, + (char *) m->reply_text.bytes); break; } case AMQP_CHANNEL_CLOSE_METHOD: { amqp_channel_close_t *m = (amqp_channel_close_t *) x.reply.decoded; - ddprintf("%s: server channel error %u, message: %.*s\n", context, - m->reply_code, (int) m->reply_text.len, - (char *) m->reply_text.bytes); + log_debug(0, "%s: server channel error %u, message: %.*s\n", + context, m->reply_code, (int) m->reply_text.len, + (char *) m->reply_text.bytes); break; } default: - ddprintf("%s: unknown server error, method id 0x%08X\n", context, - x.reply.id); + log_debug(0, "%s: unknown server error, method id 0x%08X\n", + context, x.reply.id); break; } break; @@ -57,7 +57,7 @@ bool die_on_amqp_error(amqp_rpc_reply_t x, char const *context) bool die_on_error(int x, char const *context) { if (x < 0) { - ddprintf("%s: %s\n", context, amqp_error_string2(x)); + log_debug(0, "%s: %s\n", context, amqp_error_string2(x)); return false; } @@ -73,7 +73,7 @@ bool connect_broker(amqp_connection_state_t *conn, const char *hostName) *conn = amqp_new_connection(); socket = amqp_tcp_socket_new(*conn); if (amqp_socket_open(socket, host, 5672) != AMQP_STATUS_OK) { - ddprintf("The rabbitmq broker of %s is closed\n", host); + log_debug(0, "The rabbitmq broker of %s is closed\n", host); goto destroy_connection; } @@ -197,24 +197,25 @@ bool wait_response_message(amqp_connection_state_t *conn, if (!die_on_amqp_error(amqp_get_rpc_reply(*conn), "Wait method frame")) return false; - ddprintf(MSG_PREFIX "Frame type: %u channel: %u\n", frame.frame_type, - frame.channel); + log_debug(0, MSG_PREFIX "Frame type: %u channel: %u\n", + frame.frame_type, frame.channel); if (frame.frame_type != AMQP_FRAME_METHOD) continue; - ddprintf(MSG_PREFIX "Method: %s\n", - amqp_method_name(frame.payload.method.id)); + log_debug(0, MSG_PREFIX "Method: %s\n", + amqp_method_name(frame.payload.method.id)); if (frame.payload.method.id != AMQP_BASIC_DELIVER_METHOD) continue; #if defined(ENABLE_DEBUG) d = (amqp_basic_deliver_t *) frame.payload.method.decoded; - ddprintf(MSG_PREFIX "Delivery: %u exchange: %.*s routingkey: %.*s\n", - (unsigned) d->delivery_tag, (int) d->exchange.len, - (char *) d->exchange.bytes, (int) d->routing_key.len, - (char *) d->routing_key.bytes); + log_debug(0, + MSG_PREFIX "Delivery: %u exchange: %.*s routingkey: %.*s\n", + (unsigned) d->delivery_tag, (int) d->exchange.len, + (char *) d->exchange.bytes, (int) d->routing_key.len, + (char *) d->routing_key.bytes); #endif amqp_maybe_release_buffers(*conn); @@ -227,18 +228,19 @@ bool wait_response_message(amqp_connection_state_t *conn, return false; if (frame.frame_type != AMQP_FRAME_HEADER) { - ddprintf("Unexpected header!\n"); + log_debug(0, "Unexpected header!\n"); return false; } #if defined(ENABLE_DEBUG) p = (amqp_basic_properties_t *) frame.payload.properties.decoded; if (p->_flags & AMQP_BASIC_CONTENT_TYPE_FLAG) { - ddprintf(MSG_PREFIX "Content-type: %.*s\n", - (int) p->content_type.len, (char *) p->content_type.bytes); + log_debug(0, MSG_PREFIX "Content-type: %.*s\n", + (int) p->content_type.len, + (char *) p->content_type.bytes); } #endif - ddprintf("---\n"); + log_debug(0, "---\n"); body_target = (size_t) frame.payload.properties.body_size; body_received = 0; @@ -252,24 +254,24 @@ bool wait_response_message(amqp_connection_state_t *conn, return false; if (frame.frame_type != AMQP_FRAME_BODY) { - ddprintf("Unexpected body\n"); + log_debug(0, "Unexpected body\n"); return false; } body_received += frame.payload.body_fragment.len; } if (body_received != body_target) { - ddprintf("Received body is smaller than body target\n"); + log_debug(0, "Received body is smaller than body target\n"); return false; } memcpy(frame_body, (char *) frame.payload.body_fragment.bytes, body_len); - ddprintf(MSG_PREFIX "PoW result: %.*s\n", - (int) frame.payload.body_fragment.len, - (char *) frame.payload.body_fragment.bytes); - ddprintf("---\n"); + log_debug(0, MSG_PREFIX "PoW result: %.*s\n", + (int) frame.payload.body_fragment.len, + (char *) frame.payload.body_fragment.bytes); + log_debug(0, "---\n"); /* everything was fine, we can quit now because we received the reply */ return true; @@ -315,7 +317,8 @@ bool publish_message_with_reply_to(amqp_connection_state_t *conn, "Publishing the message with reply_to")) return false; - ddprintf(MSG_PREFIX "callback queue %s \n", (char *) props.reply_to.bytes); + log_debug(0, MSG_PREFIX "callback queue %s \n", + (char *) props.reply_to.bytes); amqp_bytes_free(props.reply_to); return true; diff --git a/src/remote_interface.c b/src/remote_interface.c index f9245a7..09406f3 100644 --- a/src/remote_interface.c +++ b/src/remote_interface.c @@ -14,8 +14,9 @@ bool initializeRemoteContext(RemoteImplContext *remote_ctx) { bool res = remote_ctx->initialize(remote_ctx); if (res) { - ddprintf(MSG_PREFIX "Implementation %s is initialized successfully\n", - remote_ctx->description); + log_debug(0, + MSG_PREFIX "Implementation %s is initialized successfully\n", + remote_ctx->description); } return res; } @@ -68,20 +69,20 @@ bool PoWValidation(int8_t *output_trytes, int mwm) { Trytes_t *trytes_t = initTrytes(output_trytes, TRANSACTION_TRYTES_LENGTH); if (!trytes_t) { - ddprintf("PoW Validation: Initialization of Trytes fails\n"); + log_debug(0, "PoW Validation: Initialization of Trytes fails\n"); goto fail_to_inittrytes; } Trytes_t *hash_trytes = hashTrytes(trytes_t); if (!hash_trytes) { - ddprintf("PoW Validation: Hashing trytes fails\n"); + log_debug(0, "PoW Validation: Hashing trytes fails\n"); goto fail_to_hashtrytes; } Trits_t *ret_trits = trits_from_trytes(hash_trytes); for (int i = 243 - 1; i >= 243 - mwm; i--) { if (ret_trits->data[i] != 0) { - ddprintf("PoW Validation fails\n"); + log_debug(0, "PoW Validation fails\n"); goto fail_to_validation; } } diff --git a/src/remote_worker.c b/src/remote_worker.c index d397dfa..653fef7 100644 --- a/src/remote_worker.c +++ b/src/remote_worker.c @@ -54,7 +54,8 @@ int main(int argc, char *const *argv) if (!consume_message(&conn, 1, &envelope)) goto fail; - ddprintf( + log_debug( + 0, MSG_PREFIX "Delivery %u, exchange %.*s, routingkey %.*s, callback queue: %s " "\n", @@ -63,9 +64,9 @@ int main(int argc, char *const *argv) (char *) envelope.routing_key.bytes, (char *) envelope.message.properties.reply_to.bytes); if (envelope.message.properties._flags & AMQP_BASIC_CONTENT_TYPE_FLAG) { - ddprintf(MSG_PREFIX "Content-type: %.*s\n", - (int) envelope.message.properties.content_type.len, - (char *) envelope.message.properties.content_type.bytes); + log_debug(0, MSG_PREFIX "Content-type: %.*s\n", + (int) envelope.message.properties.content_type.len, + (char *) envelope.message.properties.content_type.bytes); } /* Message body format: transacton | mwm */ @@ -73,15 +74,15 @@ int main(int argc, char *const *argv) memcpy(buf, envelope.message.body.bytes + TRANSACTION_TRYTES_LENGTH, 4); mwm = strtol(buf, NULL, 10); - ddprintf(MSG_PREFIX "Doing PoW with mwm = %d...\n", mwm); + log_debug(0, MSG_PREFIX "Doing PoW with mwm = %d...\n", mwm); int8_t *ret_trytes = dcurl_entry((int8_t *) trytes, mwm, 0); memset(buf, '0', sizeof(buf)); - ddprintf(MSG_PREFIX "PoW is done\n"); + log_debug(0, MSG_PREFIX "PoW is done\n"); if (!acknowledge_broker(&conn, 1, &envelope)) goto fail; - ddprintf(MSG_PREFIX "Sending an ack is done\n"); + log_debug(0, MSG_PREFIX "Sending an ack is done\n"); /* Publish a message of remote PoW result */ if (!publish_message( @@ -91,9 +92,9 @@ int main(int argc, char *const *argv) free(ret_trytes); amqp_destroy_envelope(&envelope); - ddprintf(MSG_PREFIX - "Publishing PoW result to callback queue is done\n"); - ddprintf(MSG_PREFIX "---\n"); + log_debug( + 0, MSG_PREFIX "Publishing PoW result to callback queue is done\n"); + log_debug(0, MSG_PREFIX "---\n"); } fail: diff --git a/tests/test-pow.c b/tests/test-pow.c index 9666914..490d57f 100644 --- a/tests/test-pow.c +++ b/tests/test-pow.c @@ -144,7 +144,7 @@ int main() for (int idx = 0; idx < sizeof(ImplContextArr) / sizeof(ImplContext); idx++) { - printf("%s\n", description[idx]); + log_info(0, "%s\n", description[idx]); ImplContext *PoW_Context_ptr = &ImplContextArr[idx]; @@ -189,16 +189,17 @@ int main() freePoWContext(PoW_Context_ptr, pow_ctx); destroyImplContext(PoW_Context_ptr); - printf("PoW execution times: %d times.\n", pow_total); + log_info(0, "PoW execution times: %d times.\n", pow_total); #if defined(ENABLE_STAT) - printf("Hash rate average value: %.3lf kH/sec,\n", - getAvg(hashRateArr, pow_total) / 1000); - printf( + log_info(0, "Hash rate average value: %.3lf kH/sec,\n", + getAvg(hashRateArr, pow_total) / 1000); + log_info( + 0, "with the range +- %.3lf kH/sec including 95%% of the hash rate " "values.\n", 2 * getStdDeviation(hashRateArr, pow_total) / 1000); #endif - printf("Success.\n"); + log_info(0, "Success.\n"); } return 0; From ea07e4bc4e93b1f36dd636d5ba60040e2fdf642e Mon Sep 17 00:00:00 2001 From: marktwtn Date: Wed, 16 Oct 2019 17:32:31 +0800 Subject: [PATCH 02/22] CI: Integrate CppCheck and fix detected errors The detected and fixed errors list: - Assign a value that is never used - Reassign a value before the old one has been used - The scope of the variable can be reduced - The behaviour of using void pointers in calculations is undefined - Uninitialized variable - Shadow variables The file cppcheck_suppress suppresses the errors which should not be treated as errors. The reason is written in the file. The sanitizer.mk is renamed as dynamic-analysis.mk. And there is another file static-analysis.mk for static code analysis. Related to #173. --- Makefile | 5 ++- cppcheck_suppress | 15 +++++++ mk/{sanitizers.mk => dynamic-analysis.mk} | 0 mk/static-analysis.mk | 13 ++++++ src/clcontext.c | 6 +-- src/cpu-utils.h | 49 ++++++++++++----------- src/curl.c | 2 +- src/pow_avx.c | 24 +++++------ src/pow_c.c | 19 ++++----- src/pow_cl.c | 10 +++-- src/pow_fpga_accel.c | 18 ++++----- src/pow_kernel.cl | 5 ++- src/pow_sse.c | 20 ++++----- src/remote_common.c | 2 + src/remote_interface.c | 2 +- src/remote_worker.c | 5 ++- src/trinary.c | 6 +-- src/trinary_sse42.h | 15 ++----- tests/test-pow.c | 2 +- 19 files changed, 122 insertions(+), 96 deletions(-) create mode 100644 cppcheck_suppress rename mk/{sanitizers.mk => dynamic-analysis.mk} (100%) create mode 100644 mk/static-analysis.mk diff --git a/Makefile b/Makefile index 197b778..45c0474 100644 --- a/Makefile +++ b/Makefile @@ -22,13 +22,16 @@ endif ifneq ("$(BUILD_DEBUG)","0") CFLAGS += -Og -g3 -DENABLE_DEBUG ifneq ("$(BUILD_DEBUG)","1") - include mk/sanitizers.mk + include mk/dynamic-analysis.mk endif else # Enable all the valid optimizations for standard programs in release build CFLAGS += -O3 endif +# Static code analysis +include mk/static-analysis.mk + # Check specific CPU features available on build host include mk/cpu-features.mk diff --git a/cppcheck_suppress b/cppcheck_suppress new file mode 100644 index 0000000..d8a9887 --- /dev/null +++ b/cppcheck_suppress @@ -0,0 +1,15 @@ +// The most significant bit is not used as a signed bit +shiftTooManyBitsSigned:src/pow_avx.c:321 + +// The unused functions are for the ccurl compatibility +unusedFunction:src/compat-ccurl.c:18 +unusedFunction:src/compat-ccurl.c:29 +unusedFunction:src/compat-ccurl.c:34 + +// The invoked functions of OpenCL are not checked correctly with CppCheck +unusedFunction:src/pow_kernel.cl:185 +unusedFunction:src/pow_kernel.cl:216 +unusedFunction:src/pow_kernel.cl:249 + +// Do not treat system header files missing as errors +missingIncludeSystem:* diff --git a/mk/sanitizers.mk b/mk/dynamic-analysis.mk similarity index 100% rename from mk/sanitizers.mk rename to mk/dynamic-analysis.mk diff --git a/mk/static-analysis.mk b/mk/static-analysis.mk new file mode 100644 index 0000000..e672d1e --- /dev/null +++ b/mk/static-analysis.mk @@ -0,0 +1,13 @@ +static-analysis: + cppcheck \ + --enable=all \ + --error-exitcode=1 \ + --force \ + -I $(SRC) \ + $(LIBTUV_INCLUDE) \ + $(LIBRABBITMQ_INCLUDE) \ + $(SSE2NEON_INCLUDE) \ + --quiet \ + --suppressions-list=cppcheck_suppress \ + -UERANGE \ + $(SRC) tests diff --git a/src/clcontext.c b/src/clcontext.c index c817740..398b7c5 100644 --- a/src/clcontext.c +++ b/src/clcontext.c @@ -82,7 +82,7 @@ static bool init_cl_kernel(CLContext *ctx) static bool init_cl_buffer(CLContext *ctx) { - cl_ulong mem = 0, max_mem = 0; + cl_ulong mem, max_mem = 0; cl_int errno; for (int i = 0; i < ctx->kernel_info.num_buffers; i++) { @@ -157,7 +157,7 @@ int init_clcontext(CLContext *ctx) int ctx_idx = 0; cl_uint num_platform = 0; - cl_platform_id *platform = NULL; + cl_platform_id *platform; /* Get the platform */ clGetPlatformIDs(0, NULL, &num_platform); @@ -167,7 +167,7 @@ int init_clcontext(CLContext *ctx) clGetPlatformIDs(num_platform, platform, NULL); cl_uint num_devices = 0; - cl_device_id *devices = NULL; + cl_device_id *devices; /* Iterate the platform list and get its devices */ for (int i = 0; i < num_platform; i++) { diff --git a/src/cpu-utils.h b/src/cpu-utils.h index 754fdcb..5df381b 100644 --- a/src/cpu-utils.h +++ b/src/cpu-utils.h @@ -46,9 +46,9 @@ static unsigned int get_nprocs_conf() */ static inline int get_nthds_per_phys_proc() { - FILE *fd; int nthread; #if defined(__linux__) + FILE *fd; char nthd[4]; fd = popen("LC_ALL=C lscpu | grep 'Thread(s) per core' | awk '{printf $4}'", @@ -61,7 +61,11 @@ static inline int get_nthds_per_phys_proc() if (errno == ERANGE || nthread == 0) { return -1; } + + if (pclose(fd) == -1) + return -1; #elif defined(__APPLE__) + FILE *fd; char p_proc[4], l_proc[4]; int phys_proc, logic_proc; @@ -85,10 +89,12 @@ static inline int get_nthds_per_phys_proc() } nthread = logic_proc / phys_proc; -#endif if (pclose(fd) == -1) return -1; +#else + nthread = 1; +#endif return nthread; } @@ -107,33 +113,30 @@ static inline int get_nthds_per_phys_proc() static inline int get_avail_phys_nprocs() { int nthd; - size_t nproc; + size_t nproc = 0; + char *env_ncpu; nthd = get_nthds_per_phys_proc(); + env_ncpu = getenv("DCURL_NUM_CPU"); if (nthd <= 0) return -1; - else + else if (env_ncpu) { + do { + char *end; + signed int num = strtol(env_ncpu, &end, 10); + if (end == env_ncpu) { + /* if no characters were converted these pointers are equal */ + break; + } + if (errno == ERANGE || num > INT_MAX || num < 0) { + /* because strtol produces a long, check for overflow */ + break; + } + nproc = num; + } while (0); + } else nproc = (get_nprocs_conf() / nthd) - 1; - do { - char *env_ncpu = getenv("DCURL_NUM_CPU"); - if (!env_ncpu) { - break; - } - - char *end; - signed int num = strtol(env_ncpu, &end, 10); - if (end == env_ncpu) { - /* if no characters were converted these pointers are equal */ - break; - } - if (errno == ERANGE || num > INT_MAX || num < 0) { - /* because strtol produces a long, check for overflow */ - break; - } - nproc = num; - } while (0); - if (!nproc) nproc = 1; return nproc; diff --git a/src/curl.c b/src/curl.c index bc18a59..434de3f 100644 --- a/src/curl.c +++ b/src/curl.c @@ -15,7 +15,7 @@ static const int8_t truthTable[11] = {1, 0, -1, 2, 1, -1, 0, 2, -1, 1, 0}; static void _transform(int8_t state[]) { - int r = 0, i = 0; + int r, i; int8_t copy[STATE_TRITS_LENGTH] = {0}; int8_t *from = state, *to = copy; for (r = 0; r < 81; r++) { diff --git a/src/pow_avx.c b/src/pow_avx.c index d928530..350e606 100644 --- a/src/pow_avx.c +++ b/src/pow_avx.c @@ -162,12 +162,13 @@ static int loop256(__m256i *lmid, int *stopPoW, uv_rwlock_t *lock) { - int i = 0, n = 0; + int i = 0; __m256i lcpy[STATE_TRITS_LENGTH * 2], hcpy[STATE_TRITS_LENGTH * 2]; uv_rwlock_rdlock(lock); for (i = 0; !incr256(lmid, hmid) && !*stopPoW; i++) { uv_rwlock_rdunlock(lock); + int n; for (int j = 0; j < STATE_TRITS_LENGTH; j++) { lcpy[j] = lmid[j]; hcpy[j] = hmid[j]; @@ -369,12 +370,13 @@ static int loop256(__m256d *lmid, int *stopPoW, uv_rwlock_t *lock) { - int i = 0, n = 0, j = 0; + int i = 0; __m256d lcpy[STATE_TRITS_LENGTH * 2], hcpy[STATE_TRITS_LENGTH * 2]; uv_rwlock_rdlock(lock); for (i = 0; !incr256(lmid, hmid) && !*stopPoW; i++) { uv_rwlock_rdunlock(lock); + int n, j; for (j = 0; j < STATE_TRITS_LENGTH; j++) { lcpy[j] = lmid[j]; hcpy[j] = hmid[j]; @@ -596,16 +598,13 @@ static bool PoWAVX_Context_Initialize(ImplContext *impl_ctx) goto fail; for (int i = 0; i < impl_ctx->num_max_thread; i++) { - ctx[i].work_req = - (uv_work_t *) (work_req_chunk + i * sizeof(uv_work_t) * nproc); - ctx[i].pitem = - (Pwork_struct *) (pitem_chunk + i * sizeof(Pwork_struct) * nproc); - ctx[i].nonce_array = - (int8_t **) (nonce_ptr_chunk + i * sizeof(int8_t *) * nproc); + ctx[i].work_req = (uv_work_t *) (work_req_chunk) + i * nproc; + ctx[i].pitem = (Pwork_struct *) (pitem_chunk) + i * nproc; + ctx[i].nonce_array = (int8_t **) (nonce_ptr_chunk) + i * nproc; for (int j = 0; j < nproc; j++) - ctx[i].nonce_array[j] = - (int8_t *) (nonce_chunk + i * NONCE_TRITS_LENGTH * nproc + - j * NONCE_TRITS_LENGTH); + ctx[i].nonce_array[j] = (int8_t *) (nonce_chunk) + + i * NONCE_TRITS_LENGTH * nproc + + j * NONCE_TRITS_LENGTH; ctx[i].num_max_threads = nproc; impl_ctx->bitmap = impl_ctx->bitmap << 1 | 0x1; uv_loop_init(&ctx[i].loop); @@ -650,8 +649,7 @@ static void *PoWAVX_getPoWContext(ImplContext *impl_ctx, if (impl_ctx->bitmap & (0x1 << i)) { impl_ctx->bitmap &= ~(0x1 << i); uv_mutex_unlock(&impl_ctx->lock); - PoW_AVX_Context *ctx = - impl_ctx->context + sizeof(PoW_AVX_Context) * i; + PoW_AVX_Context *ctx = (PoW_AVX_Context *) impl_ctx->context + i; memcpy(ctx->input_trytes, trytes, TRANSACTION_TRYTES_LENGTH); ctx->mwm = mwm; ctx->indexOfContext = i; diff --git a/src/pow_c.c b/src/pow_c.c index 9c4c155..a246b6f 100644 --- a/src/pow_c.c +++ b/src/pow_c.c @@ -108,13 +108,13 @@ static long long int loop_cpu(uint64_t *lmid, int *stopPoW, uv_rwlock_t *lock) { - int n = 0; long long int i = 0; uint64_t lcpy[STATE_TRITS_LENGTH * 2], hcpy[STATE_TRITS_LENGTH * 2]; uv_rwlock_rdlock(lock); for (i = 0; !incr(lmid, hmid) && !*stopPoW; i++) { uv_rwlock_rdunlock(lock); + int n; memcpy(lcpy, lmid, STATE_TRITS_LENGTH * sizeof(uint64_t)); memcpy(hcpy, hmid, STATE_TRITS_LENGTH * sizeof(uint64_t)); transform64(lcpy, hcpy); @@ -360,16 +360,13 @@ static bool PoWC_Context_Initialize(ImplContext *impl_ctx) goto fail; for (int i = 0; i < impl_ctx->num_max_thread; i++) { - ctx[i].work_req = - (uv_work_t *) (work_req_chunk + i * sizeof(uv_work_t) * nproc); - ctx[i].pitem = - (Pwork_struct *) (pitem_chunk + i * sizeof(Pwork_struct) * nproc); - ctx[i].nonce_array = - (int8_t **) (nonce_ptr_chunk + i * sizeof(int8_t *) * nproc); + ctx[i].work_req = (uv_work_t *) (work_req_chunk) + i * nproc; + ctx[i].pitem = (Pwork_struct *) (pitem_chunk) + i * nproc; + ctx[i].nonce_array = (int8_t **) (nonce_ptr_chunk) + i * nproc; for (int j = 0; j < nproc; j++) - ctx[i].nonce_array[j] = - (int8_t *) (nonce_chunk + i * NONCE_TRITS_LENGTH * nproc + - j * NONCE_TRITS_LENGTH); + ctx[i].nonce_array[j] = (int8_t *) (nonce_chunk) + + i * NONCE_TRITS_LENGTH * nproc + + j * NONCE_TRITS_LENGTH; ctx[i].num_max_threads = nproc; impl_ctx->bitmap = impl_ctx->bitmap << 1 | 0x1; uv_loop_init(&ctx[i].loop); @@ -414,7 +411,7 @@ static void *PoWC_getPoWContext(ImplContext *impl_ctx, if (impl_ctx->bitmap & (0x1 << i)) { impl_ctx->bitmap &= ~(0x1 << i); uv_mutex_unlock(&impl_ctx->lock); - PoW_C_Context *ctx = impl_ctx->context + sizeof(PoW_C_Context) * i; + PoW_C_Context *ctx = (PoW_C_Context *) impl_ctx->context + i; memcpy(ctx->input_trytes, trytes, TRANSACTION_TRYTES_LENGTH); ctx->mwm = mwm; ctx->indexOfContext = i; diff --git a/src/pow_cl.c b/src/pow_cl.c index 2b3ef15..efc641d 100644 --- a/src/pow_cl.c +++ b/src/pow_cl.c @@ -210,14 +210,16 @@ static bool PowCL(void *pow_ctx) bool res = true; int8_t *c_state = NULL, *pow_result = NULL; Trits_t *tx_trit = NULL; - Trytes_t *tx_tryte = NULL, *res_tryte = NULL; + Trytes_t *tx_tryte, *res_tryte = NULL; struct timespec start_time, end_time; PoW_CL_Context *ctx = (PoW_CL_Context *) pow_ctx; tx_tryte = initTrytes(ctx->input_trytes, TRANSACTION_TRYTES_LENGTH); - if (!tx_tryte) - return false; + if (!tx_tryte) { + res = false; + goto fail; + } tx_trit = trits_from_trytes(tx_tryte); if (!tx_trit) { @@ -298,7 +300,7 @@ static void *PoWCL_getPoWContext(ImplContext *impl_ctx, impl_ctx->bitmap &= ~(0x1 << i); uv_mutex_unlock(&impl_ctx->lock); PoW_CL_Context *ctx = - impl_ctx->context + sizeof(PoW_CL_Context) * i; + (PoW_CL_Context *) impl_ctx->context + i; memcpy(ctx->input_trytes, trytes, TRANSACTION_TRYTES_LENGTH); ctx->mwm = mwm; ctx->indexOfContext = i; diff --git a/src/pow_fpga_accel.c b/src/pow_fpga_accel.c index 1f20499..b400b6e 100644 --- a/src/pow_fpga_accel.c +++ b/src/pow_fpga_accel.c @@ -42,8 +42,6 @@ static bool PoWFPGAAccel(void *pow_ctx) { PoW_FPGA_Accel_Context *ctx = (PoW_FPGA_Accel_Context *) pow_ctx; - ctx->pow_info.time = 0; - ctx->pow_info.hash_count = 0; int8_t fpga_out_nonce_trit[NONCE_TRITS_LENGTH]; @@ -51,16 +49,18 @@ static bool PoWFPGAAccel(void *pow_ctx) char buf[4]; bool res = true; - uint32_t tick_cnt_l = 0; - uint32_t tick_cnt_h = 0; - uint64_t tick_cnt = 0; + uint32_t tick_cnt_l; + uint32_t tick_cnt_h; + uint64_t tick_cnt; - Trytes_t *object_tryte = NULL, *nonce_tryte = NULL; + Trytes_t *object_tryte, *nonce_tryte = NULL; Trits_t *object_trit = NULL, *object_nonce_trit = NULL; object_tryte = initTrytes(ctx->input_trytes, TRANSACTION_TRYTES_LENGTH); - if (!object_tryte) - return false; + if (!object_tryte) { + res = false; + goto fail; + } object_trit = trits_from_trytes(object_tryte); if (!object_trit) { @@ -162,7 +162,7 @@ static bool PoWFPGAAccel_Context_Initialize(ImplContext *impl_ctx) goto fail_to_mmap; } - ctx->cpow_map = (uint32_t *) (ctx->fpga_regs_map + CPOW_BASE); + ctx->cpow_map = (uint32_t *) (ctx->fpga_regs_map) + CPOW_BASE; impl_ctx->context = ctx; diff --git a/src/pow_kernel.cl b/src/pow_kernel.cl index 55295b1..88a81ed 100644 --- a/src/pow_kernel.cl +++ b/src/pow_kernel.cl @@ -103,8 +103,8 @@ void increment(__global bc_trit_t* mid_low, __global bc_trit_t* mid_high, __private size_t from_index, __private size_t to_index) { size_t i; bc_trit_t carry = 1; - bc_trit_t low, hi; for (i = from_index; i < to_index && carry != 0; i++) { + bc_trit_t low, hi; low = mid_low[i]; hi = mid_high[i]; mid_low[i] = hi ^ low; @@ -117,8 +117,9 @@ void copy_mid_to_state(__global bc_trit_t* mid_low, __global bc_trit_t* mid_high __global bc_trit_t* state_low, __global bc_trit_t* state_high, __private size_t id, __private size_t l_size, __private size_t n_trits) { - size_t i, j; + size_t i; for (i = 0; i < n_trits; i++) { + size_t j; j = id + i * l_size; state_low[j] = mid_low[j]; state_high[j] = mid_high[j]; diff --git a/src/pow_sse.c b/src/pow_sse.c index 8bb9567..aa0097d 100644 --- a/src/pow_sse.c +++ b/src/pow_sse.c @@ -118,13 +118,13 @@ static int64_t loop128(__m128i *lmid, int *stopPoW, uv_rwlock_t *lock) { - int n = 0; int64_t i = 0; __m128i lcpy[STATE_TRITS_LENGTH * 2], hcpy[STATE_TRITS_LENGTH * 2]; uv_rwlock_rdlock(lock); for (i = 0; !incr128(lmid, hmid) && !*stopPoW; i++) { uv_rwlock_rdunlock(lock); + int n; for (int j = 0; j < STATE_TRITS_LENGTH; j++) { lcpy[j] = lmid[j]; hcpy[j] = hmid[j]; @@ -378,16 +378,13 @@ static bool PoWSSE_Context_Initialize(ImplContext *impl_ctx) goto fail; for (int i = 0; i < impl_ctx->num_max_thread; i++) { - ctx[i].work_req = - (uv_work_t *) (work_req_chunk + i * sizeof(uv_work_t) * nproc); - ctx[i].pitem = - (Pwork_struct *) (pitem_chunk + i * sizeof(Pwork_struct) * nproc); - ctx[i].nonce_array = - (int8_t **) (nonce_ptr_chunk + i * sizeof(int8_t *) * nproc); + ctx[i].work_req = (uv_work_t *) (work_req_chunk) + i * nproc; + ctx[i].pitem = (Pwork_struct *) (pitem_chunk) + i * nproc; + ctx[i].nonce_array = (int8_t **) (nonce_ptr_chunk) + i * nproc; for (int j = 0; j < nproc; j++) - ctx[i].nonce_array[j] = - (int8_t *) (nonce_chunk + i * NONCE_TRITS_LENGTH * nproc + - j * NONCE_TRITS_LENGTH); + ctx[i].nonce_array[j] = (int8_t *) (nonce_chunk) + + i * NONCE_TRITS_LENGTH * nproc + + j * NONCE_TRITS_LENGTH; ctx[i].num_max_threads = nproc; impl_ctx->bitmap = impl_ctx->bitmap << 1 | 0x1; uv_loop_init(&ctx[i].loop); @@ -432,8 +429,7 @@ static void *PoWSSE_getPoWContext(ImplContext *impl_ctx, if (impl_ctx->bitmap & (0x1 << i)) { impl_ctx->bitmap &= ~(0x1 << i); uv_mutex_unlock(&impl_ctx->lock); - PoW_SSE_Context *ctx = - impl_ctx->context + sizeof(PoW_SSE_Context) * i; + PoW_SSE_Context *ctx = (PoW_SSE_Context *) impl_ctx->context + i; memcpy(ctx->input_trytes, trytes, TRANSACTION_TRYTES_LENGTH); ctx->mwm = mwm; ctx->indexOfContext = i; diff --git a/src/remote_common.c b/src/remote_common.c index 49c0fef..39853a9 100644 --- a/src/remote_common.c +++ b/src/remote_common.c @@ -284,6 +284,7 @@ bool publish_message(amqp_connection_state_t *conn, char *message) { amqp_basic_properties_t props; + memset(&props, 0, sizeof(amqp_basic_properties_t)); props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG | AMQP_BASIC_DELIVERY_MODE_FLAG; props.content_type = amqp_cstring_bytes("text/plain"); props.delivery_mode = AMQP_DELIVERY_PERSISTENT; @@ -305,6 +306,7 @@ bool publish_message_with_reply_to(amqp_connection_state_t *conn, char *message) { amqp_basic_properties_t props; + memset(&props, 0, sizeof(amqp_basic_properties_t)); props._flags = AMQP_BASIC_CONTENT_TYPE_FLAG | AMQP_BASIC_DELIVERY_MODE_FLAG | AMQP_BASIC_REPLY_TO_FLAG; props.content_type = amqp_cstring_bytes("text/plain"); diff --git a/src/remote_interface.c b/src/remote_interface.c index 09406f3..1c66cff 100644 --- a/src/remote_interface.c +++ b/src/remote_interface.c @@ -185,7 +185,7 @@ static void *Remote_getPoWContext(RemoteImplContext *remote_ctx, uv_mutex_unlock(&remote_ctx->lock); PoW_Remote_Context *ctx = - remote_ctx->context + sizeof(PoW_Remote_Context) * i; + (PoW_Remote_Context *) remote_ctx->context + i; memcpy(ctx->input_trytes, trytes, TRANSACTION_TRYTES_LENGTH); ctx->mwm = mwm; ctx->indexOfContext = i; diff --git a/src/remote_worker.c b/src/remote_worker.c index 653fef7..f33b324 100644 --- a/src/remote_worker.c +++ b/src/remote_worker.c @@ -71,7 +71,10 @@ int main(int argc, char *const *argv) /* Message body format: transacton | mwm */ memcpy(trytes, envelope.message.body.bytes, TRANSACTION_TRYTES_LENGTH); - memcpy(buf, envelope.message.body.bytes + TRANSACTION_TRYTES_LENGTH, 4); + memcpy( + buf, + (int8_t *) envelope.message.body.bytes + TRANSACTION_TRYTES_LENGTH, + 4); mwm = strtol(buf, NULL, 10); log_debug(0, MSG_PREFIX "Doing PoW with mwm = %d...\n", mwm); diff --git a/src/trinary.c b/src/trinary.c index 17187cc..ce58277 100644 --- a/src/trinary.c +++ b/src/trinary.c @@ -14,7 +14,7 @@ #include "constants.h" #include "curl.h" -static int8_t TrytesToTritsMappings[][3] = { +int8_t TrytesToTritsMappings[][3] = { {0, 0, 0}, {1, 0, 0}, {-1, 1, 0}, {0, 1, 0}, {1, 1, 0}, {-1, -1, 1}, {0, -1, 1}, {1, -1, 1}, {-1, 0, 1}, {0, 0, 1}, {1, 0, 1}, {-1, 1, 1}, {0, 1, 1}, {1, 1, 1}, {-1, -1, -1}, {0, -1, -1}, {1, -1, -1}, {-1, 0, -1}, @@ -61,7 +61,7 @@ static bool validateTrytes(Trobject_t *trytes) Trobject_t *initTrits(int8_t *src, int len) { - Trobject_t *trits = NULL; + Trobject_t *trits; trits = (Trobject_t *) malloc(sizeof(Trobject_t)); if (!trits) @@ -92,7 +92,7 @@ Trobject_t *initTrits(int8_t *src, int len) Trobject_t *initTrytes(int8_t *src, int len) { - Trobject_t *trytes = NULL; + Trobject_t *trytes; trytes = (Trobject_t *) malloc(sizeof(Trobject_t)); if (!trytes) { diff --git a/src/trinary_sse42.h b/src/trinary_sse42.h index e379d06..93bde64 100644 --- a/src/trinary_sse42.h +++ b/src/trinary_sse42.h @@ -42,6 +42,8 @@ #define REPEAT11(str) REPEAT10(str), str #define REPEAT(n, str) REPEAT##n(str) +extern int8_t TrytesToTritsMappings[][3]; + static inline bool validateTrits_sse42(Trobject_t *trits) { const int block_8bit = BLOCK_8BIT(__m128i); @@ -249,6 +251,7 @@ static inline Trobject_t *trytes_from_trits_sse42(Trobject_t *trits) /* Store the tryte result */ _mm_store_si128((__m128i *) (src + i * block_8bit), result); } + /* The rest of the trits */ for (int i = ((trits->len) / 3 / block_8bit) * block_8bit; i < trits->len / 3; i++) { int j = trits->data[i * 3] + trits->data[i * 3 + 1] * 3 + @@ -273,13 +276,6 @@ static inline Trobject_t *trits_from_trytes_sse42(Trobject_t *trytes) const int block_8bit = BLOCK_8BIT(__m128i); /* For setting the most significant bit of a byte */ const int8_t setMSB = 0x80; - static int8_t TrytesToTritsMappings[][3] = { - {0, 0, 0}, {1, 0, 0}, {-1, 1, 0}, {0, 1, 0}, {1, 1, 0}, - {-1, -1, 1}, {0, -1, 1}, {1, -1, 1}, {-1, 0, 1}, {0, 0, 1}, - {1, 0, 1}, {-1, 1, 1}, {0, 1, 1}, {1, 1, 1}, {-1, -1, -1}, - {0, -1, -1}, {1, -1, -1}, {-1, 0, -1}, {0, 0, -1}, {1, 0, -1}, - {-1, 1, -1}, {0, 1, -1}, {1, 1, -1}, {-1, -1, 0}, {0, -1, 0}, - {1, -1, 0}, {-1, 0, 0}}; /* The set and range for indicating the trits value (0, 1, -1) * of the corresponding trytes */ /* '9', 'C', 'F', 'I', 'L', 'O', 'R', 'U', 'X' */ @@ -425,10 +421,7 @@ static inline Trobject_t *trits_from_trytes_sse42(Trobject_t *trytes) _mm_or_si128(_mm_and_si128(maskHighTrit0, zero), _mm_or_si128(_mm_and_si128(maskHighTritP1, posOne), _mm_and_si128(maskHighTritN1, negOne))); - /* Initialize with 0 */ - __m128i dataFirst = _mm_set1_epi8(0); - __m128i dataMid = _mm_set1_epi8(0); - __m128i dataLast = _mm_set1_epi8(0); + __m128i dataFirst, dataMid, dataLast; dataFirst = _mm_or_si128( _mm_shuffle_epi8(lowTrit, shuffleFirst[0]), _mm_or_si128(_mm_shuffle_epi8(midTrit, shuffleFirst[1]), diff --git a/tests/test-pow.c b/tests/test-pow.c index 490d57f..50a7f17 100644 --- a/tests/test-pow.c +++ b/tests/test-pow.c @@ -7,9 +7,9 @@ */ /* Test program for pow_*.c */ +#include #include "common.h" #include "implcontext.h" -#include "math.h" #define POW_TOTAL 100 From 1ea5a3cf2079f4c0ac6e2a1b2748a654a68ac79a Mon Sep 17 00:00:00 2001 From: marktwtn Date: Wed, 16 Oct 2019 18:09:32 +0800 Subject: [PATCH 03/22] docs: Add CppCheck testing command in the document --- docs/build-n-test.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/docs/build-n-test.md b/docs/build-n-test.md index ce2e615..9dc1d1b 100644 --- a/docs/build-n-test.md +++ b/docs/build-n-test.md @@ -132,6 +132,11 @@ Success. [ Verified ] ``` +## Static Code Analysis +``` +$ make static-analysis +``` + ## Tweaks * Number of threads to find nonce in CPU * ```$ export DCURL_NUM_CPU=26``` From da7671e5e9482eb9fc3b109b9604ef59a2c0f41e Mon Sep 17 00:00:00 2001 From: marktwtn Date: Fri, 18 Oct 2019 14:48:03 +0800 Subject: [PATCH 04/22] CI: Integrate Infer and fix detected errors The detected and fixed errors are: - Memory leak - Null pointer dereference Close #173. --- jni/iri-pearldiver-exlib.c | 20 ++++++++++++++------ mk/static-analysis.mk | 38 ++++++++++++++++++++++++++++++++++++++ src/curl.c | 3 +++ src/pow_fpga_accel.c | 1 + src/remote_common.c | 4 +++- src/remote_interface.c | 4 +++- 6 files changed, 62 insertions(+), 8 deletions(-) diff --git a/jni/iri-pearldiver-exlib.c b/jni/iri-pearldiver-exlib.c index fe0bf3c..20ec977 100644 --- a/jni/iri-pearldiver-exlib.c +++ b/jni/iri-pearldiver-exlib.c @@ -27,13 +27,17 @@ Java_com_iota_iri_crypto_PearlDiver_exlibSearch(JNIEnv *env, jint mwm, jint threads) { + jboolean ret = JNI_TRUE; + /*********** Get the Byte array from Java byte Array *************/ jbyte *c_trits = (*env)->GetByteArrayElements(env, trits, NULL); Trits_t *arg_trits = initTrits((int8_t *) c_trits, 8019); Trytes_t *arg_trytes = trytes_from_trits(arg_trits); - if (!arg_trytes) - return JNI_FALSE; + if (!arg_trytes) { + ret = JNI_FALSE; + goto fail_input; + } /****************************************************************/ int8_t *result = dcurl_entry(arg_trytes->data, mwm, threads); @@ -41,18 +45,22 @@ Java_com_iota_iri_crypto_PearlDiver_exlibSearch(JNIEnv *env, /************ Write result back Java byte array *****************/ Trytes_t *ret_trytes = initTrytes(result, 2673); Trits_t *ret_trits = trits_from_trytes(ret_trytes); - if (!ret_trits) - return JNI_FALSE; + if (!ret_trits) { + ret = JNI_FALSE; + goto fail_output; + } (*env)->SetByteArrayRegion(env, trits, 0, 8019, ret_trits->data); /****************************************************************/ +fail_output: free(result); + freeTrobject(ret_trits); freeTrobject(ret_trytes); +fail_input: freeTrobject(arg_trits); freeTrobject(arg_trytes); - freeTrobject(ret_trits); - return JNI_TRUE; + return ret; } JNIEXPORT void JNICALL diff --git a/mk/static-analysis.mk b/mk/static-analysis.mk index e672d1e..fe6abf5 100644 --- a/mk/static-analysis.mk +++ b/mk/static-analysis.mk @@ -1,4 +1,19 @@ +# Copy from mk/java.mk for Infer static code analysis, +# since Infer needs the environment variable JAVA_HOME to be set +# If JAVA_HOME is not set, guess it according to system configurations +ifndef JAVA_HOME + JAVAC := $(shell which javac) + ifeq ($(UNAME_S),Darwin) + # macOS + JAVA_HOME := $(shell /usr/libexec/java_home) + else + # Linux + JAVA_HOME := $(shell readlink -f $(JAVAC) | sed "s:/bin/javac::") + endif +endif # JAVA_HOME + static-analysis: + # CppCheck cppcheck \ --enable=all \ --error-exitcode=1 \ @@ -11,3 +26,26 @@ static-analysis: --suppressions-list=cppcheck_suppress \ -UERANGE \ $(SRC) tests + # Infer + $(MAKE) distclean + $(MAKE) BUILD_JNI=1 # Workaround: For enabling Infer to check the build option BUILD_JNI=1 + $(MAKE) distclean + JAVA_HOME=$(JAVA_HOME) infer run \ + --fail-on-issue \ + --skip-analysis-in-path +deps/rabbitmq-c/librabbitmq/amqp* \ + --skip-analysis-in-path +deps/rabbitmq-c/tests/test* \ + -- \ + $(MAKE) \ + BUILD_AVX=1 \ + BUILD_GPU=1 \ + BUILD_FPGA_ACCEL=1 \ + BUILD_REMOTE=1 \ + BUILD_JNI=1 \ + BUILD_STAT=1 + $(MAKE) distclean + infer run --fail-on-issue -- $(MAKE) \ + BUILD_SSE=1 + $(MAKE) distclean + infer run --fail-on-issue -- $(MAKE) \ + BUILD_GENERIC=1 + $(MAKE) distclean diff --git a/src/curl.c b/src/curl.c index 434de3f..4e94a7a 100644 --- a/src/curl.c +++ b/src/curl.c @@ -41,6 +41,9 @@ void Absorb(Curl *c, Trytes_t *inn) Trits_t *in = trits_from_trytes(inn); int lenn = 0; + if (!in) + return; + for (int i = 0; i < in->len; i += lenn) { lenn = 243; if (in->len - i < 243) diff --git a/src/pow_fpga_accel.c b/src/pow_fpga_accel.c index b400b6e..b4c1a76 100644 --- a/src/pow_fpga_accel.c +++ b/src/pow_fpga_accel.c @@ -177,6 +177,7 @@ static bool PoWFPGAAccel_Context_Initialize(ImplContext *impl_ctx) fail_to_open_idata: close(ctx->ctrl_fd); fail_to_open_ctrl: + free(ctx); fail_to_malloc: return false; } diff --git a/src/remote_common.c b/src/remote_common.c index 39853a9..a24fd77 100644 --- a/src/remote_common.c +++ b/src/remote_common.c @@ -72,6 +72,8 @@ bool connect_broker(amqp_connection_state_t *conn, const char *hostName) /* Connect to the rabbitmq broker */ *conn = amqp_new_connection(); socket = amqp_tcp_socket_new(*conn); + if (!socket) + goto destroy_connection; if (amqp_socket_open(socket, host, 5672) != AMQP_STATUS_OK) { log_debug(0, "The rabbitmq broker of %s is closed\n", host); goto destroy_connection; @@ -131,7 +133,7 @@ bool declare_callback_queue(amqp_connection_state_t *conn, amqp_queue_declare_ok_t *r = amqp_queue_declare(*conn, channel, amqp_empty_bytes, 0, 0, 1, 0, table); - if (!die_on_amqp_error(amqp_get_rpc_reply(*conn), + if (!r || !die_on_amqp_error(amqp_get_rpc_reply(*conn), "Declaring the private queue with TTL = 10s")) return false; diff --git a/src/remote_interface.c b/src/remote_interface.c index 1c66cff..2959855 100644 --- a/src/remote_interface.c +++ b/src/remote_interface.c @@ -139,7 +139,7 @@ static bool Remote_doPoW(RemoteImplContext *remote_ctx, void *pow_ctx) static bool Remote_init(RemoteImplContext *remote_ctx) { if (remote_ctx->num_max_thread <= 0) - goto fail_to_init; + goto fail_to_max_thread; PoW_Remote_Context *ctx = (PoW_Remote_Context *) malloc( sizeof(PoW_Remote_Context) * remote_ctx->num_max_thread); @@ -160,6 +160,8 @@ static bool Remote_init(RemoteImplContext *remote_ctx) return true; fail_to_init: + free(ctx); +fail_to_max_thread: return false; } From 076d28016f03dd03cb365c8a0f509dd4b129aa2e Mon Sep 17 00:00:00 2001 From: marktwtn Date: Fri, 25 Oct 2019 11:16:54 +0800 Subject: [PATCH 05/22] refactor: Unify local and remote implementation The functions of local and remote interface should be unified to keep consistency. The modification includes function unification and adding the hardware to the candidate list if the initialization is success. --- src/dcurl.c | 36 +++++++++++++++++++++++++----------- src/implcontext.c | 6 ++++-- src/remote_interface.c | 10 ++++++++++ src/remote_interface.h | 5 +++++ 4 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/dcurl.c b/src/dcurl.c index fae5388..b12de6e 100644 --- a/src/dcurl.c +++ b/src/dcurl.c @@ -36,6 +36,7 @@ static bool isInitialized = false; static uv_sem_t notify; LIST_HEAD(IMPL_LIST); +LIST_HEAD(REMOTE_IMPL_LIST); #if defined(ENABLE_AVX) extern ImplContext PoWAVX_Context; @@ -79,7 +80,7 @@ bool dcurl_init() #endif #if defined(ENABLE_REMOTE) - ret &= initializeRemoteContext(&Remote_Context); + ret &= registerRemoteContext(&Remote_Context); uv_sem_init(¬ify_remote, 0); #endif @@ -93,7 +94,14 @@ void dcurl_destroy() struct list_head *p; #if defined(ENABLE_REMOTE) - destroyRemoteContext(&Remote_Context); + RemoteImplContext *remoteImpl = NULL; + struct list_head *pRemote; + + list_for_each (pRemote, &REMOTE_IMPL_LIST) { + remoteImpl = list_entry(pRemote, RemoteImplContext, list); + destroyRemoteContext(remoteImpl); + list_del(pRemote); + } #endif list_for_each (p, &IMPL_LIST) { @@ -116,30 +124,36 @@ int8_t *dcurl_entry(int8_t *trytes, int mwm, int threads) return NULL; #if defined(ENABLE_REMOTE) + RemoteImplContext *remoteImpl = NULL; + struct list_head *pRemote; + do { - if (enterRemoteContext(&Remote_Context)) { - pow_ctx = getRemoteContext(&Remote_Context, trytes, mwm); - goto remote_pow; + list_for_each (pRemote, &REMOTE_IMPL_LIST) { + remoteImpl = list_entry(pRemote, RemoteImplContext, list); + if (enterRemoteContext(remoteImpl)) { + pow_ctx = getRemoteContext(remoteImpl, trytes, mwm); + goto remote_pow; + } } uv_sem_wait(¬ify_remote); } while (1); remote_pow: - if (!doRemoteContext(&Remote_Context, pow_ctx)) { + if (!doRemoteContext(remoteImpl, pow_ctx)) { /* The remote interface can not work without activated RabbitMQ broker * and remote worker. If it is not working, the PoW would be calculated * by the local machine. And the remote interface resource should be * released. */ - freeRemoteContext(&Remote_Context, pow_ctx); - exitRemoteContext(&Remote_Context); + freeRemoteContext(remoteImpl, pow_ctx); + exitRemoteContext(remoteImpl); uv_sem_post(¬ify_remote); goto local_pow; } else { - res = getRemoteResult(&Remote_Context, pow_ctx); + res = getRemoteResult(remoteImpl, pow_ctx); } - freeRemoteContext(&Remote_Context, pow_ctx); - exitRemoteContext(&Remote_Context); + freeRemoteContext(remoteImpl, pow_ctx); + exitRemoteContext(remoteImpl); uv_sem_post(¬ify_remote); return res; diff --git a/src/implcontext.c b/src/implcontext.c index ac251a4..86f72e7 100644 --- a/src/implcontext.c +++ b/src/implcontext.c @@ -15,8 +15,10 @@ extern struct list_head IMPL_LIST; bool registerImplContext(ImplContext *impl_ctx) { - list_add(&impl_ctx->list, &IMPL_LIST); - return initializeImplContext(impl_ctx); + bool res = initializeImplContext(impl_ctx); + if (res) + list_add(&impl_ctx->list, &IMPL_LIST); + return res; } bool initializeImplContext(ImplContext *impl_ctx) diff --git a/src/remote_interface.c b/src/remote_interface.c index 2959855..51f29ce 100644 --- a/src/remote_interface.c +++ b/src/remote_interface.c @@ -10,6 +10,16 @@ #include #include "trinary.h" +extern struct list_head REMOTE_IMPL_LIST; + +bool registerRemoteContext(RemoteImplContext *remote_ctx) +{ + bool res = initializeRemoteContext(remote_ctx); + if (res) + list_add(&remote_ctx->list, &REMOTE_IMPL_LIST); + return res; +} + bool initializeRemoteContext(RemoteImplContext *remote_ctx) { bool res = remote_ctx->initialize(remote_ctx); diff --git a/src/remote_interface.h b/src/remote_interface.h index 07c5411..2a33d0d 100644 --- a/src/remote_interface.h +++ b/src/remote_interface.h @@ -13,6 +13,7 @@ #include #include "common.h" #include "constants.h" +#include "list.h" #include "remote_common.h" #include "uv.h" @@ -55,8 +56,12 @@ struct _remote_impl_context { int8_t *(*getPoWResult)(void *pow_ctx); PoW_Info (*getPoWInfo)(void *pow_ctx); bool (*freePoWContext)(RemoteImplContext *remote_ctx, void *pow_ctx); + + /* Linked list */ + struct list_head list; }; +bool registerRemoteContext(RemoteImplContext *remote_ctx); bool initializeRemoteContext(RemoteImplContext *remote_ctx); void destroyRemoteContext(RemoteImplContext *remote_ctx); bool enterRemoteContext(RemoteImplContext *remote_ctx); From 6681f54f901bad526a82cc55e91e77e9339f02a9 Mon Sep 17 00:00:00 2001 From: marktwtn Date: Fri, 25 Oct 2019 22:23:10 +0800 Subject: [PATCH 06/22] feat: Use other hardwares if remote interface fails to initialize If the remote interface is not initialized succesfully, the other hardwares would be used to calculate PoW. The checking mechanism is based on the record in the initiailzation phase. Close #186. --- src/dcurl.c | 106 +++++++++++++++++++++++++++-------------- src/implcontext.c | 2 +- src/implcontext.h | 4 +- src/remote_interface.c | 2 +- src/remote_interface.h | 4 +- 5 files changed, 76 insertions(+), 42 deletions(-) diff --git a/src/dcurl.c b/src/dcurl.c index b12de6e..40f2cb9 100644 --- a/src/dcurl.c +++ b/src/dcurl.c @@ -31,8 +31,20 @@ #include "pow_c.h" #endif +/* for checking whether the corresponding implementation is initialized */ +enum Capability { + CAP_NONE = 0U, + CAP_C = 1U, + CAP_SSE = 1U << 1, + CAP_AVX = 1U << 2, + CAP_GPU = 1U << 3, + CAP_FPGA = 1U << 4, + CAP_REMOTE = 1U << 5 +}; + /* check whether dcurl is initialized */ static bool isInitialized = false; +static uint8_t runtimeCaps = CAP_NONE; static uv_sem_t notify; LIST_HEAD(IMPL_LIST); @@ -61,26 +73,44 @@ static uv_sem_t notify_remote; bool dcurl_init() { - bool ret = true; + bool ret = false; #if defined(ENABLE_AVX) - ret &= registerImplContext(&PoWAVX_Context); + if (registerImplContext(&PoWAVX_Context)) { + runtimeCaps |= CAP_AVX; + ret |= true; + } #elif defined(ENABLE_SSE) - ret &= registerImplContext(&PoWSSE_Context); + if (registerImplContext(&PoWSSE_Context)) { + runtimeCaps |= CAP_SSE; + ret |= true; + } #elif defined(ENABLE_GENERIC) - ret &= registerImplContext(&PoWC_Context); + if (registerImplContext(&PoWC_Context)) { + runtimeCaps |= CAP_C; + ret |= true; + } #endif #if defined(ENABLE_OPENCL) - ret &= registerImplContext(&PoWCL_Context); + if (registerImplContext(&PoWCL_Context)) { + runtimeCaps |= CAP_GPU; + ret |= true; + } #endif #if defined(ENABLE_FPGA_ACCEL) - ret &= registerImplContext(&PoWFPGAAccel_Context); + if (registerImplContext(&PoWFPGAAccel_Context)) { + runtimeCaps |= CAP_FPGA; + ret |= true; + } #endif #if defined(ENABLE_REMOTE) - ret &= registerRemoteContext(&Remote_Context); + if (registerRemoteContext(&Remote_Context)) { + runtimeCaps |= CAP_REMOTE; + ret |= true; + } uv_sem_init(¬ify_remote, 0); #endif @@ -98,17 +128,19 @@ void dcurl_destroy() struct list_head *pRemote; list_for_each (pRemote, &REMOTE_IMPL_LIST) { - remoteImpl = list_entry(pRemote, RemoteImplContext, list); + remoteImpl = list_entry(pRemote, RemoteImplContext, node); destroyRemoteContext(remoteImpl); list_del(pRemote); } #endif list_for_each (p, &IMPL_LIST) { - impl = list_entry(p, ImplContext, list); + impl = list_entry(p, ImplContext, node); destroyImplContext(impl); list_del(p); } + + runtimeCaps = CAP_NONE; } @@ -124,44 +156,46 @@ int8_t *dcurl_entry(int8_t *trytes, int mwm, int threads) return NULL; #if defined(ENABLE_REMOTE) - RemoteImplContext *remoteImpl = NULL; - struct list_head *pRemote; - - do { - list_for_each (pRemote, &REMOTE_IMPL_LIST) { - remoteImpl = list_entry(pRemote, RemoteImplContext, list); - if (enterRemoteContext(remoteImpl)) { - pow_ctx = getRemoteContext(remoteImpl, trytes, mwm); - goto remote_pow; + if (runtimeCaps & CAP_REMOTE) { + RemoteImplContext *remoteImpl = NULL; + struct list_head *pRemote; + + do { + list_for_each (pRemote, &REMOTE_IMPL_LIST) { + remoteImpl = list_entry(pRemote, RemoteImplContext, node); + if (enterRemoteContext(remoteImpl)) { + pow_ctx = getRemoteContext(remoteImpl, trytes, mwm); + goto remote_pow; + } } + uv_sem_wait(¬ify_remote); + } while (1); + + remote_pow: + if (!doRemoteContext(remoteImpl, pow_ctx)) { + /* The remote interface can not work without activated RabbitMQ + * broker and remote worker. If it is not working, the PoW would be + * calculated by the local machine. And the remote interface + * resource should be released. + */ + freeRemoteContext(remoteImpl, pow_ctx); + exitRemoteContext(remoteImpl); + uv_sem_post(¬ify_remote); + goto local_pow; + } else { + res = getRemoteResult(remoteImpl, pow_ctx); } - uv_sem_wait(¬ify_remote); - } while (1); - -remote_pow: - if (!doRemoteContext(remoteImpl, pow_ctx)) { - /* The remote interface can not work without activated RabbitMQ broker - * and remote worker. If it is not working, the PoW would be calculated - * by the local machine. And the remote interface resource should be - * released. - */ freeRemoteContext(remoteImpl, pow_ctx); exitRemoteContext(remoteImpl); uv_sem_post(¬ify_remote); - goto local_pow; - } else { - res = getRemoteResult(remoteImpl, pow_ctx); + return res; } - freeRemoteContext(remoteImpl, pow_ctx); - exitRemoteContext(remoteImpl); - uv_sem_post(¬ify_remote); - return res; local_pow: #endif do { list_for_each (p, &IMPL_LIST) { - impl = list_entry(p, ImplContext, list); + impl = list_entry(p, ImplContext, node); if (enterImplContext(impl)) { pow_ctx = getPoWContext(impl, trytes, mwm, threads); goto do_pow; diff --git a/src/implcontext.c b/src/implcontext.c index 86f72e7..4d4b38f 100644 --- a/src/implcontext.c +++ b/src/implcontext.c @@ -17,7 +17,7 @@ bool registerImplContext(ImplContext *impl_ctx) { bool res = initializeImplContext(impl_ctx); if (res) - list_add(&impl_ctx->list, &IMPL_LIST); + list_add(&impl_ctx->node, &IMPL_LIST); return res; } diff --git a/src/implcontext.h b/src/implcontext.h index 65495e7..68bd8bd 100644 --- a/src/implcontext.h +++ b/src/implcontext.h @@ -40,8 +40,8 @@ struct _impl_context { PoW_Info (*getPoWInfo)(void *pow_ctx); bool (*freePoWContext)(ImplContext *impl_ctx, void *pow_ctx); - /* Linked list */ - struct list_head list; + /* Node in linked list */ + struct list_head node; }; bool registerImplContext(ImplContext *impl_ctx); diff --git a/src/remote_interface.c b/src/remote_interface.c index 51f29ce..48fcc02 100644 --- a/src/remote_interface.c +++ b/src/remote_interface.c @@ -16,7 +16,7 @@ bool registerRemoteContext(RemoteImplContext *remote_ctx) { bool res = initializeRemoteContext(remote_ctx); if (res) - list_add(&remote_ctx->list, &REMOTE_IMPL_LIST); + list_add(&remote_ctx->node, &REMOTE_IMPL_LIST); return res; } diff --git a/src/remote_interface.h b/src/remote_interface.h index 2a33d0d..835df1d 100644 --- a/src/remote_interface.h +++ b/src/remote_interface.h @@ -57,8 +57,8 @@ struct _remote_impl_context { PoW_Info (*getPoWInfo)(void *pow_ctx); bool (*freePoWContext)(RemoteImplContext *remote_ctx, void *pow_ctx); - /* Linked list */ - struct list_head list; + /* Node in linked list */ + struct list_head node; }; bool registerRemoteContext(RemoteImplContext *remote_ctx); From 69ea894872aa1d16b5c2506b3e3522774cac4cb7 Mon Sep 17 00:00:00 2001 From: marktwtn Date: Tue, 29 Oct 2019 20:19:25 +0800 Subject: [PATCH 07/22] docs: Change the description of dcurl APIs --- src/dcurl.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/dcurl.h b/src/dcurl.h index f5b67e5..8e8126a 100644 --- a/src/dcurl.h +++ b/src/dcurl.h @@ -29,8 +29,8 @@ * Register the determined hardware into the list and initialize the * corresponding resource. * @return - * - true: initialization succeeded. - * - false: initialization failed. + * - true: one of the initialization succeeded. + * - false: all the initialization failed. */ bool dcurl_init(); @@ -53,7 +53,7 @@ void dcurl_destroy(); * @parblock * The thread number of calculating the PoW. It affects CPU only. * - * 0: use (maximum threads - 1). + * 0: use (maximum physical CPU - 1). * @endparblock * @return The result of PoW. */ From 2646d3836150618a4532173d574129567f7a9bd3 Mon Sep 17 00:00:00 2001 From: marktwtn Date: Sat, 2 Nov 2019 21:17:52 +0800 Subject: [PATCH 08/22] docs: Add fallback description of remote interface --- docs/remote-interface.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/docs/remote-interface.md b/docs/remote-interface.md index 557385d..d8c5dc0 100644 --- a/docs/remote-interface.md +++ b/docs/remote-interface.md @@ -77,3 +77,17 @@ $ make BUILD_REMOTE=1 BUILD_DEBUG=1 check ## Requirements Remote interface requires RabbitMQ broker + +## Fallback mechanism +If the remote interface is not working for some reason, the PoW calculation will be transferred to the local hardwares. +The possible situations are: + +* Initialization failure: +The remote interface is not initialized successfully because the RabbitMQ broker it not activated. +dcurl would record the initialization status of the remote interface. +If it does not succeed, dcurl would use local hardwares to do the PoW. + +* Runtime failure: +The remote interface is initialized successfully but the remote workers do not exist or the RabbitMQ broker is closed after initialization. +dcurl would wait 10 seconds for the responding. +If nothing returns, dcurl would use local hardwares to do the PoW. From e4138cc9cb7c4ba8a46c3b5845095273b9c95553 Mon Sep 17 00:00:00 2001 From: marktwtn Date: Mon, 4 Nov 2019 22:31:12 +0800 Subject: [PATCH 09/22] CI: Build with arm64 CPU on Travis CI --- .travis.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 4b2d057..e0d410e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,5 +1,9 @@ language: c +arch: + - amd64 + - arm64 + os: - linux - osx From abcbead95921d06899417efcfc3e7943f02fef17 Mon Sep 17 00:00:00 2001 From: marktwtn Date: Tue, 3 Dec 2019 10:39:53 +0800 Subject: [PATCH 10/22] refactor: Rename files and FPGA related variables The source code files are renamed to the same format. The word 'accel' is removed from the files and variables naming. --- AUTHORS | 2 +- Makefile | 8 +-- cppcheck_suppress | 6 +-- ...rldiver-exlib.c => iri_pearldiver_exlib.c} | 2 +- mk/java.mk | 4 +- src/{compat-ccurl.c => compat_ccurl.c} | 0 src/dcurl.c | 6 +-- src/{pow_fpga_accel.c => pow_fpga.c} | 52 +++++++++---------- src/{pow_fpga_accel.h => pow_fpga.h} | 10 ++-- tests/common.h | 2 +- tests/test-pow.c | 4 +- 11 files changed, 48 insertions(+), 48 deletions(-) rename jni/{iri-pearldiver-exlib.c => iri_pearldiver_exlib.c} (98%) rename src/{compat-ccurl.c => compat_ccurl.c} (100%) rename src/{pow_fpga_accel.c => pow_fpga.c} (79%) rename src/{pow_fpga_accel.h => pow_fpga.h} (80%) diff --git a/AUTHORS b/AUTHORS index 11ba950..0b3020b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -7,7 +7,7 @@ dcurl is written by: Externel Source: * src/pow_sse.c is derived from preliminary work of Shinya Yagyu. * src/pow_cl.c and src/pow_kernel.cl are adopted from ccurl [1]. -* src/pow_fpga_accel.c is derived from accelerator by LampaLab [2]. +* src/pow_fpga.c is derived from accelerator by LampaLab [2]. * src/list.h is adopted from National Cheng Kung University, Taiwan. [1] https://github.com/iotaledger/ccurl diff --git a/Makefile b/Makefile index 45c0474..f1daacd 100644 --- a/Makefile +++ b/Makefile @@ -140,17 +140,17 @@ endif ifeq ("$(BUILD_JNI)","1") OBJS += \ - jni/iri-pearldiver-exlib.o + jni/iri_pearldiver_exlib.o endif ifeq ("$(BUILD_COMPAT)", "1") OBJS += \ - compat-ccurl.o + compat_ccurl.o endif ifeq ("$(BUILD_FPGA_ACCEL)","1") OBJS += \ - pow_fpga_accel.o + pow_fpga.o endif ifeq ("$(BUILD_REMOTE)", "1") @@ -160,7 +160,7 @@ OBJS += \ WORKER_EXCLUDE_OBJS := remote_interface.o ifeq ("$(BUILD_JNI)", "1") -WORKER_EXCLUDE_OBJS += jni/iri-pearldiver-exlib.o +WORKER_EXCLUDE_OBJS += jni/iri_pearldiver_exlib.o endif WORKER_OBJS := $(addprefix $(OUT)/worker-,$(filter-out $(WORKER_EXCLUDE_OBJS), $(OBJS))) WORKER_CFLAGS := $(filter-out -DENABLE_REMOTE, $(CFLAGS)) diff --git a/cppcheck_suppress b/cppcheck_suppress index d8a9887..0e1c729 100644 --- a/cppcheck_suppress +++ b/cppcheck_suppress @@ -2,9 +2,9 @@ shiftTooManyBitsSigned:src/pow_avx.c:321 // The unused functions are for the ccurl compatibility -unusedFunction:src/compat-ccurl.c:18 -unusedFunction:src/compat-ccurl.c:29 -unusedFunction:src/compat-ccurl.c:34 +unusedFunction:src/compat_ccurl.c:18 +unusedFunction:src/compat_ccurl.c:29 +unusedFunction:src/compat_ccurl.c:34 // The invoked functions of OpenCL are not checked correctly with CppCheck unusedFunction:src/pow_kernel.cl:185 diff --git a/jni/iri-pearldiver-exlib.c b/jni/iri_pearldiver_exlib.c similarity index 98% rename from jni/iri-pearldiver-exlib.c rename to jni/iri_pearldiver_exlib.c index 20ec977..11cf47f 100644 --- a/jni/iri-pearldiver-exlib.c +++ b/jni/iri_pearldiver_exlib.c @@ -6,7 +6,7 @@ * "LICENSE" at the root of this distribution. */ -#include "iri-pearldiver-exlib.h" +#include "iri_pearldiver_exlib.h" #include #include #include "../src/dcurl.h" diff --git a/mk/java.mk b/mk/java.mk index b8c6812..d77122e 100644 --- a/mk/java.mk +++ b/mk/java.mk @@ -41,7 +41,7 @@ $(OUT)/com/iota/iri/crypto/PearlDiver.java: $(OUT)/com/iota/iri/crypto $(Q)$(CURL) -s -o $@ \ "https://github.com/raw/$(GITHUB_REPO)/$(PearlDriverSRC)" -$(OUT)/jni/iri-pearldiver-exlib.h: $(OUT)/com/iota/iri/crypto/PearlDiver.java +$(OUT)/jni/iri_pearldiver_exlib.h: $(OUT)/com/iota/iri/crypto/PearlDiver.java $(VECHO) " JAVAH\t$@\n" $(Q)$(JAVAH) -classpath $(OUT) -o $@ com.iota.iri.crypto.PearlDiver @@ -56,7 +56,7 @@ endif CFLAGS_JNI += -I$(JAVA_HOME)/include CFLAGS_JNI += -I$(OUT)/jni -jni/iri-pearldiver-exlib.c: $(OUT)/jni/iri-pearldiver-exlib.h +jni/iri_pearldiver_exlib.c: $(OUT)/jni/iri_pearldiver_exlib.h $(OUT)/jni/%.o: jni/%.c $(VECHO) " CC\t$@\n" diff --git a/src/compat-ccurl.c b/src/compat_ccurl.c similarity index 100% rename from src/compat-ccurl.c rename to src/compat_ccurl.c diff --git a/src/dcurl.c b/src/dcurl.c index 40f2cb9..f39f167 100644 --- a/src/dcurl.c +++ b/src/dcurl.c @@ -15,7 +15,7 @@ #include "pow_cl.h" #endif #if defined(ENABLE_FPGA_ACCEL) -#include "pow_fpga_accel.h" +#include "pow_fpga.h" #endif #if defined(ENABLE_REMOTE) #include "remote_interface.h" @@ -63,7 +63,7 @@ extern ImplContext PoWCL_Context; #endif #if defined(ENABLE_FPGA_ACCEL) -extern ImplContext PoWFPGAAccel_Context; +extern ImplContext PoWFPGA_Context; #endif #if defined(ENABLE_REMOTE) @@ -100,7 +100,7 @@ bool dcurl_init() #endif #if defined(ENABLE_FPGA_ACCEL) - if (registerImplContext(&PoWFPGAAccel_Context)) { + if (registerImplContext(&PoWFPGA_Context)) { runtimeCaps |= CAP_FPGA; ret |= true; } diff --git a/src/pow_fpga_accel.c b/src/pow_fpga.c similarity index 79% rename from src/pow_fpga_accel.c rename to src/pow_fpga.c index b4c1a76..56ca41f 100644 --- a/src/pow_fpga_accel.c +++ b/src/pow_fpga.c @@ -7,7 +7,7 @@ * "LICENSE" at the root of this distribution. */ -#include "pow_fpga_accel.h" +#include "pow_fpga.h" #include #include #include @@ -39,9 +39,9 @@ S[3] = (I >> 24) & 0xff; \ } -static bool PoWFPGAAccel(void *pow_ctx) +static bool PoWFPGA(void *pow_ctx) { - PoW_FPGA_Accel_Context *ctx = (PoW_FPGA_Accel_Context *) pow_ctx; + PoW_FPGA_Context *ctx = (PoW_FPGA_Context *) pow_ctx; int8_t fpga_out_nonce_trit[NONCE_TRITS_LENGTH]; @@ -125,10 +125,10 @@ static bool PoWFPGAAccel(void *pow_ctx) return res; } -static bool PoWFPGAAccel_Context_Initialize(ImplContext *impl_ctx) +static bool PoWFPGA_Context_Initialize(ImplContext *impl_ctx) { - PoW_FPGA_Accel_Context *ctx = - (PoW_FPGA_Accel_Context *) malloc(sizeof(PoW_FPGA_Accel_Context)); + PoW_FPGA_Context *ctx = + (PoW_FPGA_Context *) malloc(sizeof(PoW_FPGA_Context)); if (!ctx) goto fail_to_malloc; @@ -182,9 +182,9 @@ static bool PoWFPGAAccel_Context_Initialize(ImplContext *impl_ctx) return false; } -static void PoWFPGAAccel_Context_Destroy(ImplContext *impl_ctx) +static void PoWFPGA_Context_Destroy(ImplContext *impl_ctx) { - PoW_FPGA_Accel_Context *ctx = (PoW_FPGA_Accel_Context *) impl_ctx->context; + PoW_FPGA_Context *ctx = (PoW_FPGA_Context *) impl_ctx->context; close(ctx->in_fd); close(ctx->out_fd); @@ -199,12 +199,12 @@ static void PoWFPGAAccel_Context_Destroy(ImplContext *impl_ctx) free(ctx); } -static void *PoWFPGAAccel_getPoWContext(ImplContext *impl_ctx, - int8_t *trytes, - int mwm, - int threads) +static void *PoWFPGA_getPoWContext(ImplContext *impl_ctx, + int8_t *trytes, + int mwm, + int threads) { - PoW_FPGA_Accel_Context *ctx = impl_ctx->context; + PoW_FPGA_Context *ctx = impl_ctx->context; memcpy(ctx->input_trytes, trytes, TRANSACTION_TRYTES_LENGTH); ctx->mwm = mwm; ctx->indexOfContext = 0; @@ -212,37 +212,37 @@ static void *PoWFPGAAccel_getPoWContext(ImplContext *impl_ctx, return ctx; } -static bool PoWFPGAAccel_freePoWContext(ImplContext *impl_ctx, void *pow_ctx) +static bool PoWFPGA_freePoWContext(ImplContext *impl_ctx, void *pow_ctx) { return true; } -static int8_t *PoWFPGAAccel_getPoWResult(void *pow_ctx) +static int8_t *PoWFPGA_getPoWResult(void *pow_ctx) { int8_t *ret = (int8_t *) malloc(sizeof(int8_t) * TRANSACTION_TRYTES_LENGTH); if (!ret) return NULL; - memcpy(ret, ((PoW_FPGA_Accel_Context *) pow_ctx)->output_trytes, + memcpy(ret, ((PoW_FPGA_Context *) pow_ctx)->output_trytes, TRANSACTION_TRYTES_LENGTH); return ret; } -static PoW_Info PoWFPGAAccel_getPoWInfo(void *pow_ctx) +static PoW_Info PoWFPGA_getPoWInfo(void *pow_ctx) { - return ((PoW_FPGA_Accel_Context *) pow_ctx)->pow_info; + return ((PoW_FPGA_Context *) pow_ctx)->pow_info; } -ImplContext PoWFPGAAccel_Context = { +ImplContext PoWFPGA_Context = { .context = NULL, .description = "FPGA", .bitmap = 0, .num_max_thread = 1, // num_max_thread >= 1 .num_working_thread = 0, - .initialize = PoWFPGAAccel_Context_Initialize, - .destroy = PoWFPGAAccel_Context_Destroy, - .getPoWContext = PoWFPGAAccel_getPoWContext, - .freePoWContext = PoWFPGAAccel_freePoWContext, - .doThePoW = PoWFPGAAccel, - .getPoWResult = PoWFPGAAccel_getPoWResult, - .getPoWInfo = PoWFPGAAccel_getPoWInfo, + .initialize = PoWFPGA_Context_Initialize, + .destroy = PoWFPGA_Context_Destroy, + .getPoWContext = PoWFPGA_getPoWContext, + .freePoWContext = PoWFPGA_freePoWContext, + .doThePoW = PoWFPGA, + .getPoWResult = PoWFPGA_getPoWResult, + .getPoWInfo = PoWFPGA_getPoWInfo, }; diff --git a/src/pow_fpga_accel.h b/src/pow_fpga.h similarity index 80% rename from src/pow_fpga_accel.h rename to src/pow_fpga.h index 119018c..48bda32 100644 --- a/src/pow_fpga_accel.h +++ b/src/pow_fpga.h @@ -6,16 +6,16 @@ * "LICENSE" at the root of this distribution. */ -#ifndef POW_FPGA_ACCEL_H_ -#define POW_FPGA_ACCEL_H_ +#ifndef POW_FPGA_H_ +#define POW_FPGA_H_ #include #include "common.h" #include "constants.h" -typedef struct _pow_fpga_accel_context PoW_FPGA_Accel_Context; +typedef struct _pow_fpga_context PoW_FPGA_Context; -struct _pow_fpga_accel_context { +struct _pow_fpga_context { /* Management of Multi-thread */ int indexOfContext; /* Arguments of PoW */ @@ -24,7 +24,7 @@ struct _pow_fpga_accel_context { int mwm; /* PoW-related information */ PoW_Info pow_info; - /* Device files for the PFGA accelerator*/ + /* Device files for the FPGA accelerator*/ int ctrl_fd; int in_fd; int out_fd; diff --git a/tests/common.h b/tests/common.h index 62f3ad0..b6a12a6 100644 --- a/tests/common.h +++ b/tests/common.h @@ -25,7 +25,7 @@ #include "pow_cl.h" #endif #if defined(ENABLE_FPGA_ACCEL) -#include "pow_fpga_accel.h" +#include "pow_fpga.h" #endif #include diff --git a/tests/test-pow.c b/tests/test-pow.c index 50a7f17..007fb12 100644 --- a/tests/test-pow.c +++ b/tests/test-pow.c @@ -26,7 +26,7 @@ extern ImplContext PoWCL_Context; #endif #if defined(ENABLE_FPGA_ACCEL) -extern ImplContext PoWFPGAAccel_Context; +extern ImplContext PoWFPGA_Context; #endif const char *description[] = { @@ -131,7 +131,7 @@ int main() #endif #if defined(ENABLE_FPGA_ACCEL) - PoWFPGAAccel_Context, + PoWFPGA_Context, #endif }; #if defined(ENABLE_STAT) From 9d1a6d2d514737ab2da7e17fbbb562ed0f21b58b Mon Sep 17 00:00:00 2001 From: marktwtn Date: Fri, 6 Dec 2019 12:36:46 +0800 Subject: [PATCH 11/22] fix: Avoid queue missing error Declare queue in the remote worker source code to avoid queue missing error when the new RabbitMQ broker is created and the remote worker is activated right after it. Close #209. --- src/remote_worker.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/remote_worker.c b/src/remote_worker.c index f33b324..d75627a 100644 --- a/src/remote_worker.c +++ b/src/remote_worker.c @@ -47,6 +47,9 @@ int main(int argc, char *const *argv) if (!connect_broker(&conn, hostIP)) goto fail; + if (!declare_queue(&conn, 1, "incoming_queue")) + goto fail; + if (!set_consuming_queue(&conn, 1, "incoming_queue")) goto fail; From beddc3988bf8bb91717c323cbefbc53b1b6cd7d8 Mon Sep 17 00:00:00 2001 From: marktwtn Date: Fri, 3 Jan 2020 08:52:20 +0800 Subject: [PATCH 12/22] style: Unify the naming convention with snake case Besides the source code unification, the related document is added for the naming convention details. Close #207. --- Makefile | 2 +- README.md | 3 + docs/naming-convention.md | 27 +++ jni/iri_pearldiver_exlib.c | 16 +- src/clcontext.c | 36 +-- src/clcontext.h | 16 +- src/common.h | 4 +- src/compat_ccurl.c | 6 +- src/constants.c | 2 +- src/constants.h | 112 ++++----- src/curl.c | 34 +-- src/curl.h | 16 +- src/dcurl.c | 122 +++++----- src/implcontext.c | 36 +-- src/implcontext.h | 38 +-- src/list.h | 12 +- src/pow_avx.c | 188 +++++++-------- src/pow_avx.h | 18 +- src/pow_c.c | 132 +++++------ src/pow_c.h | 18 +- src/pow_cl.c | 124 +++++----- src/pow_cl.h | 10 +- src/pow_fpga.c | 82 +++---- src/pow_fpga.h | 10 +- src/pow_kernel.cl | 10 +- src/pow_sse.c | 154 ++++++------- src/pow_sse.h | 18 +- src/remote_common.c | 4 +- src/remote_interface.c | 108 ++++----- src/remote_interface.h | 44 ++-- src/remote_worker.c | 20 +- src/trinary.c | 64 ++--- src/trinary.h | 22 +- src/trinary_sse42.h | 462 ++++++++++++++++++------------------- tests/common.h | 2 +- tests/test-curl.c | 16 +- tests/test-dcurl.c | 20 +- tests/test-multi-pow.c | 22 +- tests/test-pow.c | 88 +++---- tests/test-trinary.c | 16 +- 40 files changed, 1082 insertions(+), 1052 deletions(-) create mode 100644 docs/naming-convention.md diff --git a/Makefile b/Makefile index f1daacd..4f6e5aa 100644 --- a/Makefile +++ b/Makefile @@ -75,7 +75,7 @@ include mk/opencl.mk endif ifeq ("$(BUILD_FPGA_ACCEL)","1") -CFLAGS += -DENABLE_FPGA_ACCEL +CFLAGS += -DENABLE_FPGA endif ifeq ("$(BUILD_REMOTE)","1") diff --git a/README.md b/README.md index a444256..c850796 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,9 @@ IOTA Reference Implementation (IRI) adaptation is available to benefit from hard ## Build Instructions Check [docs/build-n-test.md](docs/build-n-test.md) for details. +## Source Code Naming Convention +Check [docs/naming-convention.md](docs/naming-convention.md) for details. + ## Performance After integrating dcurl into IRI, performance of [attachToTangle](https://iota.readme.io/reference#attachtotangle) is measured as following. * Each sampling is measured with 30 transaction trytes and total 200 samples are measured. diff --git a/docs/naming-convention.md b/docs/naming-convention.md new file mode 100644 index 0000000..b3e6b30 --- /dev/null +++ b/docs/naming-convention.md @@ -0,0 +1,27 @@ +# Naming Convention + +dcurl uses the **[snake case](https://en.wikipedia.org/wiki/Snake_case)** naming convention. + +- Variable and function + ``` + bool pow_c(void *pow_ctx) { + ...... + int completed_index = -1; + ...... + } + ``` + +- Structure: The suffixes **_s** represents for structure and **_t** represents for type + ``` + typedef struct pwrok_s pwork_t; + struct pwork_s { + ...... + } + ``` + +- Macro: Use capital letters + ``` + #define MIN_TRYTE_VALUE -13 + #define MAX_TRYTE_VALUE 13 + ``` + diff --git a/jni/iri_pearldiver_exlib.c b/jni/iri_pearldiver_exlib.c index 11cf47f..1e8cab8 100644 --- a/jni/iri_pearldiver_exlib.c +++ b/jni/iri_pearldiver_exlib.c @@ -32,8 +32,8 @@ Java_com_iota_iri_crypto_PearlDiver_exlibSearch(JNIEnv *env, /*********** Get the Byte array from Java byte Array *************/ jbyte *c_trits = (*env)->GetByteArrayElements(env, trits, NULL); - Trits_t *arg_trits = initTrits((int8_t *) c_trits, 8019); - Trytes_t *arg_trytes = trytes_from_trits(arg_trits); + trits_t *arg_trits = init_trits((int8_t *) c_trits, 8019); + trytes_t *arg_trytes = trytes_from_trits(arg_trits); if (!arg_trytes) { ret = JNI_FALSE; goto fail_input; @@ -43,8 +43,8 @@ Java_com_iota_iri_crypto_PearlDiver_exlibSearch(JNIEnv *env, int8_t *result = dcurl_entry(arg_trytes->data, mwm, threads); /************ Write result back Java byte array *****************/ - Trytes_t *ret_trytes = initTrytes(result, 2673); - Trits_t *ret_trits = trits_from_trytes(ret_trytes); + trytes_t *ret_trytes = init_trytes(result, 2673); + trits_t *ret_trits = trits_from_trytes(ret_trytes); if (!ret_trits) { ret = JNI_FALSE; goto fail_output; @@ -54,11 +54,11 @@ Java_com_iota_iri_crypto_PearlDiver_exlibSearch(JNIEnv *env, fail_output: free(result); - freeTrobject(ret_trits); - freeTrobject(ret_trytes); + free_trinary_object(ret_trits); + free_trinary_object(ret_trytes); fail_input: - freeTrobject(arg_trits); - freeTrobject(arg_trytes); + free_trinary_object(arg_trits); + free_trinary_object(arg_trytes); return ret; } diff --git a/src/clcontext.c b/src/clcontext.c index 398b7c5..b7fded7 100644 --- a/src/clcontext.c +++ b/src/clcontext.c @@ -13,7 +13,7 @@ #include "constants.h" #include "pearl.cl.h" -static bool init_cl_devices(CLContext *ctx) +static bool init_cl_devices(cl_context_t *ctx) { cl_int errno; @@ -40,14 +40,14 @@ static bool init_cl_devices(CLContext *ctx) ctx->num_work_group = 1; /* Create Command Queue */ - ctx->cmdq = clCreateCommandQueue(ctx->context, ctx->device, 0, &errno); + ctx->cmd_q = clCreateCommandQueue(ctx->context, ctx->device, 0, &errno); if (errno != CL_SUCCESS) return false; /* Failed to create command queue */ return true; } -static bool init_cl_program(CLContext *ctx) +static bool init_cl_program(cl_context_t *ctx) { unsigned char *source_str = pearl_cl; size_t source_size = pearl_cl_len; @@ -67,7 +67,7 @@ static bool init_cl_program(CLContext *ctx) return true; } -static bool init_cl_kernel(CLContext *ctx) +static bool init_cl_kernel(cl_context_t *ctx) { char *kernel_name[] = {"init", "search", "finalize"}; cl_int errno; @@ -80,7 +80,7 @@ static bool init_cl_kernel(CLContext *ctx) return true; } -static bool init_cl_buffer(CLContext *ctx) +static bool init_cl_buffer(cl_context_t *ctx) { cl_ulong mem, max_mem = 0; cl_int errno; @@ -118,31 +118,31 @@ static bool init_cl_buffer(CLContext *ctx) return true; } -static bool init_BufferInfo(CLContext *ctx) +static bool init_buffer_info(cl_context_t *ctx) { ctx->kernel_info.buffer_info[INDEX_OF_TRIT_HASH] = - (BufferInfo){sizeof(char) * HASH_TRITS_LENGTH, CL_MEM_WRITE_ONLY}; - ctx->kernel_info.buffer_info[INDEX_OF_MID_LOW] = (BufferInfo){ + (buffer_info_t){sizeof(char) * HASH_TRITS_LENGTH, CL_MEM_WRITE_ONLY}; + ctx->kernel_info.buffer_info[INDEX_OF_MID_LOW] = (buffer_info_t){ sizeof(int64_t) * STATE_TRITS_LENGTH, CL_MEM_READ_WRITE, 2}; - ctx->kernel_info.buffer_info[INDEX_OF_MID_HIGH] = (BufferInfo){ + ctx->kernel_info.buffer_info[INDEX_OF_MID_HIGH] = (buffer_info_t){ sizeof(int64_t) * STATE_TRITS_LENGTH, CL_MEM_READ_WRITE, 2}; - ctx->kernel_info.buffer_info[INDEX_OF_STATE_LOW] = (BufferInfo){ + ctx->kernel_info.buffer_info[INDEX_OF_STATE_LOW] = (buffer_info_t){ sizeof(int64_t) * STATE_TRITS_LENGTH, CL_MEM_READ_WRITE, 2}; - ctx->kernel_info.buffer_info[INDEX_OF_STATE_HIGH] = (BufferInfo){ + ctx->kernel_info.buffer_info[INDEX_OF_STATE_HIGH] = (buffer_info_t){ sizeof(int64_t) * STATE_TRITS_LENGTH, CL_MEM_READ_WRITE, 2}; ctx->kernel_info.buffer_info[INDEX_OF_MWM] = - (BufferInfo){sizeof(size_t), CL_MEM_READ_ONLY}; + (buffer_info_t){sizeof(size_t), CL_MEM_READ_ONLY}; ctx->kernel_info.buffer_info[INDEX_OF_FOUND] = - (BufferInfo){sizeof(char), CL_MEM_READ_WRITE}; + (buffer_info_t){sizeof(char), CL_MEM_READ_WRITE}; ctx->kernel_info.buffer_info[INDEX_OF_NONCE_PROBE] = - (BufferInfo){sizeof(int64_t), CL_MEM_READ_WRITE, 2}; + (buffer_info_t){sizeof(int64_t), CL_MEM_READ_WRITE, 2}; ctx->kernel_info.buffer_info[INDEX_OF_LOOP_COUNT] = - (BufferInfo){sizeof(size_t), CL_MEM_READ_ONLY}; + (buffer_info_t){sizeof(size_t), CL_MEM_READ_ONLY}; return init_cl_buffer(ctx); } -static bool set_clcontext(CLContext *ctx, cl_device_id device) +static bool set_clcontext(cl_context_t *ctx, cl_device_id device) { ctx->device = device; ctx->kernel_info.num_buffers = 9; @@ -152,7 +152,7 @@ static bool set_clcontext(CLContext *ctx, cl_device_id device) return init_cl_devices(ctx) && init_cl_program(ctx); } -int init_clcontext(CLContext *ctx) +int init_clcontext(cl_context_t *ctx) { int ctx_idx = 0; @@ -181,7 +181,7 @@ int init_clcontext(CLContext *ctx) int ret = 1; ret &= set_clcontext(&ctx[ctx_idx], devices[j]); ret &= init_cl_kernel(&ctx[ctx_idx]); - ret &= init_BufferInfo(&ctx[ctx_idx]); + ret &= init_buffer_info(&ctx[ctx_idx]); if (!ret) { free(devices); goto leave; diff --git a/src/clcontext.h b/src/clcontext.h index 434bf7c..770a9da 100644 --- a/src/clcontext.h +++ b/src/clcontext.h @@ -23,19 +23,19 @@ typedef struct { size_t size; cl_mem_flags flags; size_t init_flags; -} BufferInfo; +} buffer_info_t; typedef struct { - BufferInfo buffer_info[MAX_NUM_BUFFERS]; + buffer_info_t buffer_info[MAX_NUM_BUFFERS]; size_t num_buffers; size_t num_kernels; size_t num_src; -} KernelInfo; +} kernel_info_t; -/* Every GPU device has own CLContext */ +/* Every GPU device has its own cl_context_t */ typedef struct { cl_device_id device; - cl_command_queue cmdq; + cl_command_queue cmd_q; cl_mem buffer[MAX_NUM_BUFFERS]; cl_kernel kernel[MAX_NUM_KERNEL]; cl_program program; @@ -43,9 +43,9 @@ typedef struct { cl_uint num_cores; cl_ulong max_memory; size_t num_work_group; - KernelInfo kernel_info; + kernel_info_t kernel_info; uint64_t hash_count; -} CLContext; +} cl_context_t; enum { INDEX_OF_TRIT_HASH, @@ -66,7 +66,7 @@ enum { }; /* return the number of available device */ -int init_clcontext(CLContext *ctx); +int init_clcontext(cl_context_t *ctx); #define KERNEL_PATH "./src/pow_kernel.cl" diff --git a/src/common.h b/src/common.h index d4e8ecf..c05979f 100644 --- a/src/common.h +++ b/src/common.h @@ -48,9 +48,9 @@ static inline void log_info(logger_id_t const logger_id, fflush(stdout); } -typedef struct _pow_info PoW_Info; +typedef struct pow_info_s pow_info_t; -struct _pow_info { +struct pow_info_s { double time; uint64_t hash_count; }; diff --git a/src/compat_ccurl.c b/src/compat_ccurl.c index 423de15..8816059 100644 --- a/src/compat_ccurl.c +++ b/src/compat_ccurl.c @@ -10,7 +10,7 @@ #include #include "dcurl.h" -static bool isInitialized = false; +static bool is_initialized = false; /* mutex protecting initialization section */ static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; @@ -18,9 +18,9 @@ static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; char *ccurl_pow(char *trytes, int mwm) { pthread_mutex_lock(&mtx); - if (!isInitialized) { + if (!is_initialized) { dcurl_init(); - isInitialized = true; + is_initialized = true; } pthread_mutex_unlock(&mtx); return (char *) dcurl_entry((int8_t *) trytes, mwm, 1); diff --git a/src/constants.c b/src/constants.c index 668e12b..93035c2 100644 --- a/src/constants.c +++ b/src/constants.c @@ -6,7 +6,7 @@ * "LICENSE" at the root of this distribution. */ -char TryteAlphabet[] = "9ABCDEFGHIJKLMNOPQRSTUVWXYZ"; +char tryte_alphabet[] = "9ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const int indices[] = { 0, 364, 728, 363, 727, 362, 726, 361, 725, 360, 724, 359, 723, 358, 722, diff --git a/src/constants.h b/src/constants.h index 751eb48..4b9112e 100644 --- a/src/constants.h +++ b/src/constants.h @@ -9,11 +9,11 @@ #ifndef CONSTANTS_H_ #define CONSTANTS_H_ -#define MinTryteValue -13 -#define MaxTryteValue 13 -#define SignatureSize 6561 -#define Depth 3 -#define Radix 3 +#define MIN_TRYTE_VALUE -13 +#define MAX_TRYTE_VALUE 13 +#define SIGNATURE_SIZE 6561 +#define DEPTH 3 +#define RADIX 3 #define HASH_TRYTES_LENGTH 81 #define NONCE_TRYTES_LENGTH 27 @@ -25,60 +25,60 @@ #define STATE_TRITS_LENGTH 3 * HASH_TRITS_LENGTH #define TRANSACTION_TRITS_LENGTH (TRANSACTION_TRYTES_LENGTH * 3) -#define SignatureMessageFragmentTrinaryOffset 0 -#define SignatureMessageFragmentTrinarySize 6561 -#define AddressTrinaryOffset \ - (SignatureMessageFragmentTrinaryOffset + \ - SignatureMessageFragmentTrinarySize) -#define AddressTrinarySize 243 -#define ValueTrinaryOffset (AddressTrinaryOffset + AddressTrinarySize) -#define ValueTrinarySize 81 -#define ObsoleteTagTrinaryOffset (ValueTrinaryOffset + ValueTrinarySize) -#define ObsoleteTagTrinarySize 81 -#define TimestampTrinaryOffset \ - (ObsoleteTagTrinaryOffset + ObsoleteTagTrinarySize) -#define TimestampTrinarySize 27 -#define CurrentIndexTrinaryOffset \ - (TimestampTrinaryOffset + TimestampTrinarySize) -#define CurrentIndexTrinarySize 27 -#define LastIndexTrinaryOffset \ - (CurrentIndexTrinaryOffset + CurrentIndexTrinarySize) -#define LastIndexTrinarySize 27 -#define BundleTrinaryOffset (LastIndexTrinaryOffset + LastIndexTrinarySize) -#define BundleTrinarySize 243 -#define TrunkTransactionTrinaryOffset (BundleTrinaryOffset + BundleTrinarySize) -#define TrunkTransactionTrinarySize 243 -#define BranchTransactionTrinaryOffset \ - (TrunkTransactionTrinaryOffset + TrunkTransactionTrinarySize) -#define BranchTransactionTrinarySize 243 -#define TagTrinaryOffset \ - (BranchTransactionTrinaryOffset + BranchTransactionTrinarySize) -#define TagTrinarySize 81 -#define AttachmentTimestampTrinaryOffset (TagTrinaryOffset + TagTrinarySize) -#define AttachmentTimestampTrinarySize 27 +#define SIGNATURE_MESSAGE_FRAGMENT_TRINARY_OFFSET 0 +#define SIGNATURE_MESSAGE_FRAGMENT_TRINARY_SIZE 6561 +#define ADDRESS_TRINARY_OFFSET \ + (SIGNATURE_MESSAGE_FRAGMENT_TRINARY_OFFSET + \ + SIGNATURE_MESSAGE_FRAGMENT_TRINARY_SIZE) +#define ADDRESS_TRINARY_SIZE 243 +#define VALUE_TRINARY_OFFSET (ADDRESS_TRINARY_OFFSET + ADDRESS_TRINARY_SIZE) +#define VALUE_TRINARY_SIZE 81 +#define OBSOLETE_TAG_TRINARY_OFFSET (VALUE_TRINARY_OFFSET + VALUE_TRINARY_SIZE) +#define OBSOLETE_TAG_TRINARY_SIZE 81 +#define TIMESTAMP_TRINARY_OFFSET \ + (OBSOLETE_TAG_TRINARY_OFFSET + OBSOLETE_TAG_TRINARY_SIZE) +#define TIMESTAMP_TRINARY_SIZE 27 +#define CURRENT_INDEX_TRINARY_OFFSET \ + (TIMESTAMP_TRINARY_OFFSET + TIMESTAMP_TRINARY_SIZE) +#define CURRENT_INDEX_TRINARY_SIZE 27 +#define LAST_INDEX_TRINARY_OFFSET \ + (CURRENT_INDEX_TRINARY_OFFSET + CURRENT_INDEX_TRINARY_SIZE) +#define LAST_INDEX_TRINARY_SIZE 27 +#define BUNDLE_TRINARY_OFFSET (LAST_INDEX_TRINARY_OFFSET + LAST_INDEX_TRINARY_SIZE) +#define BUNDLE_TRINARY_SIZE 243 +#define TRUNK_TRANSACTION_TRINARY_OFFSET (BUNDLE_TRINARY_OFFSET + BUNDLE_TRINARY_SIZE) +#define TRUNK_TRANSACTION_TRINARY_SIZE 243 +#define BRANCH_TRANSACTION_TRINARY_OFFSET \ + (TRUNK_TRANSACTION_TRINARY_OFFSET + TRUNK_TRANSACTION_TRINARY_SIZE) +#define BRANCH_TRANSACTION_TRINARY_SIZE 243 +#define TAG_TRINARY_OFFSET \ + (BRANCH_TRANSACTION_TRINARY_OFFSET + BRANCH_TRANSACTION_TRINARY_SIZE) +#define TAG_TRINARY_SIZE 81 +#define ATTACHMENT_TIMESTAMP_TRINARY_OFFSET (TAG_TRINARY_OFFSET + TAG_TRINARY_SIZE) +#define ATTACHMENT_TIMESTAMP_TRINARY_SIZE 27 -#define AttachmentTimestampLowerBoundTrinaryOffset \ - (AttachmentTimestampTrinaryOffset + AttachmentTimestampTrinarySize) -#define AttachmentTimestampLowerBoundTrinarySize 27 -#define AttachmentTimestampUpperBoundTrinaryOffset \ - (AttachmentTimestampLowerBoundTrinaryOffset + \ - AttachmentTimestampLowerBoundTrinarySize) -#define AttachmentTimestampUpperBoundTrinarySize 27 -#define NonceTrinaryOffset \ - (AttachmentTimestampUpperBoundTrinaryOffset + \ - AttachmentTimestampUpperBoundTrinarySize) -#define NonceTrinarySize 81 +#define ATTACHMENT_TIMESTAMP_LOWER_BOUND_TRINARY_OFFSET \ + (ATTACHMENT_TIMESTAMP_TRINARY_OFFSET + ATTACHMENT_TIMESTAMP_TRINARY_SIZE) +#define ATTACHMENT_TIMESTAMP_LOWER_BOUND_TRINARY_SIZE 27 +#define ATTACHMENT_TIMESTAMP_UPPER_BOUND_TRINARY_OFFSET \ + (ATTACHMENT_TIMESTAMP_LOWER_BOUND_TRINARY_OFFSET + \ + ATTACHMENT_TIMESTAMP_LOWER_BOUND_TRINARY_SIZE) +#define ATTACHMENT_TIMESTAMP_UPPER_BOUND_TRINARY_SIZE 27 +#define NONCE_TRINARY_OFFSET \ + (ATTACHMENT_TIMESTAMP_UPPER_BOUND_TRINARY_OFFSET + \ + ATTACHMENT_TIMESTAMP_UPPER_BOUND_TRINARY_SIZE) +#define NONCE_TRINARY_SIZE 81 -#define transactionTrinarySize \ - (SignatureMessageFragmentTrinarySize + AddressTrinarySize + \ - ValueTrinarySize + ObsoleteTagTrinarySize + TimestampTrinarySize + \ - CurrentIndexTrinarySize + LastIndexTrinarySize + BundleTrinarySize + \ - TrunkTransactionTrinarySize + BranchTransactionTrinarySize + \ - TagTrinarySize + AttachmentTimestampTrinarySize + \ - AttachmentTimestampLowerBoundTrinarySize + \ - AttachmentTimestampUpperBoundTrinarySize + NonceTrinarySize) +#define TRANSACTION_TRINARY_SIZE \ + (SIGNATURE_MESSAGE_FRAGMENT_TRINARY_SIZE + ADDRESS_TRINARY_SIZE + \ + VALUE_TRINARY_SIZE + OBSOLETE_TAG_TRINARY_SIZE + TIMESTAMP_TRINARY_SIZE + \ + CURRENT_INDEX_TRINARY_SIZE + LAST_INDEX_TRINARY_SIZE + BUNDLE_TRINARY_SIZE + \ + TRUNK_TRANSACTION_TRINARY_SIZE + BRANCH_TRANSACTION_TRINARY_SIZE + \ + TAG_TRINARY_SIZE + ATTACHMENT_TIMESTAMP_TRINARY_SIZE + \ + ATTACHMENT_TIMESTAMP_LOWER_BOUND_TRINARY_SIZE + \ + ATTACHMENT_TIMESTAMP_UPPER_BOUND_TRINARY_SIZE + NONCE_TRINARY_SIZE) -extern char TryteAlphabet[]; +extern char tryte_alphabet[]; extern const int indices[]; #endif diff --git a/src/curl.c b/src/curl.c index 4e94a7a..921f7d6 100644 --- a/src/curl.c +++ b/src/curl.c @@ -11,7 +11,7 @@ #include #include -static const int8_t truthTable[11] = {1, 0, -1, 2, 1, -1, 0, 2, -1, 1, 0}; +static const int8_t truth_table[11] = {1, 0, -1, 2, 1, -1, 0, 2, -1, 1, 0}; static void _transform(int8_t state[]) { @@ -22,7 +22,7 @@ static void _transform(int8_t state[]) for (i = 0; i < STATE_TRITS_LENGTH; i++) { int aa = indices[i]; int bb = indices[i + 1]; - to[i] = truthTable[from[aa] + (from[bb] * 4) + 5]; + to[i] = truth_table[from[aa] + (from[bb] * 4) + 5]; } int8_t *tmp = from; from = to; @@ -31,14 +31,14 @@ static void _transform(int8_t state[]) memcpy(state, copy, STATE_TRITS_LENGTH); } -void Transform(Curl *c) +void transform(curl_t *c) { _transform(c->state->data); } -void Absorb(Curl *c, Trytes_t *inn) +void absorb(curl_t *c, trytes_t *inn) { - Trits_t *in = trits_from_trytes(inn); + trits_t *in = trits_from_trytes(inn); int lenn = 0; if (!in) @@ -52,43 +52,43 @@ void Absorb(Curl *c, Trytes_t *inn) /* Copy in[i, i + lenn] to c->state->data[0, lenn] */ memcpy(c->state->data, in->data + i, lenn); - Transform(c); + transform(c); } - freeTrobject(in); + free_trinary_object(in); } -Trytes_t *Squeeze(Curl *c) +trytes_t *squeeze(curl_t *c) { int8_t src[HASH_TRITS_LENGTH] = {0}; /* Get trits[:HASH_TRITS_LENGTH] to an array */ memcpy(src, c->state->data, HASH_TRITS_LENGTH); - Trits_t *trits = initTrits(src, HASH_TRITS_LENGTH); - Trytes_t *trytes = trytes_from_trits(trits); + trits_t *trits = init_trits(src, HASH_TRITS_LENGTH); + trytes_t *trytes = trytes_from_trits(trits); - Transform(c); - freeTrobject(trits); + transform(c); + free_trinary_object(trits); return trytes; } -Curl *initCurl() +curl_t *init_curl() { - Curl *c = (Curl *) malloc(sizeof(Curl)); + curl_t *c = (curl_t *) malloc(sizeof(curl_t)); if (!c) return NULL; int8_t src[STATE_TRITS_LENGTH] = {0}; - c->state = initTrits(src, STATE_TRITS_LENGTH); + c->state = init_trits(src, STATE_TRITS_LENGTH); return c; } -void freeCurl(Curl *c) +void free_curl(curl_t *c) { if (c) { - freeTrobject(c->state); + free_trinary_object(c->state); free(c); } } diff --git a/src/curl.h b/src/curl.h index c431855..d9f1a21 100644 --- a/src/curl.h +++ b/src/curl.h @@ -12,15 +12,15 @@ #include "constants.h" #include "trinary.h" -typedef struct _curl { - Trits_t *state; -} Curl; +typedef struct curl_s { + trits_t *state; +} curl_t; -void Absorb(Curl *c, Trytes_t *inn); -void Transform(Curl *c); -Trytes_t *Squeeze(Curl *c); +void absorb(curl_t *c, trytes_t *inn); +void transform(curl_t *c); +trytes_t *squeeze(curl_t *c); -Curl *initCurl(); -void freeCurl(Curl *c); +curl_t *init_curl(); +void free_curl(curl_t *c); #endif diff --git a/src/dcurl.c b/src/dcurl.c index f39f167..790fa18 100644 --- a/src/dcurl.c +++ b/src/dcurl.c @@ -14,7 +14,7 @@ #if defined(ENABLE_OPENCL) #include "pow_cl.h" #endif -#if defined(ENABLE_FPGA_ACCEL) +#if defined(ENABLE_FPGA) #include "pow_fpga.h" #endif #if defined(ENABLE_REMOTE) @@ -32,7 +32,7 @@ #endif /* for checking whether the corresponding implementation is initialized */ -enum Capability { +enum capability { CAP_NONE = 0U, CAP_C = 1U, CAP_SSE = 1U << 1, @@ -43,31 +43,31 @@ enum Capability { }; /* check whether dcurl is initialized */ -static bool isInitialized = false; -static uint8_t runtimeCaps = CAP_NONE; +static bool is_initialized = false; +static uint8_t runtime_caps = CAP_NONE; static uv_sem_t notify; -LIST_HEAD(IMPL_LIST); -LIST_HEAD(REMOTE_IMPL_LIST); +LIST_HEAD(impl_list); +LIST_HEAD(remote_impl_list); #if defined(ENABLE_AVX) -extern ImplContext PoWAVX_Context; +extern impl_context_t pow_avx_context; #elif defined(ENABLE_SSE) -extern ImplContext PoWSSE_Context; +extern impl_context_t pow_sse_context; #elif defined(ENABLE_GENERIC) -extern ImplContext PoWC_Context; +extern impl_context_t pow_c_context; #endif #if defined(ENABLE_OPENCL) -extern ImplContext PoWCL_Context; +extern impl_context_t pow_cl_context; #endif -#if defined(ENABLE_FPGA_ACCEL) -extern ImplContext PoWFPGA_Context; +#if defined(ENABLE_FPGA) +extern impl_context_t pow_fpga_context; #endif #if defined(ENABLE_REMOTE) -extern RemoteImplContext Remote_Context; +extern remote_impl_context_t remote_context; static uv_sem_t notify_remote; #endif @@ -76,71 +76,71 @@ bool dcurl_init() bool ret = false; #if defined(ENABLE_AVX) - if (registerImplContext(&PoWAVX_Context)) { - runtimeCaps |= CAP_AVX; + if (register_impl_context(&pow_avx_context)) { + runtime_caps |= CAP_AVX; ret |= true; } #elif defined(ENABLE_SSE) - if (registerImplContext(&PoWSSE_Context)) { - runtimeCaps |= CAP_SSE; + if (register_impl_context(&pow_sse_context)) { + runtime_caps |= CAP_SSE; ret |= true; } #elif defined(ENABLE_GENERIC) - if (registerImplContext(&PoWC_Context)) { - runtimeCaps |= CAP_C; + if (register_impl_context(&pow_c_context)) { + runtime_caps |= CAP_C; ret |= true; } #endif #if defined(ENABLE_OPENCL) - if (registerImplContext(&PoWCL_Context)) { - runtimeCaps |= CAP_GPU; + if (register_impl_context(&pow_cl_context)) { + runtime_caps |= CAP_GPU; ret |= true; } #endif -#if defined(ENABLE_FPGA_ACCEL) - if (registerImplContext(&PoWFPGA_Context)) { - runtimeCaps |= CAP_FPGA; +#if defined(ENABLE_FPGA) + if (register_impl_context(&pow_fpga_context)) { + runtime_caps |= CAP_FPGA; ret |= true; } #endif #if defined(ENABLE_REMOTE) - if (registerRemoteContext(&Remote_Context)) { - runtimeCaps |= CAP_REMOTE; + if (register_remote_context(&remote_context)) { + runtime_caps |= CAP_REMOTE; ret |= true; } uv_sem_init(¬ify_remote, 0); #endif uv_sem_init(¬ify, 0); - return isInitialized = ret; + return is_initialized = ret; } void dcurl_destroy() { - ImplContext *impl = NULL; + impl_context_t *impl = NULL; struct list_head *p; #if defined(ENABLE_REMOTE) - RemoteImplContext *remoteImpl = NULL; - struct list_head *pRemote; + remote_impl_context_t *remote_impl = NULL; + struct list_head *p_remote; - list_for_each (pRemote, &REMOTE_IMPL_LIST) { - remoteImpl = list_entry(pRemote, RemoteImplContext, node); - destroyRemoteContext(remoteImpl); - list_del(pRemote); + list_for_each (p_remote, &remote_impl_list) { + remote_impl = list_entry(p_remote, remote_impl_context_t, node); + destroy_remote_context(remote_impl); + list_del(p_remote); } #endif - list_for_each (p, &IMPL_LIST) { - impl = list_entry(p, ImplContext, node); - destroyImplContext(impl); + list_for_each (p, &impl_list) { + impl = list_entry(p, impl_context_t, node); + destroy_impl_context(impl); list_del(p); } - runtimeCaps = CAP_NONE; + runtime_caps = CAP_NONE; } @@ -149,22 +149,22 @@ int8_t *dcurl_entry(int8_t *trytes, int mwm, int threads) void *pow_ctx = NULL; int8_t *res = NULL; - ImplContext *impl = NULL; + impl_context_t *impl = NULL; struct list_head *p; - if (!isInitialized) + if (!is_initialized) return NULL; #if defined(ENABLE_REMOTE) - if (runtimeCaps & CAP_REMOTE) { - RemoteImplContext *remoteImpl = NULL; - struct list_head *pRemote; + if (runtime_caps & CAP_REMOTE) { + remote_impl_context_t *remote_impl = NULL; + struct list_head *p_remote; do { - list_for_each (pRemote, &REMOTE_IMPL_LIST) { - remoteImpl = list_entry(pRemote, RemoteImplContext, node); - if (enterRemoteContext(remoteImpl)) { - pow_ctx = getRemoteContext(remoteImpl, trytes, mwm); + list_for_each (p_remote, &remote_impl_list) { + remote_impl = list_entry(p_remote, remote_impl_context_t, node); + if (enter_remote_context(remote_impl)) { + pow_ctx = get_remote_context(remote_impl, trytes, mwm); goto remote_pow; } } @@ -172,21 +172,21 @@ int8_t *dcurl_entry(int8_t *trytes, int mwm, int threads) } while (1); remote_pow: - if (!doRemoteContext(remoteImpl, pow_ctx)) { + if (!do_remote_context(remote_impl, pow_ctx)) { /* The remote interface can not work without activated RabbitMQ * broker and remote worker. If it is not working, the PoW would be * calculated by the local machine. And the remote interface * resource should be released. */ - freeRemoteContext(remoteImpl, pow_ctx); - exitRemoteContext(remoteImpl); + free_remote_context(remote_impl, pow_ctx); + exit_remote_context(remote_impl); uv_sem_post(¬ify_remote); goto local_pow; } else { - res = getRemoteResult(remoteImpl, pow_ctx); + res = get_remote_result(remote_impl, pow_ctx); } - freeRemoteContext(remoteImpl, pow_ctx); - exitRemoteContext(remoteImpl); + free_remote_context(remote_impl, pow_ctx); + exit_remote_context(remote_impl); uv_sem_post(¬ify_remote); return res; } @@ -194,10 +194,10 @@ int8_t *dcurl_entry(int8_t *trytes, int mwm, int threads) local_pow: #endif do { - list_for_each (p, &IMPL_LIST) { - impl = list_entry(p, ImplContext, node); - if (enterImplContext(impl)) { - pow_ctx = getPoWContext(impl, trytes, mwm, threads); + list_for_each (p, &impl_list) { + impl = list_entry(p, impl_context_t, node); + if (enter_impl_context(impl)) { + pow_ctx = get_pow_context(impl, trytes, mwm, threads); goto do_pow; } } @@ -205,13 +205,13 @@ int8_t *dcurl_entry(int8_t *trytes, int mwm, int threads) } while (1); do_pow: - if (!doThePoW(impl, pow_ctx)) { + if (!do_the_pow(impl, pow_ctx)) { res = NULL; } else { - res = getPoWResult(impl, pow_ctx); + res = get_pow_result(impl, pow_ctx); } - freePoWContext(impl, pow_ctx); - exitImplContext(impl); + free_pow_context(impl, pow_ctx); + exit_impl_context(impl); uv_sem_post(¬ify); return res; } diff --git a/src/implcontext.c b/src/implcontext.c index 4d4b38f..4a25d14 100644 --- a/src/implcontext.c +++ b/src/implcontext.c @@ -11,17 +11,17 @@ #define MSG_PREFIX "[dcurl] " -extern struct list_head IMPL_LIST; +extern struct list_head impl_list; -bool registerImplContext(ImplContext *impl_ctx) +bool register_impl_context(impl_context_t *impl_ctx) { - bool res = initializeImplContext(impl_ctx); + bool res = initialize_impl_context(impl_ctx); if (res) - list_add(&impl_ctx->node, &IMPL_LIST); + list_add(&impl_ctx->node, &impl_list); return res; } -bool initializeImplContext(ImplContext *impl_ctx) +bool initialize_impl_context(impl_context_t *impl_ctx) { bool res = impl_ctx->initialize(impl_ctx); if (res) { @@ -32,12 +32,12 @@ bool initializeImplContext(ImplContext *impl_ctx) return res; } -void destroyImplContext(ImplContext *impl_ctx) +void destroy_impl_context(impl_context_t *impl_ctx) { return impl_ctx->destroy(impl_ctx); } -bool enterImplContext(ImplContext *impl_ctx) +bool enter_impl_context(impl_context_t *impl_ctx) { uv_mutex_lock(&impl_ctx->lock); if (impl_ctx->num_working_thread >= impl_ctx->num_max_thread) { @@ -49,34 +49,34 @@ bool enterImplContext(ImplContext *impl_ctx) return true; /* Access Success */ } -void exitImplContext(ImplContext *impl_ctx) +void exit_impl_context(impl_context_t *impl_ctx) { uv_mutex_lock(&impl_ctx->lock); impl_ctx->num_working_thread--; uv_mutex_unlock(&impl_ctx->lock); } -void *getPoWContext(ImplContext *impl_ctx, int8_t *trytes, int mwm, int threads) +void *get_pow_context(impl_context_t *impl_ctx, int8_t *trytes, int mwm, int threads) { - return impl_ctx->getPoWContext(impl_ctx, trytes, mwm, threads); + return impl_ctx->get_pow_context(impl_ctx, trytes, mwm, threads); } -bool doThePoW(ImplContext *impl_ctx, void *pow_ctx) +bool do_the_pow(impl_context_t *impl_ctx, void *pow_ctx) { - return impl_ctx->doThePoW(pow_ctx); + return impl_ctx->do_the_pow(pow_ctx); } -bool freePoWContext(ImplContext *impl_ctx, void *pow_ctx) +bool free_pow_context(impl_context_t *impl_ctx, void *pow_ctx) { - return impl_ctx->freePoWContext(impl_ctx, pow_ctx); + return impl_ctx->free_pow_context(impl_ctx, pow_ctx); } -int8_t *getPoWResult(ImplContext *impl_ctx, void *pow_ctx) +int8_t *get_pow_result(impl_context_t *impl_ctx, void *pow_ctx) { - return impl_ctx->getPoWResult(pow_ctx); + return impl_ctx->get_pow_result(pow_ctx); } -PoW_Info getPoWInfo(ImplContext *impl_ctx, void *pow_ctx) +pow_info_t get_pow_info(impl_context_t *impl_ctx, void *pow_ctx) { - return impl_ctx->getPoWInfo(pow_ctx); + return impl_ctx->get_pow_info(pow_ctx); } diff --git a/src/implcontext.h b/src/implcontext.h index 68bd8bd..60f403a 100644 --- a/src/implcontext.h +++ b/src/implcontext.h @@ -15,9 +15,9 @@ #include "list.h" #include "uv.h" -typedef struct _impl_context ImplContext; +typedef struct impl_context_s impl_context_t; -struct _impl_context { +struct impl_context_s { void *context; char *description; @@ -28,34 +28,34 @@ struct _impl_context { int num_working_thread; /* Functions of Implementation Context */ - bool (*initialize)(ImplContext *impl_ctx); - void (*destroy)(ImplContext *impl_ctx); + bool (*initialize)(impl_context_t *impl_ctx); + void (*destroy)(impl_context_t *impl_ctx); /* Private PoW Context for each thread */ - void *(*getPoWContext)(ImplContext *impl_ctx, + void *(*get_pow_context)(impl_context_t *impl_ctx, int8_t *trytes, int mwm, int threads); - bool (*doThePoW)(void *pow_ctx); - int8_t *(*getPoWResult)(void *pow_ctx); - PoW_Info (*getPoWInfo)(void *pow_ctx); - bool (*freePoWContext)(ImplContext *impl_ctx, void *pow_ctx); + bool (*do_the_pow)(void *pow_ctx); + int8_t *(*get_pow_result)(void *pow_ctx); + pow_info_t (*get_pow_info)(void *pow_ctx); + bool (*free_pow_context)(impl_context_t *impl_ctx, void *pow_ctx); /* Node in linked list */ struct list_head node; }; -bool registerImplContext(ImplContext *impl_ctx); -bool initializeImplContext(ImplContext *impl_ctx); -void destroyImplContext(ImplContext *impl_ctx); -bool enterImplContext(ImplContext *impl_ctx); -void exitImplContext(ImplContext *impl_ctx); -void *getPoWContext(ImplContext *impl_ctx, +bool register_impl_context(impl_context_t *impl_ctx); +bool initialize_impl_context(impl_context_t *impl_ctx); +void destroy_impl_context(impl_context_t *impl_ctx); +bool enter_impl_context(impl_context_t *impl_ctx); +void exit_impl_context(impl_context_t *impl_ctx); +void *get_pow_context(impl_context_t *impl_ctx, int8_t *trytes, int mwm, int threads); -bool doThePoW(ImplContext *impl_ctx, void *pow_ctx); -bool freePoWContext(ImplContext *impl_ctx, void *pow_ctx); -int8_t *getPoWResult(ImplContext *impl_ctx, void *pow_ctx); -PoW_Info getPoWInfo(ImplContext *impl_ctx, void *pow_ctx); +bool do_the_pow(impl_context_t *impl_ctx, void *pow_ctx); +bool free_pow_context(impl_context_t *impl_ctx, void *pow_ctx); +int8_t *get_pow_result(impl_context_t *impl_ctx, void *pow_ctx); +pow_info_t get_pow_info(impl_context_t *impl_ctx, void *pow_ctx); #endif diff --git a/src/list.h b/src/list.h index 8630c46..1f03281 100644 --- a/src/list.h +++ b/src/list.h @@ -79,7 +79,7 @@ struct list_head { #define LIST_HEAD(head) struct list_head head = {&(head), &(head)} /** - * INIT_LIST_HEAD() - Initialize empty list head + * init_list_head() - Initialize empty list head * @head: pointer to list head * * This can also be used to initialize a unlinked list node. @@ -93,7 +93,7 @@ struct list_head { * list_del(_init) on an uninitialized node is undefined (unrelated memory is * modified, crashes, ...). */ -static inline void INIT_LIST_HEAD(struct list_head *head) +static inline void init_list_head(struct list_head *head) { head->next = head; head->prev = head; @@ -169,7 +169,7 @@ static inline void list_del(struct list_head *node) static inline void list_del_init(struct list_head *node) { list_del(node); - INIT_LIST_HEAD(node); + init_list_head(node); } /** @@ -263,7 +263,7 @@ static inline void list_splice_init(struct list_head *list, struct list_head *head) { list_splice(list, head); - INIT_LIST_HEAD(list); + init_list_head(list); } /** @@ -282,7 +282,7 @@ static inline void list_splice_tail_init(struct list_head *list, struct list_head *head) { list_splice_tail(list, head); - INIT_LIST_HEAD(list); + init_list_head(list); } /** @@ -307,7 +307,7 @@ static inline void list_cut_position(struct list_head *head_to, return; if (head_from == node) { - INIT_LIST_HEAD(head_to); + init_list_head(head_to); return; } diff --git a/src/pow_avx.c b/src/pow_avx.c index 350e606..370268c 100644 --- a/src/pow_avx.c +++ b/src/pow_avx.c @@ -16,7 +16,7 @@ #include "implcontext.h" #ifdef __AVX2__ -static void transform256(__m256i *lmid, __m256i *hmid) +static void transform_256(__m256i *lmid, __m256i *hmid) { __m256i one = _mm256_set_epi64x(HBITS, HBITS, HBITS, HBITS); int t1, t2; @@ -56,7 +56,7 @@ static void transform256(__m256i *lmid, __m256i *hmid) } } -static int incr256(__m256i *mid_low, __m256i *mid_high) +static int incr_256(__m256i *mid_low, __m256i *mid_high) { int i; __m256i carry = _mm256_set_epi64x(LOW00, LOW01, LOW02, LOW03); @@ -72,7 +72,7 @@ static int incr256(__m256i *mid_low, __m256i *mid_high) return i == HASH_TRITS_LENGTH; } -static void seri256(__m256i *low, __m256i *high, int n, int8_t *r) +static void seri_256(__m256i *low, __m256i *high, int n, int8_t *r) { int index = n >> 6; n = n % 64; @@ -93,7 +93,7 @@ static void seri256(__m256i *low, __m256i *high, int n, int8_t *r) } } -static int check256(__m256i *l, __m256i *h, int m) +static int check_256(__m256i *l, __m256i *h, int m) { __m256i nonce_probe = _mm256_set_epi64x(HBITS, HBITS, HBITS, HBITS); __m256i one = _mm256_set_epi64x(HBITS, HBITS, HBITS, HBITS); @@ -118,7 +118,7 @@ static int check256(__m256i *l, __m256i *h, int m) return -2; } -static void para256(int8_t in[], __m256i l[], __m256i h[]) +static void para_256(int8_t in[], __m256i l[], __m256i h[]) { for (int i = 0; i < STATE_TRITS_LENGTH; i++) { switch (in[i]) { @@ -138,7 +138,7 @@ static void para256(int8_t in[], __m256i l[], __m256i h[]) } } -static void incrN256(int n, __m256i *mid_low, __m256i *mid_high) +static void incr_n_256(int n, __m256i *mid_low, __m256i *mid_high) { __m256i one = _mm256_set_epi64x(HBITS, HBITS, HBITS, HBITS); for (int j = 0; j < n; j++) { @@ -155,28 +155,28 @@ static void incrN256(int n, __m256i *mid_low, __m256i *mid_high) } -static int loop256(__m256i *lmid, +static int loop_256(__m256i *lmid, __m256i *hmid, int m, int8_t *nonce, - int *stopPoW, + int *stop_pow, uv_rwlock_t *lock) { int i = 0; __m256i lcpy[STATE_TRITS_LENGTH * 2], hcpy[STATE_TRITS_LENGTH * 2]; uv_rwlock_rdlock(lock); - for (i = 0; !incr256(lmid, hmid) && !*stopPoW; i++) { + for (i = 0; !incr_256(lmid, hmid) && !*stop_pow; i++) { uv_rwlock_rdunlock(lock); int n; for (int j = 0; j < STATE_TRITS_LENGTH; j++) { lcpy[j] = lmid[j]; hcpy[j] = hmid[j]; } - transform256(lcpy, hcpy); - if ((n = check256(lcpy + STATE_TRITS_LENGTH, hcpy + STATE_TRITS_LENGTH, + transform_256(lcpy, hcpy); + if ((n = check_256(lcpy + STATE_TRITS_LENGTH, hcpy + STATE_TRITS_LENGTH, m)) >= 0) { - seri256(lmid, hmid, n, nonce); + seri_256(lmid, hmid, n, nonce); return i * 256; } uv_rwlock_rdlock(lock); @@ -185,16 +185,16 @@ static int loop256(__m256i *lmid, return -i * 256 - 1; } -static int64_t pwork256(int8_t mid[], +static int64_t pwork_256(int8_t mid[], int mwm, int8_t nonce[], int n, - int *stopPoW, + int *stop_pow, uv_rwlock_t *lock) { __m256i lmid[STATE_TRITS_LENGTH], hmid[STATE_TRITS_LENGTH]; int offset = HASH_TRITS_LENGTH - NONCE_TRITS_LENGTH; - para256(mid, lmid, hmid); + para_256(mid, lmid, hmid); lmid[offset] = _mm256_set_epi64x(LOW00, LOW01, LOW02, LOW03); hmid[offset] = _mm256_set_epi64x(HIGH00, HIGH01, HIGH02, HIGH03); lmid[offset + 1] = _mm256_set_epi64x(LOW10, LOW11, LOW12, LOW13); @@ -207,14 +207,14 @@ static int64_t pwork256(int8_t mid[], hmid[offset + 4] = _mm256_set_epi64x(HIGH40, HIGH41, HIGH42, HIGH43); lmid[offset + 5] = _mm256_set_epi64x(LOW50, LOW51, LOW52, LOW53); hmid[offset + 5] = _mm256_set_epi64x(HIGH50, HIGH51, HIGH52, HIGH53); - incrN256(n, lmid, hmid); + incr_n_256(n, lmid, hmid); - return loop256(lmid, hmid, mwm, nonce, stopPoW, lock); + return loop_256(lmid, hmid, mwm, nonce, stop_pow, lock); } #else /* AVX1 */ -static void transform256(__m256d *lmid, __m256d *hmid) +static void transform_256(__m256d *lmid, __m256d *hmid) { __m256d one = _mm256_set_pd(HBITS, HBITS, HBITS, HBITS); int j, r, t1, t2; @@ -254,7 +254,7 @@ static void transform256(__m256d *lmid, __m256d *hmid) } } -static int incr256(__m256d *mid_low, __m256d *mid_high) +static int incr_256(__m256d *mid_low, __m256d *mid_high) { int i; __m256d carry; @@ -269,7 +269,7 @@ static int incr256(__m256d *mid_low, __m256d *mid_high) return i == HASH_TRITS_LENGTH; } -static void seri256(__m256d *low, __m256d *high, int n, int8_t *r) +static void seri_256(__m256d *low, __m256d *high, int n, int8_t *r) { int i = 0, index = 0; if (n > 63 && n < 128) { @@ -302,7 +302,7 @@ static void seri256(__m256d *low, __m256d *high, int n, int8_t *r) } } -static int check256(__m256d *l, __m256d *h, int m) +static int check_256(__m256d *l, __m256d *h, int m) { int i, j; // omit init for speed @@ -326,7 +326,7 @@ static int check256(__m256d *l, __m256d *h, int m) return -2; } -static void para256(int8_t in[], __m256d l[], __m256d h[]) +static void para_256(int8_t in[], __m256d l[], __m256d h[]) { int i = 0; for (i = 0; i < STATE_TRITS_LENGTH; i++) { @@ -347,7 +347,7 @@ static void para256(int8_t in[], __m256d l[], __m256d h[]) } } -static void incrN256(int n, __m256d *mid_low, __m256d *mid_high) +static void incr_n_256(int n, __m256d *mid_low, __m256d *mid_high) { int i, j; for (j = 0; j < n; j++) { @@ -363,28 +363,28 @@ static void incrN256(int n, __m256d *mid_low, __m256d *mid_high) } } -static int loop256(__m256d *lmid, +static int loop_256(__m256d *lmid, __m256d *hmid, int m, int8_t *nonce, - int *stopPoW, + int *stop_pow, uv_rwlock_t *lock) { int i = 0; __m256d lcpy[STATE_TRITS_LENGTH * 2], hcpy[STATE_TRITS_LENGTH * 2]; uv_rwlock_rdlock(lock); - for (i = 0; !incr256(lmid, hmid) && !*stopPoW; i++) { + for (i = 0; !incr_256(lmid, hmid) && !*stop_pow; i++) { uv_rwlock_rdunlock(lock); int n, j; for (j = 0; j < STATE_TRITS_LENGTH; j++) { lcpy[j] = lmid[j]; hcpy[j] = hmid[j]; } - transform256(lcpy, hcpy); - if ((n = check256(lcpy + STATE_TRITS_LENGTH, hcpy + STATE_TRITS_LENGTH, + transform_256(lcpy, hcpy); + if ((n = check_256(lcpy + STATE_TRITS_LENGTH, hcpy + STATE_TRITS_LENGTH, m)) >= 0) { - seri256(lmid, hmid, n, nonce); + seri_256(lmid, hmid, n, nonce); return i * 256; } uv_rwlock_rdlock(lock); @@ -393,16 +393,16 @@ static int loop256(__m256d *lmid, return -i * 256 - 1; } -static long long int pwork256(int8_t mid[], +static long long int pwork_256(int8_t mid[], int mwm, int8_t nonce[], int n, - int *stopPoW, + int *stop_pow, uv_rwlock_t *lock) { __m256d lmid[STATE_TRITS_LENGTH], hmid[STATE_TRITS_LENGTH]; int offset = HASH_TRITS_LENGTH - NONCE_TRITS_LENGTH; - para256(mid, lmid, hmid); + para_256(mid, lmid, hmid); lmid[offset] = _mm256_set_pd(LOW00, LOW01, LOW02, LOW03); hmid[offset] = _mm256_set_pd(HIGH00, HIGH01, HIGH02, HIGH03); lmid[offset + 1] = _mm256_set_pd(LOW10, LOW11, LOW12, LOW13); @@ -415,36 +415,36 @@ static long long int pwork256(int8_t mid[], hmid[offset + 4] = _mm256_set_pd(HIGH40, HIGH41, HIGH42, HIGH43); lmid[offset + 5] = _mm256_set_pd(LOW50, LOW51, LOW52, LOW53); hmid[offset + 5] = _mm256_set_pd(HIGH50, HIGH51, HIGH52, HIGH53); - incrN256(n, lmid, hmid); + incr_n_256(n, lmid, hmid); - return loop256(lmid, hmid, mwm, nonce, stopPoW, lock); + return loop_256(lmid, hmid, mwm, nonce, stop_pow, lock); } #endif /* __AVX2__ */ static void work_cb(uv_work_t *req) { - Pwork_struct *pworkInfo = (Pwork_struct *) req->data; - pworkInfo->ret = - pwork256(pworkInfo->mid, pworkInfo->mwm, pworkInfo->nonce, pworkInfo->n, - pworkInfo->stopPoW, pworkInfo->lock); - - uv_rwlock_wrlock(pworkInfo->lock); - if (pworkInfo->ret >= 0) { - *pworkInfo->stopPoW = 1; + pwork_t *pwork_info = (pwork_t *) req->data; + pwork_info->ret = + pwork_256(pwork_info->mid, pwork_info->mwm, pwork_info->nonce, pwork_info->n, + pwork_info->stop_pow, pwork_info->lock); + + uv_rwlock_wrlock(pwork_info->lock); + if (pwork_info->ret >= 0) { + *pwork_info->stop_pow = 1; /* This means this thread got the result */ - pworkInfo->n = -1; + pwork_info->n = -1; } - uv_rwlock_wrunlock(pworkInfo->lock); + uv_rwlock_wrunlock(pwork_info->lock); } -static int8_t *tx_to_cstate(Trytes_t *tx) +static int8_t *tx_to_cstate(trytes_t *tx) { - Trytes_t *inn = NULL; - Trits_t *tr = NULL; + trytes_t *inn = NULL; + trits_t *tr = NULL; int8_t tyt[TRANSACTION_TRYTES_LENGTH - HASH_TRYTES_LENGTH] = {0}; - Curl *c = initCurl(); + curl_t *c = init_curl(); int8_t *c_state = (int8_t *) malloc(STATE_TRITS_LENGTH); if (!c || !c_state) goto fail; @@ -452,11 +452,11 @@ static int8_t *tx_to_cstate(Trytes_t *tx) /* Copy tx->data[:TRANSACTION_TRYTES_LENGTH - HASH_TRYTES_LENGTH] to tyt */ memcpy(tyt, tx->data, TRANSACTION_TRYTES_LENGTH - HASH_TRYTES_LENGTH); - inn = initTrytes(tyt, TRANSACTION_TRYTES_LENGTH - HASH_TRYTES_LENGTH); + inn = init_trytes(tyt, TRANSACTION_TRYTES_LENGTH - HASH_TRYTES_LENGTH); if (!inn) goto fail; - Absorb(c, inn); + absorb(c, inn); tr = trits_from_trytes(tx); if (!tr) @@ -472,19 +472,19 @@ static int8_t *tx_to_cstate(Trytes_t *tx) c->state->len - tr->len + (TRANSACTION_TRITS_LENGTH - HASH_TRITS_LENGTH)); - freeTrobject(inn); - freeTrobject(tr); - freeCurl(c); + free_trinary_object(inn); + free_trinary_object(tr); + free_curl(c); return c_state; fail: - freeTrobject(inn); - freeTrobject(tr); - freeCurl(c); + free_trinary_object(inn); + free_trinary_object(tr); + free_curl(c); free(c_state); return NULL; } -static void nonce_to_result(Trytes_t *tx, Trytes_t *nonce, int8_t *ret) +static void nonce_to_result(trytes_t *tx, trytes_t *nonce, int8_t *ret) { int rst_len = tx->len - NONCE_TRYTES_LENGTH + nonce->len; @@ -493,26 +493,26 @@ static void nonce_to_result(Trytes_t *tx, Trytes_t *nonce, int8_t *ret) rst_len - (tx->len - NONCE_TRYTES_LENGTH)); } -static bool PowAVX(void *pow_ctx) +static bool pow_avx(void *pow_ctx) { bool res = true; - Trits_t *nonce_trit = NULL; - Trytes_t *tx_tryte = NULL, *nonce_tryte = NULL; + trits_t *nonce_trit = NULL; + trytes_t *tx_tryte = NULL, *nonce_tryte = NULL; struct timespec start_time, end_time; /* Initialize the context */ - PoW_AVX_Context *ctx = (PoW_AVX_Context *) pow_ctx; - ctx->stopPoW = 0; + pow_avx_context_t *ctx = (pow_avx_context_t *) pow_ctx; + ctx->stop_pow = 0; ctx->pow_info.time = 0; ctx->pow_info.hash_count = 0; uv_rwlock_init(&ctx->lock); uv_loop_t *loop_ptr = &ctx->loop; uv_work_t *work_req = ctx->work_req; - Pwork_struct *pitem = ctx->pitem; + pwork_t *pitem = ctx->pitem; int8_t **nonce_array = ctx->nonce_array; /* Prepare the input trytes for algorithm */ - tx_tryte = initTrytes(ctx->input_trytes, TRANSACTION_TRYTES_LENGTH); + tx_tryte = init_trytes(ctx->input_trytes, TRANSACTION_TRYTES_LENGTH); if (!tx_tryte) return false; @@ -530,7 +530,7 @@ static bool PowAVX(void *pow_ctx) pitem[i].nonce = nonce_array[i]; pitem[i].n = i; pitem[i].lock = &ctx->lock; - pitem[i].stopPoW = &ctx->stopPoW; + pitem[i].stop_pow = &ctx->stop_pow; pitem[i].ret = 0; work_req[i].data = &pitem[i]; uv_queue_work(loop_ptr, &work_req[i], work_cb, NULL); @@ -538,17 +538,17 @@ static bool PowAVX(void *pow_ctx) uv_run(loop_ptr, UV_RUN_DEFAULT); - int completedIndex = -1; + int completed_index = -1; for (int i = 0; i < ctx->num_threads; i++) { if (pitem[i].n == -1) - completedIndex = i; + completed_index = i; ctx->pow_info.hash_count += (uint64_t)(pitem[i].ret >= 0 ? pitem[i].ret : -pitem[i].ret + 1); } clock_gettime(CLOCK_REALTIME, &end_time); ctx->pow_info.time = diff_in_second(start_time, end_time); - nonce_trit = initTrits(nonce_array[completedIndex], NONCE_TRITS_LENGTH); + nonce_trit = init_trits(nonce_array[completed_index], NONCE_TRITS_LENGTH); if (!nonce_trit) { res = false; goto fail; @@ -566,21 +566,21 @@ static bool PowAVX(void *pow_ctx) /* Free resource */ uv_rwlock_destroy(&ctx->lock); free(c_state); - freeTrobject(tx_tryte); - freeTrobject(nonce_trit); - freeTrobject(nonce_tryte); + free_trinary_object(tx_tryte); + free_trinary_object(nonce_trit); + free_trinary_object(nonce_tryte); return res; } -static bool PoWAVX_Context_Initialize(ImplContext *impl_ctx) +static bool pow_avx_context_initialize(impl_context_t *impl_ctx) { impl_ctx->num_max_thread = get_nthds_per_phys_proc(); int nproc = get_avail_phys_nprocs(); if (impl_ctx->num_max_thread <= 0 || nproc <= 0) return false; - PoW_AVX_Context *ctx = (PoW_AVX_Context *) malloc(sizeof(PoW_AVX_Context) * + pow_avx_context_t *ctx = (pow_avx_context_t *) malloc(sizeof(pow_avx_context_t) * impl_ctx->num_max_thread); if (!ctx) return false; @@ -589,7 +589,7 @@ static bool PoWAVX_Context_Initialize(ImplContext *impl_ctx) void *work_req_chunk = malloc(impl_ctx->num_max_thread * sizeof(uv_work_t) * nproc); void *pitem_chunk = - malloc(impl_ctx->num_max_thread * sizeof(Pwork_struct) * nproc); + malloc(impl_ctx->num_max_thread * sizeof(pwork_t) * nproc); void *nonce_ptr_chunk = malloc(impl_ctx->num_max_thread * sizeof(int8_t *) * nproc); void *nonce_chunk = @@ -599,7 +599,7 @@ static bool PoWAVX_Context_Initialize(ImplContext *impl_ctx) for (int i = 0; i < impl_ctx->num_max_thread; i++) { ctx[i].work_req = (uv_work_t *) (work_req_chunk) + i * nproc; - ctx[i].pitem = (Pwork_struct *) (pitem_chunk) + i * nproc; + ctx[i].pitem = (pwork_t *) (pitem_chunk) + i * nproc; ctx[i].nonce_array = (int8_t **) (nonce_ptr_chunk) + i * nproc; for (int j = 0; j < nproc; j++) ctx[i].nonce_array[j] = (int8_t *) (nonce_chunk) + @@ -626,9 +626,9 @@ static bool PoWAVX_Context_Initialize(ImplContext *impl_ctx) return false; } -static void PoWAVX_Context_Destroy(ImplContext *impl_ctx) +static void pow_avx_context_destroy(impl_context_t *impl_ctx) { - PoW_AVX_Context *ctx = (PoW_AVX_Context *) impl_ctx->context; + pow_avx_context_t *ctx = (pow_avx_context_t *) impl_ctx->context; for (int i = 0; i < impl_ctx->num_max_thread; i++) { uv_loop_close(&ctx[i].loop); } @@ -639,7 +639,7 @@ static void PoWAVX_Context_Destroy(ImplContext *impl_ctx) free(ctx); } -static void *PoWAVX_getPoWContext(ImplContext *impl_ctx, +static void *pow_avx_get_pow_context(impl_context_t *impl_ctx, int8_t *trytes, int mwm, int threads) @@ -649,10 +649,10 @@ static void *PoWAVX_getPoWContext(ImplContext *impl_ctx, if (impl_ctx->bitmap & (0x1 << i)) { impl_ctx->bitmap &= ~(0x1 << i); uv_mutex_unlock(&impl_ctx->lock); - PoW_AVX_Context *ctx = (PoW_AVX_Context *) impl_ctx->context + i; + pow_avx_context_t *ctx = (pow_avx_context_t *) impl_ctx->context + i; memcpy(ctx->input_trytes, trytes, TRANSACTION_TRYTES_LENGTH); ctx->mwm = mwm; - ctx->indexOfContext = i; + ctx->index_of_context = i; if (threads > 0 && threads < ctx->num_max_threads) ctx->num_threads = threads; else @@ -664,41 +664,41 @@ static void *PoWAVX_getPoWContext(ImplContext *impl_ctx, return NULL; /* It should not happen */ } -static bool PoWAVX_freePoWContext(ImplContext *impl_ctx, void *pow_ctx) +static bool pow_avx_free_pow_context(impl_context_t *impl_ctx, void *pow_ctx) { uv_mutex_lock(&impl_ctx->lock); - impl_ctx->bitmap |= 0x1 << ((PoW_AVX_Context *) pow_ctx)->indexOfContext; + impl_ctx->bitmap |= 0x1 << ((pow_avx_context_t *) pow_ctx)->index_of_context; uv_mutex_unlock(&impl_ctx->lock); return true; } -static int8_t *PoWAVX_getPoWResult(void *pow_ctx) +static int8_t *pow_avx_get_pow_result(void *pow_ctx) { int8_t *ret = (int8_t *) malloc(sizeof(int8_t) * (TRANSACTION_TRYTES_LENGTH)); if (!ret) return NULL; - memcpy(ret, ((PoW_AVX_Context *) pow_ctx)->output_trytes, + memcpy(ret, ((pow_avx_context_t *) pow_ctx)->output_trytes, TRANSACTION_TRYTES_LENGTH); return ret; } -static PoW_Info PoWAVX_getPoWInfo(void *pow_ctx) +static pow_info_t pow_avx_get_pow_info(void *pow_ctx) { - return ((PoW_AVX_Context *) pow_ctx)->pow_info; + return ((pow_avx_context_t *) pow_ctx)->pow_info; } -ImplContext PoWAVX_Context = { +impl_context_t pow_avx_context = { .context = NULL, .description = "CPU (Intel AVX)", .bitmap = 0, .num_max_thread = 0, .num_working_thread = 0, - .initialize = PoWAVX_Context_Initialize, - .destroy = PoWAVX_Context_Destroy, - .getPoWContext = PoWAVX_getPoWContext, - .freePoWContext = PoWAVX_freePoWContext, - .doThePoW = PowAVX, - .getPoWResult = PoWAVX_getPoWResult, - .getPoWInfo = PoWAVX_getPoWInfo, + .initialize = pow_avx_context_initialize, + .destroy = pow_avx_context_destroy, + .get_pow_context = pow_avx_get_pow_context, + .free_pow_context = pow_avx_free_pow_context, + .do_the_pow = pow_avx, + .get_pow_result = pow_avx_get_pow_result, + .get_pow_info = pow_avx_get_pow_info, }; diff --git a/src/pow_avx.h b/src/pow_avx.h index 7818abc..346aca0 100644 --- a/src/pow_avx.h +++ b/src/pow_avx.h @@ -8,39 +8,39 @@ #include "trinary.h" #include "uv.h" -typedef struct _pwork_struct Pwork_struct; +typedef struct pwork_s pwork_t; -struct _pwork_struct { +struct pwork_s { int8_t *mid; int mwm; int8_t *nonce; int n; uv_rwlock_t *lock; - int *stopPoW; + int *stop_pow; int64_t ret; }; -typedef struct _pow_avx_context PoW_AVX_Context; +typedef struct pow_avx_context_s pow_avx_context_t; -struct _pow_avx_context { +struct pow_avx_context_s { /* Resource of computing */ uv_rwlock_t lock; /* Data type of libtuv */ uv_loop_t loop; uv_work_t *work_req; - Pwork_struct *pitem; + pwork_t *pitem; int8_t **nonce_array; - int stopPoW; + int stop_pow; int num_threads; int num_max_threads; /* Management of Multi-thread */ - int indexOfContext; + int index_of_context; /* Arguments of PoW */ int8_t input_trytes[TRANSACTION_TRYTES_LENGTH]; /* 2673 */ int8_t output_trytes[TRANSACTION_TRYTES_LENGTH]; /* 2673 */ int mwm; /* PoW-related information */ - PoW_Info pow_info; + pow_info_t pow_info; }; #ifdef _MSC_VER diff --git a/src/pow_c.c b/src/pow_c.c index a246b6f..8dcc322 100644 --- a/src/pow_c.c +++ b/src/pow_c.c @@ -15,7 +15,7 @@ #include "curl.h" #include "implcontext.h" -static void transform64(uint64_t *lmid, uint64_t *hmid) +static void transform_64(uint64_t *lmid, uint64_t *hmid) { uint64_t alpha, beta, delta; uint64_t *lfrom = lmid, *hfrom = hmid; @@ -105,19 +105,19 @@ static long long int loop_cpu(uint64_t *lmid, uint64_t *hmid, int m, int8_t *nonce, - int *stopPoW, + int *stop_pow, uv_rwlock_t *lock) { long long int i = 0; uint64_t lcpy[STATE_TRITS_LENGTH * 2], hcpy[STATE_TRITS_LENGTH * 2]; uv_rwlock_rdlock(lock); - for (i = 0; !incr(lmid, hmid) && !*stopPoW; i++) { + for (i = 0; !incr(lmid, hmid) && !*stop_pow; i++) { uv_rwlock_rdunlock(lock); int n; memcpy(lcpy, lmid, STATE_TRITS_LENGTH * sizeof(uint64_t)); memcpy(hcpy, hmid, STATE_TRITS_LENGTH * sizeof(uint64_t)); - transform64(lcpy, hcpy); + transform_64(lcpy, hcpy); if ((n = check(lcpy + STATE_TRITS_LENGTH, hcpy + STATE_TRITS_LENGTH, m)) >= 0) { seri(lmid, hmid, n, nonce); @@ -149,7 +149,7 @@ static void para(int8_t in[], uint64_t l[], uint64_t h[]) } } -static void incrN(int n, uint64_t *mid_low, uint64_t *mid_high) +static void incr_n(int n, uint64_t *mid_low, uint64_t *mid_high) { for (int j = 0; j < n; j++) { uint64_t carry = 1; @@ -166,7 +166,7 @@ static int64_t pwork(int8_t mid[], int mwm, int8_t nonce[], int n, - int *stopPoW, + int *stop_pow, uv_rwlock_t *lock) { uint64_t lmid[STATE_TRITS_LENGTH] = {0}, hmid[STATE_TRITS_LENGTH] = {0}; @@ -181,33 +181,33 @@ static int64_t pwork(int8_t mid[], hmid[offset + 2] = HIGH2; lmid[offset + 3] = LOW3; hmid[offset + 3] = HIGH3; - incrN(n, lmid, hmid); + incr_n(n, lmid, hmid); - return loop_cpu(lmid, hmid, mwm, nonce, stopPoW, lock); + return loop_cpu(lmid, hmid, mwm, nonce, stop_pow, lock); } static void work_cb(uv_work_t *req) { - Pwork_struct *pworkInfo = (Pwork_struct *) req->data; - pworkInfo->ret = pwork(pworkInfo->mid, pworkInfo->mwm, pworkInfo->nonce, - pworkInfo->n, pworkInfo->stopPoW, pworkInfo->lock); + pwork_t *pwork_info = (pwork_t *) req->data; + pwork_info->ret = pwork(pwork_info->mid, pwork_info->mwm, pwork_info->nonce, + pwork_info->n, pwork_info->stop_pow, pwork_info->lock); - uv_rwlock_wrlock(pworkInfo->lock); - if (pworkInfo->ret >= 0) { - *pworkInfo->stopPoW = 1; + uv_rwlock_wrlock(pwork_info->lock); + if (pwork_info->ret >= 0) { + *pwork_info->stop_pow = 1; /* This means this thread got the result */ - pworkInfo->n = -1; + pwork_info->n = -1; } - uv_rwlock_wrunlock(pworkInfo->lock); + uv_rwlock_wrunlock(pwork_info->lock); } -static int8_t *tx_to_cstate(Trytes_t *tx) +static int8_t *tx_to_cstate(trytes_t *tx) { - Trytes_t *inn = NULL; - Trits_t *tr = NULL; + trytes_t *inn = NULL; + trits_t *tr = NULL; int8_t tyt[TRANSACTION_TRYTES_LENGTH - HASH_TRYTES_LENGTH] = {0}; - Curl *c = initCurl(); + curl_t *c = init_curl(); int8_t *c_state = (int8_t *) malloc(STATE_TRITS_LENGTH); if (!c || !c_state) goto fail; @@ -215,11 +215,11 @@ static int8_t *tx_to_cstate(Trytes_t *tx) /* Copy tx->data[:TRANSACTION_TRYTES_LENGTH - HASH_TRYTES_LENGTH] to tyt */ memcpy(tyt, tx->data, TRANSACTION_TRYTES_LENGTH - HASH_TRYTES_LENGTH); - inn = initTrytes(tyt, TRANSACTION_TRYTES_LENGTH - HASH_TRYTES_LENGTH); + inn = init_trytes(tyt, TRANSACTION_TRYTES_LENGTH - HASH_TRYTES_LENGTH); if (!inn) goto fail; - Absorb(c, inn); + absorb(c, inn); tr = trits_from_trytes(tx); if (!tr) @@ -235,19 +235,19 @@ static int8_t *tx_to_cstate(Trytes_t *tx) c->state->len - tr->len + (TRANSACTION_TRITS_LENGTH - HASH_TRITS_LENGTH)); - freeTrobject(inn); - freeTrobject(tr); - freeCurl(c); + free_trinary_object(inn); + free_trinary_object(tr); + free_curl(c); return c_state; fail: - freeTrobject(inn); - freeTrobject(tr); - freeCurl(c); + free_trinary_object(inn); + free_trinary_object(tr); + free_curl(c); free(c_state); return NULL; } -static void nonce_to_result(Trytes_t *tx, Trytes_t *nonce, int8_t *ret) +static void nonce_to_result(trytes_t *tx, trytes_t *nonce, int8_t *ret) { int rst_len = tx->len - NONCE_TRYTES_LENGTH + nonce->len; @@ -256,26 +256,26 @@ static void nonce_to_result(Trytes_t *tx, Trytes_t *nonce, int8_t *ret) rst_len - (tx->len - NONCE_TRYTES_LENGTH)); } -bool PowC(void *pow_ctx) +bool pow_c(void *pow_ctx) { bool res = true; - Trits_t *nonce_trit = NULL; - Trytes_t *tx_tryte = NULL, *nonce_tryte = NULL; + trits_t *nonce_trit = NULL; + trytes_t *tx_tryte = NULL, *nonce_tryte = NULL; struct timespec start_time, end_time; /* Initialize the context */ - PoW_C_Context *ctx = (PoW_C_Context *) pow_ctx; - ctx->stopPoW = 0; + pow_c_context_t *ctx = (pow_c_context_t *) pow_ctx; + ctx->stop_pow = 0; ctx->pow_info.time = 0; ctx->pow_info.hash_count = 0; uv_rwlock_init(&ctx->lock); uv_loop_t *loop_ptr = &ctx->loop; uv_work_t *work_req = ctx->work_req; - Pwork_struct *pitem = ctx->pitem; + pwork_t *pitem = ctx->pitem; int8_t **nonce_array = ctx->nonce_array; /* Prepare the input trytes for algorithm */ - tx_tryte = initTrytes(ctx->input_trytes, TRANSACTION_TRYTES_LENGTH); + tx_tryte = init_trytes(ctx->input_trytes, TRANSACTION_TRYTES_LENGTH); if (!tx_tryte) return false; @@ -293,7 +293,7 @@ bool PowC(void *pow_ctx) pitem[i].nonce = nonce_array[i]; pitem[i].n = i; pitem[i].lock = &ctx->lock; - pitem[i].stopPoW = &ctx->stopPoW; + pitem[i].stop_pow = &ctx->stop_pow; pitem[i].ret = 0; work_req[i].data = &pitem[i]; uv_queue_work(loop_ptr, &work_req[i], work_cb, NULL); @@ -301,17 +301,17 @@ bool PowC(void *pow_ctx) uv_run(loop_ptr, UV_RUN_DEFAULT); - int completedIndex = -1; + int completed_index = -1; for (int i = 0; i < ctx->num_threads; i++) { if (pitem[i].n == -1) - completedIndex = i; + completed_index = i; ctx->pow_info.hash_count += (uint64_t)(pitem[i].ret >= 0 ? pitem[i].ret : -pitem[i].ret + 1); } clock_gettime(CLOCK_REALTIME, &end_time); ctx->pow_info.time = diff_in_second(start_time, end_time); - nonce_trit = initTrits(nonce_array[completedIndex], NONCE_TRITS_LENGTH); + nonce_trit = init_trits(nonce_array[completed_index], NONCE_TRITS_LENGTH); if (!nonce_trit) { res = false; goto fail; @@ -329,20 +329,20 @@ bool PowC(void *pow_ctx) /* Free resource */ uv_rwlock_destroy(&ctx->lock); free(c_state); - freeTrobject(tx_tryte); - freeTrobject(nonce_trit); - freeTrobject(nonce_tryte); + free_trinary_object(tx_tryte); + free_trinary_object(nonce_trit); + free_trinary_object(nonce_tryte); return res; } -static bool PoWC_Context_Initialize(ImplContext *impl_ctx) +static bool pow_c_context_initialize(impl_context_t *impl_ctx) { impl_ctx->num_max_thread = get_nthds_per_phys_proc(); int nproc = get_avail_phys_nprocs(); if (impl_ctx->num_max_thread <= 0 || nproc <= 0) return false; - PoW_C_Context *ctx = (PoW_C_Context *) malloc(sizeof(PoW_C_Context) * + pow_c_context_t *ctx = (pow_c_context_t *) malloc(sizeof(pow_c_context_t) * impl_ctx->num_max_thread); if (!ctx) return false; @@ -351,7 +351,7 @@ static bool PoWC_Context_Initialize(ImplContext *impl_ctx) void *work_req_chunk = malloc(impl_ctx->num_max_thread * sizeof(uv_work_t) * nproc); void *pitem_chunk = - malloc(impl_ctx->num_max_thread * sizeof(Pwork_struct) * nproc); + malloc(impl_ctx->num_max_thread * sizeof(pwork_t) * nproc); void *nonce_ptr_chunk = malloc(impl_ctx->num_max_thread * sizeof(int8_t *) * nproc); void *nonce_chunk = @@ -361,7 +361,7 @@ static bool PoWC_Context_Initialize(ImplContext *impl_ctx) for (int i = 0; i < impl_ctx->num_max_thread; i++) { ctx[i].work_req = (uv_work_t *) (work_req_chunk) + i * nproc; - ctx[i].pitem = (Pwork_struct *) (pitem_chunk) + i * nproc; + ctx[i].pitem = (pwork_t *) (pitem_chunk) + i * nproc; ctx[i].nonce_array = (int8_t **) (nonce_ptr_chunk) + i * nproc; for (int j = 0; j < nproc; j++) ctx[i].nonce_array[j] = (int8_t *) (nonce_chunk) + @@ -388,9 +388,9 @@ static bool PoWC_Context_Initialize(ImplContext *impl_ctx) return false; } -static void PoWC_Context_Destroy(ImplContext *impl_ctx) +static void pow_c_context_destroy(impl_context_t *impl_ctx) { - PoW_C_Context *ctx = (PoW_C_Context *) impl_ctx->context; + pow_c_context_t *ctx = (pow_c_context_t *) impl_ctx->context; for (int i = 0; i < impl_ctx->num_max_thread; i++) { uv_loop_close(&ctx[i].loop); } @@ -401,7 +401,7 @@ static void PoWC_Context_Destroy(ImplContext *impl_ctx) free(ctx); } -static void *PoWC_getPoWContext(ImplContext *impl_ctx, +static void *pow_c_get_pow_context(impl_context_t *impl_ctx, int8_t *trytes, int mwm, int threads) @@ -411,10 +411,10 @@ static void *PoWC_getPoWContext(ImplContext *impl_ctx, if (impl_ctx->bitmap & (0x1 << i)) { impl_ctx->bitmap &= ~(0x1 << i); uv_mutex_unlock(&impl_ctx->lock); - PoW_C_Context *ctx = (PoW_C_Context *) impl_ctx->context + i; + pow_c_context_t *ctx = (pow_c_context_t *) impl_ctx->context + i; memcpy(ctx->input_trytes, trytes, TRANSACTION_TRYTES_LENGTH); ctx->mwm = mwm; - ctx->indexOfContext = i; + ctx->index_of_context = i; if (threads > 0 && threads < ctx->num_max_threads) ctx->num_threads = threads; else @@ -426,41 +426,41 @@ static void *PoWC_getPoWContext(ImplContext *impl_ctx, return NULL; /* It should not happen */ } -static bool PoWC_freePoWContext(ImplContext *impl_ctx, void *pow_ctx) +static bool pow_c_free_pow_context(impl_context_t *impl_ctx, void *pow_ctx) { uv_mutex_lock(&impl_ctx->lock); - impl_ctx->bitmap |= 0x1 << ((PoW_C_Context *) pow_ctx)->indexOfContext; + impl_ctx->bitmap |= 0x1 << ((pow_c_context_t *) pow_ctx)->index_of_context; uv_mutex_unlock(&impl_ctx->lock); return true; } -static int8_t *PoWC_getPoWResult(void *pow_ctx) +static int8_t *pow_c_get_pow_result(void *pow_ctx) { int8_t *ret = (int8_t *) malloc(sizeof(int8_t) * (TRANSACTION_TRYTES_LENGTH)); if (!ret) return NULL; - memcpy(ret, ((PoW_C_Context *) pow_ctx)->output_trytes, + memcpy(ret, ((pow_c_context_t *) pow_ctx)->output_trytes, TRANSACTION_TRYTES_LENGTH); return ret; } -static PoW_Info PoWC_getPoWInfo(void *pow_ctx) +static pow_info_t pow_c_get_pow_info(void *pow_ctx) { - return ((PoW_C_Context *) pow_ctx)->pow_info; + return ((pow_c_context_t *) pow_ctx)->pow_info; } -ImplContext PoWC_Context = { +impl_context_t pow_c_context = { .context = NULL, .description = "CPU (Pure C)", .bitmap = 0, .num_max_thread = 0, .num_working_thread = 0, - .initialize = PoWC_Context_Initialize, - .destroy = PoWC_Context_Destroy, - .getPoWContext = PoWC_getPoWContext, - .freePoWContext = PoWC_freePoWContext, - .doThePoW = PowC, - .getPoWResult = PoWC_getPoWResult, - .getPoWInfo = PoWC_getPoWInfo, + .initialize = pow_c_context_initialize, + .destroy = pow_c_context_destroy, + .get_pow_context = pow_c_get_pow_context, + .free_pow_context = pow_c_free_pow_context, + .do_the_pow = pow_c, + .get_pow_result = pow_c_get_pow_result, + .get_pow_info = pow_c_get_pow_info, }; diff --git a/src/pow_c.h b/src/pow_c.h index bab7478..a99e798 100644 --- a/src/pow_c.h +++ b/src/pow_c.h @@ -16,40 +16,40 @@ #include "trinary.h" #include "uv.h" -typedef struct _pwork_struct Pwork_struct; +typedef struct pwork_s pwork_t; -struct _pwork_struct { +struct pwork_s { int8_t *mid; int mwm; int8_t *nonce; int n; uv_rwlock_t *lock; - int *stopPoW; + int *stop_pow; int index; int64_t ret; }; -typedef struct _pow_c_context PoW_C_Context; +typedef struct pow_c_context_s pow_c_context_t; -struct _pow_c_context { +struct pow_c_context_s { /* Resource of computing */ uv_rwlock_t lock; /* Data type of libtuv */ uv_loop_t loop; uv_work_t *work_req; - Pwork_struct *pitem; + pwork_t *pitem; int8_t **nonce_array; - int stopPoW; + int stop_pow; int num_threads; int num_max_threads; /* Management of Multi-thread */ - int indexOfContext; + int index_of_context; /* Arguments of PoW */ int8_t input_trytes[TRANSACTION_TRYTES_LENGTH]; /* 2673 */ int8_t output_trytes[TRANSACTION_TRYTES_LENGTH]; /* 2673 */ int mwm; /* PoW-related information */ - PoW_Info pow_info; + pow_info_t pow_info; }; #define HBITS 0xFFFFFFFFFFFFFFFFuLL diff --git a/src/pow_cl.c b/src/pow_cl.c index efc641d..a8459ce 100644 --- a/src/pow_cl.c +++ b/src/pow_cl.c @@ -22,31 +22,31 @@ #include "curl.h" #include "implcontext.h" -static CLContext _opencl_ctx[MAX_NUM_DEVICES]; +static cl_context_t opencl_ctx[MAX_NUM_DEVICES]; -static bool write_cl_buffer(CLContext *ctx, +static bool write_cl_buffer(cl_context_t *ctx, int64_t *mid_low, int64_t *mid_high, int mwm, int loop_count) { - cl_command_queue cmdq = ctx->cmdq; - cl_mem *memobj = ctx->buffer; - BufferInfo *buffer_info = ctx->kernel_info.buffer_info; + cl_command_queue cmd_q = ctx->cmd_q; + cl_mem *mem_obj = ctx->buffer; + buffer_info_t *buffer_info = ctx->kernel_info.buffer_info; - if (clEnqueueWriteBuffer(cmdq, memobj[INDEX_OF_MID_LOW], CL_TRUE, 0, + if (clEnqueueWriteBuffer(cmd_q, mem_obj[INDEX_OF_MID_LOW], CL_TRUE, 0, buffer_info[INDEX_OF_MID_LOW].size, mid_low, 0, NULL, NULL) != CL_SUCCESS) return false; - if (clEnqueueWriteBuffer(cmdq, memobj[INDEX_OF_MID_HIGH], CL_TRUE, 0, + if (clEnqueueWriteBuffer(cmd_q, mem_obj[INDEX_OF_MID_HIGH], CL_TRUE, 0, buffer_info[INDEX_OF_MID_HIGH].size, mid_high, 0, NULL, NULL) != CL_SUCCESS) return false; - if (clEnqueueWriteBuffer(cmdq, memobj[INDEX_OF_MWM], CL_TRUE, 0, + if (clEnqueueWriteBuffer(cmd_q, mem_obj[INDEX_OF_MWM], CL_TRUE, 0, buffer_info[INDEX_OF_MWM].size, &mwm, 0, NULL, NULL) != CL_SUCCESS) return false; - if (clEnqueueWriteBuffer(cmdq, memobj[INDEX_OF_LOOP_COUNT], CL_TRUE, 0, + if (clEnqueueWriteBuffer(cmd_q, mem_obj[INDEX_OF_LOOP_COUNT], CL_TRUE, 0, buffer_info[INDEX_OF_LOOP_COUNT].size, &loop_count, 0, NULL, NULL) != CL_SUCCESS) return false; @@ -83,12 +83,12 @@ static void init_state(int8_t *state, mid_high[offset + 3] = HIGH_3; } -static int8_t *pwork(int8_t *state, int mwm, CLContext *ctx) +static int8_t *pwork(int8_t *state, int mwm, cl_context_t *ctx) { size_t local_work_size, global_work_size, global_offset, num_groups; char found = 0; cl_event ev, ev1; - CLContext *titan = ctx; + cl_context_t *titan = ctx; ctx->hash_count = 0; global_offset = 0; num_groups = titan->num_cores; @@ -108,7 +108,7 @@ static int8_t *pwork(int8_t *state, int mwm, CLContext *ctx) return NULL; if (CL_SUCCESS == - clEnqueueNDRangeKernel(titan->cmdq, titan->kernel[INDEX_OF_KERNEL_INIT], + clEnqueueNDRangeKernel(titan->cmd_q, titan->kernel[INDEX_OF_KERNEL_INIT], 1, &global_offset, &global_work_size, &local_work_size, 0, NULL, &ev)) { clWaitForEvents(1, &ev); @@ -118,14 +118,14 @@ static int8_t *pwork(int8_t *state, int mwm, CLContext *ctx) while (found == 0) { if (CL_SUCCESS != clEnqueueNDRangeKernel( - titan->cmdq, titan->kernel[INDEX_OF_KERNEL_SEARCH], 1, NULL, + titan->cmd_q, titan->kernel[INDEX_OF_KERNEL_SEARCH], 1, NULL, &global_work_size, &local_work_size, 0, NULL, &ev1)) { clReleaseEvent(ev1); return NULL; /* Running "search" kernel function failed */ } clWaitForEvents(1, &ev1); clReleaseEvent(ev1); - if (CL_SUCCESS != clEnqueueReadBuffer(titan->cmdq, + if (CL_SUCCESS != clEnqueueReadBuffer(titan->cmd_q, titan->buffer[INDEX_OF_FOUND], CL_TRUE, 0, sizeof(char), &found, 0, NULL, NULL)) { @@ -137,7 +137,7 @@ static int8_t *pwork(int8_t *state, int mwm, CLContext *ctx) } if (CL_SUCCESS != clEnqueueNDRangeKernel( - titan->cmdq, titan->kernel[INDEX_OF_KERNEL_FINALIZE], + titan->cmd_q, titan->kernel[INDEX_OF_KERNEL_FINALIZE], 1, NULL, &global_work_size, &local_work_size, 0, NULL, &ev)) { return NULL; /* Running "finalize" kernel function failed */ @@ -149,7 +149,7 @@ static int8_t *pwork(int8_t *state, int mwm, CLContext *ctx) if (found > 0) { if (CL_SUCCESS != - clEnqueueReadBuffer(titan->cmdq, titan->buffer[INDEX_OF_TRIT_HASH], + clEnqueueReadBuffer(titan->cmd_q, titan->buffer[INDEX_OF_TRIT_HASH], CL_TRUE, 0, HASH_TRITS_LENGTH * sizeof(int8_t), buf, 1, &ev, NULL)) { return NULL; /* Read buffer failed */ @@ -159,13 +159,13 @@ static int8_t *pwork(int8_t *state, int mwm, CLContext *ctx) return buf; } -static int8_t *tx_to_cstate(Trytes_t *tx) +static int8_t *tx_to_cstate(trytes_t *tx) { - Trytes_t *inn = NULL; - Trits_t *tr = NULL; + trytes_t *inn = NULL; + trits_t *tr = NULL; int8_t tyt[TRANSACTION_TRYTES_LENGTH - HASH_TRYTES_LENGTH] = {0}; - Curl *c = initCurl(); + curl_t *c = init_curl(); int8_t *c_state = (int8_t *) malloc(STATE_TRITS_LENGTH); if (!c || !c_state) goto fail; @@ -173,11 +173,11 @@ static int8_t *tx_to_cstate(Trytes_t *tx) /* Copy tx->data[:TRANSACTION_TRYTES_LENGTH - HASH_TRYTES_LENGTH] to tyt */ memcpy(tyt, tx->data, TRANSACTION_TRYTES_LENGTH - HASH_TRYTES_LENGTH); - inn = initTrytes(tyt, TRANSACTION_TRYTES_LENGTH - HASH_TRYTES_LENGTH); + inn = init_trytes(tyt, TRANSACTION_TRYTES_LENGTH - HASH_TRYTES_LENGTH); if (!inn) goto fail; - Absorb(c, inn); + absorb(c, inn); tr = trits_from_trytes(tx); if (!tr) @@ -193,29 +193,29 @@ static int8_t *tx_to_cstate(Trytes_t *tx) c->state->len - tr->len + (TRANSACTION_TRITS_LENGTH - HASH_TRITS_LENGTH)); - freeTrobject(inn); - freeTrobject(tr); - freeCurl(c); + free_trinary_object(inn); + free_trinary_object(tr); + free_curl(c); return c_state; fail: - freeTrobject(inn); - freeTrobject(tr); - freeCurl(c); + free_trinary_object(inn); + free_trinary_object(tr); + free_curl(c); free(c_state); return NULL; } -static bool PowCL(void *pow_ctx) +static bool pow_cl(void *pow_ctx) { bool res = true; int8_t *c_state = NULL, *pow_result = NULL; - Trits_t *tx_trit = NULL; - Trytes_t *tx_tryte, *res_tryte = NULL; + trits_t *tx_trit = NULL; + trytes_t *tx_tryte, *res_tryte = NULL; struct timespec start_time, end_time; - PoW_CL_Context *ctx = (PoW_CL_Context *) pow_ctx; + pow_cl_context_t *ctx = (pow_cl_context_t *) pow_ctx; - tx_tryte = initTrytes(ctx->input_trytes, TRANSACTION_TRYTES_LENGTH); + tx_tryte = init_trytes(ctx->input_trytes, TRANSACTION_TRYTES_LENGTH); if (!tx_tryte) { res = false; goto fail; @@ -234,7 +234,7 @@ static bool PowCL(void *pow_ctx) } clock_gettime(CLOCK_REALTIME, &start_time); - pow_result = pwork(c_state, ctx->mwm, ctx->clctx); + pow_result = pwork(c_state, ctx->mwm, ctx->cl_ctx); clock_gettime(CLOCK_REALTIME, &end_time); ctx->pow_info.time = diff_in_second(start_time, end_time); if (!pow_result) { @@ -251,27 +251,27 @@ static bool PowCL(void *pow_ctx) } memcpy(ctx->output_trytes, res_tryte->data, TRANSACTION_TRYTES_LENGTH); - ctx->pow_info.hash_count = ctx->clctx->hash_count; + ctx->pow_info.hash_count = ctx->cl_ctx->hash_count; fail: - freeTrobject(tx_trit); - freeTrobject(tx_tryte); - freeTrobject(res_tryte); + free_trinary_object(tx_trit); + free_trinary_object(tx_tryte); + free_trinary_object(res_tryte); free(c_state); free(pow_result); return res; } -static bool PoWCL_Context_Initialize(ImplContext *impl_ctx) +static bool pow_cl_context_initialize(impl_context_t *impl_ctx) { - impl_ctx->num_max_thread = init_clcontext(_opencl_ctx); - PoW_CL_Context *ctx = (PoW_CL_Context *) malloc(sizeof(PoW_CL_Context) * + impl_ctx->num_max_thread = init_clcontext(opencl_ctx); + pow_cl_context_t *ctx = (pow_cl_context_t *) malloc(sizeof(pow_cl_context_t) * impl_ctx->num_max_thread); if (!ctx) goto fail; for (int i = 0; i < impl_ctx->num_max_thread; i++) { - ctx[i].clctx = &_opencl_ctx[i]; + ctx[i].cl_ctx = &opencl_ctx[i]; impl_ctx->bitmap = impl_ctx->bitmap << 1 | 0x1; } impl_ctx->context = ctx; @@ -283,13 +283,13 @@ static bool PoWCL_Context_Initialize(ImplContext *impl_ctx) return false; } -static void PoWCL_Context_Destroy(ImplContext *impl_ctx) +static void pow_cl_context_destroy(impl_context_t *impl_ctx) { - PoW_CL_Context *ctx = (PoW_CL_Context *) impl_ctx->context; + pow_cl_context_t *ctx = (pow_cl_context_t *) impl_ctx->context; free(ctx); } -static void *PoWCL_getPoWContext(ImplContext *impl_ctx, +static void *pow_cl_get_pow_context(impl_context_t *impl_ctx, int8_t *trytes, int mwm, int threads) @@ -299,11 +299,11 @@ static void *PoWCL_getPoWContext(ImplContext *impl_ctx, if (impl_ctx->bitmap & (0x1 << i)) { impl_ctx->bitmap &= ~(0x1 << i); uv_mutex_unlock(&impl_ctx->lock); - PoW_CL_Context *ctx = - (PoW_CL_Context *) impl_ctx->context + i; + pow_cl_context_t *ctx = + (pow_cl_context_t *) impl_ctx->context + i; memcpy(ctx->input_trytes, trytes, TRANSACTION_TRYTES_LENGTH); ctx->mwm = mwm; - ctx->indexOfContext = i; + ctx->index_of_context = i; return ctx; } } @@ -311,41 +311,41 @@ static void *PoWCL_getPoWContext(ImplContext *impl_ctx, return NULL; /* It should not happen */ } -static bool PoWCL_freePoWContext(ImplContext *impl_ctx, void *pow_ctx) +static bool pow_cl_free_pow_context(impl_context_t *impl_ctx, void *pow_ctx) { uv_mutex_lock(&impl_ctx->lock); - impl_ctx->bitmap |= 0x1 << ((PoW_CL_Context *) pow_ctx)->indexOfContext; + impl_ctx->bitmap |= 0x1 << ((pow_cl_context_t *) pow_ctx)->index_of_context; uv_mutex_unlock(&impl_ctx->lock); return true; } -static int8_t *PoWCL_getPoWResult(void *pow_ctx) +static int8_t *pow_cl_get_pow_result(void *pow_ctx) { int8_t *ret = (int8_t *) malloc(sizeof(int8_t) * (TRANSACTION_TRYTES_LENGTH)); if (!ret) return NULL; - memcpy(ret, ((PoW_CL_Context *) pow_ctx)->output_trytes, + memcpy(ret, ((pow_cl_context_t *) pow_ctx)->output_trytes, TRANSACTION_TRYTES_LENGTH); return ret; } -static PoW_Info PoWCL_getPoWInfo(void *pow_ctx) +static pow_info_t pow_cl_get_pow_info(void *pow_ctx) { - return ((PoW_CL_Context *) pow_ctx)->pow_info; + return ((pow_cl_context_t *) pow_ctx)->pow_info; } -ImplContext PoWCL_Context = { +impl_context_t pow_cl_context = { .context = NULL, .description = "GPU (OpenCL)", .bitmap = 0, .num_max_thread = 0, .num_working_thread = 0, - .initialize = PoWCL_Context_Initialize, - .destroy = PoWCL_Context_Destroy, - .getPoWContext = PoWCL_getPoWContext, - .freePoWContext = PoWCL_freePoWContext, - .doThePoW = PowCL, - .getPoWResult = PoWCL_getPoWResult, - .getPoWInfo = PoWCL_getPoWInfo, + .initialize = pow_cl_context_initialize, + .destroy = pow_cl_context_destroy, + .get_pow_context = pow_cl_get_pow_context, + .free_pow_context = pow_cl_free_pow_context, + .do_the_pow = pow_cl, + .get_pow_result = pow_cl_get_pow_result, + .get_pow_info = pow_cl_get_pow_info, }; diff --git a/src/pow_cl.h b/src/pow_cl.h index 34c2cd7..5e00f7f 100644 --- a/src/pow_cl.h +++ b/src/pow_cl.h @@ -15,18 +15,18 @@ #include "constants.h" #include "trinary.h" -typedef struct _pow_cl_context PoW_CL_Context; +typedef struct pow_cl_context_s pow_cl_context_t; -struct _pow_cl_context { - CLContext *clctx; +struct pow_cl_context_s { + cl_context_t *cl_ctx; /* Management of Multi-thread */ - int indexOfContext; + int index_of_context; /* Arguments of PoW */ int8_t input_trytes[TRANSACTION_TRYTES_LENGTH]; /* 2673 */ int8_t output_trytes[TRANSACTION_TRYTES_LENGTH]; /* 2673 */ int mwm; /* PoW-related information */ - PoW_Info pow_info; + pow_info_t pow_info; }; /* Number of GPU devices supported */ diff --git a/src/pow_fpga.c b/src/pow_fpga.c index 56ca41f..753973b 100644 --- a/src/pow_fpga.c +++ b/src/pow_fpga.c @@ -31,7 +31,7 @@ /* Set FPGA operation frequency 100 MHz */ #define FPGA_OPERATION_FREQUENCY 100000000 -#define INT2STRING(I, S) \ +#define INT_TO_STRING(I, S) \ { \ S[0] = I & 0xff; \ S[1] = (I >> 8) & 0xff; \ @@ -39,9 +39,9 @@ S[3] = (I >> 24) & 0xff; \ } -static bool PoWFPGA(void *pow_ctx) +static bool pow_fpga(void *pow_ctx) { - PoW_FPGA_Context *ctx = (PoW_FPGA_Context *) pow_ctx; + pow_fpga_context_t *ctx = (pow_fpga_context_t *) pow_ctx; int8_t fpga_out_nonce_trit[NONCE_TRITS_LENGTH]; @@ -53,10 +53,10 @@ static bool PoWFPGA(void *pow_ctx) uint32_t tick_cnt_h; uint64_t tick_cnt; - Trytes_t *object_tryte, *nonce_tryte = NULL; - Trits_t *object_trit = NULL, *object_nonce_trit = NULL; + trytes_t *object_tryte, *nonce_tryte = NULL; + trits_t *object_trit = NULL, *object_nonce_trit = NULL; - object_tryte = initTrytes(ctx->input_trytes, TRANSACTION_TRYTES_LENGTH); + object_tryte = init_trytes(ctx->input_trytes, TRANSACTION_TRYTES_LENGTH); if (!object_tryte) { res = false; goto fail; @@ -78,7 +78,7 @@ static bool PoWFPGA(void *pow_ctx) goto fail; } - INT2STRING(ctx->mwm, buf); + INT_TO_STRING(ctx->mwm, buf); if (write(ctx->ctrl_fd, buf, sizeof(buf)) < 0) { res = false; goto fail; @@ -94,7 +94,7 @@ static bool PoWFPGA(void *pow_ctx) goto fail; } - object_nonce_trit = initTrits(fpga_out_nonce_trit, NONCE_TRITS_LENGTH); + object_nonce_trit = init_trits(fpga_out_nonce_trit, NONCE_TRITS_LENGTH); if (!object_nonce_trit) { res = false; goto fail; @@ -113,22 +113,22 @@ static bool PoWFPGA(void *pow_ctx) ctx->pow_info.time = (double) tick_cnt / (double) FPGA_OPERATION_FREQUENCY; ctx->pow_info.hash_count = *(ctx->cpow_map + HASH_CNT_REG_OFFSET); - memcpy(ctx->output_trytes, ctx->input_trytes, (NonceTrinaryOffset) / 3); - memcpy(ctx->output_trytes + ((NonceTrinaryOffset) / 3), nonce_tryte->data, - ((TRANSACTION_TRITS_LENGTH) - (NonceTrinaryOffset)) / 3); + memcpy(ctx->output_trytes, ctx->input_trytes, (NONCE_TRINARY_OFFSET) / 3); + memcpy(ctx->output_trytes + ((NONCE_TRINARY_OFFSET) / 3), nonce_tryte->data, + ((TRANSACTION_TRITS_LENGTH) - (NONCE_TRINARY_OFFSET)) / 3); fail: - freeTrobject(object_tryte); - freeTrobject(object_trit); - freeTrobject(object_nonce_trit); - freeTrobject(nonce_tryte); + free_trinary_object(object_tryte); + free_trinary_object(object_trit); + free_trinary_object(object_nonce_trit); + free_trinary_object(nonce_tryte); return res; } -static bool PoWFPGA_Context_Initialize(ImplContext *impl_ctx) +static bool pow_fpga_context_initialize(impl_context_t *impl_ctx) { - PoW_FPGA_Context *ctx = - (PoW_FPGA_Context *) malloc(sizeof(PoW_FPGA_Context)); + pow_fpga_context_t *ctx = + (pow_fpga_context_t *) malloc(sizeof(pow_fpga_context_t)); if (!ctx) goto fail_to_malloc; @@ -148,15 +148,15 @@ static bool PoWFPGA_Context_Initialize(ImplContext *impl_ctx) goto fail_to_open_odata; } - ctx->devmem_fd = open(DEV_MEM_FPGA, O_RDWR | O_SYNC); - if (ctx->devmem_fd < 0) { + ctx->dev_mem_fd = open(DEV_MEM_FPGA, O_RDWR | O_SYNC); + if (ctx->dev_mem_fd < 0) { perror("devmem open fail"); goto fail_to_open_mem; } ctx->fpga_regs_map = (uint32_t *) mmap(NULL, HPS_TO_FPGA_SPAN, PROT_READ | PROT_WRITE, - MAP_SHARED, ctx->devmem_fd, HPS_TO_FPGA_BASE); + MAP_SHARED, ctx->dev_mem_fd, HPS_TO_FPGA_BASE); if (ctx->fpga_regs_map == MAP_FAILED) { perror("devmem mmap fial"); goto fail_to_mmap; @@ -169,7 +169,7 @@ static bool PoWFPGA_Context_Initialize(ImplContext *impl_ctx) return true; fail_to_mmap: - close(ctx->devmem_fd); + close(ctx->dev_mem_fd); fail_to_open_mem: close(ctx->out_fd); fail_to_open_odata: @@ -182,9 +182,9 @@ static bool PoWFPGA_Context_Initialize(ImplContext *impl_ctx) return false; } -static void PoWFPGA_Context_Destroy(ImplContext *impl_ctx) +static void pow_fpga_context_destroy(impl_context_t *impl_ctx) { - PoW_FPGA_Context *ctx = (PoW_FPGA_Context *) impl_ctx->context; + pow_fpga_context_t *ctx = (pow_fpga_context_t *) impl_ctx->context; close(ctx->in_fd); close(ctx->out_fd); @@ -194,55 +194,55 @@ static void PoWFPGA_Context_Destroy(ImplContext *impl_ctx) if (result < 0) { perror("devmem munmap fail"); } - close(ctx->devmem_fd); + close(ctx->dev_mem_fd); free(ctx); } -static void *PoWFPGA_getPoWContext(ImplContext *impl_ctx, +static void *pow_fpga_get_pow_context(impl_context_t *impl_ctx, int8_t *trytes, int mwm, int threads) { - PoW_FPGA_Context *ctx = impl_ctx->context; + pow_fpga_context_t *ctx = impl_ctx->context; memcpy(ctx->input_trytes, trytes, TRANSACTION_TRYTES_LENGTH); ctx->mwm = mwm; - ctx->indexOfContext = 0; + ctx->index_of_context = 0; return ctx; } -static bool PoWFPGA_freePoWContext(ImplContext *impl_ctx, void *pow_ctx) +static bool pow_fpga_free_pow_context(impl_context_t *impl_ctx, void *pow_ctx) { return true; } -static int8_t *PoWFPGA_getPoWResult(void *pow_ctx) +static int8_t *pow_fpga_get_pow_result(void *pow_ctx) { int8_t *ret = (int8_t *) malloc(sizeof(int8_t) * TRANSACTION_TRYTES_LENGTH); if (!ret) return NULL; - memcpy(ret, ((PoW_FPGA_Context *) pow_ctx)->output_trytes, + memcpy(ret, ((pow_fpga_context_t *) pow_ctx)->output_trytes, TRANSACTION_TRYTES_LENGTH); return ret; } -static PoW_Info PoWFPGA_getPoWInfo(void *pow_ctx) +static pow_info_t pow_fpga_get_pow_info(void *pow_ctx) { - return ((PoW_FPGA_Context *) pow_ctx)->pow_info; + return ((pow_fpga_context_t *) pow_ctx)->pow_info; } -ImplContext PoWFPGA_Context = { +impl_context_t pow_fpga_context = { .context = NULL, .description = "FPGA", .bitmap = 0, .num_max_thread = 1, // num_max_thread >= 1 .num_working_thread = 0, - .initialize = PoWFPGA_Context_Initialize, - .destroy = PoWFPGA_Context_Destroy, - .getPoWContext = PoWFPGA_getPoWContext, - .freePoWContext = PoWFPGA_freePoWContext, - .doThePoW = PoWFPGA, - .getPoWResult = PoWFPGA_getPoWResult, - .getPoWInfo = PoWFPGA_getPoWInfo, + .initialize = pow_fpga_context_initialize, + .destroy = pow_fpga_context_destroy, + .get_pow_context = pow_fpga_get_pow_context, + .free_pow_context = pow_fpga_free_pow_context, + .do_the_pow = pow_fpga, + .get_pow_result = pow_fpga_get_pow_result, + .get_pow_info = pow_fpga_get_pow_info, }; diff --git a/src/pow_fpga.h b/src/pow_fpga.h index 48bda32..19e3e60 100644 --- a/src/pow_fpga.h +++ b/src/pow_fpga.h @@ -13,22 +13,22 @@ #include "common.h" #include "constants.h" -typedef struct _pow_fpga_context PoW_FPGA_Context; +typedef struct pow_fpga_context_s pow_fpga_context_t; -struct _pow_fpga_context { +struct pow_fpga_context_s { /* Management of Multi-thread */ - int indexOfContext; + int index_of_context; /* Arguments of PoW */ int8_t input_trytes[TRANSACTION_TRYTES_LENGTH]; /* 2673 */ int8_t output_trytes[TRANSACTION_TRYTES_LENGTH]; /* 2673 */ int mwm; /* PoW-related information */ - PoW_Info pow_info; + pow_info_t pow_info; /* Device files for the FPGA accelerator*/ int ctrl_fd; int in_fd; int out_fd; - int devmem_fd; + int dev_mem_fd; /* Memory map of fpga */ void *fpga_regs_map; uint32_t *cpow_map; diff --git a/src/pow_kernel.cl b/src/pow_kernel.cl index 88a81ed..7fbf05a 100644 --- a/src/pow_kernel.cl +++ b/src/pow_kernel.cl @@ -25,7 +25,7 @@ /** * t1 = j == 0? 0:(((j - 1)%2)+1)*HALF_LENGTH - ((j-1)>>1); */ -__constant size_t INDEX[STATE_TRITS_LENGTH + 1] = { +__constant size_t index[STATE_TRITS_LENGTH + 1] = { 0, 364, 728, 363, 727, 362, 726, 361, 725, 360, 724, 359, 723, 358, 722, 357, 721, 356, 720, 355, 719, 354, 718, 353, 717, 352, 716, 351, 715, 350, 714, 349, 713, 348, 712, 347, 711, 346, 710, 345, 709, 344, 708, 343, 707, @@ -135,11 +135,11 @@ void transform(__global bc_trit_t* state_low, __global bc_trit_t* state_high, for (i = 0; i < n_trits; i++) { j = id + i * l_size; k = j+1; - alpha = state_low[INDEX[j]]; - beta = state_high[INDEX[j]]; - delta = alpha & (beta ^ state_low[INDEX[k]]); + alpha = state_low[index[j]]; + beta = state_high[index[j]]; + delta = alpha & (beta ^ state_low[index[k]]); sp_low[i] = ~delta; - sp_high[i] = (alpha ^ state_high[INDEX[k]]) | delta; + sp_high[i] = (alpha ^ state_high[index[k]]) | delta; } barrier(CLK_LOCAL_MEM_FENCE); for (i = 0; i < n_trits; i++) { diff --git a/src/pow_sse.c b/src/pow_sse.c index aa0097d..bb75ff1 100644 --- a/src/pow_sse.c +++ b/src/pow_sse.c @@ -16,7 +16,7 @@ #include "curl.h" #include "implcontext.h" -static void transform128(__m128i *lmid, __m128i *hmid) +static void transform_128(__m128i *lmid, __m128i *hmid) { int t1, t2; __m128i alpha, beta, delta; @@ -50,7 +50,7 @@ static void transform128(__m128i *lmid, __m128i *hmid) } } -static int incr128(__m128i *mid_low, __m128i *mid_high) +static int incr_128(__m128i *mid_low, __m128i *mid_high) { int i; __m128i carry; @@ -66,7 +66,7 @@ static int incr128(__m128i *mid_low, __m128i *mid_high) return i == HASH_TRITS_LENGTH; } -static void seri128(__m128i *low, __m128i *high, int n, int8_t *r) +static void seri_128(__m128i *low, __m128i *high, int n, int8_t *r) { int index = 0; @@ -91,7 +91,7 @@ static void seri128(__m128i *low, __m128i *high, int n, int8_t *r) } } -static int check128(__m128i *l, __m128i *h, int m) +static int check_128(__m128i *l, __m128i *h, int m) { __m128i nonce_probe = _mm_set_epi64x(HBITS, HBITS); @@ -111,18 +111,18 @@ static int check128(__m128i *l, __m128i *h, int m) return -2; } -static int64_t loop128(__m128i *lmid, +static int64_t loop_128(__m128i *lmid, __m128i *hmid, int m, int8_t *nonce, - int *stopPoW, + int *stop_pow, uv_rwlock_t *lock) { int64_t i = 0; __m128i lcpy[STATE_TRITS_LENGTH * 2], hcpy[STATE_TRITS_LENGTH * 2]; uv_rwlock_rdlock(lock); - for (i = 0; !incr128(lmid, hmid) && !*stopPoW; i++) { + for (i = 0; !incr_128(lmid, hmid) && !*stop_pow; i++) { uv_rwlock_rdunlock(lock); int n; for (int j = 0; j < STATE_TRITS_LENGTH; j++) { @@ -130,11 +130,11 @@ static int64_t loop128(__m128i *lmid, hcpy[j] = hmid[j]; } - transform128(lcpy, hcpy); + transform_128(lcpy, hcpy); - if ((n = check128(lcpy + STATE_TRITS_LENGTH, hcpy + STATE_TRITS_LENGTH, + if ((n = check_128(lcpy + STATE_TRITS_LENGTH, hcpy + STATE_TRITS_LENGTH, m)) >= 0) { - seri128(lmid, hmid, n, nonce); + seri_128(lmid, hmid, n, nonce); return i * 128; } uv_rwlock_rdlock(lock); @@ -143,7 +143,7 @@ static int64_t loop128(__m128i *lmid, return -i * 128 - 1; } -static void para128(int8_t in[], __m128i l[], __m128i h[]) +static void para_128(int8_t in[], __m128i l[], __m128i h[]) { for (int i = 0; i < STATE_TRITS_LENGTH; i++) { switch (in[i]) { @@ -163,7 +163,7 @@ static void para128(int8_t in[], __m128i l[], __m128i h[]) } } -static void incrN128(int n, __m128i *mid_low, __m128i *mid_high) +static void incr_n_128(int n, __m128i *mid_low, __m128i *mid_high) { for (int j = 0; j < n; j++) { __m128i carry = _mm_set_epi64x(HBITS, HBITS); @@ -177,15 +177,15 @@ static void incrN128(int n, __m128i *mid_low, __m128i *mid_high) } } -static int64_t pwork128(int8_t mid[], +static int64_t pwork_128(int8_t mid[], int mwm, int8_t nonce[], int n, - int *stopPoW, + int *stop_pow, uv_rwlock_t *lock) { __m128i lmid[STATE_TRITS_LENGTH], hmid[STATE_TRITS_LENGTH]; - para128(mid, lmid, hmid); + para_128(mid, lmid, hmid); int offset = HASH_TRITS_LENGTH - NONCE_TRITS_LENGTH; lmid[offset] = _mm_set_epi64x(LOW00, LOW01); @@ -198,34 +198,34 @@ static int64_t pwork128(int8_t mid[], hmid[offset + 3] = _mm_set_epi64x(HIGH30, HIGH31); lmid[offset + 4] = _mm_set_epi64x(LOW40, LOW41); hmid[offset + 4] = _mm_set_epi64x(HIGH40, HIGH41); - incrN128(n, lmid, hmid); + incr_n_128(n, lmid, hmid); - return loop128(lmid, hmid, mwm, nonce, stopPoW, lock); + return loop_128(lmid, hmid, mwm, nonce, stop_pow, lock); } static void work_cb(uv_work_t *req) { - Pwork_struct *pworkInfo = (Pwork_struct *) req->data; - pworkInfo->ret = - pwork128(pworkInfo->mid, pworkInfo->mwm, pworkInfo->nonce, pworkInfo->n, - pworkInfo->stopPoW, pworkInfo->lock); - - uv_rwlock_wrlock(pworkInfo->lock); - if (pworkInfo->ret >= 0) { - *pworkInfo->stopPoW = 1; + pwork_t *pwork_info = (pwork_t *) req->data; + pwork_info->ret = + pwork_128(pwork_info->mid, pwork_info->mwm, pwork_info->nonce, pwork_info->n, + pwork_info->stop_pow, pwork_info->lock); + + uv_rwlock_wrlock(pwork_info->lock); + if (pwork_info->ret >= 0) { + *pwork_info->stop_pow = 1; /* This means this thread got the result */ - pworkInfo->n = -1; + pwork_info->n = -1; } - uv_rwlock_wrunlock(pworkInfo->lock); + uv_rwlock_wrunlock(pwork_info->lock); } -static int8_t *tx_to_cstate(Trytes_t *tx) +static int8_t *tx_to_cstate(trytes_t *tx) { - Trytes_t *inn = NULL; - Trits_t *tr = NULL; + trytes_t *inn = NULL; + trits_t *tr = NULL; int8_t tyt[TRANSACTION_TRYTES_LENGTH - HASH_TRYTES_LENGTH] = {0}; - Curl *c = initCurl(); + curl_t *c = init_curl(); int8_t *c_state = (int8_t *) malloc(STATE_TRITS_LENGTH); if (!c || !c_state) goto fail; @@ -233,11 +233,11 @@ static int8_t *tx_to_cstate(Trytes_t *tx) /* Copy tx->data[:TRANSACTION_TRYTES_LENGTH - HASH_TRYTES_LENGTH] to tyt */ memcpy(tyt, tx->data, TRANSACTION_TRYTES_LENGTH - HASH_TRYTES_LENGTH); - inn = initTrytes(tyt, TRANSACTION_TRYTES_LENGTH - HASH_TRYTES_LENGTH); + inn = init_trytes(tyt, TRANSACTION_TRYTES_LENGTH - HASH_TRYTES_LENGTH); if (!inn) goto fail; - Absorb(c, inn); + absorb(c, inn); tr = trits_from_trytes(tx); if (!tr) @@ -253,19 +253,19 @@ static int8_t *tx_to_cstate(Trytes_t *tx) c->state->len - tr->len + (TRANSACTION_TRITS_LENGTH - HASH_TRITS_LENGTH)); - freeTrobject(inn); - freeTrobject(tr); - freeCurl(c); + free_trinary_object(inn); + free_trinary_object(tr); + free_curl(c); return c_state; fail: - freeTrobject(inn); - freeTrobject(tr); - freeCurl(c); + free_trinary_object(inn); + free_trinary_object(tr); + free_curl(c); free(c_state); return NULL; } -static void nonce_to_result(Trytes_t *tx, Trytes_t *nonce, int8_t *ret) +static void nonce_to_result(trytes_t *tx, trytes_t *nonce, int8_t *ret) { int rst_len = tx->len - NONCE_TRYTES_LENGTH + nonce->len; @@ -274,26 +274,26 @@ static void nonce_to_result(Trytes_t *tx, Trytes_t *nonce, int8_t *ret) rst_len - (tx->len - NONCE_TRYTES_LENGTH)); } -static bool PowSSE(void *pow_ctx) +static bool pow_sse(void *pow_ctx) { bool res = true; - Trits_t *nonce_trit = NULL; - Trytes_t *tx_tryte = NULL, *nonce_tryte = NULL; + trits_t *nonce_trit = NULL; + trytes_t *tx_tryte = NULL, *nonce_tryte = NULL; struct timespec start_time, end_time; /* Initialize the context */ - PoW_SSE_Context *ctx = (PoW_SSE_Context *) pow_ctx; - ctx->stopPoW = 0; + pow_sse_context_t *ctx = (pow_sse_context_t *) pow_ctx; + ctx->stop_pow = 0; ctx->pow_info.time = 0; ctx->pow_info.hash_count = 0; uv_rwlock_init(&ctx->lock); uv_loop_t *loop_ptr = &ctx->loop; uv_work_t *work_req = ctx->work_req; - Pwork_struct *pitem = ctx->pitem; + pwork_t *pitem = ctx->pitem; int8_t **nonce_array = ctx->nonce_array; /* Prepare the input trytes for algorithm */ - tx_tryte = initTrytes(ctx->input_trytes, TRANSACTION_TRYTES_LENGTH); + tx_tryte = init_trytes(ctx->input_trytes, TRANSACTION_TRYTES_LENGTH); if (!tx_tryte) return false; @@ -311,7 +311,7 @@ static bool PowSSE(void *pow_ctx) pitem[i].nonce = nonce_array[i]; pitem[i].n = i; pitem[i].lock = &ctx->lock; - pitem[i].stopPoW = &ctx->stopPoW; + pitem[i].stop_pow = &ctx->stop_pow; pitem[i].ret = 0; work_req[i].data = &pitem[i]; uv_queue_work(loop_ptr, &work_req[i], work_cb, NULL); @@ -319,17 +319,17 @@ static bool PowSSE(void *pow_ctx) uv_run(loop_ptr, UV_RUN_DEFAULT); - int completedIndex = -1; + int completed_index = -1; for (int i = 0; i < ctx->num_threads; i++) { if (pitem[i].n == -1) - completedIndex = i; + completed_index = i; ctx->pow_info.hash_count += (uint64_t)(pitem[i].ret >= 0 ? pitem[i].ret : -pitem[i].ret + 1); } clock_gettime(CLOCK_REALTIME, &end_time); ctx->pow_info.time = diff_in_second(start_time, end_time); - nonce_trit = initTrits(nonce_array[completedIndex], NONCE_TRITS_LENGTH); + nonce_trit = init_trits(nonce_array[completed_index], NONCE_TRITS_LENGTH); if (!nonce_trit) { res = false; goto fail; @@ -347,20 +347,20 @@ static bool PowSSE(void *pow_ctx) /* Free resource */ uv_rwlock_destroy(&ctx->lock); free(c_state); - freeTrobject(tx_tryte); - freeTrobject(nonce_trit); - freeTrobject(nonce_tryte); + free_trinary_object(tx_tryte); + free_trinary_object(nonce_trit); + free_trinary_object(nonce_tryte); return res; } -static bool PoWSSE_Context_Initialize(ImplContext *impl_ctx) +static bool pow_sse_context_initialize(impl_context_t *impl_ctx) { impl_ctx->num_max_thread = get_nthds_per_phys_proc(); int nproc = get_avail_phys_nprocs(); if (impl_ctx->num_max_thread <= 0 || nproc <= 0) return false; - PoW_SSE_Context *ctx = (PoW_SSE_Context *) malloc(sizeof(PoW_SSE_Context) * + pow_sse_context_t *ctx = (pow_sse_context_t *) malloc(sizeof(pow_sse_context_t) * impl_ctx->num_max_thread); if (!ctx) return false; @@ -369,7 +369,7 @@ static bool PoWSSE_Context_Initialize(ImplContext *impl_ctx) void *work_req_chunk = malloc(impl_ctx->num_max_thread * sizeof(uv_work_t) * nproc); void *pitem_chunk = - malloc(impl_ctx->num_max_thread * sizeof(Pwork_struct) * nproc); + malloc(impl_ctx->num_max_thread * sizeof(pwork_t) * nproc); void *nonce_ptr_chunk = malloc(impl_ctx->num_max_thread * sizeof(int8_t *) * nproc); void *nonce_chunk = @@ -379,7 +379,7 @@ static bool PoWSSE_Context_Initialize(ImplContext *impl_ctx) for (int i = 0; i < impl_ctx->num_max_thread; i++) { ctx[i].work_req = (uv_work_t *) (work_req_chunk) + i * nproc; - ctx[i].pitem = (Pwork_struct *) (pitem_chunk) + i * nproc; + ctx[i].pitem = (pwork_t *) (pitem_chunk) + i * nproc; ctx[i].nonce_array = (int8_t **) (nonce_ptr_chunk) + i * nproc; for (int j = 0; j < nproc; j++) ctx[i].nonce_array[j] = (int8_t *) (nonce_chunk) + @@ -406,9 +406,9 @@ static bool PoWSSE_Context_Initialize(ImplContext *impl_ctx) return false; } -static void PoWSSE_Context_Destroy(ImplContext *impl_ctx) +static void pow_sse_context_destroy(impl_context_t *impl_ctx) { - PoW_SSE_Context *ctx = (PoW_SSE_Context *) impl_ctx->context; + pow_sse_context_t *ctx = (pow_sse_context_t *) impl_ctx->context; for (int i = 0; i < impl_ctx->num_max_thread; i++) { uv_loop_close(&ctx[i].loop); } @@ -419,7 +419,7 @@ static void PoWSSE_Context_Destroy(ImplContext *impl_ctx) free(ctx); } -static void *PoWSSE_getPoWContext(ImplContext *impl_ctx, +static void *pow_sse_get_pow_context(impl_context_t *impl_ctx, int8_t *trytes, int mwm, int threads) @@ -429,10 +429,10 @@ static void *PoWSSE_getPoWContext(ImplContext *impl_ctx, if (impl_ctx->bitmap & (0x1 << i)) { impl_ctx->bitmap &= ~(0x1 << i); uv_mutex_unlock(&impl_ctx->lock); - PoW_SSE_Context *ctx = (PoW_SSE_Context *) impl_ctx->context + i; + pow_sse_context_t *ctx = (pow_sse_context_t *) impl_ctx->context + i; memcpy(ctx->input_trytes, trytes, TRANSACTION_TRYTES_LENGTH); ctx->mwm = mwm; - ctx->indexOfContext = i; + ctx->index_of_context = i; if (threads > 0 && threads < ctx->num_max_threads) ctx->num_threads = threads; else @@ -444,41 +444,41 @@ static void *PoWSSE_getPoWContext(ImplContext *impl_ctx, return NULL; /* It should not happen */ } -static bool PoWSSE_freePoWContext(ImplContext *impl_ctx, void *pow_ctx) +static bool pow_sse_free_pow_context(impl_context_t *impl_ctx, void *pow_ctx) { uv_mutex_lock(&impl_ctx->lock); - impl_ctx->bitmap |= 0x1 << ((PoW_SSE_Context *) pow_ctx)->indexOfContext; + impl_ctx->bitmap |= 0x1 << ((pow_sse_context_t *) pow_ctx)->index_of_context; uv_mutex_unlock(&impl_ctx->lock); return true; } -static int8_t *PoWSSE_getPoWResult(void *pow_ctx) +static int8_t *pow_sse_get_pow_result(void *pow_ctx) { int8_t *ret = (int8_t *) malloc(sizeof(int8_t) * (TRANSACTION_TRYTES_LENGTH)); if (!ret) return NULL; - memcpy(ret, ((PoW_SSE_Context *) pow_ctx)->output_trytes, + memcpy(ret, ((pow_sse_context_t *) pow_ctx)->output_trytes, TRANSACTION_TRYTES_LENGTH); return ret; } -static PoW_Info PoWSSE_getPoWInfo(void *pow_ctx) +static pow_info_t pow_sse_get_pow_info(void *pow_ctx) { - return ((PoW_SSE_Context *) pow_ctx)->pow_info; + return ((pow_sse_context_t *) pow_ctx)->pow_info; } -ImplContext PoWSSE_Context = { +impl_context_t pow_sse_context = { .context = NULL, .description = "CPU (Intel SSE)", .bitmap = 0, .num_max_thread = 0, .num_working_thread = 0, - .initialize = PoWSSE_Context_Initialize, - .destroy = PoWSSE_Context_Destroy, - .getPoWContext = PoWSSE_getPoWContext, - .freePoWContext = PoWSSE_freePoWContext, - .doThePoW = PowSSE, - .getPoWResult = PoWSSE_getPoWResult, - .getPoWInfo = PoWSSE_getPoWInfo, + .initialize = pow_sse_context_initialize, + .destroy = pow_sse_context_destroy, + .get_pow_context = pow_sse_get_pow_context, + .free_pow_context = pow_sse_free_pow_context, + .do_the_pow = pow_sse, + .get_pow_result = pow_sse_get_pow_result, + .get_pow_info = pow_sse_get_pow_info, }; diff --git a/src/pow_sse.h b/src/pow_sse.h index 4216b59..c08f5ad 100644 --- a/src/pow_sse.h +++ b/src/pow_sse.h @@ -16,39 +16,39 @@ #include "trinary.h" #include "uv.h" -typedef struct _pwork_struct Pwork_struct; +typedef struct pwork_s pwork_t; -struct _pwork_struct { +struct pwork_s { int8_t *mid; int mwm; int8_t *nonce; int n; uv_rwlock_t *lock; - int *stopPoW; + int *stop_pow; int64_t ret; }; -typedef struct _pow_sse_context PoW_SSE_Context; +typedef struct pow_sse_context_s pow_sse_context_t; -struct _pow_sse_context { +struct pow_sse_context_s { /* Resource of computing */ uv_rwlock_t lock; /* Data type of libtuv */ uv_loop_t loop; uv_work_t *work_req; - Pwork_struct *pitem; + pwork_t *pitem; int8_t **nonce_array; - int stopPoW; + int stop_pow; int num_threads; int num_max_threads; /* Management of Multi-thread */ - int indexOfContext; + int index_of_context; /* Arguments of PoW */ int8_t input_trytes[TRANSACTION_TRYTES_LENGTH]; /* 2673 */ int8_t output_trytes[TRANSACTION_TRYTES_LENGTH]; /* 2673 */ int mwm; /* PoW-related information */ - PoW_Info pow_info; + pow_info_t pow_info; }; #ifdef _MSC_VER diff --git a/src/remote_common.c b/src/remote_common.c index a24fd77..5d813c8 100644 --- a/src/remote_common.c +++ b/src/remote_common.c @@ -64,10 +64,10 @@ bool die_on_error(int x, char const *context) return true; } -bool connect_broker(amqp_connection_state_t *conn, const char *hostName) +bool connect_broker(amqp_connection_state_t *conn, const char *host_name) { amqp_socket_t *socket = NULL; - const char *host = (hostName != NULL) ? hostName : "localhost"; + const char *host = (host_name != NULL) ? host_name : "localhost"; /* Connect to the rabbitmq broker */ *conn = amqp_new_connection(); diff --git a/src/remote_interface.c b/src/remote_interface.c index 48fcc02..0c55144 100644 --- a/src/remote_interface.c +++ b/src/remote_interface.c @@ -10,17 +10,17 @@ #include #include "trinary.h" -extern struct list_head REMOTE_IMPL_LIST; +extern struct list_head remote_impl_list; -bool registerRemoteContext(RemoteImplContext *remote_ctx) +bool register_remote_context(remote_impl_context_t *remote_ctx) { - bool res = initializeRemoteContext(remote_ctx); + bool res = initialize_remote_context(remote_ctx); if (res) - list_add(&remote_ctx->node, &REMOTE_IMPL_LIST); + list_add(&remote_ctx->node, &remote_impl_list); return res; } -bool initializeRemoteContext(RemoteImplContext *remote_ctx) +bool initialize_remote_context(remote_impl_context_t *remote_ctx) { bool res = remote_ctx->initialize(remote_ctx); if (res) { @@ -31,12 +31,12 @@ bool initializeRemoteContext(RemoteImplContext *remote_ctx) return res; } -void destroyRemoteContext(RemoteImplContext *remote_ctx) +void destroy_remote_context(remote_impl_context_t *remote_ctx) { return remote_ctx->destroy(remote_ctx); } -bool enterRemoteContext(RemoteImplContext *remote_ctx) +bool enter_remote_context(remote_impl_context_t *remote_ctx) { uv_mutex_lock(&remote_ctx->lock); if (remote_ctx->num_working_thread >= remote_ctx->num_max_thread) { @@ -48,48 +48,48 @@ bool enterRemoteContext(RemoteImplContext *remote_ctx) return true; /* Access Success */ } -void *getRemoteContext(RemoteImplContext *remote_ctx, int8_t *trytes, int mwm) +void *get_remote_context(remote_impl_context_t *remote_ctx, int8_t *trytes, int mwm) { - return remote_ctx->getPoWContext(remote_ctx, trytes, mwm); + return remote_ctx->get_pow_context(remote_ctx, trytes, mwm); } -bool doRemoteContext(RemoteImplContext *remote_ctx, void *pow_ctx) +bool do_remote_context(remote_impl_context_t *remote_ctx, void *pow_ctx) { - return remote_ctx->doThePoW(remote_ctx, pow_ctx); + return remote_ctx->do_the_pow(remote_ctx, pow_ctx); } -int8_t *getRemoteResult(RemoteImplContext *remote_ctx, void *pow_ctx) +int8_t *get_remote_result(remote_impl_context_t *remote_ctx, void *pow_ctx) { - return remote_ctx->getPoWResult(pow_ctx); + return remote_ctx->get_pow_result(pow_ctx); } -bool freeRemoteContext(RemoteImplContext *remote_ctx, void *pow_ctx) +bool free_remote_context(remote_impl_context_t *remote_ctx, void *pow_ctx) { - return remote_ctx->freePoWContext(remote_ctx, pow_ctx); + return remote_ctx->free_pow_context(remote_ctx, pow_ctx); } -void exitRemoteContext(RemoteImplContext *remote_ctx) +void exit_remote_context(remote_impl_context_t *remote_ctx) { uv_mutex_lock(&remote_ctx->lock); remote_ctx->num_working_thread--; uv_mutex_unlock(&remote_ctx->lock); } -bool PoWValidation(int8_t *output_trytes, int mwm) +bool pow_validation(int8_t *output_trytes, int mwm) { - Trytes_t *trytes_t = initTrytes(output_trytes, TRANSACTION_TRYTES_LENGTH); - if (!trytes_t) { + trytes_t *trytes = init_trytes(output_trytes, TRANSACTION_TRYTES_LENGTH); + if (!trytes) { log_debug(0, "PoW Validation: Initialization of Trytes fails\n"); goto fail_to_inittrytes; } - Trytes_t *hash_trytes = hashTrytes(trytes_t); - if (!hash_trytes) { + trytes_t *hashed_trytes = hash_trytes(trytes); + if (!hashed_trytes) { log_debug(0, "PoW Validation: Hashing trytes fails\n"); goto fail_to_hashtrytes; } - Trits_t *ret_trits = trits_from_trytes(hash_trytes); + trits_t *ret_trits = trits_from_trytes(hashed_trytes); for (int i = 243 - 1; i >= 243 - mwm; i--) { if (ret_trits->data[i] != 0) { log_debug(0, "PoW Validation fails\n"); @@ -100,45 +100,45 @@ bool PoWValidation(int8_t *output_trytes, int mwm) return true; fail_to_validation: - freeTrobject(ret_trits); - freeTrobject(hash_trytes); + free_trinary_object(ret_trits); + free_trinary_object(hashed_trytes); fail_to_hashtrytes: - freeTrobject(trytes_t); + free_trinary_object(trytes); fail_to_inittrytes: return false; } -static bool Remote_doPoW(RemoteImplContext *remote_ctx, void *pow_ctx) +static bool remote_do_pow(remote_impl_context_t *remote_ctx, void *pow_ctx) { char buf[4]; char messagebody[TRANSACTION_TRYTES_LENGTH + 4]; amqp_bytes_t reply_to_queue; - PoW_Remote_Context *ctx = (PoW_Remote_Context *) pow_ctx; + pow_remote_context_t *ctx = (pow_remote_context_t *) pow_ctx; /* Message body format: transacton | mwm */ memcpy(messagebody, ctx->input_trytes, TRANSACTION_TRYTES_LENGTH); snprintf(buf, sizeof(buf), "%d", ctx->mwm); memcpy(messagebody + TRANSACTION_TRYTES_LENGTH, buf, 4); - if (!declare_callback_queue(&remote_ctx->conn[ctx->indexOfContext], 1, + if (!declare_callback_queue(&remote_ctx->conn[ctx->index_of_context], 1, &reply_to_queue)) goto fail; - if (!publish_message_with_reply_to(&remote_ctx->conn[ctx->indexOfContext], + if (!publish_message_with_reply_to(&remote_ctx->conn[ctx->index_of_context], 1, "incoming_queue", reply_to_queue, messagebody)) goto fail; - if (!wait_response_message(&remote_ctx->conn[ctx->indexOfContext], 1, + if (!wait_response_message(&remote_ctx->conn[ctx->index_of_context], 1, reply_to_queue, (char *) (ctx->output_trytes), TRANSACTION_TRYTES_LENGTH)) goto fail; amqp_bytes_free(reply_to_queue); - PoWValidation(ctx->output_trytes, ctx->mwm); + pow_validation(ctx->output_trytes, ctx->mwm); return true; @@ -146,13 +146,13 @@ static bool Remote_doPoW(RemoteImplContext *remote_ctx, void *pow_ctx) return false; } -static bool Remote_init(RemoteImplContext *remote_ctx) +static bool remote_init(remote_impl_context_t *remote_ctx) { if (remote_ctx->num_max_thread <= 0) goto fail_to_max_thread; - PoW_Remote_Context *ctx = (PoW_Remote_Context *) malloc( - sizeof(PoW_Remote_Context) * remote_ctx->num_max_thread); + pow_remote_context_t *ctx = (pow_remote_context_t *) malloc( + sizeof(pow_remote_context_t) * remote_ctx->num_max_thread); memset(remote_ctx->slots, 0, remote_ctx->num_max_thread * sizeof(bool)); @@ -175,9 +175,9 @@ static bool Remote_init(RemoteImplContext *remote_ctx) return false; } -static void Remote_destroy(RemoteImplContext *remote_ctx) +static void remote_destroy(remote_impl_context_t *remote_ctx) { - PoW_Remote_Context *ctx = (PoW_Remote_Context *) remote_ctx->context; + pow_remote_context_t *ctx = (pow_remote_context_t *) remote_ctx->context; for (int i = 0; i < CONN_MAX; i++) disconnect_broker(&remote_ctx->conn[i]); @@ -185,7 +185,7 @@ static void Remote_destroy(RemoteImplContext *remote_ctx) free(ctx); } -static void *Remote_getPoWContext(RemoteImplContext *remote_ctx, +static void *remote_get_pow_context(remote_impl_context_t *remote_ctx, int8_t *trytes, int mwm) { @@ -196,11 +196,11 @@ static void *Remote_getPoWContext(RemoteImplContext *remote_ctx, remote_ctx->slots[i] = true; uv_mutex_unlock(&remote_ctx->lock); - PoW_Remote_Context *ctx = - (PoW_Remote_Context *) remote_ctx->context + i; + pow_remote_context_t *ctx = + (pow_remote_context_t *) remote_ctx->context + i; memcpy(ctx->input_trytes, trytes, TRANSACTION_TRYTES_LENGTH); ctx->mwm = mwm; - ctx->indexOfContext = i; + ctx->index_of_context = i; return ctx; } @@ -211,42 +211,42 @@ static void *Remote_getPoWContext(RemoteImplContext *remote_ctx, return NULL; /* It should not happen */ } -static bool Remote_freePoWContext(RemoteImplContext *remote_ctx, void *pow_ctx) +static bool remote_free_pow_context(remote_impl_context_t *remote_ctx, void *pow_ctx) { uv_mutex_lock(&remote_ctx->lock); - remote_ctx->slots[((PoW_Remote_Context *) pow_ctx)->indexOfContext] = false; + remote_ctx->slots[((pow_remote_context_t *) pow_ctx)->index_of_context] = false; uv_mutex_unlock(&remote_ctx->lock); return true; } -static int8_t *Remote_getPoWResult(void *pow_ctx) +static int8_t *remote_get_pow_result(void *pow_ctx) { int8_t *ret = (int8_t *) malloc(sizeof(int8_t) * TRANSACTION_TRYTES_LENGTH); if (!ret) return NULL; - memcpy(ret, ((PoW_Remote_Context *) pow_ctx)->output_trytes, + memcpy(ret, ((pow_remote_context_t *) pow_ctx)->output_trytes, TRANSACTION_TRYTES_LENGTH); return ret; } -static PoW_Info Remote_getPoWInfo(void *pow_ctx) +static pow_info_t remote_get_pow_info(void *pow_ctx) { - return ((PoW_Remote_Context *) pow_ctx)->pow_info; + return ((pow_remote_context_t *) pow_ctx)->pow_info; } -RemoteImplContext Remote_Context = { +remote_impl_context_t remote_context = { .context = NULL, .description = "Remote interface", .num_max_thread = CONN_MAX, // 1 <= num_max_thread .num_working_thread = 0, - .initialize = Remote_init, - .destroy = Remote_destroy, - .getPoWContext = Remote_getPoWContext, - .freePoWContext = Remote_freePoWContext, - .doThePoW = Remote_doPoW, - .getPoWResult = Remote_getPoWResult, - .getPoWInfo = Remote_getPoWInfo, + .initialize = remote_init, + .destroy = remote_destroy, + .get_pow_context = remote_get_pow_context, + .free_pow_context = remote_free_pow_context, + .do_the_pow = remote_do_pow, + .get_pow_result = remote_get_pow_result, + .get_pow_info = remote_get_pow_info, }; diff --git a/src/remote_interface.h b/src/remote_interface.h index 835df1d..7d3d560 100644 --- a/src/remote_interface.h +++ b/src/remote_interface.h @@ -19,21 +19,21 @@ #define CONN_MAX 20 -typedef struct _pow_remote_context PoW_Remote_Context; -typedef struct _remote_impl_context RemoteImplContext; +typedef struct pow_remote_context_s pow_remote_context_t; +typedef struct remote_impl_context_s remote_impl_context_t; -struct _pow_remote_context { +struct pow_remote_context_s { /* Thread management */ - int indexOfContext; + int index_of_context; /* Arguments of PoW */ int8_t input_trytes[TRANSACTION_TRYTES_LENGTH]; /* 2673 */ int8_t output_trytes[TRANSACTION_TRYTES_LENGTH]; /* 2673 */ int mwm; /* PoW-related information */ - PoW_Info pow_info; + pow_info_t pow_info; }; -struct _remote_impl_context { +struct remote_impl_context_s { void *context; char *description; /* Connection parameters */ @@ -46,29 +46,29 @@ struct _remote_impl_context { int num_working_thread; /* Functions of Implementation Context */ - bool (*initialize)(RemoteImplContext *remote_ctx); - void (*destroy)(RemoteImplContext *remote_ctx); + bool (*initialize)(remote_impl_context_t *remote_ctx); + void (*destroy)(remote_impl_context_t *remote_ctx); /* Private PoW Context for each thread */ - void *(*getPoWContext)(RemoteImplContext *remote_ctx, + void *(*get_pow_context)(remote_impl_context_t *remote_ctx, int8_t *trytes, int mwm); - bool (*doThePoW)(RemoteImplContext *remote_ctx, void *pow_ctx); - int8_t *(*getPoWResult)(void *pow_ctx); - PoW_Info (*getPoWInfo)(void *pow_ctx); - bool (*freePoWContext)(RemoteImplContext *remote_ctx, void *pow_ctx); + bool (*do_the_pow)(remote_impl_context_t *remote_ctx, void *pow_ctx); + int8_t *(*get_pow_result)(void *pow_ctx); + pow_info_t (*get_pow_info)(void *pow_ctx); + bool (*free_pow_context)(remote_impl_context_t *remote_ctx, void *pow_ctx); /* Node in linked list */ struct list_head node; }; -bool registerRemoteContext(RemoteImplContext *remote_ctx); -bool initializeRemoteContext(RemoteImplContext *remote_ctx); -void destroyRemoteContext(RemoteImplContext *remote_ctx); -bool enterRemoteContext(RemoteImplContext *remote_ctx); -void *getRemoteContext(RemoteImplContext *remote_ctx, int8_t *trytes, int mwm); -bool doRemoteContext(RemoteImplContext *remote_ctx, void *pow_ctx); -int8_t *getRemoteResult(RemoteImplContext *remote_ctx, void *pow_ctx); -bool freeRemoteContext(RemoteImplContext *remote_ctx, void *pow_ctx); -void exitRemoteContext(RemoteImplContext *remote_ctx); +bool register_remote_context(remote_impl_context_t *remote_ctx); +bool initialize_remote_context(remote_impl_context_t *remote_ctx); +void destroy_remote_context(remote_impl_context_t *remote_ctx); +bool enter_remote_context(remote_impl_context_t *remote_ctx); +void *get_remote_context(remote_impl_context_t *remote_ctx, int8_t *trytes, int mwm); +bool do_remote_context(remote_impl_context_t *remote_ctx, void *pow_ctx); +int8_t *get_remote_result(remote_impl_context_t *remote_ctx, void *pow_ctx); +bool free_remote_context(remote_impl_context_t *remote_ctx, void *pow_ctx); +void exit_remote_context(remote_impl_context_t *remote_ctx); #endif diff --git a/src/remote_worker.c b/src/remote_worker.c index d75627a..5d8a601 100644 --- a/src/remote_worker.c +++ b/src/remote_worker.c @@ -17,34 +17,34 @@ int main(int argc, char *const *argv) char trytes[TRANSACTION_TRYTES_LENGTH]; char buf[4]; int mwm; - int cmdOpt; - int optIdx; - const struct option longOpt[] = {{"broker", required_argument, NULL, 'b'}, + int cmd_opt; + int opt_idx; + const struct option long_opt[] = {{"broker", required_argument, NULL, 'b'}, {NULL, 0, NULL, 0}}; amqp_connection_state_t conn; amqp_envelope_t envelope; - char *hostIP = NULL; + char *host_ip = NULL; /* Parse the command line options */ /* TODO: Support macOS since getopt_long() is GNU extension */ while (1) { - cmdOpt = getopt_long(argc, argv, "b:", longOpt, &optIdx); - if (cmdOpt == -1) + cmd_opt = getopt_long(argc, argv, "b:", long_opt, &opt_idx); + if (cmd_opt == -1) break; /* Invalid option */ - if (cmdOpt == '?') + if (cmd_opt == '?') break; - if (cmdOpt == 'b') { - hostIP = optarg; + if (cmd_opt == 'b') { + host_ip = optarg; } } dcurl_init(); - if (!connect_broker(&conn, hostIP)) + if (!connect_broker(&conn, host_ip)) goto fail; if (!declare_queue(&conn, 1, "incoming_queue")) diff --git a/src/trinary.c b/src/trinary.c index ce58277..8370e33 100644 --- a/src/trinary.c +++ b/src/trinary.c @@ -14,14 +14,14 @@ #include "constants.h" #include "curl.h" -int8_t TrytesToTritsMappings[][3] = { +int8_t trytes_to_trits_mappings[][3] = { {0, 0, 0}, {1, 0, 0}, {-1, 1, 0}, {0, 1, 0}, {1, 1, 0}, {-1, -1, 1}, {0, -1, 1}, {1, -1, 1}, {-1, 0, 1}, {0, 0, 1}, {1, 0, 1}, {-1, 1, 1}, {0, 1, 1}, {1, 1, 1}, {-1, -1, -1}, {0, -1, -1}, {1, -1, -1}, {-1, 0, -1}, {0, 0, -1}, {1, 0, -1}, {-1, 1, -1}, {0, 1, -1}, {1, 1, -1}, {-1, -1, 0}, {0, -1, 0}, {1, -1, 0}, {-1, 0, 0}}; -void freeTrobject(Trobject_t *t) +void free_trinary_object(trinary_object_t *t) { if (t) { if (t->data) @@ -30,13 +30,13 @@ void freeTrobject(Trobject_t *t) } } -static bool validateTrits(Trobject_t *trits) +static bool validate_trits(trinary_object_t *trits) { if (trits->type != TYPE_TRITS) return false; #if defined(__SSE4_2__) || defined(__ARM_NEON) - return validateTrits_sse42(trits); + return validate_trits_sse42(trits); #endif for (int i = 0; i < trits->len; i++) if (trits->data[i] < -1 || trits->data[i] > 1) @@ -44,13 +44,13 @@ static bool validateTrits(Trobject_t *trits) return true; } -static bool validateTrytes(Trobject_t *trytes) +static bool validate_trytes(trinary_object_t *trytes) { if (trytes->type != TYPE_TRYTES) return false; #if defined(__SSE4_2__) - return validateTrytes_sse42(trytes); + return validate_trytes_sse42(trytes); #endif for (int i = 0; i < trytes->len; i++) if ((trytes->data[i] < 'A' || trytes->data[i] > 'Z') && @@ -59,11 +59,11 @@ static bool validateTrytes(Trobject_t *trytes) return true; } -Trobject_t *initTrits(int8_t *src, int len) +trinary_object_t *init_trits(int8_t *src, int len) { - Trobject_t *trits; + trinary_object_t *trits; - trits = (Trobject_t *) malloc(sizeof(Trobject_t)); + trits = (trinary_object_t *) malloc(sizeof(trinary_object_t)); if (!trits) return NULL; @@ -81,8 +81,8 @@ Trobject_t *initTrits(int8_t *src, int len) trits->data[len] = '\0'; /* Check validation */ - if (!validateTrits(trits)) { - freeTrobject(trits); + if (!validate_trits(trits)) { + free_trinary_object(trits); /* Not availabe src */ return NULL; } @@ -90,11 +90,11 @@ Trobject_t *initTrits(int8_t *src, int len) return trits; } -Trobject_t *initTrytes(int8_t *src, int len) +trinary_object_t *init_trytes(int8_t *src, int len) { - Trobject_t *trytes; + trinary_object_t *trytes; - trytes = (Trobject_t *) malloc(sizeof(Trobject_t)); + trytes = (trinary_object_t *) malloc(sizeof(trinary_object_t)); if (!trytes) { return NULL; } @@ -113,8 +113,8 @@ Trobject_t *initTrytes(int8_t *src, int len) trytes->data[len] = '\0'; /* Check validation */ - if (!validateTrytes(trytes)) { - freeTrobject(trytes); + if (!validate_trytes(trytes)) { + free_trinary_object(trytes); /* Not available src */ return NULL; } @@ -122,13 +122,13 @@ Trobject_t *initTrytes(int8_t *src, int len) return trytes; } -Trobject_t *trytes_from_trits(Trobject_t *trits) +trinary_object_t *trytes_from_trits(trinary_object_t *trits) { if (!trits) { return NULL; } - if (trits->len % 3 != 0 || !validateTrits(trits)) { + if (trits->len % 3 != 0 || !validate_trits(trits)) { /* Not available trits to convert */ return NULL; } @@ -136,7 +136,7 @@ Trobject_t *trytes_from_trits(Trobject_t *trits) #if defined(__SSE4_2__) return trytes_from_trits_sse42(trits); #endif - Trobject_t *trytes = NULL; + trinary_object_t *trytes = NULL; int8_t *src = (int8_t *) malloc(trits->len / 3); /* Start converting */ @@ -146,21 +146,21 @@ Trobject_t *trytes_from_trits(Trobject_t *trits) if (j < 0) j += 27; - src[i] = TryteAlphabet[j]; + src[i] = tryte_alphabet[j]; } - trytes = initTrytes(src, trits->len / 3); + trytes = init_trytes(src, trits->len / 3); free(src); return trytes; } -Trobject_t *trits_from_trytes(Trobject_t *trytes) +trinary_object_t *trits_from_trytes(trinary_object_t *trytes) { if (!trytes) return NULL; - if (!validateTrytes(trytes)) { + if (!validate_trytes(trytes)) { /* trytes is not available to convert */ return NULL; } @@ -168,39 +168,39 @@ Trobject_t *trits_from_trytes(Trobject_t *trytes) #if defined(__SSE4_2__) return trits_from_trytes_sse42(trytes); #endif - Trobject_t *trits = NULL; + trinary_object_t *trits = NULL; int8_t *src = (int8_t *) malloc(trytes->len * 3); /* Start converting */ for (int i = 0; i < trytes->len; i++) { int idx = (trytes->data[i] == '9') ? 0 : trytes->data[i] - 'A' + 1; for (int j = 0; j < 3; j++) { - src[i * 3 + j] = TrytesToTritsMappings[idx][j]; + src[i * 3 + j] = trytes_to_trits_mappings[idx][j]; } } - trits = initTrits(src, trytes->len * 3); + trits = init_trits(src, trytes->len * 3); free(src); return trits; } -Trobject_t *hashTrytes(Trobject_t *t) +trinary_object_t *hash_trytes(trinary_object_t *t) { if (t->type != TYPE_TRYTES) return NULL; - Curl *c = initCurl(); + curl_t *c = init_curl(); if (!c) return NULL; - Absorb(c, t); - Trobject_t *ret = Squeeze(c); + absorb(c, t); + trinary_object_t *ret = squeeze(c); - freeCurl(c); + free_curl(c); return ret; } -bool compareTrobject(Trobject_t *a, Trobject_t *b) +bool compare_trinary_object(trinary_object_t *a, trinary_object_t *b) { if (a->type != b->type || a->len != b->len) return false; diff --git a/src/trinary.h b/src/trinary.h index f01cffc..7e23104 100644 --- a/src/trinary.h +++ b/src/trinary.h @@ -18,23 +18,23 @@ #define TYPE_TRITS 1 #define TYPE_TRYTES 2 -typedef struct _trinary_object { +typedef struct trinary_object_s { int8_t *data; int len; int type; -} Trobject_t; +} trinary_object_t; -typedef Trobject_t Trits_t; -typedef Trobject_t Trytes_t; +typedef trinary_object_t trits_t; +typedef trinary_object_t trytes_t; -Trobject_t *initTrits(int8_t *src, int len); -Trobject_t *initTrytes(int8_t *src, int len); +trinary_object_t *init_trits(int8_t *src, int len); +trinary_object_t *init_trytes(int8_t *src, int len); -Trobject_t *trytes_from_trits(Trobject_t *trits); -Trobject_t *trits_from_trytes(Trobject_t *trytes); -Trobject_t *hashTrytes(Trobject_t *t); +trinary_object_t *trytes_from_trits(trinary_object_t *trits); +trinary_object_t *trits_from_trytes(trinary_object_t *trytes); +trinary_object_t *hash_trytes(trinary_object_t *t); -bool compareTrobject(Trobject_t *a, Trobject_t *b); -void freeTrobject(Trobject_t *t); +bool compare_trinary_object(trinary_object_t *a, trinary_object_t *b); +void free_trinary_object(trinary_object_t *t); #endif diff --git a/src/trinary_sse42.h b/src/trinary_sse42.h index 93bde64..b662640 100644 --- a/src/trinary_sse42.h +++ b/src/trinary_sse42.h @@ -42,28 +42,28 @@ #define REPEAT11(str) REPEAT10(str), str #define REPEAT(n, str) REPEAT##n(str) -extern int8_t TrytesToTritsMappings[][3]; +extern int8_t trytes_to_trits_mappings[][3]; -static inline bool validateTrits_sse42(Trobject_t *trits) +static inline bool validate_trits_sse42(trinary_object_t *trits) { const int block_8bit = BLOCK_8BIT(__m128i); - const int posOneElement = 0x01010101; - const int negOneElement = 0xFFFFFFFF; - const __m128i posOne = _mm_set_epi32(posOneElement, posOneElement, - posOneElement, posOneElement); - const __m128i negOne = _mm_set_epi32(negOneElement, negOneElement, - negOneElement, negOneElement); + const int pos_one_element = 0x01010101; + const int neg_one_element = 0xFFFFFFFF; + const __m128i pos_one = _mm_set_epi32(pos_one_element, pos_one_element, + pos_one_element, pos_one_element); + const __m128i neg_one = _mm_set_epi32(neg_one_element, neg_one_element, + neg_one_element, neg_one_element); /* The for loop handles the group of the 128-bit characters without the * end-of-string */ for (int i = 0; i < (trits->len) / block_8bit; i++) { __m128i data = _mm_loadu_si128((__m128i *) (trits->data) + i); __m128i result = _mm_or_si128( /* > 1 */ - _mm_cmpgt_epi8(data, posOne), + _mm_cmpgt_epi8(data, pos_one), /* < -1 */ - _mm_cmplt_epi8(data, negOne)); - int notValid = !_mm_test_all_zeros(result, result); - if (notValid) + _mm_cmplt_epi8(data, neg_one)); + int not_valid = !_mm_test_all_zeros(result, result); + if (not_valid) return false; } /* The for loop handles the rest of the characters until the end-of-string @@ -77,7 +77,7 @@ static inline bool validateTrits_sse42(Trobject_t *trits) } #if defined(__SSE4_2__) -static inline bool validateTrytes_sse42(Trobject_t *trytes) +static inline bool validate_trytes_sse42(trinary_object_t *trytes) { const int block_8bit = BLOCK_8BIT(__m128i); /* Characters from 'A' to 'Z' and '9' to '9' */ @@ -90,7 +90,7 @@ static inline bool validateTrytes_sse42(Trobject_t *trytes) /* Check whether the characters are in the defined range or not * Return 0 if all the characters are in the range, otherwise return 1 */ - int notValid = _mm_cmpistrc(pattern, src, + int not_valid = _mm_cmpistrc(pattern, src, /* Signed byte comparison */ _SIDD_SBYTE_OPS | /* Compare with the character range */ @@ -98,7 +98,7 @@ static inline bool validateTrytes_sse42(Trobject_t *trytes) /* Negate the comparison result */ _SIDD_MASKED_NEGATIVE_POLARITY); - if (notValid) + if (not_valid) return false; } /* The for loop handles the rest of the characters until the end-of-string @@ -112,142 +112,142 @@ static inline bool validateTrytes_sse42(Trobject_t *trytes) return true; } -static inline Trobject_t *trytes_from_trits_sse42(Trobject_t *trits) +static inline trinary_object_t *trytes_from_trits_sse42(trinary_object_t *trits) { - Trobject_t *trytes = NULL; + trinary_object_t *trytes = NULL; int8_t *src = (int8_t *) malloc(trits->len / 3); const int block_8bit = BLOCK_8BIT(__m128i); - const int8_t setMSB = 0x80; - const __m128i tryteAlphabet[2] = { - _mm_setr_epi8(TryteAlphabet[0], TryteAlphabet[1], TryteAlphabet[2], - TryteAlphabet[3], TryteAlphabet[4], TryteAlphabet[5], - TryteAlphabet[6], TryteAlphabet[7], TryteAlphabet[8], - TryteAlphabet[9], TryteAlphabet[10], TryteAlphabet[11], - TryteAlphabet[12], TryteAlphabet[13], TryteAlphabet[14], - TryteAlphabet[15]), - _mm_setr_epi8(TryteAlphabet[16], TryteAlphabet[17], TryteAlphabet[18], - TryteAlphabet[19], TryteAlphabet[20], TryteAlphabet[21], - TryteAlphabet[22], TryteAlphabet[23], TryteAlphabet[24], - TryteAlphabet[25], TryteAlphabet[26], 0, 0, 0, 0, 0)}; + const int8_t set_msb = 0x80; + const __m128i tryte_alphabet_for_simd[2] = { + _mm_setr_epi8(tryte_alphabet[0], tryte_alphabet[1], tryte_alphabet[2], + tryte_alphabet[3], tryte_alphabet[4], tryte_alphabet[5], + tryte_alphabet[6], tryte_alphabet[7], tryte_alphabet[8], + tryte_alphabet[9], tryte_alphabet[10], tryte_alphabet[11], + tryte_alphabet[12], tryte_alphabet[13], tryte_alphabet[14], + tryte_alphabet[15]), + _mm_setr_epi8(tryte_alphabet[16], tryte_alphabet[17], tryte_alphabet[18], + tryte_alphabet[19], tryte_alphabet[20], tryte_alphabet[21], + tryte_alphabet[22], tryte_alphabet[23], tryte_alphabet[24], + tryte_alphabet[25], tryte_alphabet[26], 0, 0, 0, 0, 0)}; /* For shuffling the bytes of the input trits */ - const __m128i shuffleLow[3] = { - _mm_setr_epi8(REPEAT(0, setMSB) COMMA(0) INDEX_3DIFF_0F COMMA(1) - REPEAT(10, setMSB)), - _mm_setr_epi8(REPEAT(6, setMSB) COMMA(1) INDEX_3DIFF_2E COMMA(1) - REPEAT(5, setMSB)), - _mm_setr_epi8(REPEAT(11, setMSB) COMMA(1) INDEX_3DIFF_1D COMMA(0) - REPEAT(0, setMSB))}; - const __m128i shuffleMid[3] = { - _mm_setr_epi8(REPEAT(0, setMSB) COMMA(0) INDEX_3DIFF_1D COMMA(1) - REPEAT(11, setMSB)), - _mm_setr_epi8(REPEAT(5, setMSB) COMMA(1) INDEX_3DIFF_0F COMMA(1) - REPEAT(5, setMSB)), - _mm_setr_epi8(REPEAT(11, setMSB) COMMA(1) INDEX_3DIFF_2E COMMA(0) - REPEAT(0, setMSB))}; - const __m128i shuffleHigh[3] = { - _mm_setr_epi8(REPEAT(0, setMSB) COMMA(0) INDEX_3DIFF_2E COMMA(1) - REPEAT(11, setMSB)), - _mm_setr_epi8(REPEAT(5, setMSB) COMMA(1) INDEX_3DIFF_1D COMMA(1) - REPEAT(6, setMSB)), - _mm_setr_epi8(REPEAT(10, setMSB) COMMA(1) INDEX_3DIFF_0F COMMA(0) - REPEAT(0, setMSB))}; + const __m128i shuffle_low[3] = { + _mm_setr_epi8(REPEAT(0, set_msb) COMMA(0) INDEX_3DIFF_0F COMMA(1) + REPEAT(10, set_msb)), + _mm_setr_epi8(REPEAT(6, set_msb) COMMA(1) INDEX_3DIFF_2E COMMA(1) + REPEAT(5, set_msb)), + _mm_setr_epi8(REPEAT(11, set_msb) COMMA(1) INDEX_3DIFF_1D COMMA(0) + REPEAT(0, set_msb))}; + const __m128i shuffle_mid[3] = { + _mm_setr_epi8(REPEAT(0, set_msb) COMMA(0) INDEX_3DIFF_1D COMMA(1) + REPEAT(11, set_msb)), + _mm_setr_epi8(REPEAT(5, set_msb) COMMA(1) INDEX_3DIFF_0F COMMA(1) + REPEAT(5, set_msb)), + _mm_setr_epi8(REPEAT(11, set_msb) COMMA(1) INDEX_3DIFF_2E COMMA(0) + REPEAT(0, set_msb))}; + const __m128i shuffle_high[3] = { + _mm_setr_epi8(REPEAT(0, set_msb) COMMA(0) INDEX_3DIFF_2E COMMA(1) + REPEAT(11, set_msb)), + _mm_setr_epi8(REPEAT(5, set_msb) COMMA(1) INDEX_3DIFF_1D COMMA(1) + REPEAT(6, set_msb)), + _mm_setr_epi8(REPEAT(10, set_msb) COMMA(1) INDEX_3DIFF_0F COMMA(0) + REPEAT(0, set_msb))}; /* The mask with interleaved bytes of 0xFF and 0x00 */ - const __m128i byteInterMask = + const __m128i byte_inter_mask = _mm_set_epi32(0xFF00FF00, 0xFF00FF00, 0xFF00FF00, 0xFF00FF00); /* Start converting */ for (int i = 0; i < trits->len / 3 / block_8bit; i++) { /* Get trit data */ - __m128i dataFirst = _mm_loadu_si128((__m128i *) (trits->data) + i * 3); - __m128i dataMid = + __m128i data_first = _mm_loadu_si128((__m128i *) (trits->data) + i * 3); + __m128i data_mid = _mm_loadu_si128((__m128i *) (trits->data) + i * 3 + 1); - __m128i dataLast = + __m128i data_last = _mm_loadu_si128((__m128i *) (trits->data) + i * 3 + 2); /* * Each block represents a trit. - * shuffle - * ---------------- ------ ------ ------ ------ - * dataFirst = | a1 | a2 | a3 | ...... | f1 | lowTrit = | a1 | ... | f1 | ... | p1 | - * ---------------- ------ ------ ------ ------ - * ---------------- ------ ------ ------ ------ - * dataMid = | f2 | f3 | g1 | ...... | k2 | => midTrit = | a2 | ... | f2 | ... | p2 | - * ---------------- ------ ------ ------ ------ - * ---------------- ------ ------ ------ ------ - * dataLast = | k3 | l1 | l2 | ...... | p3 | highTrit = | a3 | ... | f3 | ... | p3 | - * ---------------- ------ ------ ------ ------ + * shuffle + * ---------------- ------ ------ ------ ------ + * data_first = | a1 | a2 | a3 | ...... | f1 | low_trit = | a1 | ... | f1 | ... | p1 | + * ---------------- ------ ------ ------ ------ + * ---------------- ------ ------ ------ ------ + * data_mid = | f2 | f3 | g1 | ...... | k2 | => mid_trit = | a2 | ... | f2 | ... | p2 | + * ---------------- ------ ------ ------ ------ + * ---------------- ------ ------ ------ ------ + * data_last = | k3 | l1 | l2 | ...... | p3 | high_trit = | a3 | ... | f3 | ... | p3 | + * ---------------- ------ ------ ------ ------ */ - __m128i lowTrit = _mm_or_si128( - _mm_shuffle_epi8(dataFirst, shuffleLow[0]), - _mm_or_si128(_mm_shuffle_epi8(dataMid, shuffleLow[1]), - _mm_shuffle_epi8(dataLast, shuffleLow[2]))); - __m128i midTrit = _mm_or_si128( - _mm_shuffle_epi8(dataFirst, shuffleMid[0]), - _mm_or_si128(_mm_shuffle_epi8(dataMid, shuffleMid[1]), - _mm_shuffle_epi8(dataLast, shuffleMid[2]))); - __m128i highTrit = _mm_or_si128( - _mm_shuffle_epi8(dataFirst, shuffleHigh[0]), - _mm_or_si128(_mm_shuffle_epi8(dataMid, shuffleHigh[1]), - _mm_shuffle_epi8(dataLast, shuffleHigh[2]))); - /* lowResult = (lowTrit) */ - __m128i lowResult = lowTrit; - /* midResult = (midTrit * 3) */ - __m128i midResult = _mm_or_si128( + __m128i low_trit = _mm_or_si128( + _mm_shuffle_epi8(data_first, shuffle_low[0]), + _mm_or_si128(_mm_shuffle_epi8(data_mid, shuffle_low[1]), + _mm_shuffle_epi8(data_last, shuffle_low[2]))); + __m128i mid_trit = _mm_or_si128( + _mm_shuffle_epi8(data_first, shuffle_mid[0]), + _mm_or_si128(_mm_shuffle_epi8(data_mid, shuffle_mid[1]), + _mm_shuffle_epi8(data_last, shuffle_mid[2]))); + __m128i high_trit = _mm_or_si128( + _mm_shuffle_epi8(data_first, shuffle_high[0]), + _mm_or_si128(_mm_shuffle_epi8(data_mid, shuffle_high[1]), + _mm_shuffle_epi8(data_last, shuffle_high[2]))); + /* low_result = (low_trit) */ + __m128i low_result = low_trit; + /* mid_result = (mid_trit * 3) */ + __m128i mid_result = _mm_or_si128( _mm_and_si128( - byteInterMask, - _mm_mullo_epi16(_mm_and_si128(midTrit, byteInterMask), + byte_inter_mask, + _mm_mullo_epi16(_mm_and_si128(mid_trit, byte_inter_mask), _mm_set_epi16(0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003))), _mm_andnot_si128( - byteInterMask, + byte_inter_mask, _mm_mullo_epi16( - _mm_and_si128(midTrit, ~byteInterMask), + _mm_and_si128(mid_trit, ~byte_inter_mask), _mm_set_epi16(0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003, 0x0003)))); - /* highResult = (highTrit * 9) */ - __m128i highResult = _mm_or_si128( + /* high_result = (high_trit * 9) */ + __m128i high_result = _mm_or_si128( _mm_and_si128( - byteInterMask, - _mm_mullo_epi16(_mm_and_si128(highTrit, byteInterMask), + byte_inter_mask, + _mm_mullo_epi16(_mm_and_si128(high_trit, byte_inter_mask), _mm_set_epi16(0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009))), _mm_andnot_si128( - byteInterMask, + byte_inter_mask, _mm_mullo_epi16( - _mm_and_si128(highTrit, ~byteInterMask), + _mm_and_si128(high_trit, ~byte_inter_mask), _mm_set_epi16(0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009, 0x0009)))); - /* alphabetOffset = (lowResult + midResult + highResult) */ - __m128i alphabetOffset = - _mm_add_epi8(lowResult, _mm_add_epi8(midResult, highResult)); + /* alphabet_offset = (low_result + mid_result + high_result) */ + __m128i alphabet_offset = + _mm_add_epi8(low_result, _mm_add_epi8(mid_result, high_result)); /* Check whether the offset is < 0 */ - __m128i tmpMask = - _mm_cmplt_epi8(alphabetOffset, _mm_set_epi32(0, 0, 0, 0)); + __m128i tmp_mask = + _mm_cmplt_epi8(alphabet_offset, _mm_set_epi32(0, 0, 0, 0)); /* If the offset is < 0, then offset += 27 */ - __m128i alphabetOffsetAdd = _mm_add_epi8( - alphabetOffset, + __m128i alphabet_offset_add = _mm_add_epi8( + alphabet_offset, _mm_set_epi32(0x1B1B1B1B, 0x1B1B1B1B, 0x1B1B1B1B, 0x1B1B1B1B)); - alphabetOffset = - _mm_or_si128(_mm_and_si128(tmpMask, alphabetOffsetAdd), - _mm_andnot_si128(tmpMask, alphabetOffset)); + alphabet_offset = + _mm_or_si128(_mm_and_si128(tmp_mask, alphabet_offset_add), + _mm_andnot_si128(tmp_mask, alphabet_offset)); /* Assign tryte alphabet */ /* If the offset is >= 16 (> 15), then the compared result byte = 0xFF, * else = 0x00 */ - __m128i cmpResult = _mm_cmpgt_epi8( - alphabetOffset, _mm_set_epi8(15, 15, 15, 15, 15, 15, 15, 15, 15, 15, + __m128i cmp_result = _mm_cmpgt_epi8( + alphabet_offset, _mm_set_epi8(15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15)); - /* Use the offset to get the correct tryte alphabet from tryteAlphabet[] + /* Use the offset to get the correct tryte alphabet from tryte_alphabet_for_simd[] */ - __m128i resultLt = _mm_shuffle_epi8(tryteAlphabet[0], alphabetOffset); - __m128i resultGe = _mm_shuffle_epi8( - tryteAlphabet[1], - /* alphabetOffset - 16 */ - _mm_sub_epi8(alphabetOffset, + __m128i result_lt = _mm_shuffle_epi8(tryte_alphabet_for_simd[0], alphabet_offset); + __m128i result_ge = _mm_shuffle_epi8( + tryte_alphabet_for_simd[1], + /* alphabet_offset - 16 */ + _mm_sub_epi8(alphabet_offset, _mm_set_epi8(16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, 16))); - __m128i result = _mm_or_si128(_mm_andnot_si128(cmpResult, resultLt), - _mm_and_si128(cmpResult, resultGe)); + __m128i result = _mm_or_si128(_mm_andnot_si128(cmp_result, result_lt), + _mm_and_si128(cmp_result, result_ge)); /* Store the tryte result */ _mm_store_si128((__m128i *) (src + i * block_8bit), result); } @@ -259,96 +259,96 @@ static inline Trobject_t *trytes_from_trits_sse42(Trobject_t *trits) if (j < 0) j += 27; - src[i] = TryteAlphabet[j]; + src[i] = tryte_alphabet[j]; } - trytes = initTrytes(src, trits->len / 3); + trytes = init_trytes(src, trits->len / 3); free(src); return trytes; } -static inline Trobject_t *trits_from_trytes_sse42(Trobject_t *trytes) +static inline trinary_object_t *trits_from_trytes_sse42(trinary_object_t *trytes) { - Trobject_t *trits = NULL; + trinary_object_t *trits = NULL; int8_t *src = (int8_t *) malloc(trytes->len * 3); const int block_8bit = BLOCK_8BIT(__m128i); /* For setting the most significant bit of a byte */ - const int8_t setMSB = 0x80; + const int8_t set_msb = 0x80; /* The set and range for indicating the trits value (0, 1, -1) * of the corresponding trytes */ /* '9', 'C', 'F', 'I', 'L', 'O', 'R', 'U', 'X' */ - const char setLowTrit0[BYTE_OF_128BIT] = "9CFILORUX"; + const char set_low_trit_0[BYTE_OF_128BIT] = "9CFILORUX"; /* 'A', 'D', 'G', 'J', 'M', 'P', 'S', 'V', 'Y' */ - const char setLowTritP1[BYTE_OF_128BIT] = "ADGJMPSVY"; + const char set_low_trit_p1[BYTE_OF_128BIT] = "ADGJMPSVY"; /* 'B', 'E', 'H', 'K', 'N', 'Q', 'T', 'W', 'Z' */ - const char setLowTritN1[BYTE_OF_128BIT] = "BEHKNQTWZ"; + const char set_low_trit_n1[BYTE_OF_128BIT] = "BEHKNQTWZ"; /* '9', 'A', 'H', 'I', 'J', 'Q', 'R', 'S', 'Z' */ - const char rangeMidTrit0[BYTE_OF_128BIT] = "99AAHJQSZZ"; + const char range_mid_trit_0[BYTE_OF_128BIT] = "99AAHJQSZZ"; /* 'B', 'C', 'D', 'K', 'L', 'M', 'T', 'U', 'V' */ - const char rangeMidTritP1[BYTE_OF_128BIT] = "BDKMTV"; + const char range_mid_trit_p1[BYTE_OF_128BIT] = "BDKMTV"; /* 'E', 'F', 'G', 'N', 'O', 'P', 'W', 'X', 'Y' */ - const char rangeMidTritN1[BYTE_OF_128BIT] = "EGNPWY"; + const char range_mid_trit_n1[BYTE_OF_128BIT] = "EGNPWY"; /* '9', 'A', 'B', 'C', 'D', 'W', 'X', 'Y', 'Z' */ - const char rangeHighTrit0[BYTE_OF_128BIT] = "99ADWZ"; + const char range_high_trit_0[BYTE_OF_128BIT] = "99ADWZ"; /* 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M' */ - const char rangeHighTritP1[BYTE_OF_128BIT] = "EM"; + const char range_high_trit_p1[BYTE_OF_128BIT] = "EM"; /* 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V' */ - const char rangeHighTritN1[BYTE_OF_128BIT] = "NV"; + const char range_high_trit_n1[BYTE_OF_128BIT] = "NV"; /* Convert the char array to the 128-bit data */ - const __m128i patternLowTrit0 = _mm_loadu_si128((__m128i *) (setLowTrit0)); - const __m128i patternLowTritP1 = - _mm_loadu_si128((__m128i *) (setLowTritP1)); - const __m128i patternLowTritN1 = - _mm_loadu_si128((__m128i *) (setLowTritN1)); - const __m128i patternMidTrit0 = - _mm_loadu_si128((__m128i *) (rangeMidTrit0)); - const __m128i patternMidTritP1 = - _mm_loadu_si128((__m128i *) (rangeMidTritP1)); - const __m128i patternMidTritN1 = - _mm_loadu_si128((__m128i *) (rangeMidTritN1)); - const __m128i patternHighTrit0 = - _mm_loadu_si128((__m128i *) (rangeHighTrit0)); - const __m128i patternHighTritP1 = - _mm_loadu_si128((__m128i *) (rangeHighTritP1)); - const __m128i patternHighTritN1 = - _mm_loadu_si128((__m128i *) (rangeHighTritN1)); + const __m128i pattern_low_trit_0 = _mm_loadu_si128((__m128i *) (set_low_trit_0)); + const __m128i pattern_low_trit_p1 = + _mm_loadu_si128((__m128i *) (set_low_trit_p1)); + const __m128i pattern_low_trit_n1 = + _mm_loadu_si128((__m128i *) (set_low_trit_n1)); + const __m128i pattern_mid_trit_0 = + _mm_loadu_si128((__m128i *) (range_mid_trit_0)); + const __m128i pattern_mid_trit_p1 = + _mm_loadu_si128((__m128i *) (range_mid_trit_p1)); + const __m128i pattern_mid_trit_n1 = + _mm_loadu_si128((__m128i *) (range_mid_trit_n1)); + const __m128i pattern_high_trit_0 = + _mm_loadu_si128((__m128i *) (range_high_trit_0)); + const __m128i pattern_high_trit_p1 = + _mm_loadu_si128((__m128i *) (range_high_trit_p1)); + const __m128i pattern_high_trit_n1 = + _mm_loadu_si128((__m128i *) (range_high_trit_n1)); /* The 128-bit data with the repeated same bytes */ - const __m128i posOne = _mm_set1_epi8(1); - const __m128i negOne = _mm_set1_epi8(-1); + const __m128i pos_one = _mm_set1_epi8(1); + const __m128i neg_one = _mm_set1_epi8(-1); const __m128i zero = _mm_set1_epi8(0); /* For shuffling the bytes of the trits transformed from the input trytes */ - const __m128i shuffleFirst[3] = { - _mm_setr_epi8(0x00, REPEAT2(setMSB), 0x01, REPEAT2(setMSB), 0x02, - REPEAT2(setMSB), 0x03, REPEAT2(setMSB), 0x04, - REPEAT2(setMSB), 0x05), - _mm_setr_epi8(REPEAT1(setMSB), 0x00, REPEAT2(setMSB), 0x01, - REPEAT2(setMSB), 0x02, REPEAT2(setMSB), 0x03, - REPEAT2(setMSB), 0x04, REPEAT2(setMSB)), - _mm_setr_epi8(REPEAT2(setMSB), 0x00, REPEAT2(setMSB), 0x01, - REPEAT2(setMSB), 0x02, REPEAT2(setMSB), 0x03, - REPEAT2(setMSB), 0x04, REPEAT1(setMSB))}; - const __m128i shuffleMid[3] = { - _mm_setr_epi8(REPEAT2(setMSB), 0x06, REPEAT2(setMSB), 0x07, - REPEAT2(setMSB), 0x08, REPEAT2(setMSB), 0x09, - REPEAT2(setMSB), 0x0A, REPEAT1(setMSB)), - _mm_setr_epi8(0x05, REPEAT2(setMSB), 0x06, REPEAT2(setMSB), 0x07, - REPEAT2(setMSB), 0x08, REPEAT2(setMSB), 0x09, - REPEAT2(setMSB), 0x0A), - _mm_setr_epi8(REPEAT1(setMSB), 0x05, REPEAT2(setMSB), 0x06, - REPEAT2(setMSB), 0x07, REPEAT2(setMSB), 0x08, - REPEAT2(setMSB), 0x09, REPEAT2(setMSB))}; - const __m128i shuffleLast[3] = { - _mm_setr_epi8(REPEAT1(setMSB), 0x0B, REPEAT2(setMSB), 0x0C, - REPEAT2(setMSB), 0x0D, REPEAT2(setMSB), 0x0E, - REPEAT2(setMSB), 0x0F, REPEAT2(setMSB)), - _mm_setr_epi8(REPEAT2(setMSB), 0x0B, REPEAT2(setMSB), 0x0C, - REPEAT2(setMSB), 0x0D, REPEAT2(setMSB), 0x0E, - REPEAT2(setMSB), 0x0F, REPEAT1(setMSB)), - _mm_setr_epi8(0x0A, REPEAT2(setMSB), 0x0B, REPEAT2(setMSB), 0x0C, - REPEAT2(setMSB), 0x0D, REPEAT2(setMSB), 0x0E, - REPEAT2(setMSB), 0x0F)}; + const __m128i shuffle_first[3] = { + _mm_setr_epi8(0x00, REPEAT2(set_msb), 0x01, REPEAT2(set_msb), 0x02, + REPEAT2(set_msb), 0x03, REPEAT2(set_msb), 0x04, + REPEAT2(set_msb), 0x05), + _mm_setr_epi8(REPEAT1(set_msb), 0x00, REPEAT2(set_msb), 0x01, + REPEAT2(set_msb), 0x02, REPEAT2(set_msb), 0x03, + REPEAT2(set_msb), 0x04, REPEAT2(set_msb)), + _mm_setr_epi8(REPEAT2(set_msb), 0x00, REPEAT2(set_msb), 0x01, + REPEAT2(set_msb), 0x02, REPEAT2(set_msb), 0x03, + REPEAT2(set_msb), 0x04, REPEAT1(set_msb))}; + const __m128i shuffle_mid[3] = { + _mm_setr_epi8(REPEAT2(set_msb), 0x06, REPEAT2(set_msb), 0x07, + REPEAT2(set_msb), 0x08, REPEAT2(set_msb), 0x09, + REPEAT2(set_msb), 0x0A, REPEAT1(set_msb)), + _mm_setr_epi8(0x05, REPEAT2(set_msb), 0x06, REPEAT2(set_msb), 0x07, + REPEAT2(set_msb), 0x08, REPEAT2(set_msb), 0x09, + REPEAT2(set_msb), 0x0A), + _mm_setr_epi8(REPEAT1(set_msb), 0x05, REPEAT2(set_msb), 0x06, + REPEAT2(set_msb), 0x07, REPEAT2(set_msb), 0x08, + REPEAT2(set_msb), 0x09, REPEAT2(set_msb))}; + const __m128i shuffle_last[3] = { + _mm_setr_epi8(REPEAT1(set_msb), 0x0B, REPEAT2(set_msb), 0x0C, + REPEAT2(set_msb), 0x0D, REPEAT2(set_msb), 0x0E, + REPEAT2(set_msb), 0x0F, REPEAT2(set_msb)), + _mm_setr_epi8(REPEAT2(set_msb), 0x0B, REPEAT2(set_msb), 0x0C, + REPEAT2(set_msb), 0x0D, REPEAT2(set_msb), 0x0E, + REPEAT2(set_msb), 0x0F, REPEAT1(set_msb)), + _mm_setr_epi8(0x0A, REPEAT2(set_msb), 0x0B, REPEAT2(set_msb), 0x0C, + REPEAT2(set_msb), 0x0D, REPEAT2(set_msb), 0x0E, + REPEAT2(set_msb), 0x0F)}; /* Start converting */ /* The for loop handles the group of the 128-bit characters without the @@ -358,98 +358,98 @@ static inline Trobject_t *trits_from_trytes_sse42(Trobject_t *trytes) __m128i data = _mm_loadu_si128((__m128i *) (trytes->data) + i); /* The masks for setting the corresponding trits */ - __m128i maskLowTrit0 = _mm_cmpistrm( - patternLowTrit0, data, + __m128i mask_low_trit_0 = _mm_cmpistrm( + pattern_low_trit_0, data, /* Signed byte comparison */ _SIDD_SBYTE_OPS | /* Compare with the character set */ _SIDD_CMP_EQUAL_ANY | /* Expand the corrsponding bit result to byte unit */ _SIDD_UNIT_MASK); - __m128i maskLowTritP1 = _mm_cmpistrm( - patternLowTritP1, data, + __m128i mask_low_trit_p1 = _mm_cmpistrm( + pattern_low_trit_p1, data, _SIDD_SBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_UNIT_MASK); - __m128i maskLowTritN1 = _mm_cmpistrm( - patternLowTritN1, data, + __m128i mask_low_trit_n1 = _mm_cmpistrm( + pattern_low_trit_n1, data, _SIDD_SBYTE_OPS | _SIDD_CMP_EQUAL_ANY | _SIDD_UNIT_MASK); - __m128i maskMidTrit0 = _mm_cmpistrm( - patternMidTrit0, data, + __m128i mask_mid_trit_0 = _mm_cmpistrm( + pattern_mid_trit_0, data, /* Signed byte comparison */ _SIDD_SBYTE_OPS | /* Compare with the character range */ _SIDD_CMP_RANGES | /* Expand the corrsponding bit result to byte unit */ _SIDD_UNIT_MASK); - __m128i maskMidTritP1 = - _mm_cmpistrm(patternMidTritP1, data, + __m128i mask_mid_trit_p1 = + _mm_cmpistrm(pattern_mid_trit_p1, data, _SIDD_SBYTE_OPS | _SIDD_CMP_RANGES | _SIDD_UNIT_MASK); - __m128i maskMidTritN1 = - _mm_cmpistrm(patternMidTritN1, data, + __m128i mask_mid_trit_n1 = + _mm_cmpistrm(pattern_mid_trit_n1, data, _SIDD_SBYTE_OPS | _SIDD_CMP_RANGES | _SIDD_UNIT_MASK); - __m128i maskHighTrit0 = - _mm_cmpistrm(patternHighTrit0, data, + __m128i mask_high_trit_0 = + _mm_cmpistrm(pattern_high_trit_0, data, _SIDD_SBYTE_OPS | _SIDD_CMP_RANGES | _SIDD_UNIT_MASK); - __m128i maskHighTritP1 = - _mm_cmpistrm(patternHighTritP1, data, + __m128i mask_high_trit_p1 = + _mm_cmpistrm(pattern_high_trit_p1, data, _SIDD_SBYTE_OPS | _SIDD_CMP_RANGES | _SIDD_UNIT_MASK); - __m128i maskHighTritN1 = - _mm_cmpistrm(patternHighTritN1, data, + __m128i mask_high_trit_n1 = + _mm_cmpistrm(pattern_high_trit_n1, data, _SIDD_SBYTE_OPS | _SIDD_CMP_RANGES | _SIDD_UNIT_MASK); /* * Each block represents a trit. - * shuffle - * ------ ------ ------ ---------------- ------ - * lowTrit = | a1 | ... | f1 | ... | p1 | dataFirst = | a1 | a2 | a3 | ...... | f1 | - * ------ ------ ------ ---------------- ------ - * ------ ------ ------ ---------------- ------ - * midTrit = | a2 | ... | f2 | ... | p2 | => dataMid = | f2 | f3 | g1 | ...... | k2 | - * ------ ------ ------ ---------------- ------ - * ------ ------ ------ ---------------- ------ - * highTrit = | a3 | ... | f3 | ... | p3 | dataLast = | k3 | l1 | l2 | ...... | p3 | - * ------ ------ ------ ---------------- ------ + * shuffle + * ------ ------ ------ ---------------- ------ + * low_trit = | a1 | ... | f1 | ... | p1 | data_first = | a1 | a2 | a3 | ...... | f1 | + * ------ ------ ------ ---------------- ------ + * ------ ------ ------ ---------------- ------ + * mid_trit = | a2 | ... | f2 | ... | p2 | => data_mid = | f2 | f3 | g1 | ...... | k2 | + * ------ ------ ------ ---------------- ------ + * ------ ------ ------ ---------------- ------ + * high_trit = | a3 | ... | f3 | ... | p3 | data_last = | k3 | l1 | l2 | ...... | p3 | + * ------ ------ ------ ---------------- ------ */ - __m128i lowTrit = - _mm_or_si128(_mm_and_si128(maskLowTrit0, zero), - _mm_or_si128(_mm_and_si128(maskLowTritP1, posOne), - _mm_and_si128(maskLowTritN1, negOne))); - __m128i midTrit = - _mm_or_si128(_mm_and_si128(maskMidTrit0, zero), - _mm_or_si128(_mm_and_si128(maskMidTritP1, posOne), - _mm_and_si128(maskMidTritN1, negOne))); - __m128i highTrit = - _mm_or_si128(_mm_and_si128(maskHighTrit0, zero), - _mm_or_si128(_mm_and_si128(maskHighTritP1, posOne), - _mm_and_si128(maskHighTritN1, negOne))); - __m128i dataFirst, dataMid, dataLast; - dataFirst = _mm_or_si128( - _mm_shuffle_epi8(lowTrit, shuffleFirst[0]), - _mm_or_si128(_mm_shuffle_epi8(midTrit, shuffleFirst[1]), - _mm_shuffle_epi8(highTrit, shuffleFirst[2]))); - dataMid = _mm_or_si128( - _mm_shuffle_epi8(lowTrit, shuffleMid[0]), - _mm_or_si128(_mm_shuffle_epi8(midTrit, shuffleMid[1]), - _mm_shuffle_epi8(highTrit, shuffleMid[2]))); - dataLast = _mm_or_si128( - _mm_shuffle_epi8(lowTrit, shuffleLast[0]), - _mm_or_si128(_mm_shuffle_epi8(midTrit, shuffleLast[1]), - _mm_shuffle_epi8(highTrit, shuffleLast[2]))); + __m128i low_trit = + _mm_or_si128(_mm_and_si128(mask_low_trit_0, zero), + _mm_or_si128(_mm_and_si128(mask_low_trit_p1, pos_one), + _mm_and_si128(mask_low_trit_n1, neg_one))); + __m128i mid_trit = + _mm_or_si128(_mm_and_si128(mask_mid_trit_0, zero), + _mm_or_si128(_mm_and_si128(mask_mid_trit_p1, pos_one), + _mm_and_si128(mask_mid_trit_n1, neg_one))); + __m128i high_trit = + _mm_or_si128(_mm_and_si128(mask_high_trit_0, zero), + _mm_or_si128(_mm_and_si128(mask_high_trit_p1, pos_one), + _mm_and_si128(mask_high_trit_n1, neg_one))); + __m128i data_first, data_mid, data_last; + data_first = _mm_or_si128( + _mm_shuffle_epi8(low_trit, shuffle_first[0]), + _mm_or_si128(_mm_shuffle_epi8(mid_trit, shuffle_first[1]), + _mm_shuffle_epi8(high_trit, shuffle_first[2]))); + data_mid = _mm_or_si128( + _mm_shuffle_epi8(low_trit, shuffle_mid[0]), + _mm_or_si128(_mm_shuffle_epi8(mid_trit, shuffle_mid[1]), + _mm_shuffle_epi8(high_trit, shuffle_mid[2]))); + data_last = _mm_or_si128( + _mm_shuffle_epi8(low_trit, shuffle_last[0]), + _mm_or_si128(_mm_shuffle_epi8(mid_trit, shuffle_last[1]), + _mm_shuffle_epi8(high_trit, shuffle_last[2]))); /* Store the 3 * 128-bit trits converted from trytes */ - _mm_store_si128((__m128i *) (src + (3 * i) * block_8bit), dataFirst); - _mm_store_si128((__m128i *) (src + (3 * i + 1) * block_8bit), dataMid); - _mm_store_si128((__m128i *) (src + (3 * i + 2) * block_8bit), dataLast); + _mm_store_si128((__m128i *) (src + (3 * i) * block_8bit), data_first); + _mm_store_si128((__m128i *) (src + (3 * i + 1) * block_8bit), data_mid); + _mm_store_si128((__m128i *) (src + (3 * i + 2) * block_8bit), data_last); } /* The rest of the trytes */ for (int i = (trytes->len / block_8bit) * block_8bit; i < trytes->len; i++) { int idx = (trytes->data[i] == '9') ? 0 : trytes->data[i] - 'A' + 1; for (int j = 0; j < 3; j++) { - src[i * 3 + j] = TrytesToTritsMappings[idx][j]; + src[i * 3 + j] = trytes_to_trits_mappings[idx][j]; } } - trits = initTrits(src, trytes->len * 3); + trits = init_trits(src, trytes->len * 3); free(src); return trits; diff --git a/tests/common.h b/tests/common.h index b6a12a6..804a1b4 100644 --- a/tests/common.h +++ b/tests/common.h @@ -24,7 +24,7 @@ #if defined(ENABLE_OPENCL) #include "pow_cl.h" #endif -#if defined(ENABLE_FPGA_ACCEL) +#if defined(ENABLE_FPGA) #include "pow_fpga.h" #endif diff --git a/tests/test-curl.c b/tests/test-curl.c index dca9a96..33b3e64 100644 --- a/tests/test-curl.c +++ b/tests/test-curl.c @@ -52,19 +52,19 @@ int main() "SYVDPCXX9LLAT"; int length_test_case = 2673; - Trytes_t *answer = initTrytes((signed char *) "WPM9JCTQH9QHBHBJCODWDNPSLFLQDZADRAEZTZDL9OEGTVRZARVLVJHZIMPBPCTAIYJKWTUSRKNNTMFOQ", 81); + trytes_t *answer = init_trytes((signed char *) "WPM9JCTQH9QHBHBJCODWDNPSLFLQDZADRAEZTZDL9OEGTVRZARVLVJHZIMPBPCTAIYJKWTUSRKNNTMFOQ", 81); assert(answer); - Trytes_t *trytes = - initTrytes((signed char *) trytes_test_case, length_test_case); + trytes_t *trytes = + init_trytes((signed char *) trytes_test_case, length_test_case); assert(trytes); - Trytes_t *ret_trytes = hashTrytes(trytes); + trytes_t *ret_trytes = hash_trytes(trytes); assert(ret_trytes); - int ret = compareTrobject(ret_trytes, answer); + int ret = compare_trinary_object(ret_trytes, answer); - freeTrobject(answer); - freeTrobject(trytes); - freeTrobject(ret_trytes); + free_trinary_object(answer); + free_trinary_object(trytes); + free_trinary_object(ret_trytes); assert(ret != 0); diff --git a/tests/test-dcurl.c b/tests/test-dcurl.c index 3fb5a10..d321268 100644 --- a/tests/test-dcurl.c +++ b/tests/test-dcurl.c @@ -14,7 +14,7 @@ int main() { - char *trytes = + char *transaction_trytes = "9999999999999999999999999999999999999999999999999999999999999999999999" "9999999999999999999999999999999999999999999999999999999999999999999999" "9999999999999999999999999999999999999999999999999999999999999999999999" @@ -60,25 +60,25 @@ int main() for (int loop_count = 0; loop_count < LOOP_MAX; loop_count++) { /* test dcurl Implementation with mwm = 14 */ dcurl_init(); - int8_t *ret_trytes = dcurl_entry((int8_t *) trytes, mwm, 8); + int8_t *ret_trytes = dcurl_entry((int8_t *) transaction_trytes, mwm, 8); assert(ret_trytes); dcurl_destroy(); - Trytes_t *trytes_t = initTrytes(ret_trytes, 2673); - assert(trytes_t); - Trytes_t *hash_trytes = hashTrytes(trytes_t); - assert(hash_trytes); + trytes_t *trytes = init_trytes(ret_trytes, 2673); + assert(trytes); + trytes_t *hashed_trytes = hash_trytes(trytes); + assert(hashed_trytes); /* Validation */ - Trits_t *ret_trits = trits_from_trytes(hash_trytes); + trits_t *ret_trits = trits_from_trytes(hashed_trytes); for (int i = 243 - 1; i >= 243 - mwm; i--) { assert(ret_trits->data[i] == 0); } free(ret_trytes); - freeTrobject(trytes_t); - freeTrobject(hash_trytes); - freeTrobject(ret_trits); + free_trinary_object(trytes); + free_trinary_object(hashed_trytes); + free_trinary_object(ret_trits); } return 0; diff --git a/tests/test-multi-pow.c b/tests/test-multi-pow.c index df77c72..4a453be 100644 --- a/tests/test-multi-pow.c +++ b/tests/test-multi-pow.c @@ -34,7 +34,7 @@ void *dcurl_entry_cb(void *arg) int main() { - char *trytes = + char *transaction_trytes = "9999999999999999999999999999999999999999999999999999999999999999999999" "9999999999999999999999999999999999999999999999999999999999999999999999" "9999999999999999999999999999999999999999999999999999999999999999999999" @@ -82,7 +82,7 @@ int main() dcurl_init(); for (int i = 0; i < THREAD_MAX; i++) { - memcpy(items[i].input_trytes, trytes, TRANSACTION_TRYTES_LENGTH); + memcpy(items[i].input_trytes, transaction_trytes, TRANSACTION_TRYTES_LENGTH); items[i].mwm = mwm; pthread_create(&threads[i], NULL, dcurl_entry_cb, (void *) &items[i]); } @@ -91,21 +91,21 @@ int main() pthread_join(threads[i], NULL); for (int i = 0; i < THREAD_MAX; i++) { - Trytes_t *trytes_t = - initTrytes(items[i].output_trytes, TRANSACTION_TRYTES_LENGTH); - assert(trytes_t && "initTrytes() failed"); - Trytes_t *hash_trytes = hashTrytes(trytes_t); - assert(hash_trytes && "hashTrytes() failed"); + trytes_t *trytes = + init_trytes(items[i].output_trytes, TRANSACTION_TRYTES_LENGTH); + assert(trytes && "init_trytes() failed"); + trytes_t *hashed_trytes = hash_trytes(trytes); + assert(hashed_trytes && "hash_trytes() failed"); /* Validation */ - Trits_t *ret_trits = trits_from_trytes(hash_trytes); + trits_t *ret_trits = trits_from_trytes(hashed_trytes); for (int j = 243 - 1; j >= 243 - items[i].mwm; j--) { assert(ret_trits->data[j] == 0 && "Validation failed"); } - freeTrobject(trytes_t); - freeTrobject(hash_trytes); - freeTrobject(ret_trits); + free_trinary_object(trytes); + free_trinary_object(hashed_trytes); + free_trinary_object(ret_trits); } dcurl_destroy(); diff --git a/tests/test-pow.c b/tests/test-pow.c index 007fb12..9becc01 100644 --- a/tests/test-pow.c +++ b/tests/test-pow.c @@ -14,19 +14,19 @@ #define POW_TOTAL 100 #if defined(ENABLE_AVX) -extern ImplContext PoWAVX_Context; +extern impl_context_t pow_avx_context; #elif defined(ENABLE_SSE) -extern ImplContext PoWSSE_Context; +extern impl_context_t pow_sse_context; #elif defined(ENABLE_GENERIC) -extern ImplContext PoWC_Context; +extern impl_context_t pow_c_context; #endif #if defined(ENABLE_OPENCL) -extern ImplContext PoWCL_Context; +extern impl_context_t pow_cl_context; #endif -#if defined(ENABLE_FPGA_ACCEL) -extern ImplContext PoWFPGA_Context; +#if defined(ENABLE_FPGA) +extern impl_context_t pow_fpga_context; #endif const char *description[] = { @@ -42,39 +42,39 @@ const char *description[] = { "GPU - OpenCL", #endif -#if defined(ENABLE_FPGA_ACCEL) +#if defined(ENABLE_FPGA) "FPGA", #endif }; -double getAvg(const double arr[], int arrLen) +double get_avg(const double arr[], int arr_len) { double avg, sum = 0; - for (int idx = 0; idx < arrLen; idx++) { + for (int idx = 0; idx < arr_len; idx++) { sum += arr[idx]; } - avg = sum / arrLen; + avg = sum / arr_len; return avg; } -double getStdDeviation(const double arr[], int arrLen) +double get_std_deviation(const double arr[], int arr_len) { double sigma, variance = 0; - double avg = getAvg(arr, arrLen); + double avg = get_avg(arr, arr_len); - for (int idx = 0; idx < arrLen; idx++) { + for (int idx = 0; idx < arr_len; idx++) { variance += pow(arr[idx] - avg, 2); } - sigma = sqrt(variance / arrLen); + sigma = sqrt(variance / arr_len); return sigma; } int main() { - char *trytes = + char *transaction_trytes = "9999999999999999999999999999999999999999999999999999999999999999999999" "9999999999999999999999999999999999999999999999999999999999999999999999" "9999999999999999999999999999999999999999999999999999999999999999999999" @@ -117,57 +117,57 @@ int main() int mwm = 14; - ImplContext ImplContextArr[] = { + impl_context_t impl_context_arr[] = { #if defined(ENABLE_AVX) - PoWAVX_Context, + pow_avx_context, #elif defined(ENABLE_SSE) - PoWSSE_Context, + pow_sse_context, #elif defined(ENABLE_GENERIC) - PoWC_Context, + pow_c_context, #endif #if defined(ENABLE_OPENCL) - PoWCL_Context, + pow_cl_context, #endif -#if defined(ENABLE_FPGA_ACCEL) - PoWFPGA_Context, +#if defined(ENABLE_FPGA) + pow_fpga_context, #endif }; #if defined(ENABLE_STAT) - double hashRateArr[POW_TOTAL]; + double hash_rate_arr[POW_TOTAL]; int pow_total = POW_TOTAL; #else int pow_total = 1; #endif - for (int idx = 0; idx < sizeof(ImplContextArr) / sizeof(ImplContext); + for (int idx = 0; idx < sizeof(impl_context_arr) / sizeof(impl_context_t); idx++) { log_info(0, "%s\n", description[idx]); - ImplContext *PoW_Context_ptr = &ImplContextArr[idx]; + impl_context_t *pow_context_ptr = &impl_context_arr[idx]; /* test implementation with mwm = 14 */ - initializeImplContext(PoW_Context_ptr); + initialize_impl_context(pow_context_ptr); void *pow_ctx = - getPoWContext(PoW_Context_ptr, (int8_t *) trytes, mwm, 8); + get_pow_context(pow_context_ptr, (int8_t *) transaction_trytes, mwm, 8); assert(pow_ctx); for (int count = 0; count < pow_total; count++) { - doThePoW(PoW_Context_ptr, pow_ctx); - int8_t *ret_trytes = getPoWResult(PoW_Context_ptr, pow_ctx); + do_the_pow(pow_context_ptr, pow_ctx); + int8_t *ret_trytes = get_pow_result(pow_context_ptr, pow_ctx); assert(ret_trytes); #if defined(ENABLE_STAT) - PoW_Info pow_info = getPoWInfo(PoW_Context_ptr, pow_ctx); + pow_info_t pow_info = get_pow_info(pow_context_ptr, pow_ctx); #endif - Trytes_t *trytes_t = - initTrytes(ret_trytes, TRANSACTION_TRYTES_LENGTH); - assert(trytes_t); - Trytes_t *hash_trytes = hashTrytes(trytes_t); - assert(hash_trytes); - Trits_t *ret_trits = trits_from_trytes(hash_trytes); + trytes_t *trytes = + init_trytes(ret_trytes, TRANSACTION_TRYTES_LENGTH); + assert(trytes); + trytes_t *hashed_trytes = hash_trytes(trytes); + assert(hashed_trytes); + trits_t *ret_trits = trits_from_trytes(hashed_trytes); assert(ret_trits); /* Validation */ @@ -177,27 +177,27 @@ int main() } free(ret_trytes); - freeTrobject(trytes_t); - freeTrobject(hash_trytes); - freeTrobject(ret_trits); + free_trinary_object(trytes); + free_trinary_object(hashed_trytes); + free_trinary_object(ret_trits); #if defined(ENABLE_STAT) - hashRateArr[count] = pow_info.hash_count / pow_info.time; + hash_rate_arr[count] = pow_info.hash_count / pow_info.time; #endif } - freePoWContext(PoW_Context_ptr, pow_ctx); - destroyImplContext(PoW_Context_ptr); + free_pow_context(pow_context_ptr, pow_ctx); + destroy_impl_context(pow_context_ptr); log_info(0, "PoW execution times: %d times.\n", pow_total); #if defined(ENABLE_STAT) log_info(0, "Hash rate average value: %.3lf kH/sec,\n", - getAvg(hashRateArr, pow_total) / 1000); + get_avg(hash_rate_arr, pow_total) / 1000); log_info( 0, "with the range +- %.3lf kH/sec including 95%% of the hash rate " "values.\n", - 2 * getStdDeviation(hashRateArr, pow_total) / 1000); + 2 * get_std_deviation(hash_rate_arr, pow_total) / 1000); #endif log_info(0, "Success.\n"); } diff --git a/tests/test-trinary.c b/tests/test-trinary.c index b69079a..0e8ec9d 100644 --- a/tests/test-trinary.c +++ b/tests/test-trinary.c @@ -15,19 +15,19 @@ int main() "UG9OEOZPOTD"; int length_test_case = 81; - Trytes_t *trytes = - initTrytes((signed char *) trytes_test_case, length_test_case); + trytes_t *trytes = + init_trytes((signed char *) trytes_test_case, length_test_case); assert(trytes); - Trits_t *trits = trits_from_trytes(trytes); + trits_t *trits = trits_from_trytes(trytes); assert(trits); - Trytes_t *ret_trytes = trytes_from_trits(trits); + trytes_t *ret_trytes = trytes_from_trits(trits); assert(ret_trytes); - int ret = compareTrobject(trytes, ret_trytes); + int ret = compare_trinary_object(trytes, ret_trytes); - freeTrobject(trytes); - freeTrobject(trits); - freeTrobject(ret_trytes); + free_trinary_object(trytes); + free_trinary_object(trits); + free_trinary_object(ret_trytes); assert(ret != 0); From 966cbf9500b13a685662ccbcb8eb280d514c51f2 Mon Sep 17 00:00:00 2001 From: marktwtn Date: Fri, 3 Jan 2020 09:26:19 +0800 Subject: [PATCH 13/22] style: Revise source code for coding style --- cppcheck_suppress | 6 +- src/common.h | 4 +- src/constants.h | 26 +-- src/implcontext.c | 5 +- src/implcontext.h | 12 +- src/pow_avx.c | 64 ++++---- src/pow_c.c | 13 +- src/pow_cl.c | 25 ++- src/pow_fpga.c | 8 +- src/pow_kernel.cl | 353 +++++++++++++++++++++++------------------ src/pow_sse.c | 42 ++--- src/remote_common.c | 2 +- src/remote_interface.c | 14 +- src/remote_interface.h | 8 +- src/remote_worker.c | 2 +- src/trinary_sse42.h | 53 ++++--- 16 files changed, 348 insertions(+), 289 deletions(-) diff --git a/cppcheck_suppress b/cppcheck_suppress index 0e1c729..1aa3cc4 100644 --- a/cppcheck_suppress +++ b/cppcheck_suppress @@ -7,9 +7,9 @@ unusedFunction:src/compat_ccurl.c:29 unusedFunction:src/compat_ccurl.c:34 // The invoked functions of OpenCL are not checked correctly with CppCheck -unusedFunction:src/pow_kernel.cl:185 -unusedFunction:src/pow_kernel.cl:216 -unusedFunction:src/pow_kernel.cl:249 +unusedFunction:src/pow_kernel.cl:213 +unusedFunction:src/pow_kernel.cl:248 +unusedFunction:src/pow_kernel.cl:284 // Do not treat system header files missing as errors missingIncludeSystem:* diff --git a/src/common.h b/src/common.h index c05979f..74fa362 100644 --- a/src/common.h +++ b/src/common.h @@ -38,8 +38,8 @@ static inline void log_debug(logger_id_t const logger_id, } static inline void log_info(logger_id_t const logger_id, - const char *format, - ...) + const char *format, + ...) { va_list ap; va_start(ap, format); diff --git a/src/constants.h b/src/constants.h index 4b9112e..a0fa32d 100644 --- a/src/constants.h +++ b/src/constants.h @@ -27,7 +27,7 @@ #define SIGNATURE_MESSAGE_FRAGMENT_TRINARY_OFFSET 0 #define SIGNATURE_MESSAGE_FRAGMENT_TRINARY_SIZE 6561 -#define ADDRESS_TRINARY_OFFSET \ +#define ADDRESS_TRINARY_OFFSET \ (SIGNATURE_MESSAGE_FRAGMENT_TRINARY_OFFSET + \ SIGNATURE_MESSAGE_FRAGMENT_TRINARY_SIZE) #define ADDRESS_TRINARY_SIZE 243 @@ -44,9 +44,11 @@ #define LAST_INDEX_TRINARY_OFFSET \ (CURRENT_INDEX_TRINARY_OFFSET + CURRENT_INDEX_TRINARY_SIZE) #define LAST_INDEX_TRINARY_SIZE 27 -#define BUNDLE_TRINARY_OFFSET (LAST_INDEX_TRINARY_OFFSET + LAST_INDEX_TRINARY_SIZE) +#define BUNDLE_TRINARY_OFFSET \ + (LAST_INDEX_TRINARY_OFFSET + LAST_INDEX_TRINARY_SIZE) #define BUNDLE_TRINARY_SIZE 243 -#define TRUNK_TRANSACTION_TRINARY_OFFSET (BUNDLE_TRINARY_OFFSET + BUNDLE_TRINARY_SIZE) +#define TRUNK_TRANSACTION_TRINARY_OFFSET \ + (BUNDLE_TRINARY_OFFSET + BUNDLE_TRINARY_SIZE) #define TRUNK_TRANSACTION_TRINARY_SIZE 243 #define BRANCH_TRANSACTION_TRINARY_OFFSET \ (TRUNK_TRANSACTION_TRINARY_OFFSET + TRUNK_TRANSACTION_TRINARY_SIZE) @@ -54,7 +56,8 @@ #define TAG_TRINARY_OFFSET \ (BRANCH_TRANSACTION_TRINARY_OFFSET + BRANCH_TRANSACTION_TRINARY_SIZE) #define TAG_TRINARY_SIZE 81 -#define ATTACHMENT_TIMESTAMP_TRINARY_OFFSET (TAG_TRINARY_OFFSET + TAG_TRINARY_SIZE) +#define ATTACHMENT_TIMESTAMP_TRINARY_OFFSET \ + (TAG_TRINARY_OFFSET + TAG_TRINARY_SIZE) #define ATTACHMENT_TIMESTAMP_TRINARY_SIZE 27 #define ATTACHMENT_TIMESTAMP_LOWER_BOUND_TRINARY_OFFSET \ @@ -64,17 +67,18 @@ (ATTACHMENT_TIMESTAMP_LOWER_BOUND_TRINARY_OFFSET + \ ATTACHMENT_TIMESTAMP_LOWER_BOUND_TRINARY_SIZE) #define ATTACHMENT_TIMESTAMP_UPPER_BOUND_TRINARY_SIZE 27 -#define NONCE_TRINARY_OFFSET \ +#define NONCE_TRINARY_OFFSET \ (ATTACHMENT_TIMESTAMP_UPPER_BOUND_TRINARY_OFFSET + \ ATTACHMENT_TIMESTAMP_UPPER_BOUND_TRINARY_SIZE) #define NONCE_TRINARY_SIZE 81 -#define TRANSACTION_TRINARY_SIZE \ - (SIGNATURE_MESSAGE_FRAGMENT_TRINARY_SIZE + ADDRESS_TRINARY_SIZE + \ - VALUE_TRINARY_SIZE + OBSOLETE_TAG_TRINARY_SIZE + TIMESTAMP_TRINARY_SIZE + \ - CURRENT_INDEX_TRINARY_SIZE + LAST_INDEX_TRINARY_SIZE + BUNDLE_TRINARY_SIZE + \ - TRUNK_TRANSACTION_TRINARY_SIZE + BRANCH_TRANSACTION_TRINARY_SIZE + \ - TAG_TRINARY_SIZE + ATTACHMENT_TIMESTAMP_TRINARY_SIZE + \ +#define TRANSACTION_TRINARY_SIZE \ + (SIGNATURE_MESSAGE_FRAGMENT_TRINARY_SIZE + ADDRESS_TRINARY_SIZE + \ + VALUE_TRINARY_SIZE + OBSOLETE_TAG_TRINARY_SIZE + TIMESTAMP_TRINARY_SIZE + \ + CURRENT_INDEX_TRINARY_SIZE + LAST_INDEX_TRINARY_SIZE + \ + BUNDLE_TRINARY_SIZE + TRUNK_TRANSACTION_TRINARY_SIZE + \ + BRANCH_TRANSACTION_TRINARY_SIZE + TAG_TRINARY_SIZE + \ + ATTACHMENT_TIMESTAMP_TRINARY_SIZE + \ ATTACHMENT_TIMESTAMP_LOWER_BOUND_TRINARY_SIZE + \ ATTACHMENT_TIMESTAMP_UPPER_BOUND_TRINARY_SIZE + NONCE_TRINARY_SIZE) diff --git a/src/implcontext.c b/src/implcontext.c index 4a25d14..46c80c6 100644 --- a/src/implcontext.c +++ b/src/implcontext.c @@ -56,7 +56,10 @@ void exit_impl_context(impl_context_t *impl_ctx) uv_mutex_unlock(&impl_ctx->lock); } -void *get_pow_context(impl_context_t *impl_ctx, int8_t *trytes, int mwm, int threads) +void *get_pow_context(impl_context_t *impl_ctx, + int8_t *trytes, + int mwm, + int threads) { return impl_ctx->get_pow_context(impl_ctx, trytes, mwm, threads); } diff --git a/src/implcontext.h b/src/implcontext.h index 60f403a..8b230dc 100644 --- a/src/implcontext.h +++ b/src/implcontext.h @@ -32,9 +32,9 @@ struct impl_context_s { void (*destroy)(impl_context_t *impl_ctx); /* Private PoW Context for each thread */ void *(*get_pow_context)(impl_context_t *impl_ctx, - int8_t *trytes, - int mwm, - int threads); + int8_t *trytes, + int mwm, + int threads); bool (*do_the_pow)(void *pow_ctx); int8_t *(*get_pow_result)(void *pow_ctx); pow_info_t (*get_pow_info)(void *pow_ctx); @@ -50,9 +50,9 @@ void destroy_impl_context(impl_context_t *impl_ctx); bool enter_impl_context(impl_context_t *impl_ctx); void exit_impl_context(impl_context_t *impl_ctx); void *get_pow_context(impl_context_t *impl_ctx, - int8_t *trytes, - int mwm, - int threads); + int8_t *trytes, + int mwm, + int threads); bool do_the_pow(impl_context_t *impl_ctx, void *pow_ctx); bool free_pow_context(impl_context_t *impl_ctx, void *pow_ctx); int8_t *get_pow_result(impl_context_t *impl_ctx, void *pow_ctx); diff --git a/src/pow_avx.c b/src/pow_avx.c index 370268c..0911b73 100644 --- a/src/pow_avx.c +++ b/src/pow_avx.c @@ -156,11 +156,11 @@ static void incr_n_256(int n, __m256i *mid_low, __m256i *mid_high) static int loop_256(__m256i *lmid, - __m256i *hmid, - int m, - int8_t *nonce, - int *stop_pow, - uv_rwlock_t *lock) + __m256i *hmid, + int m, + int8_t *nonce, + int *stop_pow, + uv_rwlock_t *lock) { int i = 0; __m256i lcpy[STATE_TRITS_LENGTH * 2], hcpy[STATE_TRITS_LENGTH * 2]; @@ -175,7 +175,7 @@ static int loop_256(__m256i *lmid, } transform_256(lcpy, hcpy); if ((n = check_256(lcpy + STATE_TRITS_LENGTH, hcpy + STATE_TRITS_LENGTH, - m)) >= 0) { + m)) >= 0) { seri_256(lmid, hmid, n, nonce); return i * 256; } @@ -186,11 +186,11 @@ static int loop_256(__m256i *lmid, } static int64_t pwork_256(int8_t mid[], - int mwm, - int8_t nonce[], - int n, - int *stop_pow, - uv_rwlock_t *lock) + int mwm, + int8_t nonce[], + int n, + int *stop_pow, + uv_rwlock_t *lock) { __m256i lmid[STATE_TRITS_LENGTH], hmid[STATE_TRITS_LENGTH]; int offset = HASH_TRITS_LENGTH - NONCE_TRITS_LENGTH; @@ -364,11 +364,11 @@ static void incr_n_256(int n, __m256d *mid_low, __m256d *mid_high) } static int loop_256(__m256d *lmid, - __m256d *hmid, - int m, - int8_t *nonce, - int *stop_pow, - uv_rwlock_t *lock) + __m256d *hmid, + int m, + int8_t *nonce, + int *stop_pow, + uv_rwlock_t *lock) { int i = 0; @@ -383,7 +383,7 @@ static int loop_256(__m256d *lmid, } transform_256(lcpy, hcpy); if ((n = check_256(lcpy + STATE_TRITS_LENGTH, hcpy + STATE_TRITS_LENGTH, - m)) >= 0) { + m)) >= 0) { seri_256(lmid, hmid, n, nonce); return i * 256; } @@ -394,11 +394,11 @@ static int loop_256(__m256d *lmid, } static long long int pwork_256(int8_t mid[], - int mwm, - int8_t nonce[], - int n, - int *stop_pow, - uv_rwlock_t *lock) + int mwm, + int8_t nonce[], + int n, + int *stop_pow, + uv_rwlock_t *lock) { __m256d lmid[STATE_TRITS_LENGTH], hmid[STATE_TRITS_LENGTH]; int offset = HASH_TRITS_LENGTH - NONCE_TRITS_LENGTH; @@ -426,8 +426,8 @@ static void work_cb(uv_work_t *req) { pwork_t *pwork_info = (pwork_t *) req->data; pwork_info->ret = - pwork_256(pwork_info->mid, pwork_info->mwm, pwork_info->nonce, pwork_info->n, - pwork_info->stop_pow, pwork_info->lock); + pwork_256(pwork_info->mid, pwork_info->mwm, pwork_info->nonce, + pwork_info->n, pwork_info->stop_pow, pwork_info->lock); uv_rwlock_wrlock(pwork_info->lock); if (pwork_info->ret >= 0) { @@ -580,8 +580,8 @@ static bool pow_avx_context_initialize(impl_context_t *impl_ctx) if (impl_ctx->num_max_thread <= 0 || nproc <= 0) return false; - pow_avx_context_t *ctx = (pow_avx_context_t *) malloc(sizeof(pow_avx_context_t) * - impl_ctx->num_max_thread); + pow_avx_context_t *ctx = (pow_avx_context_t *) malloc( + sizeof(pow_avx_context_t) * impl_ctx->num_max_thread); if (!ctx) return false; @@ -640,16 +640,17 @@ static void pow_avx_context_destroy(impl_context_t *impl_ctx) } static void *pow_avx_get_pow_context(impl_context_t *impl_ctx, - int8_t *trytes, - int mwm, - int threads) + int8_t *trytes, + int mwm, + int threads) { uv_mutex_lock(&impl_ctx->lock); for (int i = 0; i < impl_ctx->num_max_thread; i++) { if (impl_ctx->bitmap & (0x1 << i)) { impl_ctx->bitmap &= ~(0x1 << i); uv_mutex_unlock(&impl_ctx->lock); - pow_avx_context_t *ctx = (pow_avx_context_t *) impl_ctx->context + i; + pow_avx_context_t *ctx = + (pow_avx_context_t *) impl_ctx->context + i; memcpy(ctx->input_trytes, trytes, TRANSACTION_TRYTES_LENGTH); ctx->mwm = mwm; ctx->index_of_context = i; @@ -667,7 +668,8 @@ static void *pow_avx_get_pow_context(impl_context_t *impl_ctx, static bool pow_avx_free_pow_context(impl_context_t *impl_ctx, void *pow_ctx) { uv_mutex_lock(&impl_ctx->lock); - impl_ctx->bitmap |= 0x1 << ((pow_avx_context_t *) pow_ctx)->index_of_context; + impl_ctx->bitmap |= 0x1 + << ((pow_avx_context_t *) pow_ctx)->index_of_context; uv_mutex_unlock(&impl_ctx->lock); return true; } diff --git a/src/pow_c.c b/src/pow_c.c index 8dcc322..0e14575 100644 --- a/src/pow_c.c +++ b/src/pow_c.c @@ -189,8 +189,9 @@ static int64_t pwork(int8_t mid[], static void work_cb(uv_work_t *req) { pwork_t *pwork_info = (pwork_t *) req->data; - pwork_info->ret = pwork(pwork_info->mid, pwork_info->mwm, pwork_info->nonce, - pwork_info->n, pwork_info->stop_pow, pwork_info->lock); + pwork_info->ret = + pwork(pwork_info->mid, pwork_info->mwm, pwork_info->nonce, + pwork_info->n, pwork_info->stop_pow, pwork_info->lock); uv_rwlock_wrlock(pwork_info->lock); if (pwork_info->ret >= 0) { @@ -343,7 +344,7 @@ static bool pow_c_context_initialize(impl_context_t *impl_ctx) return false; pow_c_context_t *ctx = (pow_c_context_t *) malloc(sizeof(pow_c_context_t) * - impl_ctx->num_max_thread); + impl_ctx->num_max_thread); if (!ctx) return false; @@ -402,9 +403,9 @@ static void pow_c_context_destroy(impl_context_t *impl_ctx) } static void *pow_c_get_pow_context(impl_context_t *impl_ctx, - int8_t *trytes, - int mwm, - int threads) + int8_t *trytes, + int mwm, + int threads) { uv_mutex_lock(&impl_ctx->lock); for (int i = 0; i < impl_ctx->num_max_thread; i++) { diff --git a/src/pow_cl.c b/src/pow_cl.c index a8459ce..450b61a 100644 --- a/src/pow_cl.c +++ b/src/pow_cl.c @@ -107,10 +107,10 @@ static int8_t *pwork(int8_t *state, int mwm, cl_context_t *ctx) if (!write_cl_buffer(titan, mid_low, mid_high, mwm, LOOP_COUNT)) return NULL; - if (CL_SUCCESS == - clEnqueueNDRangeKernel(titan->cmd_q, titan->kernel[INDEX_OF_KERNEL_INIT], - 1, &global_offset, &global_work_size, - &local_work_size, 0, NULL, &ev)) { + if (CL_SUCCESS == clEnqueueNDRangeKernel( + titan->cmd_q, titan->kernel[INDEX_OF_KERNEL_INIT], 1, + &global_offset, &global_work_size, &local_work_size, + 0, NULL, &ev)) { clWaitForEvents(1, &ev); clReleaseEvent(ev); ctx->hash_count += 64 * num_groups * LOOP_COUNT; @@ -118,8 +118,8 @@ static int8_t *pwork(int8_t *state, int mwm, cl_context_t *ctx) while (found == 0) { if (CL_SUCCESS != clEnqueueNDRangeKernel( - titan->cmd_q, titan->kernel[INDEX_OF_KERNEL_SEARCH], 1, NULL, - &global_work_size, &local_work_size, 0, NULL, &ev1)) { + titan->cmd_q, titan->kernel[INDEX_OF_KERNEL_SEARCH], 1, + NULL, &global_work_size, &local_work_size, 0, NULL, &ev1)) { clReleaseEvent(ev1); return NULL; /* Running "search" kernel function failed */ } @@ -265,8 +265,8 @@ static bool pow_cl(void *pow_ctx) static bool pow_cl_context_initialize(impl_context_t *impl_ctx) { impl_ctx->num_max_thread = init_clcontext(opencl_ctx); - pow_cl_context_t *ctx = (pow_cl_context_t *) malloc(sizeof(pow_cl_context_t) * - impl_ctx->num_max_thread); + pow_cl_context_t *ctx = (pow_cl_context_t *) malloc( + sizeof(pow_cl_context_t) * impl_ctx->num_max_thread); if (!ctx) goto fail; @@ -290,17 +290,16 @@ static void pow_cl_context_destroy(impl_context_t *impl_ctx) } static void *pow_cl_get_pow_context(impl_context_t *impl_ctx, - int8_t *trytes, - int mwm, - int threads) + int8_t *trytes, + int mwm, + int threads) { uv_mutex_lock(&impl_ctx->lock); for (int i = 0; i < impl_ctx->num_max_thread; i++) { if (impl_ctx->bitmap & (0x1 << i)) { impl_ctx->bitmap &= ~(0x1 << i); uv_mutex_unlock(&impl_ctx->lock); - pow_cl_context_t *ctx = - (pow_cl_context_t *) impl_ctx->context + i; + pow_cl_context_t *ctx = (pow_cl_context_t *) impl_ctx->context + i; memcpy(ctx->input_trytes, trytes, TRANSACTION_TRYTES_LENGTH); ctx->mwm = mwm; ctx->index_of_context = i; diff --git a/src/pow_fpga.c b/src/pow_fpga.c index 753973b..8e2b7f8 100644 --- a/src/pow_fpga.c +++ b/src/pow_fpga.c @@ -31,7 +31,7 @@ /* Set FPGA operation frequency 100 MHz */ #define FPGA_OPERATION_FREQUENCY 100000000 -#define INT_TO_STRING(I, S) \ +#define INT_TO_STRING(I, S) \ { \ S[0] = I & 0xff; \ S[1] = (I >> 8) & 0xff; \ @@ -200,9 +200,9 @@ static void pow_fpga_context_destroy(impl_context_t *impl_ctx) } static void *pow_fpga_get_pow_context(impl_context_t *impl_ctx, - int8_t *trytes, - int mwm, - int threads) + int8_t *trytes, + int mwm, + int threads) { pow_fpga_context_t *ctx = impl_ctx->context; memcpy(ctx->input_trytes, trytes, TRANSACTION_TRYTES_LENGTH); diff --git a/src/pow_kernel.cl b/src/pow_kernel.cl index 7fbf05a..96063bf 100644 --- a/src/pow_kernel.cl +++ b/src/pow_kernel.cl @@ -19,9 +19,9 @@ #define HIGH_BITS 0xFFFFFFFFFFFFFFFF #define LOW_BITS 0x0000000000000000 //#define HIGH_BITS -//0b1111111111111111111111111111111111111111111111111111111111111111L +// 0b1111111111111111111111111111111111111111111111111111111111111111L //#define LOW_BITS -//0b0000000000000000000000000000000000000000000000000000000000000000L +// 0b0000000000000000000000000000000000000000000000000000000000000000L /** * t1 = j == 0? 0:(((j - 1)%2)+1)*HALF_LENGTH - ((j-1)>>1); */ @@ -82,189 +82,228 @@ __constant size_t index[STATE_TRITS_LENGTH + 1] = { typedef long bc_trit_t; -void increment(__global bc_trit_t* mid_low, __global bc_trit_t* mid_high, - __private size_t from_index, __private size_t to_index); -void copy_mid_to_state(__global bc_trit_t* mid_low, __global bc_trit_t* mid_high, - __global bc_trit_t* state_low, __global bc_trit_t* state_high, - __private size_t id, __private size_t l_size, +void increment(__global bc_trit_t *mid_low, + __global bc_trit_t *mid_high, + __private size_t from_index, + __private size_t to_index); +void copy_mid_to_state(__global bc_trit_t *mid_low, + __global bc_trit_t *mid_high, + __global bc_trit_t *state_low, + __global bc_trit_t *state_high, + __private size_t id, + __private size_t l_size, __private size_t l_trits); -void transform(__global bc_trit_t* state_low, __global bc_trit_t* state_high, - __private size_t id, __private size_t l_size, +void transform(__global bc_trit_t *state_low, + __global bc_trit_t *state_high, + __private size_t id, + __private size_t l_size, __private size_t l_trits); -void check(__global bc_trit_t* state_low, __global bc_trit_t* state_high, - __global volatile char* found, - __constant size_t* min_weight_magnitude, - __global bc_trit_t* nonce_probe, __private size_t gr_id); -void setup_ids(__private size_t* id, __private size_t* gid, - __private size_t* gr_id, __private size_t* l_size, - __private size_t* n_trits); +void check(__global bc_trit_t *state_low, + __global bc_trit_t *state_high, + __global volatile char *found, + __constant size_t *min_weight_magnitude, + __global bc_trit_t *nonce_probe, + __private size_t gr_id); +void setup_ids(__private size_t *id, + __private size_t *gid, + __private size_t *gr_id, + __private size_t *l_size, + __private size_t *n_trits); -void increment(__global bc_trit_t* mid_low, __global bc_trit_t* mid_high, - __private size_t from_index, __private size_t to_index) { - size_t i; - bc_trit_t carry = 1; - for (i = from_index; i < to_index && carry != 0; i++) { - bc_trit_t low, hi; - low = mid_low[i]; - hi = mid_high[i]; - mid_low[i] = hi ^ low; - mid_high[i] = low; - carry = hi & (~low); - } -} - -void copy_mid_to_state(__global bc_trit_t* mid_low, __global bc_trit_t* mid_high, - __global bc_trit_t* state_low, __global bc_trit_t* state_high, - __private size_t id, __private size_t l_size, - __private size_t n_trits) { - size_t i; - for (i = 0; i < n_trits; i++) { - size_t j; - j = id + i * l_size; - state_low[j] = mid_low[j]; - state_high[j] = mid_high[j]; - } +void increment(__global bc_trit_t *mid_low, + __global bc_trit_t *mid_high, + __private size_t from_index, + __private size_t to_index) +{ + size_t i; + bc_trit_t carry = 1; + for (i = from_index; i < to_index && carry != 0; i++) { + bc_trit_t low, hi; + low = mid_low[i]; + hi = mid_high[i]; + mid_low[i] = hi ^ low; + mid_high[i] = low; + carry = hi & (~low); + } } -void transform(__global bc_trit_t* state_low, __global bc_trit_t* state_high, - __private size_t id, __private size_t l_size, - __private size_t n_trits) { - __private size_t round, i, j, k; - __private bc_trit_t alpha, beta, delta, sp_low[3], sp_high[3]; - for (round = 0; round < NUMBER_OF_ROUNDS; round++) { +void copy_mid_to_state(__global bc_trit_t *mid_low, + __global bc_trit_t *mid_high, + __global bc_trit_t *state_low, + __global bc_trit_t *state_high, + __private size_t id, + __private size_t l_size, + __private size_t n_trits) +{ + size_t i; for (i = 0; i < n_trits; i++) { - j = id + i * l_size; - k = j+1; - alpha = state_low[index[j]]; - beta = state_high[index[j]]; - delta = alpha & (beta ^ state_low[index[k]]); - sp_low[i] = ~delta; - sp_high[i] = (alpha ^ state_high[index[k]]) | delta; + size_t j; + j = id + i * l_size; + state_low[j] = mid_low[j]; + state_high[j] = mid_high[j]; } - barrier(CLK_LOCAL_MEM_FENCE); - for (i = 0; i < n_trits; i++) { - j = id + i * l_size; - state_low[j] = sp_low[i]; - state_high[j] = sp_high[i]; +} + +void transform(__global bc_trit_t *state_low, + __global bc_trit_t *state_high, + __private size_t id, + __private size_t l_size, + __private size_t n_trits) +{ + __private size_t round, i, j, k; + __private bc_trit_t alpha, beta, delta, sp_low[3], sp_high[3]; + for (round = 0; round < NUMBER_OF_ROUNDS; round++) { + for (i = 0; i < n_trits; i++) { + j = id + i * l_size; + k = j + 1; + alpha = state_low[index[j]]; + beta = state_high[index[j]]; + delta = alpha & (beta ^ state_low[index[k]]); + sp_low[i] = ~delta; + sp_high[i] = (alpha ^ state_high[index[k]]) | delta; + } + barrier(CLK_LOCAL_MEM_FENCE); + for (i = 0; i < n_trits; i++) { + j = id + i * l_size; + state_low[j] = sp_low[i]; + state_high[j] = sp_high[i]; + } + barrier(CLK_LOCAL_MEM_FENCE); } - barrier(CLK_LOCAL_MEM_FENCE); - } } -void check(__global bc_trit_t* state_low, __global bc_trit_t* state_high, - __global volatile char* found, - __constant size_t* min_weight_magnitude, - __global bc_trit_t* nonce_probe, __private size_t gr_id) { - int i; - *nonce_probe = HIGH_BITS; - for (i = HASH_TRITS_LENGTH - *min_weight_magnitude; i < HASH_TRITS_LENGTH; i++) { - *nonce_probe &= ~(state_low[i] ^ state_high[i]); - if (*nonce_probe == 0) - return; - } - if (*nonce_probe != 0) { - //*nonce_probe = 1 << __builtin_ctzl(*nonce_probe); - *found = gr_id + 1; - } +void check(__global bc_trit_t *state_low, + __global bc_trit_t *state_high, + __global volatile char *found, + __constant size_t *min_weight_magnitude, + __global bc_trit_t *nonce_probe, + __private size_t gr_id) +{ + int i; + *nonce_probe = HIGH_BITS; + for (i = HASH_TRITS_LENGTH - *min_weight_magnitude; i < HASH_TRITS_LENGTH; + i++) { + *nonce_probe &= ~(state_low[i] ^ state_high[i]); + if (*nonce_probe == 0) + return; + } + if (*nonce_probe != 0) { + //*nonce_probe = 1 << __builtin_ctzl(*nonce_probe); + *found = gr_id + 1; + } } -void setup_ids(__private size_t* id, __private size_t* gid, - __private size_t* gr_id, __private size_t* l_size, - __private size_t* n_trits) { - __private size_t l_rem; - *id = get_local_id(0); - *l_size = get_local_size(0); - *gr_id = get_global_id(0) / *l_size; - *gid = *gr_id * STATE_TRITS_LENGTH; - l_rem = STATE_TRITS_LENGTH % *l_size; - *n_trits = STATE_TRITS_LENGTH / *l_size; - *n_trits += l_rem == 0 ? 0 : 1; - *n_trits -= (*n_trits) * (*id) < STATE_TRITS_LENGTH ? 0 : 1; +void setup_ids(__private size_t *id, + __private size_t *gid, + __private size_t *gr_id, + __private size_t *l_size, + __private size_t *n_trits) +{ + __private size_t l_rem; + *id = get_local_id(0); + *l_size = get_local_size(0); + *gr_id = get_global_id(0) / *l_size; + *gid = *gr_id * STATE_TRITS_LENGTH; + l_rem = STATE_TRITS_LENGTH % *l_size; + *n_trits = STATE_TRITS_LENGTH / *l_size; + *n_trits += l_rem == 0 ? 0 : 1; + *n_trits -= (*n_trits) * (*id) < STATE_TRITS_LENGTH ? 0 : 1; } -__kernel void init(__global char* trit_hash, __global bc_trit_t* mid_low, - __global bc_trit_t* mid_high, __global bc_trit_t* state_low, - __global bc_trit_t* state_high, - __constant size_t* min_weight_magnitude, - __global volatile char* found, __global bc_trit_t* nonce_probe, - __constant size_t* loop_count) { - __private size_t i, j, id, gid, gr_id, gl_off, l_size, n_trits; - setup_ids(&id, &gid, &gr_id, &l_size, &n_trits); - gl_off = get_global_offset(0); +__kernel void init(__global char *trit_hash, + __global bc_trit_t *mid_low, + __global bc_trit_t *mid_high, + __global bc_trit_t *state_low, + __global bc_trit_t *state_high, + __constant size_t *min_weight_magnitude, + __global volatile char *found, + __global bc_trit_t *nonce_probe, + __constant size_t *loop_count) +{ + __private size_t i, j, id, gid, gr_id, gl_off, l_size, n_trits; + setup_ids(&id, &gid, &gr_id, &l_size, &n_trits); + gl_off = get_global_offset(0); - if (id == 0 && gr_id == 0) { - *found = 0; - } + if (id == 0 && gr_id == 0) { + *found = 0; + } - if (gr_id == 0) - return; + if (gr_id == 0) + return; - for (i = 0; i < n_trits; i++) { - j = id + i * l_size; - mid_low[gid + j] = mid_low[j]; - mid_high[gid + j] = mid_high[j]; - } + for (i = 0; i < n_trits; i++) { + j = id + i * l_size; + mid_low[gid + j] = mid_low[j]; + mid_high[gid + j] = mid_high[j]; + } - if (id == 0) { - for (i = 0; i < gr_id + gl_off; i++) { - increment(&(mid_low[gid]), &(mid_high[gid]), NONCE_INIT_START, - NONCE_INCREMENT_START); + if (id == 0) { + for (i = 0; i < gr_id + gl_off; i++) { + increment(&(mid_low[gid]), &(mid_high[gid]), NONCE_INIT_START, + NONCE_INCREMENT_START); + } } - } } -__kernel void search(__global char* trit_hash, __global bc_trit_t* mid_low, - __global bc_trit_t* mid_high, __global bc_trit_t* state_low, - __global bc_trit_t* state_high, - __constant size_t* min_weight_magnitude, - __global volatile char* found, - __global bc_trit_t* nonce_probe, - __constant size_t* loop_count) { - __private size_t i, id, gid, gr_id, l_size, n_trits; - setup_ids(&id, &gid, &gr_id, &l_size, &n_trits); +__kernel void search(__global char *trit_hash, + __global bc_trit_t *mid_low, + __global bc_trit_t *mid_high, + __global bc_trit_t *state_low, + __global bc_trit_t *state_high, + __constant size_t *min_weight_magnitude, + __global volatile char *found, + __global bc_trit_t *nonce_probe, + __constant size_t *loop_count) +{ + __private size_t i, id, gid, gr_id, l_size, n_trits; + setup_ids(&id, &gid, &gr_id, &l_size, &n_trits); - for (i = 0; i < *loop_count; i++) { - if (id == 0) - increment(&(mid_low[gid]), &(mid_high[gid]), NONCE_INCREMENT_START, - HASH_TRITS_LENGTH); + for (i = 0; i < *loop_count; i++) { + if (id == 0) + increment(&(mid_low[gid]), &(mid_high[gid]), NONCE_INCREMENT_START, + HASH_TRITS_LENGTH); - barrier(CLK_LOCAL_MEM_FENCE); - copy_mid_to_state(&(mid_low[gid]), &(mid_high[gid]), &(state_low[gid]), - &(state_high[gid]), id, l_size, n_trits); + barrier(CLK_LOCAL_MEM_FENCE); + copy_mid_to_state(&(mid_low[gid]), &(mid_high[gid]), &(state_low[gid]), + &(state_high[gid]), id, l_size, n_trits); - barrier(CLK_LOCAL_MEM_FENCE); - transform(&(state_low[gid]), &(state_high[gid]), id, l_size, n_trits); + barrier(CLK_LOCAL_MEM_FENCE); + transform(&(state_low[gid]), &(state_high[gid]), id, l_size, n_trits); - barrier(CLK_LOCAL_MEM_FENCE); - if (id == 0) - check(&(state_low[gid]), &(state_high[gid]), found, min_weight_magnitude, - &(nonce_probe[gr_id]), gr_id); + barrier(CLK_LOCAL_MEM_FENCE); + if (id == 0) + check(&(state_low[gid]), &(state_high[gid]), found, + min_weight_magnitude, &(nonce_probe[gr_id]), gr_id); - barrier(CLK_LOCAL_MEM_FENCE); - if (*found != 0) - break; - } + barrier(CLK_LOCAL_MEM_FENCE); + if (*found != 0) + break; + } } -__kernel void finalize(__global char* trit_hash, __global bc_trit_t* mid_low, - __global bc_trit_t* mid_high, __global bc_trit_t* state_low, - __global bc_trit_t* state_high, - __constant size_t* min_weight_magnitude, - __global volatile char* found, - __global bc_trit_t* nonce_probe, - __constant size_t* loop_count) { - __private size_t i, j, id, gid, gr_id, l_size, n_trits; - setup_ids(&id, &gid, &gr_id, &l_size, &n_trits); +__kernel void finalize(__global char *trit_hash, + __global bc_trit_t *mid_low, + __global bc_trit_t *mid_high, + __global bc_trit_t *state_low, + __global bc_trit_t *state_high, + __constant size_t *min_weight_magnitude, + __global volatile char *found, + __global bc_trit_t *nonce_probe, + __constant size_t *loop_count) +{ + __private size_t i, j, id, gid, gr_id, l_size, n_trits; + setup_ids(&id, &gid, &gr_id, &l_size, &n_trits); - if (gr_id == (size_t)(*found - 1) && nonce_probe[gr_id] != 0) { - for (i = 0; i < n_trits; i++) { - j = id + i * l_size; - if (j < HASH_TRITS_LENGTH) { - trit_hash[j] = - (mid_low[gid + j] & nonce_probe[gr_id]) == 0 - ? 1 - : (mid_high[gid + j] & nonce_probe[gr_id]) == 0 ? -1 : 0; - } + if (gr_id == (size_t)(*found - 1) && nonce_probe[gr_id] != 0) { + for (i = 0; i < n_trits; i++) { + j = id + i * l_size; + if (j < HASH_TRITS_LENGTH) { + trit_hash[j] = + (mid_low[gid + j] & nonce_probe[gr_id]) == 0 + ? 1 + : (mid_high[gid + j] & nonce_probe[gr_id]) == 0 ? -1 + : 0; + } + } } - } } diff --git a/src/pow_sse.c b/src/pow_sse.c index bb75ff1..f6bcd61 100644 --- a/src/pow_sse.c +++ b/src/pow_sse.c @@ -112,11 +112,11 @@ static int check_128(__m128i *l, __m128i *h, int m) } static int64_t loop_128(__m128i *lmid, - __m128i *hmid, - int m, - int8_t *nonce, - int *stop_pow, - uv_rwlock_t *lock) + __m128i *hmid, + int m, + int8_t *nonce, + int *stop_pow, + uv_rwlock_t *lock) { int64_t i = 0; __m128i lcpy[STATE_TRITS_LENGTH * 2], hcpy[STATE_TRITS_LENGTH * 2]; @@ -133,7 +133,7 @@ static int64_t loop_128(__m128i *lmid, transform_128(lcpy, hcpy); if ((n = check_128(lcpy + STATE_TRITS_LENGTH, hcpy + STATE_TRITS_LENGTH, - m)) >= 0) { + m)) >= 0) { seri_128(lmid, hmid, n, nonce); return i * 128; } @@ -178,11 +178,11 @@ static void incr_n_128(int n, __m128i *mid_low, __m128i *mid_high) } static int64_t pwork_128(int8_t mid[], - int mwm, - int8_t nonce[], - int n, - int *stop_pow, - uv_rwlock_t *lock) + int mwm, + int8_t nonce[], + int n, + int *stop_pow, + uv_rwlock_t *lock) { __m128i lmid[STATE_TRITS_LENGTH], hmid[STATE_TRITS_LENGTH]; para_128(mid, lmid, hmid); @@ -207,8 +207,8 @@ static void work_cb(uv_work_t *req) { pwork_t *pwork_info = (pwork_t *) req->data; pwork_info->ret = - pwork_128(pwork_info->mid, pwork_info->mwm, pwork_info->nonce, pwork_info->n, - pwork_info->stop_pow, pwork_info->lock); + pwork_128(pwork_info->mid, pwork_info->mwm, pwork_info->nonce, + pwork_info->n, pwork_info->stop_pow, pwork_info->lock); uv_rwlock_wrlock(pwork_info->lock); if (pwork_info->ret >= 0) { @@ -360,8 +360,8 @@ static bool pow_sse_context_initialize(impl_context_t *impl_ctx) if (impl_ctx->num_max_thread <= 0 || nproc <= 0) return false; - pow_sse_context_t *ctx = (pow_sse_context_t *) malloc(sizeof(pow_sse_context_t) * - impl_ctx->num_max_thread); + pow_sse_context_t *ctx = (pow_sse_context_t *) malloc( + sizeof(pow_sse_context_t) * impl_ctx->num_max_thread); if (!ctx) return false; @@ -420,16 +420,17 @@ static void pow_sse_context_destroy(impl_context_t *impl_ctx) } static void *pow_sse_get_pow_context(impl_context_t *impl_ctx, - int8_t *trytes, - int mwm, - int threads) + int8_t *trytes, + int mwm, + int threads) { uv_mutex_lock(&impl_ctx->lock); for (int i = 0; i < impl_ctx->num_max_thread; i++) { if (impl_ctx->bitmap & (0x1 << i)) { impl_ctx->bitmap &= ~(0x1 << i); uv_mutex_unlock(&impl_ctx->lock); - pow_sse_context_t *ctx = (pow_sse_context_t *) impl_ctx->context + i; + pow_sse_context_t *ctx = + (pow_sse_context_t *) impl_ctx->context + i; memcpy(ctx->input_trytes, trytes, TRANSACTION_TRYTES_LENGTH); ctx->mwm = mwm; ctx->index_of_context = i; @@ -447,7 +448,8 @@ static void *pow_sse_get_pow_context(impl_context_t *impl_ctx, static bool pow_sse_free_pow_context(impl_context_t *impl_ctx, void *pow_ctx) { uv_mutex_lock(&impl_ctx->lock); - impl_ctx->bitmap |= 0x1 << ((pow_sse_context_t *) pow_ctx)->index_of_context; + impl_ctx->bitmap |= 0x1 + << ((pow_sse_context_t *) pow_ctx)->index_of_context; uv_mutex_unlock(&impl_ctx->lock); return true; } diff --git a/src/remote_common.c b/src/remote_common.c index 5d813c8..89234a2 100644 --- a/src/remote_common.c +++ b/src/remote_common.c @@ -134,7 +134,7 @@ bool declare_callback_queue(amqp_connection_state_t *conn, amqp_queue_declare_ok_t *r = amqp_queue_declare(*conn, channel, amqp_empty_bytes, 0, 0, 1, 0, table); if (!r || !die_on_amqp_error(amqp_get_rpc_reply(*conn), - "Declaring the private queue with TTL = 10s")) + "Declaring the private queue with TTL = 10s")) return false; *reply_to_queue = amqp_bytes_malloc_dup(r->queue); diff --git a/src/remote_interface.c b/src/remote_interface.c index 0c55144..6812179 100644 --- a/src/remote_interface.c +++ b/src/remote_interface.c @@ -48,7 +48,9 @@ bool enter_remote_context(remote_impl_context_t *remote_ctx) return true; /* Access Success */ } -void *get_remote_context(remote_impl_context_t *remote_ctx, int8_t *trytes, int mwm) +void *get_remote_context(remote_impl_context_t *remote_ctx, + int8_t *trytes, + int mwm) { return remote_ctx->get_pow_context(remote_ctx, trytes, mwm); } @@ -186,8 +188,8 @@ static void remote_destroy(remote_impl_context_t *remote_ctx) } static void *remote_get_pow_context(remote_impl_context_t *remote_ctx, - int8_t *trytes, - int mwm) + int8_t *trytes, + int mwm) { uv_mutex_lock(&remote_ctx->lock); @@ -211,11 +213,13 @@ static void *remote_get_pow_context(remote_impl_context_t *remote_ctx, return NULL; /* It should not happen */ } -static bool remote_free_pow_context(remote_impl_context_t *remote_ctx, void *pow_ctx) +static bool remote_free_pow_context(remote_impl_context_t *remote_ctx, + void *pow_ctx) { uv_mutex_lock(&remote_ctx->lock); - remote_ctx->slots[((pow_remote_context_t *) pow_ctx)->index_of_context] = false; + remote_ctx->slots[((pow_remote_context_t *) pow_ctx)->index_of_context] = + false; uv_mutex_unlock(&remote_ctx->lock); diff --git a/src/remote_interface.h b/src/remote_interface.h index 7d3d560..456ea70 100644 --- a/src/remote_interface.h +++ b/src/remote_interface.h @@ -50,8 +50,8 @@ struct remote_impl_context_s { void (*destroy)(remote_impl_context_t *remote_ctx); /* Private PoW Context for each thread */ void *(*get_pow_context)(remote_impl_context_t *remote_ctx, - int8_t *trytes, - int mwm); + int8_t *trytes, + int mwm); bool (*do_the_pow)(remote_impl_context_t *remote_ctx, void *pow_ctx); int8_t *(*get_pow_result)(void *pow_ctx); pow_info_t (*get_pow_info)(void *pow_ctx); @@ -65,7 +65,9 @@ bool register_remote_context(remote_impl_context_t *remote_ctx); bool initialize_remote_context(remote_impl_context_t *remote_ctx); void destroy_remote_context(remote_impl_context_t *remote_ctx); bool enter_remote_context(remote_impl_context_t *remote_ctx); -void *get_remote_context(remote_impl_context_t *remote_ctx, int8_t *trytes, int mwm); +void *get_remote_context(remote_impl_context_t *remote_ctx, + int8_t *trytes, + int mwm); bool do_remote_context(remote_impl_context_t *remote_ctx, void *pow_ctx); int8_t *get_remote_result(remote_impl_context_t *remote_ctx, void *pow_ctx); bool free_remote_context(remote_impl_context_t *remote_ctx, void *pow_ctx); diff --git a/src/remote_worker.c b/src/remote_worker.c index 5d8a601..1a7055b 100644 --- a/src/remote_worker.c +++ b/src/remote_worker.c @@ -20,7 +20,7 @@ int main(int argc, char *const *argv) int cmd_opt; int opt_idx; const struct option long_opt[] = {{"broker", required_argument, NULL, 'b'}, - {NULL, 0, NULL, 0}}; + {NULL, 0, NULL, 0}}; amqp_connection_state_t conn; amqp_envelope_t envelope; diff --git a/src/trinary_sse42.h b/src/trinary_sse42.h index b662640..a271c74 100644 --- a/src/trinary_sse42.h +++ b/src/trinary_sse42.h @@ -50,9 +50,9 @@ static inline bool validate_trits_sse42(trinary_object_t *trits) const int pos_one_element = 0x01010101; const int neg_one_element = 0xFFFFFFFF; const __m128i pos_one = _mm_set_epi32(pos_one_element, pos_one_element, - pos_one_element, pos_one_element); + pos_one_element, pos_one_element); const __m128i neg_one = _mm_set_epi32(neg_one_element, neg_one_element, - neg_one_element, neg_one_element); + neg_one_element, neg_one_element); /* The for loop handles the group of the 128-bit characters without the * end-of-string */ for (int i = 0; i < (trits->len) / block_8bit; i++) { @@ -91,12 +91,12 @@ static inline bool validate_trytes_sse42(trinary_object_t *trytes) * Return 0 if all the characters are in the range, otherwise return 1 */ int not_valid = _mm_cmpistrc(pattern, src, - /* Signed byte comparison */ - _SIDD_SBYTE_OPS | - /* Compare with the character range */ - _SIDD_CMP_RANGES | - /* Negate the comparison result */ - _SIDD_MASKED_NEGATIVE_POLARITY); + /* Signed byte comparison */ + _SIDD_SBYTE_OPS | + /* Compare with the character range */ + _SIDD_CMP_RANGES | + /* Negate the comparison result */ + _SIDD_MASKED_NEGATIVE_POLARITY); if (not_valid) return false; @@ -235,11 +235,13 @@ static inline trinary_object_t *trytes_from_trits_sse42(trinary_object_t *trits) /* If the offset is >= 16 (> 15), then the compared result byte = 0xFF, * else = 0x00 */ __m128i cmp_result = _mm_cmpgt_epi8( - alphabet_offset, _mm_set_epi8(15, 15, 15, 15, 15, 15, 15, 15, 15, 15, - 15, 15, 15, 15, 15, 15)); - /* Use the offset to get the correct tryte alphabet from tryte_alphabet_for_simd[] + alphabet_offset, _mm_set_epi8(15, 15, 15, 15, 15, 15, 15, 15, 15, + 15, 15, 15, 15, 15, 15, 15)); + /* Use the offset to get the correct tryte alphabet from + * tryte_alphabet_for_simd[] */ - __m128i result_lt = _mm_shuffle_epi8(tryte_alphabet_for_simd[0], alphabet_offset); + __m128i result_lt = + _mm_shuffle_epi8(tryte_alphabet_for_simd[0], alphabet_offset); __m128i result_ge = _mm_shuffle_epi8( tryte_alphabet_for_simd[1], /* alphabet_offset - 16 */ @@ -297,7 +299,8 @@ static inline trinary_object_t *trits_from_trytes_sse42(trinary_object_t *trytes /* 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V' */ const char range_high_trit_n1[BYTE_OF_128BIT] = "NV"; /* Convert the char array to the 128-bit data */ - const __m128i pattern_low_trit_0 = _mm_loadu_si128((__m128i *) (set_low_trit_0)); + const __m128i pattern_low_trit_0 = + _mm_loadu_si128((__m128i *) (set_low_trit_0)); const __m128i pattern_low_trit_p1 = _mm_loadu_si128((__m128i *) (set_low_trit_p1)); const __m128i pattern_low_trit_n1 = @@ -409,18 +412,18 @@ static inline trinary_object_t *trits_from_trytes_sse42(trinary_object_t *trytes * high_trit = | a3 | ... | f3 | ... | p3 | data_last = | k3 | l1 | l2 | ...... | p3 | * ------ ------ ------ ---------------- ------ */ - __m128i low_trit = - _mm_or_si128(_mm_and_si128(mask_low_trit_0, zero), - _mm_or_si128(_mm_and_si128(mask_low_trit_p1, pos_one), - _mm_and_si128(mask_low_trit_n1, neg_one))); - __m128i mid_trit = - _mm_or_si128(_mm_and_si128(mask_mid_trit_0, zero), - _mm_or_si128(_mm_and_si128(mask_mid_trit_p1, pos_one), - _mm_and_si128(mask_mid_trit_n1, neg_one))); - __m128i high_trit = - _mm_or_si128(_mm_and_si128(mask_high_trit_0, zero), - _mm_or_si128(_mm_and_si128(mask_high_trit_p1, pos_one), - _mm_and_si128(mask_high_trit_n1, neg_one))); + __m128i low_trit = _mm_or_si128( + _mm_and_si128(mask_low_trit_0, zero), + _mm_or_si128(_mm_and_si128(mask_low_trit_p1, pos_one), + _mm_and_si128(mask_low_trit_n1, neg_one))); + __m128i mid_trit = _mm_or_si128( + _mm_and_si128(mask_mid_trit_0, zero), + _mm_or_si128(_mm_and_si128(mask_mid_trit_p1, pos_one), + _mm_and_si128(mask_mid_trit_n1, neg_one))); + __m128i high_trit = _mm_or_si128( + _mm_and_si128(mask_high_trit_0, zero), + _mm_or_si128(_mm_and_si128(mask_high_trit_p1, pos_one), + _mm_and_si128(mask_high_trit_n1, neg_one))); __m128i data_first, data_mid, data_last; data_first = _mm_or_si128( _mm_shuffle_epi8(low_trit, shuffle_first[0]), From 1af1e2d921ba93733bbbe6f74cbb331fcae5ff34 Mon Sep 17 00:00:00 2001 From: Jim Huang Date: Fri, 3 Jan 2020 11:56:13 +0800 Subject: [PATCH 14/22] Bump copyright date --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 3d2d9ab..bb5c56e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (C) 2018-2019 BiiLabs Co., Ltd. and Contributors. +Copyright (C) 2018-2020 BiiLabs Co., Ltd. and Contributors. Copyright (C) 2018 Ievgen Korokyi. Copyright (C) 2017 IOTA AS, IOTA Foundation and Developers. Copyright (C) 2016 Shinya Yagyu. From c33068fef96835a03f27e23f4ccff04f8171b75b Mon Sep 17 00:00:00 2001 From: marktwtn Date: Fri, 3 Jan 2020 15:16:28 +0800 Subject: [PATCH 15/22] fix: Add brackets to avoid unexpected macro behavior --- docs/naming-convention.md | 2 +- src/constants.h | 2 +- src/pow_avx.h | 2 +- src/pow_c.h | 2 +- src/pow_sse.h | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/naming-convention.md b/docs/naming-convention.md index b3e6b30..ac59096 100644 --- a/docs/naming-convention.md +++ b/docs/naming-convention.md @@ -21,7 +21,7 @@ dcurl uses the **[snake case](https://en.wikipedia.org/wiki/Snake_case)** naming - Macro: Use capital letters ``` - #define MIN_TRYTE_VALUE -13 + #define MIN_TRYTE_VALUE (-13) #define MAX_TRYTE_VALUE 13 ``` diff --git a/src/constants.h b/src/constants.h index a0fa32d..3e12130 100644 --- a/src/constants.h +++ b/src/constants.h @@ -9,7 +9,7 @@ #ifndef CONSTANTS_H_ #define CONSTANTS_H_ -#define MIN_TRYTE_VALUE -13 +#define MIN_TRYTE_VALUE (-13) #define MAX_TRYTE_VALUE 13 #define SIGNATURE_SIZE 6561 #define DEPTH 3 diff --git a/src/pow_avx.h b/src/pow_avx.h index 346aca0..a654331 100644 --- a/src/pow_avx.h +++ b/src/pow_avx.h @@ -49,7 +49,7 @@ struct pow_avx_context_s { #include #endif -#define INCR_START HASH_TRITS_LENGTH - NONCE_TRITS_LENGTH + 4 + 27 +#define INCR_START (HASH_TRITS_LENGTH - NONCE_TRITS_LENGTH + 4 + 27) #ifdef __AVX2__ #define HBITS 0xFFFFFFFFFFFFFFFFuLL diff --git a/src/pow_c.h b/src/pow_c.h index a99e798..0851dfb 100644 --- a/src/pow_c.h +++ b/src/pow_c.h @@ -54,7 +54,7 @@ struct pow_c_context_s { #define HBITS 0xFFFFFFFFFFFFFFFFuLL #define LBITS 0x0000000000000000uLL -#define INCR_START HASH_TRITS_LENGTH - NONCE_TRITS_LENGTH + 4 + 27 +#define INCR_START (HASH_TRITS_LENGTH - NONCE_TRITS_LENGTH + 4 + 27) #define LOW0 \ 0xDB6DB6DB6DB6DB6DuLL // 0b1101101101101101101101101101101101101101101101101101101101101101L; #define HIGH0 \ diff --git a/src/pow_sse.h b/src/pow_sse.h index c08f5ad..088dce3 100644 --- a/src/pow_sse.h +++ b/src/pow_sse.h @@ -59,7 +59,7 @@ struct pow_sse_context_s { #define HBITS 0xFFFFFFFFFFFFFFFFuLL #define LBITS 0x0000000000000000uLL -#define INCR_START HASH_TRITS_LENGTH - NONCE_TRITS_LENGTH + 4 + 27 +#define INCR_START (HASH_TRITS_LENGTH - NONCE_TRITS_LENGTH + 4 + 27) #define LOW00 \ 0xDB6DB6DB6DB6DB6DuLL // 0b1101101101101101101101101101101101101101101101101101101101101101L; #define HIGH00 \ From bff88e4fb719b5d15e6cc3a4fb8054a18231b169 Mon Sep 17 00:00:00 2001 From: marktwtn Date: Mon, 6 Jan 2020 16:39:03 +0800 Subject: [PATCH 16/22] docs: Fix typo --- docs/naming-convention.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/naming-convention.md b/docs/naming-convention.md index ac59096..663e7df 100644 --- a/docs/naming-convention.md +++ b/docs/naming-convention.md @@ -13,7 +13,7 @@ dcurl uses the **[snake case](https://en.wikipedia.org/wiki/Snake_case)** naming - Structure: The suffixes **_s** represents for structure and **_t** represents for type ``` - typedef struct pwrok_s pwork_t; + typedef struct pwork_s pwork_t; struct pwork_s { ...... } From 59becd644e685664076a572e673d75e92b8ebb43 Mon Sep 17 00:00:00 2001 From: marktwtn Date: Fri, 31 Jan 2020 11:28:18 +0800 Subject: [PATCH 17/22] CI: Suppress CppCheck warning with --inline-suppr option Use the CppCheck --inline-suppr option to suppress the detected warnings by adding the corresponding comment in the source code. The previous method needs to specify the source code line number in the suppression file, which is less flexible to maintain. Close #215. --- cppcheck_suppress | 13 ------------- mk/static-analysis.mk | 1 + src/compat_ccurl.c | 3 +++ src/pow_avx.c | 1 + src/pow_kernel.cl | 3 +++ 5 files changed, 8 insertions(+), 13 deletions(-) diff --git a/cppcheck_suppress b/cppcheck_suppress index 1aa3cc4..0b5795e 100644 --- a/cppcheck_suppress +++ b/cppcheck_suppress @@ -1,15 +1,2 @@ -// The most significant bit is not used as a signed bit -shiftTooManyBitsSigned:src/pow_avx.c:321 - -// The unused functions are for the ccurl compatibility -unusedFunction:src/compat_ccurl.c:18 -unusedFunction:src/compat_ccurl.c:29 -unusedFunction:src/compat_ccurl.c:34 - -// The invoked functions of OpenCL are not checked correctly with CppCheck -unusedFunction:src/pow_kernel.cl:213 -unusedFunction:src/pow_kernel.cl:248 -unusedFunction:src/pow_kernel.cl:284 - // Do not treat system header files missing as errors missingIncludeSystem:* diff --git a/mk/static-analysis.mk b/mk/static-analysis.mk index fe6abf5..4c40206 100644 --- a/mk/static-analysis.mk +++ b/mk/static-analysis.mk @@ -18,6 +18,7 @@ static-analysis: --enable=all \ --error-exitcode=1 \ --force \ + --inline-suppr \ -I $(SRC) \ $(LIBTUV_INCLUDE) \ $(LIBRABBITMQ_INCLUDE) \ diff --git a/src/compat_ccurl.c b/src/compat_ccurl.c index 8816059..d914986 100644 --- a/src/compat_ccurl.c +++ b/src/compat_ccurl.c @@ -15,6 +15,7 @@ static bool is_initialized = false; /* mutex protecting initialization section */ static pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER; +// cppcheck-suppress unusedFunction ; The unused functions are for the ccurl compatibility char *ccurl_pow(char *trytes, int mwm) { pthread_mutex_lock(&mtx); @@ -26,11 +27,13 @@ char *ccurl_pow(char *trytes, int mwm) return (char *) dcurl_entry((int8_t *) trytes, mwm, 1); } +// cppcheck-suppress unusedFunction ; The unused functions are for the ccurl compatibility void ccurl_pow_finalize(void) { dcurl_destroy(); } +// cppcheck-suppress unusedFunction ; The unused functions are for the ccurl compatibility void ccurl_pow_interrupt(void) { /* Do Nothing */ diff --git a/src/pow_avx.c b/src/pow_avx.c index 0911b73..8c7216a 100644 --- a/src/pow_avx.c +++ b/src/pow_avx.c @@ -318,6 +318,7 @@ static int check_256(__m256d *l, __m256d *h, int m) for (j = 0; j < 4; j++) { for (i = 0; i < 64; i++) { long long np = ((dl) nonce_probe[j]).l; + // cppcheck-suppress shiftTooManyBitsSigned ; The most significant bit is not used as a signed bit if ((np >> i) & 1) { return i + j * 64; } diff --git a/src/pow_kernel.cl b/src/pow_kernel.cl index 96063bf..09f82c1 100644 --- a/src/pow_kernel.cl +++ b/src/pow_kernel.cl @@ -210,6 +210,7 @@ void setup_ids(__private size_t *id, *n_trits -= (*n_trits) * (*id) < STATE_TRITS_LENGTH ? 0 : 1; } +// cppcheck-suppress unusedFunction ; The invoked functions of OpenCL are not checked correctly with CppCheck __kernel void init(__global char *trit_hash, __global bc_trit_t *mid_low, __global bc_trit_t *mid_high, @@ -245,6 +246,7 @@ __kernel void init(__global char *trit_hash, } } +// cppcheck-suppress unusedFunction ; The invoked functions of OpenCL are not checked correctly with CppCheck __kernel void search(__global char *trit_hash, __global bc_trit_t *mid_low, __global bc_trit_t *mid_high, @@ -281,6 +283,7 @@ __kernel void search(__global char *trit_hash, } } +// cppcheck-suppress unusedFunction ; The invoked functions of OpenCL are not checked correctly with CppCheck __kernel void finalize(__global char *trit_hash, __global bc_trit_t *mid_low, __global bc_trit_t *mid_high, From 1be7d2cb7b77e672b5ac9e9cf08e3062677fa6f7 Mon Sep 17 00:00:00 2001 From: marktwtn Date: Fri, 14 Feb 2020 04:29:52 +0800 Subject: [PATCH 18/22] docs: Update dcurl performance data Close #100. --- README.md | 35 +++++++++++++++++++++++++++++++---- docs/benchmark.png | Bin 83406 -> 42013 bytes 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index c850796..3372dcb 100644 --- a/README.md +++ b/README.md @@ -20,12 +20,39 @@ Check [docs/build-n-test.md](docs/build-n-test.md) for details. Check [docs/naming-convention.md](docs/naming-convention.md) for details. ## Performance -After integrating dcurl into IRI, performance of [attachToTangle](https://iota.readme.io/reference#attachtotangle) is measured as following. -* Each sampling is measured with 30 transaction trytes and total 200 samples are measured. -* mwm = 14, 26 CPU threads to find nonce -* Settings: enable 2 pow tasks in CPU, 1 pow tasks in GPU at the same time +After integrating dcurl into IRI, performance of [attachToTangle](https://docs.iota.org/docs/node-software/0.1/iri/references/api-reference#attachtotangle) is measured as the following. + +* Setting: MWM = 14, 200 attachToTangle API requests with each containing 2 transactions +* Local CPU: + * AMD Ryzen Threadripper 2990WX 32-Core Processor + * 2 PoW tasks at the same time + * Each task uses 32 CPU threads to find nonce + * SIMD enabled +* Remote worker: + * The board with Intel/Altera Cyclone V SoC + * 1 PoW task at the same time in a board + * FPGA acceleration enabled + * Connected with local network + ![](https://github.com/raw/DLTcollab/dcurl/develop/docs/benchmark.png) +### Conclusion + +Except the original IRI, the other instances use the [DLTcollab/IRI](https://github.com/DLTcollab/iri) instead of [iotaledger/IRI](https://github.com/iotaledger/iri). + +| IRI version | attachToTangle API behavior | Effect | +|:-|:-|:-| +| IOTA IRI | One transaction bundle at the same time **(Synchronized)** | Transactions of a bundle are calculated one by one | +| DLTCollab IRI | Multiple transaction bundles at the same time | Transactions of different bundles compete for the PoW calculation resources | + +The original IRI should be the slowest one since it does not contain any PoW acceleration. +However, the graph is different from the expectation. +This is caused by 2 factors: +* The graph shows the execution time of each API request instead of the overall throughput. +* The table shows that there are competition of the PoW resources, which means the execution time would be longer than expected. + +And from the graph we can see that 4 remote workers would be a good choice to accelerate PoW. + ## IRI Adaptation [Modified IRI accepting external PoW Library](https://github.com/DLTcollab/iri) Supported IRI version: 1.7.0 diff --git a/docs/benchmark.png b/docs/benchmark.png index 12ebd627d25e4bd45b1be60767c869b0df5b17b0..1f5edf378674a13a629638ae1f4c7a08510ea23e 100644 GIT binary patch literal 42013 zcmdSB2{hJi+c$cVBne4E=Al%EC{)IzXhJDerjWTr=2=KGmSj#sQs#LcLZ*tS%tIQ? z^E~h0b>Hv%e9!Z}&%4*R*52RR`*W|=<(97NKb+@r{HEjYtD>Z^laiT|Kp^Zqrzn4g zKp=G|5J>tdNb!@R>hk9CsYS*r zKF)m2hw^6x3-fwhsuiQ22+mC(&QpuJvm^J8fb{h*Bd#}}WEFK}WgU8FHC!yV|DAP2 zq~aSz)1taWFUF&P7HgNCKYtbpj7wH6c@eZR6ur1w(w9E_LOA`z|3a3F-G zj9+!s#BUh=IY_qPmB*co3NOI~x+8dzB~`4z3t{{J0e_h_w=mu{*c2PWx|Ptso3Ndc z>Y{|*MD$4;QzxfYpE2vv@2OP}ceZ}}wsZUT<=}POe2cy^rlW?z`>G@!KYlDCEX*nK zIH=RdAtYob>6oG{DLGwtfn`-!S66$xhPt}lkN4iP9ZyqUi z-=rg%Qr;YMj}ipsqO36VAi(UiOr44OPx`9q;M zZrnIjw$WedNf8$v9er3m&A`aWqBG~*wQDvDV;wOuG4>`}S}|0w+-MADJ}fCZk}x{Z z-IrOSxOVMYs&=X4^33nd%uFjQD+*3Gx6Oe8y)9d|WSw4ZpI&zM3V!?6G&b+;yLY2D z0p=0m;r*(`Gcz-1&z=<&6r40UoRyH6C~!0H;;B=d0s?n_ehAPy&&tAb?AS3{xopEv zBFBzt7FnCzzWsaXOMLyK9Gc$6eLqhxkRCa*b>{}Bh=^5t#;vY=i`pz9!?mU9rOn2M z1`Yn_uV26R^{pTI_AV+aYWh`1#t}Qa#fFB4<=Me^$;lm^ozI^?&&$nC)hd2osmr); zU+i&9xssWb>)BWhhD|S|oR{uNNEC-0P##G9^yyPq-ktl_)>p4x6FqwLf}$dAUvpJe zd{)-e8oe*ZIk+*B4l~tVT{l%#RdsaSrUz<5Lqj!01q1|!tJ0E_ujd#)$;(>^7uHvb zmF{U>n)~|sg_P5uPfu+YlkxacW)`T0{;nFqee5-+ZU zlhf$PhzO(q?Z)Rn*k4joQU8=3-Ch)J{$QxYTPV zGJ1e1QQdJLLkeRwzmAt%t|AU)2C0*&&^%D zcu~xvH~QJLgrp>+J9ngPM!xPjtQL(6sI$4UH{h((%&+a*4t2qtj*gB_ixW~#3n}^e z;&MaXh4(c~u3mi>5OB%de9U{t-m>LC`@CqQK7A0+!B=MH^<2|$9$U6~$^DocZWZ9? z7ZDNJSetFC@!M-;X!v;Jghz*2dr?tQ{Mi6X8X6ggnO_O#LY_T)rd{UTk<{b1v9?_1 zvPvsAJUpx^nBVwNYWy?q{la8l5ba5u5&E!3mz6n_MbYZ`%W7(3)RY5`F{{8zNvhD&{dJXmU z<2}WDZ&K~tnb@wCv&9y=7Kli1j0R2R2Sep+_kNW2iXw!S`W?YNkl&~fnkIQKL)oxEJ) zmEXTN%jnK%YinP=oawYm>cJr{-qzUo?zbCO;>hS|@#Ghr^a+;F54P^es42WZXdCPO z{p;5R6~2*?ky+FqVg0kH`HR`)EsJT1iMclDkvH=n`uL#eZ;wjlZTDKbHp+gzv_6sZ zcVEGrP=_x0cE+`Uv+)7Uq9`Qi^-L~Z3Q*xQIKnt^cqbKA#{IOOgM56}CM=v^J32a4 zC-FNdf$fPGQ&UqtJUsM2_@7f$G`6rn#~K?NqP4ibMn6COvo=0HUSD4ym4b%RxR zJYFFP6{pqZok9@X^zxd!JK^_cW_I>zic-ho?852a3vxCpLT7I*I487LjiwNqAZ!h-7Tys_rQS-HQZ+_WX+TU1Fp#m0w3w|erU z1(eKdo~5NON=iy*W~0HJr;F&B7#Xpvlaym0r~jI^M~QiQuI<~mZ{+0U?Xh#O&iLVa zqby|jJ?b+9z9-Vr>;xJ~2@}jE-hmDBcw@ zv?#scwCy_o_lG<8p+8LY6dT>T^&~V@)bL~Y#5ZeeYd-phO#RxjrGXs-?-tY}v>Me8W zYJIo=z=5{%*sik4@=vb88@&5I_ERvfotBrE$DOgaFIZ~0Klr)Sbv;rkNjdV^!4oH# zHV2$HH`ZUhdga<@xn08S(Rw*RhLluKef@UM>cQFUtgPq!*B`h<+S%ID^#zkiw7>dd zd?8G5etP;KKR>-t=(YCsyFT`I52;yEnwi>f@2vcD{``4rYHI9-(bnmlkBgb<>0t!` z1;-^M?jMg9x9Fwcv*(tD`vm@psgY6GvuE<%H*9R?1NMnC2x*(I%ZQ1I0V|Bm-!Rsz zF4ZZr#!;RS6SGBG#11=r_%L^`SN}C!qk(CAd+N`hKTpt+kKF3jc<2^IRyvoZ0Bjn;x~_ioi|*J=zz zj*5r?K8)g1_U>(KTX(E=8EYN=R)Z$AW5*8Vn3Fa?KkTITQPt8Cpr_2_a&cJ)5Nc_; zVlFH#UH0;&E*c$nOaN+pOOku2KZfF&k`nu-h)(#gxrL=U#LwqC}~KjroLCLS$s8 zU7yPV%bnAIu)LyA+2N)H^Y(2+MMcG@Pdoea3JThLdbBPOzZyS%5)c>9zn~lIve1DyElM#rHhy^} zS!QD?{!PA<)~>MgV=h?bIG^@#KlxW^YFCoKdU<(iZ+X7-*2dQM;lqc4jKc5R+wFUb zY*0GsDYuqW-uOBmF#V$U7uM>qMYKJcyCTo4NBv=6+^KHey5&R73iQp};Xx2_aCE$( zp<&*UwUv{HmI9wqQc`j@h%F`};+(B9p~Mc5nZQxonxqVf>!*{zEhJ=d`*w})k+0vr z)$gQor`ZDH=gvZ06P=yAcI^U=m5ZA~k>=#&1pm<}ca`dhBbnj^KOzKso{j(g`}cP5 z_sObBhYlYuE+_!=xqqBx+9_zu5%`v*Nc^Jv9jxWw1L5q2J=v zsZ+MLwnm?$IVEV1Or65zb1#pGifSF61D1KhO2N3)f8`{T=eynYq}tDwvc);z zsqm5^WknK~kWkZ?FHg=VK4qm?I##g@oW8Ci)@`HSKm;4gOOCT6)BO}B?zrv|l;@Kt zPvTxFlFcTHkmH1$520&eS^WOhf1FHlYuba2_P-9BWcz1G1+smT_EYX-v@3>#pJP;$ zlmNx!R>Ku$;MYp|l=@OkE9UUDX z{dpIc(j~5kN=Z@S;m)h$`RIvshqsszml>4-Ha&x{JZQ7Qww7%-^Y6M$^;b5>oxXkL zQXbeQk-Z;1s-C795gjdw3v9PWek8m;gcUcWMB#u^bbGE@7|?Eq2Nf;a3o|n_1?S$q zd-e5y0)(QAw0CwsWoD{O!vVZO1%I4`2%o&;^ax-qR5B{ULKx0 zgQS#{6k0j#G7*zIv=4|oWm4VJGBYMd3-uS(?|oI3a;&rz$OlfLM9#)07Yy&olgsAj zDd5^md0-UOl$0w!eAtNxwQJX@#4Et^ixWLvrD3>IXn`Qx)gL~XnwqXGF9VX?I^(o3 zcJ9(8t%7^EZrq5>&Ypd|=P-KF+{Eg&t5>~fnMF;XJ(~xSLt)3CGH-D0@dhYnG4{`&Rn>tqYA>+fH`>N0NA z{k23F-;|b?g7Kd`$z1;Xd12vlweRlPnVBiFlvl3?CMSg~?;i?1B(%A>Ef>`h7^XTB zg;HbT48^T-e#ecq6M1i5zI3NGH8Cl){CW1=xq2)%b{W_1@}3A`ee#9aTU8HTW{rmUQ zTZ5lJUx3nr3p3uCYlaPmCACxg*TjUhUiBl_i~Ae@BJ%k;Idc^rTU>e=*20XZo`i)3 z1qL$c90d<$m9XviJFJ$Hk&`o)tN5z&L;}Hm(cp9R3E+wLO^K5y0d#>AHB5e+HoG9UmpVY;a(k($niKRBJ#915m zeD*|{1|J`=$Geg3rbg2Z4)xuAAdu(<{ZysY75E4@6qgRSKdF}f3j+&ap zva%OdKm6HcUW_%9zpkrO95`s)!JJ{CIXpZv!sUflF(o=bKaX;K`XLo3-^!FFDWRHa z-@ZO9w~9?+EFC`?H4-YGdu0CDQYhkw4;`8kMe#j)>==(ADIxf7g^|vY3>+N=r-j8N z#3J3zK|tTnF*i|t)6bwo$(HYYMW(5$TJ_`JaTXv`EL#@pZJXl`_wL=Zw46rS1gM9c zx8yACs&7ra)P$FPSpL05Ht#(D`cmPOyw~rJZ-atp)C~0XLqbDqe%$Ns=@}gzMa{#m zaTFjWI3Gc~#p*XuAaUov+*=!}<;mntdYaPR9}-WhPWcO^B=u|8cJ`aSs8mq;!#?Rb zM8Qay@{JU^-LN$M)5hAmNK%!;U749jmr$|FOHYY+!`)l$c@I(ZGsMO5PSNQ;4*4@@ zZUx0m2EJ6>-)pz38%#74>?aE}?`moF6z9B5NcejD(#@MUm4m)<^F8&|?kczZ`7l2p z>R@JC+QfVB9TwdM9;wQTiWL^`60kl@Oqf_%*Z+Llmtu{JN>7LVj|4wk6oZuY`atFz1-XM^u0Q33tbk)Ikb$7ig7B`?9$!06^xHXLdd~J z3O%geD_nPqg6MD5U6GS}|LmYDB)~$)`4M6%v$nn%E4>c9Yw!KH1Wptt`_RwQw2Gab zoqI>UxuL}2dYGG-bd);T$;*=koQ;A)2;s!>t&osVY-HqPnNmhh9(qb}&7xSBruzEj zpFuLDTejeaBwdQiGiiOjm`k&TUh^}7U|-%_d¥28zZzDEDQ~4ruJ){&IDFedXX3 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 literal 83406 zcmeFYWl$VW@HUv>36|h4!QF#H0tAPJ0Kwf|7GET|LvV+ni@Uo!OK@FmfyLeRe*dd_ z@2=|JulMafP0jRlS4}@XRo&CiM5rjsV16X|`0m|1OgUMppYPrw5x#qe07OIiZ$q_Kh8$=R3C1<_xI53M9+(q!dH^`ZN(gJVAqpvGz_iH&Av?NKB0|G z>=^Kh07a0mMr2=Zt1q@}I$#u+{gjG-7hw?mt@92FdfSj+fwq_HYj6q(K8pE*#wXHw zx`jPX{~LHBi>*m68IXd1fBJ+V@eK{_JvG(;Jqh@Z!->J2BZd3_7X6?5zA?P#Vwe5? zztQ|3aj4X{XmrUwhWL>Gt?~a+CI0_a|G#t-_V@oMm{Br40}+6nt%tbSX(R4U(wshW z@vflsfU!X}xt|381F;Vik`9y4i|T93F4<%m>igQLhlRKW&QZ96oF2|+1bFsuPxdU2 z!Y?ZSSDfr~ysz{Vwp~1h>DePH#ki?^+~e*sgoeCcCOZ9(!Q>B~pAV~5^*3bIOxetT zP+mFwqC3Q$6RxgJg_{^>80%F#7qa@Pw>`ZYgm_w)P`onFM9EP@AKZ#Ru0jZwE%{>yRu z0QGewC#APm6Jh4wf66az?wxJFZjs5Vqt{Nd-q(>L$Q}`P+6At8*khTkYk?w^wJu0_2wx19y8~4)TK{f z?ADzb%dB3|mJl^IYg5sjeDVav2O;P~RJ5s{1b6Axj9ld9p!|xe_lBjt%sTu4zP|NM z2^B)ZA`R&9MI=Z|>eB||o=9%k=%z?5#NS-2E=Y=z_iXvuu z%NuoA%rgtT&Yln1sYvGg8wmC%nl2dPF<;Olm;zV?=PHCRpuN1!>j-N887)5ciHyxD zY$yvL7?*YXhGslnK$I&G)ZkT08@x*4Ls=&*&~&Ss<9YW9v+0@96H{StA@}8Xk?PB= zZsjEWtos#_G;ZFM%^-3*Y%@)6!Vt({YY_r_9%}iiXv@48l=?O>j9kR4g={>{5O8$* zLaiC+!G%|pV}2C{xM(JaTe&$XF-wbd`kZ4EE4v;O(bG;^I6S&;uPvC9xCy^b6!=35 z8}i8K`{T|_4dKIg9CU4ljE`!$0()z~V@#39a@+8uRG;A%eM@G`W}m()X6MRF^2=>9p68CJ)32Ps3VN$swvlbBVYD0 z$iQ}GT%5uyJ%;Y4p`7AARLSB7+kZe_*a{RVDfH7?%;R^qm+*4^8z*?ItfbWbFTNv! zWC0N$b%Y>#3O5HAS@mmS0UwawpXR9f#N=%nhuJ36dKj_$@76$cj^gE75vvlpl94!- z6b!XkC!@jy5BoWEkjw30a?Q{D3-yapgie1Bzu|T@X%wR)_wsm=BQ1}^ zGxZ&NjGL-u6Yv>k>A7bZqOMDViRJ%M8sO-I820%y`S6mQS~?GZ3{$61(0rXz$N7%! zPAb1~U*hk5-qYs;(ZbMM21FyV7h-_u1qm{H*ECj{Hoyn$a;Jt}Cos|Y+;k~X*JPIH zzlp}6z*1`KFuaK?dtSpR9SfimbQ3#>sOq{xG1+6IzvwJDKC0MRS$bP0%+hi~G<~|- zsy$@rme|ChrW(A(@%ofMM1|InT61&ezuCwpQ&R6oYj2{ib2u*O)pMCU4yUBMY)jMhp$vF&V03E3;;Iy-Vt=xjN;>Alf!%(_7y#I0N+k%y zC|}6UYcMd+nCJe>2c+$;*$73BYPba!sh3=HvRlQ3J?vn2?@sFP3Y0IY>&EWBsb8>v z^*v`N-T+0PO?;p@2cqy4wKqBcQ!4nuu*<*cx}~C>Vc33mpit2ZaXo^Aw(r)d3-Y~3 z9G4b;$(4Cfx2gQ8_hM5bV`Uc+qSw=hA4k^?`fC2A-L?6Z-wyOB72LyUGr#!MPcfX?}ABlT#vT8Y$+9w}B+M$E@45zG);5`Ijc))^p zEH0f}gWInqa$ZexxOxl<4JefS7{BrK9p%d|{=%t%WYjD_o=ypiI7DpRf6vk<$(!_U zqdqwPlvON+VNq+~soOWc`A%?=_=I;p$z|!X8-$x{-x7HS^$=AH^!6!ftIwbIyr=QI z>(f0htxImG0-Y$$Wr@x_bc3!eef$PJTHiuTUyh905zWht;QzUI*e%T3iJK^cq|Dm7 zWbgO_!DXSde}5kP;{32y^e}`XztP*ha&^Z@t0tJMIg940p0z5oK2oflQK6M-10vLE z-1|j}$1Npnt=TV#;MMk23HuP130BR#BJ{gcrT&^})ZAyIK>R>@DNrwvq6*O{_D*@W zf6^x+5K8V@o0d0qvxdLbzIfSbJrUrhZVY-jWGMwlP37xo_FdEsIRrTgW5Si4nm(hQ z{3>3gj0u%|V2^ooC}_+nXpl#?gat0hUW9R6ta`ZLRmf!6F#QJ%y9s>g&dag)MZ|qd zG0W12iMoCy?GkW%a!BI!Q=z%;Vv{dg$)(I{jhTTzxTi?6=V89vl^0hj_!}kC3i>+S zkyM|Uz*}1V==Q1_{x+m+SsuVwvM|xRn7h*&2O=S;_+HVyS0>u=IB_=G;A4hz5BBul z+O2w-rPPij6jMg zVw@MI2*mvH!_v*`_;daudYRClOXK3EeVQE5HNN|Nt9L%h%C~{M%@bGwDCL(%<9i_Q zBDvWKaO&cM2`t^JVdn3*8drOpZt1!DpDmf|SeHmFjq50of^iC|0kh>*o!|-}d6NEV zL>Jq4CGy_ns8sBx*7MRQ2WF>Lqj0qER2f}dhUnrypP^j$5Epm;TwEvSRtH{xqtPs? zZeEIP=2(|3nO%u$j#snbSfhZcr3p^dT5lgfH){3yGrYa-i0CwJ?=Gjp{D;sf+rP55 zB+aQ#1^^6p@`g9^T9zZ`ysEF-_^j4tZckBC&nms?Q;%U)+{o&)qXlq8{YKZ_OigYmq(KUm{$_7`L}AT~gO@tez=TUg{Q0*G zhz)!TPv|_$3L>ri)t=4a4(+Q55tYebjjP(7%FUjM(PO?JoV0M3{_;6TDQmqxee&s; z2C4&9UiWPNt?dEm_jtF=IW!4>Ji?C^#5^jQNA`*LN}@k%R{mhJ-S{_nd_3@UwL8L8^kc=6FYfkXRNU;|6~=mJ#}qcWh8Mb z&e(*7n*pfXn)TItoisa!jWF-7iqQk!8t=%)BW*2>H5N_Ra2#}CfQUrOdY!J!DHr7x z8R}$XTDHt#0mI?-2x`}lqmW`>aI`l-Z;(GFdM3u{5RuXI2fa|tzP7Zk0sI8fyFh*s zXu#{pTp%HGV8sYCyAX3f6_jujW{fN_c*H~Tt_TJLk0who_)F4sGD}3dQjaV2vr3wq zc_(%=AD&h)iq~>B|H}w+^W#;c&Wz@1Jqk!Df|b(N?yQJDey?|gttS@<3znTIspm3% z@#sgnRM0&k&sga9xqoFR@aIQQ=6AReu)ZukBwZ-yzUk zK4PfM5v}f4UY`KTHFvpohLer4!P3mvT1`4gP4fcb=Mjo7<3-g;t4t8+@-Evv@!ZJ% zft-LhABfX^I%aLtH}aS5%M$UgB9k+rI_0JDWSoqVga_D%e+=bBXgMO|suoWl#C%S@ z#KbH>M*3WMhF^vlIGxRqzOVmVSLrR?MkHglT@aOtDV97t&lLZ0wRAUQ@4}&&4W6!H z$P{hbGDa?#{=K}WKQa&8*(KY0yqA0NT)a_XA8;0Sb9-#Vj~4rm^h9c1UY=JfGi+GI zeI?rTUoy+$t!P-M7z7IOh}3ai>x{@~`hz@cdSNdtv(?10_|pNn_8Fuv~b{7$szB)b8$55=^Z*bx=Hunbbw!< z_}3&M*Ugwb+)=Hhu|h_FyePu0T8T@K6L8^lbUxAk6HmdlrhJE<{u1N5+s#Ra z5s2Vqayir&8>9*a67~DomQ@Bo@CQ`?(RMN;|9iaveb7k|FrAJP5UnxuDc+lN!@0lbD1|x1DRkhgX zImo9Nqy+W~M-FJo@KZO^CoZmwhOaM_+{c+g`n(j$iKAseh~^AYOYOGUGPXiOxs6Bg z%1@kh=^t{0mlq>`6&QQ4hp_Ra^Zk)7HZT_?Kp>3h`J0JEC}$}53vCI_Ge*&3Ynw~a zpd)SBG>Dv3Q`2CuZ_%%}T5Kk+DzikuR-2Y#$yvE*VWcXK|EJ9vY>Vqqp5pmoG2KXC z*Z4t#zUv;>FI969x-?w^fsUM#f)gBc-+GEOo)F`#EDYU5>$4@&uo@F>x!AR;S$b*N z4f``xV=1|hPS*V}U#ABES;5_W|B}pp!l$TDr*p4XsCAEmV_{DMOD%!2`tX5IjcL`B zZ_&eF)t4@{6Q8)!7nMv~-6AEPs23_(>PXR4h*Fv|ifCNhyyHwx`3fpXmi&}Jwo6H% zI$%sFBr4RYxVj@J*_TMs4#5?bB0i$flD7TedLKatyOI856X6P`z;9{`WbEh5U&9*d zniX43kEUk+x5&G=1?1zA8Vgi@n0{Qekc>%L+e|i7E*4EYSV)+GMf;>mfogoB+;q$b z#iK?*1*e?^Gcj?e;?)5-mLiWPol|vDP%dM1&1?34e2T)d(_Tuu;KJzr@B|Yr=5=}A zLJjDN8dWlPcxnE5N^+4)K6hAy-$_P^OII8!uO<;pS`aU)rqfSRce^CaGsMNxVsTHu zzCQgzU_F04A~rG^p&$AcG|?3oU0Yg+;yVOpXlF*Q6bZBcvB+Z_X<(d9cEh@?8)cvE zKj=>aOq{yB2>nh(cuwonr)Y8XjibW{pV&qmFj} z(9V7!^`S^*4pjTes_D>?Y`DxeQ0q-uOn=2z-EOLQKUA)TC1at4@O2T_&=7!EKzTu2 zuGPpIw8NE`o#SmYPJC$q3fS;>mcN76Osos_21rg;M7op>uVB}l*7vsw^?w`a13m0Q zN53N8UJj~x?ZN>yc@?YMg?zOhY7`m=sa$J1!#XI3*uD_(kJ~efF{eG>yHp?B6t|2; z?i9s0QgMGD@}dRRn-qz!yXu_&=5Gu2HT8Tz?_n%?SNjh>i7hXL*mbNDcfLFF4t6Y- z8^wU-gU=iNKi1i+pJXe|K<>5K*&bgsD>*N=R)U~zvGQ^bSPWIfgId1aqDZYRn_K}6 z%Q6o;QKybw4+7fS;1-jZ*(4!dbzGSy3+I(FdE%k0>(L$mB*Ac1cjS$IB#TKB(Aj@m+JElnxyk(m%Aq#{BimmwTi`tmwt&3ig&+TF#>HQ+KB z)V)*e*-33iXX{YDD|>5cSEl?ojIB~vm(B_&f+przc;y9Z%}o2IB3$q7h=IXejU$Jq zCyUU=d@n&yQy0?nz+e=vKal>Vx^EM?VbJ)2|_i=!}Jj{QU zkz7`+S5@7a^Rw)B!;=Cc+2w=-0h6o%TkEDoTX+vI>lthK4x^)$wMQ-+X!Ql>N>-CYNCDgH zjr;?DGKy{WboJDm@m)Rky`}lGmxdN_7ettm=q)*YH`ysfk#(yX0~A{yx#@*m$%Gh1 z-5?frH7GC4FBwyKDq7~%3V0iy^xEKG`X$l4XM6oqv8x#0Q_L_vqu-wbPA$6XjeA|x zF3hDK`R}Jitz$QED-(_}+g)>b;D*MP?u6Q?$Fb8Cu%Frutk68ag))ynzAB4eVsAFr zYWb)iG@;``apL0~-ClG|rtKK$DI+Kwp9`Vh=vSeFK7WKe12Zyj)<5XWxsgFkHR0Rh zP&tsY*R~0{Nl5jGod`#d%`n#!#pk;nI*VNOk5RC151Ub=&@7 zzGP~n7zkJla|Ci5s5K;$9_fPll zgCj|$qv?Mw8VkM2Tl1cbnrSwpd#3t`CusU-6ZbxHA7<4_j2zGFo$|7-`55s(es_jz zNeXM0uEd8x9X5Mgl9r{Alxf@|eG^D@$lL2aLP@$pi~GNsu-p$Ro9k4dBX<3WmcgqP z6`8}he-u0$DR8N}=X@-(jHXGDbv2N}M*N&eFUY=RE2I!HxmpIik-#D^t#u3T{pMgf}IITX~`koV8KDg24IIZ1wGike;NzB%qdISvjDEyv=3wk&zVVt zPSU#NpPEmPjf{)!81WuyXh4E3{z5e4G(&I(-*Vw_a@N&SQ>wY*<@&O{!8EVw4tU``{>6o5Dc(CcLW5D^xgb zSZg!yUKd$`9`xJU?qfY0Ibk>LPw)XokPZ!~&Rd(eDitaDT(Iyc6ooA+%>injO;8lI z^s^^L?@1z7Uh5tv^bQ=vbDWZsvc_;wRD3MMMOuq`h;dbe8u^UyXB-`US8e)ktB^*jl4miL_eH>ZtR8I-JlDl|lBl=xwg z988-JxguAL{_8FnP#5_ZMcH0{3nXt;O5mt-XkChnIBtrO#AXMMz{c&+Raq7qE`l%4 zzr#_lt+0+XxHq4@g3lm-zr->$Uer`mxPl?noazW+edw?Hxi;yJ4lk6ee` zHvbRr=WeCTlqso>3iv%8tNm2DDe2jD2Z+GE*5&f@RzizxPidmIl`$DuSdNcb0EJ6e zni!OPf@+Jdpx!~|t-iO6^0->Z>hG4j&BfMKobEWL{jLQ<+07lYdR2KRDll|%i z2lvvi*DCa9O7f3uaF(k>&00L#?aJ!PIrFzV&d*s zp}Qzm@cIwjaV?(d$-osZsCJZ1V`dA!k-UFJ3JMw3f&)Bg2Hx{r+l8z>A- z2DEf`M@JXa7H`KX9dqC&ECsqm`C`hpdY98cYCX@)TsDc}li#ji z)=qPyMx1(dNI4=ELfHl+R|Rd-l@5u}BWtHUz7c zv2@h<_#Pom+X_a%uRQV;GCYh_;8hId3ru*$D2JKq=fopKSpmk@EV90DRI6>jf==)p zs@8`=Q(`@En&Nt+2bUCx(wCKLe;1|U`cY9+%C=i2MRRXUVJT`eY39UN)t;_X5gR_? z(RF`xwM2a%!is--uOtx)3Z^@#;DZdPdFf(PZ97*wZ+4z;<%oH`Lq@Fggx-ua(cgul zf8Pz}tc1>ywdrm}bVZcE48^#m5%9=vb;|H)0PQvmcnLSCP0wZNW3W!9*U#nJvWlDq zJHYkttdwMy&%<(SPoSfP9NLh}5FTRkxo+tYXHVJ`ZC>*QZm4^c?UO>brQBKipLU7O zZQOlB>+XB+NEC@4zW0?mz}-jXdNs~7wBkZGT2U|FJa&cl(5o!K;P~*3dwe9nm@=rU zl>8(cQ)zJ$pFzK?a5fgoab?Kgxu#%~BW1oe*_?U+785|dGn$CBO|QQ|c4^ZOpXWL9 zJgV?jkR9|FTC5^D%b(q1J?hJ9Cg_^v38^v%O}$cZKy#}|p+_GrwM(wL9YyG>#fkwLKtdyGWhgF{Y84&NrlhkMAr@d zl-NWzb2U!%=t+LX+t40dyDiYp{~Wa_=9UF24+e8N*3F81umV zZvZ;t<0lP4%ISF$m-W@~syK`kXhc<8R;_5)_$05OlE&4wiy8#qv4d^H3@VXHenOr- zL^DoHSlPO4jPH*w-9z^>mQ(5s^~yb zEccl%cj}cdaxU4>^k$bQ;$R-lZre(^%6AOEi?&#?8PkuEdbCjS(qg0Q^rL(^gLwPz zy`5#zF5gaDd+jxW4(r@p4NO^T+IG8(sl`Er?E#XSPMOew9gowYfLTM5}lN!L#o z55uC$SJp5OpD|KLyMZ=kOG~RbRkI25-I<;pY5HtZUt%L1r{din?@dfHa$;H=I$v$HiW9Hzxf7je6-)St|zJ#x0dF zjEGQAoUqkf4rgDr(l9|M@~1=(`TN1#O~{t=%by%}CtX2g(v81HvpNfq&TP<`j%>y3 zx6I`>k8Hk-{FZ|xVom{HLf*s=iA9b}tFHRxYf-PZJ>nK5=+#|0wmi~D1YN+&G#r6U zTMo*8NOSD+ufkvUm1s0HDOL3LpLE??l~0}x`1tr{$|Ru&74Bz zIHBVKV&3`PG1Ko$PgLZwcH79YFGJe}v>>9}YU!1R6zlx)a|iFu%ync2SDD7vmFM%v z$>5epA#H-c0xkZC4W^2=x558q#MZL42PZGa99PiH)!8-egDs;o#@FHrqLMNnN0fxH zQX7T7iutjSlCukC6ZNP2AMs@^y3J)J>`#?0tSv2j0rdo$#ktr-yHO4g?eXO;QH6Ro z;0T&UiHa*c>|^u4y>CIpE{uJcU`8-tZ!o&oz4@vg>%;T zyXLD4-PX|DK}d!dD|r@ZT7~bFu1j9yzYZtg#-o@{AoD$-H9(g~&$G;`Y&L`EBT7)O zQY+_XN7A3s!gAdS`igcwcc!H)QU|p)Bd5pH%zsgJAxBr=sHraK{a#gg-=4eqm%JdA2~G?OX9r!;Tb7|Cjf} zpcP8?Z|-;q40^qHlv@3s@c8(E;^KQ8{K~U%4E1jwoX!|+t}hP<+k}51$SKcGIr6I|B+D(<(O4*(JDi9$p`9D8tu=@>eRoa$_pa(`pl&l$ zd<&9J=$X_FNXC24&nMou!_CxcjQRS~UgWtwzYJ^+X?cf=B9c`G8b5ES5?-;*&;hmk zl0qSWJ{lOnS8d-b4%dw~R(|?ufUA~%U^a4-nb61ka$S1+rOrbg(*`rqfJby7vvOE$ zXR!O!>Hd`2*m~_|l1@rc99=;t(tJx__pTNAUaNljm@|2>>gUv;V~n&u!$dzKs%je7 zD(hEwrfeCD`ozyYzYUVq_QjO(pQSnWa>8=qqm*kS&ma2r{8)s?Tpq5}{Ha#0eczX# zHw9@Q|2xUpN;SI}o2getQ&u*w^Xn-r{apd|mWa?x~Qf0yF_TDV`+>R5D1Do`ue+HB^KpWODA3lNq^DRw*g(J6T&;4t=yCs zS9EJ9+vkq*()XR(whoRKO|f#s#s&qxD!0USBW3D@{*A5nZdCiyB?%;ngD3 zXm3viy8|sYOM*;x>5op6__!l4GPMp<&e+n1er!NJc9a9!O@y4sskhG@{w&Mp1(k-Q z-of0~qxOnA9ihOdrt^y@%9_@ap}c}=?;T%*jg;QF)N9Mg@7+J$FwCxLxc!8zqcm&3 z__BU~@ub&B5RrXd7#HC*BkTcEA0goIy&krT5SFrP=9o#s#*OV8 zbAK_sl;Ad06$O{tD_#Oy3NZ7|@gScWo65>-k3=S;%k9_ZjHv9k$DIjYwLf2=0;k^c zE8&eia0CA^VHAG^A!z!ssA6Lm!MI{Xj)5{3moQ+Zyxh*#%hf;y0S$BdX2@Hbcpw=I z%MxyUHcX60>9BL3uR62DfZ!l0hznLXw6Yb0vsS+Z?)LF3lFQH+eN!<44 zr}Iq`i(^|&gLFhXPU(#*4L8+q72G}Wo+VAL4&WG;Ltr?%E`IoDRwFm(IbtcnAV7ZQ*s?E1XQEt<+w zVl#n;b6;~mVLXD77Ksdv2rb=RR1+|{vkPq#J)5v(6j7OMq^Zn)7t&)iu6GG+TGEje z#ZrS;cr-|pR9v+PR}-TV7jJN^lALe9l04H83;T(@_7pPlq>)-se^zV~i!#Tcp(eOBE<0vYO|a+}JsUceYOdy(h?N){Do zQ=Tp_t*4N#^vg>Bt;xC3H6Eqr7wE$~M>Hz;J$xS)FR`l)uN2Egf>lze4&swL{&b4i za9*$d#kUcb=Ef%BW@+dn+;V9JEM}o>26uUkoR219bm%TE1YpxL)OXol%a(uP0E#a* z?8cYt{)Grr2MIa|EBZ29VH+)DZrX0_)J;<`qR<$K1q27n;P6eHZNRhZcNVs9%%>U$ z&7;w~>Wj^zgvay4+pPI)maQQfR4bDWe(jO;^2%B6u3leyt%#B3K-BMS5TuZ2mMUm28ZpeZ)frYZJNFzbCQ51w!;zQQ=p@uw? zCbl-l;G*?0a$;2?Oq6JYE+ot-D&{X{Mn_h+@s%8JP4Bz+4=SFkOD7EPKXZs&p&++O zn~w*OA3GZKh@`5$O(@R>_AK>7567qC3mK76{wrbq15olSgYgj%ssG-8Cf+?3s+e9Y z+_+o+CaaYusU~U5Tu{-wPE|)|%?wj)jxt*0qfw>#vNn}n|Dz)fm102O50%9}hlD_1 zhw<5yT;`g6lu&I@fzEy~*O{fO7ax|@CUVnQ6{CbWx4KC>S-3+?%fP_H#uRW-@P(u8 zKYkFwfA4U5{^$qZ9-5Vr$JkBVD%T(>vOZ+VPahVckUFB_DOHd@+vGxTi}FQEBd)v3 z?)LmK;Lt`6OHf}S?~b8`J(?rpfX6k5^go8L*e*xzp?>E}T8491hp-3{MeaoOj#&a& ziOzYONcy>*n1Iz4-*I^Gronw>g`A@0lsKzeQd~MF#+}o~O6h5oW8qE(S~%|)yhgs; zrYufmikr^6??qiTYb|P|Eo}TJWX-D*Wl>J=yu7&1zTdjeqVDsHWu6NPm&)EOkarB!@8NwSgKXN{`q#-p} zjE!gA74d(mBbrJe@ffJ<(ujjb&_acjE$Vnva z2alHjHU8_Nnpxn?B-4Sgn=vvfuVIRH#TIB*K8>zu!~V4bsYhPu8k0K6pzOG(lD93e z#6J*4=n9RF+WS@XllD2r_p|AlYntHFu%)+SboqC^STr8=B&52iZ$3{yX1`6$mBylj zZ060n+H(>N2o0>@0}R!*s%LybsHQVN1-g|HCh;szX1tVdSk&6SG1Ij!dkU_ly=J6ro;{C7@0u{2J(Gw{23(YlFc zy^rbjO|JQ37%P;W7f}NNSElY}Rr=2GH%^-3BVKlD#;+f*u{7>+}Ci?Si+T zZ@!W?DL*8iMsj)|V8!>_M<&K2%3L1__Q?wgw%KMnQBveBtPM! zeE(K%`DAE7%iu(<$qq2KgRhHv3(_-tbV1rd+0up4G-)E!)0w@WL_?VRH}(qM&S)wl zo&jB(u9wLJ+Hk*&v8CsAf@^yP*vRt4TwKC_Vs~LIzJvvb`R!5rvWc7OJjqh4Sk%}u zqT%v&j*6eW^%mw%B%Hce-=78IDpA`_&{Ptl6SxK^z-rihGTa{?1{ME z*>hN^(A1)*a6SZS)+l%W5FKB@1hvxp6$izaiR+YEif!hFeccp(Bl%^>6(?s5Dd41M zb`du!@9)}^Hh~QbC`MSZPtY5}b;>Zhv%+#Zv*k{^OmxU~b6Qh3R*QdFC+(U8_a8sd zYHb|7n)Toe+2S13_buJGuIocdw5hG6QQ)A3aE-_AlWOWD&halH<_pEG()LPhB(Xyq zSK0n?wdmR+7Ub3Bja3@&><1k$uN_72PqW8~&N|K`N+ScY-$usI$QCMv5#?o>HQ5gB zg*O6htN2c6Y~vvNLk?{@7~J$^v5D=$-JAU)!{4!|xM0)5gf@-sBSL>yhi3#rk0||v zZB1_o&^o1=EyW*^u{+!chWdTJWUldOI_YP%3q0PpnbQ3}IG8=(NH@(bE^fCEm#3EO zJ}fw0_g~A?fwal^PoS>oRcZUuUE$Jr+tC|Wtq(qB#;)c>g~U_4u$m%fvnoQ*=R$4B zzN&EtbFW!*Exrjr61J+z0yy4|u978bKN=<=HIOJ%3Vk~*m2eTiC#_8cClFD}c>W>O zQQ)Kd(Y|Ehx!{adWd2lM%A&O?GPlDOi;ON^e_9D^8hl>C>V(jAiwp(|!iX$NU`w}3 zW|Y(Xj|l0lE?Zs{jcvaReG{}q_!I0YbL(Tu8VK!;V54+voO|Wkm}z6TiP_8h7CMoE zmiJN?N*K+2rwwiLWxBRZ(0hK0jcb(tVfutmlrm=Fl+r*%bD7&3U&jd3pfM1F0%1)3 zXv=Sa)$e@1GVI+1>wg@$RfJpLM_SAh@{W@yL_Lgjr+lMY+@cS zZqxs0$b1>rrR=*Sy+K(Ojig_MZn!ZlPs#bYW_zzpN=R&Zk0B=24s$<004&_AZ|Wsv zT|Opu+}2Ln=>HoV9Tyw8!NtiU;BlP+*uw7j_&ra4M+F8jsMi0gvFdXWxMVh_w<|f6#exNJhdJ z_fyvVna2uN;$ISS+Fwzh6nT@&$d}3HVxovlExE?6SJIL-7OMkBw1Grdd!J*q#v2}Z z1qHz^LXc6q4X*rgp10BiTGX9{(!0513~M7P8B@!ER;$&|b@hRE-8(lVkIYv5SYEC?a1x+(XZrZ9( zEoewS=NG3<&l#kQOcVKqH6DD?TL)`ya1pTm5vz0bfWA9Rs=4UUuw?}%P0XWdx{oL8 zY=}z8pY&!Yg$!7S9N~M8JOzpY4!x0*srAj4#*4fh}Ux$>-|IHbN&a>?JhhuSyT*?^F}!#M zPF-k^b!_E-o5BPDVARR zv$#?w*u)TJdJ04zGM;GJ4O`=bi`dg&S-C-o+?BVZR^VwmNf!{3?^l*$LHhac`I?GBAV z`ZM44ky&I{G4)V2{3kLG#f9YWl0;Vy9T}5h>zg%h?+k7Cu44gSz_9vv=t%zb)ek5N z`kpu>67b6#TYljA{1;N)%A(-x+|EH|&3qq*x<}G+RDLI;^WMeF_=7c#F~$CL#GM?$ z%`f;zbN~|q=;S1it29|-;K}mftu-1E5f{)R_biy&ga9brJ^DGbJxt!(fnd0rRH*~2 zl5f|*-xvHxj3&H-EtZ0SNQR5w*XYK-`XK8pQ-^#oQ@qcuzULdpY}(6B?P<3m8|wW& zcBcpjU6Q%DZ-6jvdw{!`W0W&wrewydRA7RAynEG0y9ui^q&-z?8553W%$FfQwdAo| z)1WL9O?^7^(jj2Q!64Bi-;+GL;tlW%=_yj^`2>j$8NGIt`3mSusMD zKSTKXhp3V81^+J-Su1THI`5nexmoXG3J6`?)M+OQ`FXQuD7vd+v`HxJ9l&F)%{iSKQR;WQE$@5Y{p8R&+;;iL9UH_V{5O?%zy4j%fQ@6nY+ml%L<1_MO3fimrr11qq<-ROA?NF4^a8ohAHiTzJ5gXtw*6 zrmOo4B&K#cs0IJd`E4HeaZPBNC}SW4)vqVH;HgSi&tlk=d%P-r$muQ!c59WhrTDgj z_3scDWxPpvtSm?#x3i1Pk+s{--n`-^u7U|S7>E5d%=}>NjRXWqG^Auj5;N{oICvHB#cb*)5UoA zxa1u>^-5*!@WcTO?54(u7dSj9JQq($P$El+01x}U`o+(0APSG#DG!Y(+~689C)+(u zU(joZkYd|&RFL^7!%8#e{vH{Jgm`@a9;p~?@rRphBJW~Xo+WOC_tZ-u=ejbto~inG zKX|Of+OFU3{ELwmUI9IAe4Ufv6>k4i(yqLp<08g)8Y28tfYJ|K@<@jF@de?h<*M`H zW>EA0#RXteFqg2s7M5-RvEFjO5^-$OSg#U^tb2+~4MCL8zJpjEHDfy*BpVWrsp{F07JAnS9%wp?0{ytK}jcu|73nG#34 z!EwpFNhIlNsv&j*+3qalBqIyfw8@%2)-qv`*hgte9yd(p+xai}9bv;baDkG%sF5R4IOU25fhV_f8(i2`~saeu0CELHH@r4{JjH-j!y?(yof<(V2s9` zp+>|9&tZ{*8GqK(A83A|c%t8Qag_VsJTG~aAue`KcXCaQ-a(9-)|5!XS001oVc*%c zFtD`pIvG-!-c(DZ%(T2lC}AdoO3@)}GF|AXkSoG62ug2uO4V2pgv39Us?Uz}zf+wEOKakV?`jzropCh%-C88fT7DoUwGK<8(w>H1hR58@b zVlX=+h13`PP<}r-b*TXF_fI+yoJ^mPZ_pWa2U1PWn9)CdL$EV5cv$N4^D%i4;l8}N z8_t{07-V)7w#sv^vN}IQel<3@l!m-44_JO7w|&eS|CvVW5J@cH+WvbE;@D=#VU5{D zz^m7hn>9$cJ>6#8kK~~eVjZa7VJ{3%pXYQ~8{KW)$8eE|g^nKVXJc}DbAJ^=FKZrO zHF6x(A0u%WV<8vP)g=g$fxeWdEHaXpW3PV}!s%HS6EZC}%_i@8`xz+$zpqAeL?R(x zPN5=g&ujEcB@x7w%W;xhwy=kSO22zj+Q_#pC;Jr=m>-!sF=wmS)+-?X(SyS~I57~W zC+`A1+@{yPt&Bz|h&O)hEW6wIr3J=_`oYfmSX3bYuHx07c>(o*tkUsffy?vY>PF&V zLU1HI24`qZAf;t7fCM^{FM0p>(H&qi?87%?P67S&voc+&jY^w2ENDz{!3+q%$sw1| zFbB=3XT!Y2LXF{$S#!{aX?JNO^*@9Xiff%8@V_tL*?_P=KO%ccH5bBWsxY_qqQJOT|T zCe}?mO#CGupbqanmFG?tqfp{8d7DJwXQFF0cyCDSRf3$Q-drnt zON4pP2F_T#)qAV;-Fq$O6K99T!?*n^W5bifaK!uwettM?_OFn;@_VJF$){EAqB8EH zwBU3fFi;`}k(S$EMxvg&~C{*fTVo%IJ2fkqYVdI}-uW$Tj0#C` zFL>YbWIf^Lr>-=hW#qqo<`!#ZhMrK~;LwDCfI(%_E0WWfI&d4~Dm2F*$9R;Y*fV*0 z+ji?@`eH9!Die?I=p2odlP-Gl?pp_Ja;GQ%6$k(m1{c$yXl9VFhrY*;LYJ}F+E<1D=H3$8Up=t&S;IgfWc z%%%fXVh%T*aY9pG`mKCrc3937cUvy{Jj!*p^Wt|+up5Wru5tuc>Xs&>bzZ!T`5g}q^?oxYA@k(>Tze(UwKs^ z#CK+3$>%v@SK(iuGqB9kbLyhd$57dnM>PpL<=TPq$#~F{pdh zJEobWuS%dUg!v3S=>)Q4v8)Mf6>&5LiOKGycP4{UO94g6%I}dATR-9Vqj@)y#O40Xq;8aVV{FEm|<vi3Avv^*ak=kkW`S5cO~ujI&iJCm zwW5`_`kQD_*HQ|Sf+>*wMy2al8ESc=wYt|NI$y`5yrT4@fFdY7QWPp-|NZ=8-b%{| z!T~9AUWX=5X{(p1l&NT#&zR~mPR_lRcM~W-?zc%BR?y58D|y|cnVHy5OcQcYG0yuf>a_PP%m2Re2s{vcU0^hmP^%?WfgRh9@5sw#;R(ET!S{dv6ELFTDyLt)W` zrv{6B&Aj_KZ)?@$UO`E*YQ3@K*;s+g!LRy-G7WKOGmEoeFk(k*TuEc?N#fk~zO+Wu zt>@jHDu3qd>~zw=BNo$Gi<|L8VlZO$D1V7Y5@-$@zQ2$&Mw>d^hREVLgjT&-cS1!2 z@i-G^cNJd)-JRVpY$eE!Z4xKU%>Qo0vX>R*#kzqlx6+cABT;_y6+qRa_Stu;GjBD!z-5~`&u`2Z3v@05tWyn{ zw%D1R$2}7ekXCKIuo*U|x^=~4ie5j{xbkka#P8;_NH;mZW=WBch3t<+9H^%sFV0D5 zr02x-4WA+##>B5hjVY9beCDY%Z$nqEm@Z2^-yFMX&cz7#6oxw9ZFTRT@YLlGp;!+) zIh@QTxy)>T&{V8Mx7IDHRy|PB4$KZ9lHY0GCr&?@b1Qm-eyPi=*;k)7WKBzU4hH?3AL;Wb6Q z%!H>wloUJ@+ssUkA(}GHLbWy_yXC~tOHHCm&9hrR7tl%7z?Nnjw>ZU3jhN;IUuGI~ z6>2W*MT$WoOd+3;U6yaC9P>3NJO@NH-zZ7wqLi1NDW{oMD~^$-k;9nAcRHbBS`-$= zeX+t}=AC{b-WIoJp{RKFeow7j>foRtb^Gf1?4aWw+w8EL-hz0u6{YMhlGs^`)r zLmkC#@1bX(pH>#Ps&usCR(g)TxLzOrgyYQ=;rFd5$H~TA`|I9pYo6u2)Y!$G<#vqOhVi zT~^m9EzP>Yz3M3*6L(>p&=$D=QpGj{nmOU%t2Ieza&#{F7|E~S@HBN~z~}g>mHjrI zFvT0)?}XM@d2y*4-&5J5MsazXVCQ}8v z#$=UxVjhcDNMqfdkUKDfk8iUx7x$#d%Og``y;pS|+3oneMi6wg1qf5gQo$ox{7xx7a;86m^WVCZM1w2w-hVM*Kd*#D7PVt_0rKA`EwE z7ZS$HA|Vh>R~YsX`@~-du~dL|rs?g)F|$%L%I53D9d{?nG45q=W>Vl?S z$|Avt8%Qi3883aVd9J6+6ri%n+PN?_$`_XuLeT%%EXmUNSS)yM*7w zZ;1KscLE=S5f%MUY$h)D8)R`WUaHx4C#qyA#?R*2+^yzb-^Vjf#9(r`>MNV~`d`;0 z-U~))U)2$NTSHs6u{%fcn1qcLQ-r2K(=}o@(D2x}oZmyh3Vy>I-uMpE~ce~rNF zB+X{XjSn70ZasiGWMDKl4GQ)?w$U9C?WVPmOZ?aKrXGaLt=@|tVy67V~gk@#lMWKeOS8HOxhdShM1T18>h74UZ zvz|X|Hm#px+=jVSkK6FChl`(wrll*2`w>?U)@`XbmJSHK{E6rFgWqe!axG<7_Z5XE zi@>=gJ;QOXxoT5>`~(L^X(4f}3?3m;)g;K=dJBrT-T#VSx!6@?VEMIg&pj zeK&VY$YFk$ievI~$N8O&JMOz!fnudrH{_x?lS=g8e8vI-4vq0Fqp8osv_0$j%Z;)G z9xd|Zsiu0%qoo+4-fpP9DA@_-u((Z2iIJ?^W+55Mr%L%wCMufSH(v48dr>&nBB&}m z2IOg5hFve(M^B~XI5?F9+78XP-{?5qAHAm6@11(L*&qp+3^Rxb{MBphOG>l?HsG|6 z!2AewY@-No9y!+S<31O$l{q@HEIQtsp4ucKj^wj5VAS@Rsc;%2xC%7&U_D!wX3MPp zfz$Ezytz9OIQ8R+iFtK|`AJ>Mvm=k~U{ilr8%XhZ0`5<@Z{3WY7|r!{2fjKUcI6r= zl%c%zHT%=)Ngd=OXxtoARiR9{+bccraNu<`_tTP{)$rj>Ug~7roOYSS#k6-L#bf?3Hzb@N<-RB<;vF51a+x12eq^^^*yD86LdAgmh9JchB3Icu zk06%%jDmkDBfT*A>to1zg~h~q?MERT!Z#NLxr}rsV;?X`Gy?PDdRey^ittysrZ`pn;a>sn1Ckz3!=gCl>2!! z=8gi(93S}Z)Ghz%y&q=Til4Cs=%qrh59gxm9noan^LRhjTxB zoLdNH$_tf?I$GS+_KNdoof>t+Gn}6ds8bv$#c1{8K;@Ne2aB zLS(X1d+`+S3zOQL9#=((yl%ZwgN(zsW;abDka^+gQ_Y1Tln8IZ#QIs14a z?QSk0v{bdGEPeNJZ{{{G)oT~OQFjT!OM&(LQ& zIeuv(2f=~mRG9V5_UoI5B&qoqB$IhB7vT7yhqQHzGx4=5OOzY0EM7i`aB5Fa(Yf_t zZ0E@@m6%~!=RD?|S6>q}30dV0bgv*nsdU<`QYQjAsZzS>GV=Y0=}P)yjr zWg$5Zewm+^RttV(6F!_3%*E_H(N&e?l+~a!uAX_DX0f2ZC-5AP+3=;s@h`jt;q)}8 z%7*^v^qb1Hy^Yh!k%R3Z9IDgj7F|>&W1$})0p~1pIvCRU*~{dL+(un4tG?(i5{7}~ zX*wt^=&-bO4Ud4EvG61Y2A(pccxq-BR|nTsulRH7b$Q>R!ab2*lfV1If272ymoG|F zf2%TgK2%Gy+tKIBn1A}CR#-U}d^909v3xt2pcdv-fN{$HuI%K6fn5;)ab$0@)*7ee z4Q2h>w?vP<+QpH5@uuP=;;q-Urv`ns*DTk)Y%EU?zd*7RyAxY%;S@!GXWp&k*Bcw> zU#~$2Cw%IE#OvNGve_TSpSBJ3lL+3=F+XcyVgq$`I9>HwfGs{hMRwobaWYr7Kf~4mPiy z1C-x^Ds>Eck#qbdnM~N}mg6jtxa(xmHxcm1Nz8`#niqgwC z2}GC2#5AAbtXYl+MyZ;wUTE{@H-9BWC8dCTtULp!9f!SIJFkk-^zhhlHKbruHeYhy zl#twE*7bW0nOGD$a5@a-6;Hd`U^LsBoS(_OC{N+5n%03>t6G>90GN z8Gs~e*DD+Msaj`Q^D0tpbrZg{`0dk_K~t{-xo^;lPj)NM37pxLyFsK{v4p5Lvb1W0 zYS6~Y+n21(y>2i-nkQLCfy5d{m7~%`jTq3weU0pEUF`{vs#GOo?OVj`)UwhG!zVQz zovFnUUMqxk=c8n|qRq`|wQ%FDT=cKcE>++6Jo9Wykr$jWRtjUy4!nC$ERs&{ULfv& z!k=y9bM*6GzMVVrHVmt~%Z`7OD0=R@hN*LJ2AJ{}7ZRzj;O(^xlV}NNj^||~z zL(Tc|b8EQQP~@C;9oPCM9s3FoBCq<>T_}Ii-u~g4EiFkIwKh9JH_c5DKl=^QT>bjD z!sGa}j(CRQ6cXUr#L2amCS7ihFRkb0Go!=nG3D{+yFA(N_pBDK;ylG&&^giSizJ&u zw7pUf?)2tJKLH#!`HIQwJUaMzQilj~C73ktDQdHqrzk$c&UX!2Fk5wL`Y!rg_{^yQ zfE<3r>uGaHEzP^W{(&F6=x#h24q>Ot*VZ?oL)_2t*V!I z&nBbA1PTDap4Qe)JxY!dAL|mEs4h{bXZ&D+KZD|IZ+nwD%FsO|T|PxXC9~`X&&Wbz z<=GRKwWRdZxhB=JuQZJj*x(95H*zmXTZFIlW44GBA%^)cS8b?Wcfg< zqvz+7Zj0@?n|hm&O`h@(C^j`xjFz4v^^JSeXRB$a=We=VSNeUv2Op*0IcK0>WmFIt z_n*1sw;`iXrq}1XRyP%lD@RB)G2oy%x5^~&>L%cN75BvLGor~C@EXePG%@wMO zO`FH5iE%x8gKY_M;t`J5((d90_b0cf(Z`P7dEBE|*#k`s-0hgmjC@8?YTvy3A=>$aJO;ISv;B)qS zD6O@25#1!zUL3-?e0sle7{j#keB3iK|2H>OF>N?Qh|0%Q*| z4L6ESsU4TxpM=*HGR_mW)oH3=8K;d3^Ims*iI$Ly4EV(KHZsm&JFVnfo}?&#w*;Hh z#@JWZV$#|72Uvv~?fG@b-7L2~i&L>0SG)E0-bSIf6x#T$;rPy)2Xo$hIIPB=i>7u9 zWL9%SgKnQ~kC`hiI-%7I$!kk;o~QnNh`sy)6p} z5HaO`)C?-G$pT0*#_gWON9X;Zl{Qv6ck9DP!s;vnSv`*-ztsYDM;t63x5g|2>sK{8 z{&G_vr!6f%NIBjQRuy3aq)F&|DKbznaVGfU=w0^5es#QX8p$A3vqb?Fm@Q><&kzad z?Mz;)o~nFnM3hs}^v*Zy7Fu+mgZof(T@_cPS00g zFzzE9#jL*3djjQNC^>c_HYzac%I5CT4jWOK^I+V$yVmKRc9RRjO)%E5w~m53&lL|5 z`nW69KRsEo3Zi>b-qpz?KB3JsN1_B;NY5qKEHb>ibDH4Kd1A`$u@RLBnJt|6c#4`6 z`k9Zzs$Jp5{Z10i?L@WEeZ12V?$e~-j|Mnmcn%a&1iBB#o97 zRe^5G8O;Jc1T2A$r5ksqW+yedETd*qY$Zw+yD0kh@m6dX*#&&%q9n zJaD(#i|MkpJfGh$<%8cuV2H7|6&9)&{*LcE!x$?gJe{XK$g_UrgD#f{@sbJK$9rcw zsaAY!=!VoKN!tbopiD~(0ulpiZ&*2Cc(`m=)HM_5t8B)^H-G`$`z4@Zr7nRw+IB7K zT}(eCSYNzcyF4k~R??o(M9&Gq)tPk5T%NnjBKABQ?6P^o-3{C}PBK(y*w5j!vA*|= z9-pVwCnt2aR)d@4T~(cNrjA!Vd1;{$C*>CRT>%D!ZqTE(9{Tofxha+#+x^mq6Ipyy z%~Yt1u(ELUN_0|Xu0Z_k_TGE`)@d~F&0yp2UPgk9Y-tLmJ~i1ldrI_NHp$R{sSB`< zk5wSKkNN2Z3ob)+b{$*u#2q8ikq^Ug&ek!lX@REYdxh~r>B=n1!IkgEU+-^Qq`4i3 zr8Gd(%_>O|jzm6-AGZqC3HI6z=!o3U>>8ElCMrP?ySuOM`Vml@P}5t_KBC11_zfG$ zb9HG}fp>1wGwTzl>qAY)=o8Gg4I>np?3k4jv`Qb}Ve+)Ba-zYid~qE%qJjym z21rL7cHCY*QQE#&zSwH%o~Ss<;(%NF$N&k*Ndi*5-9~Zh}TGT%h}TGAvDeV@T>Ug zeAGCmaEfK6vh_F$hNt|(WqjHe1_U1bMKJoUBI9^A%k2_M{gT(+es1%~%v$T3Y2Erv z`gEAj*ua68wz73Hlf0>}S9&|zIzb<&uyjAs8b+w|?zlzC0gqd0xkc3V$+TuV1$c=# zb?7w>@g_~pUDp>w7?R+<2#QLZHBbsPfZ??rWhAqC)Js`!DU5^ju3}Hk63fePIRkwm zdT6L?GRb*DhUGMt(t+nBN`Yduj;3p@vbF2d*Q56&oA(zMMpvMUdq#nA)wHzlBRz5> zznDb3CBIH56*##rs94R~4>lM0Ih1^L3Msw{95C<7Yn_#qFwdnQ`uT%#r>iZl@H6e% zcDM!Lr9$ylE|iLyFTLazfF5k|LWxS{fXc{z{MpPwV}U?;Vg^1-j+y2AV&*WDF%{*l z&ilP-yYEdWxRw-b+WErV%Pk+ycO$kAx>a^K2osHG?sg9L_%6ZWHLWid4d2Lqu)Xh_ zCz`~OYI)W8K{^MjT+d$FQ|u#O(%_S6!pPmUER^T)bLM5gX|Z&-RbYkp+D-wgr=KN6 zyYEby+g`7l-DWnYO%^PX6qTK?di%M_eoe%Ov{V}VKEA)?K5bOhnzMjJpg}#XD!Yze zesjM>pd{lh3#*~Qk7Mzy&IzsDW3QP?FZpbZS?PDmE9G-`k{ybyU!0C|tw*O1pmKx+ zmX-THlFhg49_|L?ma($*AK&MsR|P!tDs?Iv-_LtSC!SOgjlvH}8o)0!FOXCBY-(>j z{D!U;hu(ZtP^H5oYD|WE@WaXSLW=L?RK@4rvMU-qWdJi(3IwH}dYk>JU&-xf!4h=g zgcYiMS6iPZx!%|d7?;vQ!qf`-Vv-RF`yhbO%cN1`T1PzBsJ`diIPYUsNw7{w@T&yM zcOsKuo0wzFpBZAJ*>~d%ndK12dEA)e@hXK`MY{RcYfZqr+56_yUD+)=JOHC&sSl$f zy`#1NNyM>yy-3<+FB*3V>uU9Vr0H25lX2Ng#>BklJM$7x=h%5~r_ACsCRM80<5TzR zBO?67nq7#97zZH6A6C_W@^CFu);b%HEvk{UoxA%8<;Jwyxfo?QcE}C_6@p(H}3MFA_wYYgWCGpkEC*9Z_x{ef1)gW-Lo_U@+NX zV1kQ9?23vSHKDeA=!29T*j@o`Y-)<8_kdPO543v~Z@&MfdB~%Z-!0;mlE000yk3wv z7hmOIOwFH%B_tsw~QO zU(%lao{89QCe}*#l8s|-?;k~VaT~@I*Q}hbDw-9@dTkhBB8yVZAs)oKV*WKMC;8Sg zn*dD#P-4V=zLr4!s(aww*kD}o&!3AS$mulZ)GqtX^l#_#HZZCs#W6N*16d2cI^qd9 ztgEH4XA0Uh>QdNLqtgYT$`>$~pD1yH3ftuqip!=rJ%_ z!fcv~t5s}<`|s8YKxT2OZ@YW(^MByvfUXPOG-_;%b5>pMhqj`$+Ap)~RstOyw>(NL z)@}$ZttQ}z^=wWS>Rg$=2;MiWjP=ZF2d4M)2^h4!0risy?J6&8}Oon38wSKH8b zu1dXGs8(J%DY(`1_cWE?M=f-d%C&I62U+FuT)CE=-U7RJk1J*CtM-pDDi37_3rC*L zjAT3|B!p#>8q9aQ_vh)MU$#F;{MEWoe^IJ*w;XXgwqO;fil2CKrMqph@$`+`tLacl zJ|TGLm1lRSJr`!ONij?t4%fdYaK$TJr2Rr9nN#3B*SX&soQZb4_dsDEE!3j4)Zm}EbpL&_fF8n;&-HdYg*vvv z$#Ml`r zXP8b}z|3&^nZ{0L_E&O<<)KA)#H6|vDFwR@B*9w=gN(n2i$HZKk5KU|QMa#FG zn0XIB_xKOYF5U*5Tb4K%xy#4)r?rkMR$R{hpdxB#tym*-g0UTUSjW>;z8|K7=QF(8 zM3*ihD04*L&RP3*9cIt)Z__dC#!;2M8;z~vc(a1bTWLoXN?aUC#|E?Uhyg9uvzz{U zr!Oi^if=Uo#Cn@VP}CQ=~{dJ52bJWs)^qrVPE8)=;*PUdN+v zv?o4^7YT`T1SDrbL}K`5T>jAvrbaisNif58r$U${+bU0u93f3GgGjBYTxz3}$jid8WbPmOsuramFdL_Li(?Qij${nWh7AJV##6LLzuAz zge7bvgAND}Y(W3>LRs;M4;Q=6E&tWSZ()BIhV6Z9hIPRKloBB4f4_kJUXs>C4)#f} z{qZ&M13Y)QPbmMxBmin!>(B)LF*nSPfKl<>4ecLJ0GkS6tw;=%jwcFSf6x2h5(Mb@ zF8&-O{QCIc@*>j%?b!6B_->fK4>TlwcMAAK!2GvY|CU$643HOju0aX?AMO5n2TsQ& zt$BCazWT3`{&a#rWZ`9!j9M38;wL$i(%}V*J;; z$U#8f|6xfYnNQV47@yYLC8b{X9h~+C2!ohWSe;tYu4fn0a+y+1_T10;=b)<^MAkjy zS%?!m;hMM*RyKFz*QS3=4#={sObYg3xU7KIK0VzCQ?J{kT^QpiA;=UixqClgc@XK+ zk$FAVmc(kXwRe3RNR_{S_VjeHn?U_&IwXehPgNd)sh?5W+P*(_a+DBDd?xkA+`z7i z*CgD&jGjoXUM@D@bTb+L6ls)+`RK_E-;# zX1Z**+W352xLxQY@R=j317)Od7Z6MVsX+Rx(R#tVftc#_kA2P!>=b`(2mdjSJ3R6$ ztw`=fkn)5%>x@>t`|~5LPGLJ=ekDiBGwmD5)%{ipmTQoK0~gY&~?$9136Y`-pTL%dM=^g_G7`C??qY^HV1d;;|Q zfMj@k7jjl)1I@hOTPU9JqbS)qdLhnA&LPgN0^#1cA1qLnZ7k}&6*9igM5F4PsM^c( z?sBwd&TwiK*EZVr2dG&h2++#zGN&_QzUye{@1#7R$ zuLbbtC zy)&R%u)hUkB6OV#P~pmpcG`-h@Am19Hjka^mr{DJi$^ML{8saIicYaNV|pH}+&r2% zQn|D@{%r2vS5i~zHd}LbSTsp2vcX@lib_OQzx)wjq>-rb!5#uuFSl@nQg^czKAz_z3(S8Gy*=Bvh~+)Q7O< z3k+ZUe~I(I!~eIL{{Lm1EJ2u9sIk5!ptMBYYm%;Qqy*9FP?T8yn}W!j$)JZzdqe>w zGVke-XmU&!c%s1S?s~)Q(IMipU1txJR{uz5OOb#4le7r|?!nKNG>;alQvqFEVKZ z?9PZk{suk-x_EvYzlVSw|2W?z-2i4b;o~f4fsusGp+)%*F3;y5Fa8L+4>?1hxVX%k^)oh+d16t|Rsq z@@5azis3s5&{42V(A#KC8SguEMC~0vmkYY${vh~JK+akq;=U5vA;2Sv2(}dP?B+x} zxBos4A$FdD5y|Zt-%5Qm8u$}?%4e|Y6|~{#sq_5yr+i9 z6yTKth=teoT~$U#tDTPbJ>81ar`h{cRu-F$gYshN4@d*435+0Gj(m8BfGyrqa5hk_ z_cC;+FotC)^TbT^q9QpJjrZZIkb1*@Z!`1J9${ImMb)E|9>TI9bQr~arj=0pyDX_- zZSG3NmSx}}reFpFYrkANM9mC;^aeAzcS!NWw7O#(YpnBl;Oqrz*rw4E;sZ~zdkc6f zLsFO!1*R^1t1)%o&y_avWCDahF;|xcGD!ZLCK|voA1MA^5gVzmdU*(*U}I{& ztBycXPB*t_9dC_~dAqhh%v|RN(s&F%bTKd)VB&YbS}1{AClze?a9<_q9r#zV$qV{F zj2b%thsop!!wo1f8R4BZ%XingflR+1w)b(jVuUd|DwQ5$U&4)Ux%ndv?GKf20F@1z z!>GyN?dTUFe4B9#o%pXQURR21hmN9V$I?4gk9ed%#ekJz|5EvRXVwT>~3ZpR)}X!9TFhe@Jy{Ta5f`J zJ1(8~2gBQJ(@qxm#8GFNy(C?3JC1{gOGDZYBVT$2X6@wKwypkkwvq`776nET8hO8S zJskD+xRrBK)1`~~qom^~m?-|j3Ge2C zu>?ts^XNXeq=@0Qbm76z({NNb}78rY$N zwrYL}y3?kg%uRL365ei4HmfvkKlUQ-k$V`|LG)lsB!&vJl`kbbw%e%M6*WrM{#G+7 zwez+!KO=7}JDVA+rUQpbF)!d-Q&CLbOQtz7i9e@4s}S91lG&Z4dcpI+06|<}KMV%7 zO33L?o-+cb8}by*O{Iwsa@OIFg(^;a(S`0~qch#Tj7m8I)0hrnB4ErQQ#eTREPYe% z_XB;b{`dXA!uvC=<`m25({2)>4*<_sa2JKr)wXpweL{D%y^5T^#w@&SZt;D{n`9>K zDXXN@+v8aGovqwc>p7&@zJweE9d3&A5)r9yk?<;pv8z_G3d2ULp}giqin;WW2F5OPS7Q9<8+%KZ9ApDE5xY1sw&bq=y=cZ2>HPr?_}VE z?+hDF6RqoRFzU8MWXdH@Y-$xxY`E;60=`5V4Z{FFssx*Ki_|TLV&$Fgg|2!p|3bq` z`*njw@WW{RK_5BEhifpCI!qRM2;aK+vr8pp^V!l{f|8iv^4Ge7(;U1bPPiox)<=+3 z42EZBZ6D|mu-~_+It&&CsJk9_y{aFd*lJwlomLSTa$@KwCNx4@9jjcXU<8$y6y1D`T{3`j6?A%5LaLvoYE@W^Pb}0y> z{)`RfXHxGES_Sv-7eX@xZ=83xe_A|<5Cd6YqQXj~wfCg&5j-owvE)zQQIbnUdanmk zj%0>69(1XCP}d~rqun3U+Zd-kARYNv4d|2u~?c7X5Bw-n5V!(6k178d z{13`S$Pvbu!_|1y0=4|yWGae!36(o6{HGIWH1u+RtV}ukfxNP7CA@R)G@u|J(~umYN0J#-gy%jc(F!hW|GIGy73!a#qYyxse)CSyj{j zdw~DCD7tXE#VGuj8Glx21DwiGZpLp917$IZ!kx_&oIe^mlK=%AJ9Hh*+ z7b!# z-IV2X0`TO^L&QMQ=VI(NdJ%lWGq#l$zg4jTXB9YOaQ-FjT@2jl3 zZ?YC_JAeorNVF@(u~)^08irSVPD%2>FXi3<+|x*CR~%MZ6}HoK&Cq0Lb#>z7kJsLD zP4ccNbe-lI4%8nbe!{!sihymU{T)7fo3IVz6#BOmkumU1buG*>SFf2-DUP2|Jd5SF zN;jGT>E0Nvj!=m{m<|(36NrOJBUmtbA*-F86F#{2R~w;FZ@~YPopzPjx$(C77o$+>NS12hj?@eCB+mRlpneiq)t_%xfU<8> zx&?Q$R_~>Vb9PX%8$qg4c3Ri3aBW%Fu)pEMSCAF9IErZvSQ3J8w56!orbwSr&^51< zEwmfYi%L2{<}!kk1%3}MxP|Q`rB!8QA^q|fd{^@>2H-)pMb_{X4}fd(b1zQ__!2zU4{-tlecKMMoAgLO!e_I|1WS;f~^*<+Hg zr{Mcg?mXJZ!8inKZ(0 zlXiD3Wjqb7eY_9g#<%4i&_c!&vn&%L9YQQj6t;d5=nhyoJpb!@H{C0$`fMFo6*2ew zArNBXy@AbwAj^(K`B`v73d?^bpt5eO{4owsu{wX@RW$y?D7yp}#r8GOK>h`QX4`^8 z>s!z3T?l1cjLQX$`k6R|3JLbZ76JGk@c+#;9C4t%Er3v1*WwqB*v67>SSn$%Z(a}FPwcKQJwFcvy8JtiV+_3NjtiS)5yjpm9wKtSgDoAq58P~l8+)>$i8mihUZ+CtRqSIX zaucU&RL%Z>*;fd#uW*p`FcRh0zgAIOe(6wdeR7O5+clB*H4CK;WSX6C;a@3T4+)qF zm5f1>B2orErH%YJ6IaW&frrXjtC2V1GN1N=1|MIL)?g}oGmDej0U9`l8Vn$cvsjHA zD@fIO2C_pk4P2HVDdIdZm4OLqr!{X#xL_fYT9~qecv4LC8wyjS(J!(58wAy;R)nchdnaOzyw4x_JXi#v z3z3`jGIyAGPvCU5^|FI*vGD_#P`S=iM7vk7m`|jQNFcE;H{DGbCX5f%K|%%E!au(w z!yd~hOl*d*wd$nGyCmgf07EJ96yb>q(_0?@r-yQQJ63zW$x5^D zSNMC})CWv9s6r6_DK4Fpt5>vX%=+A=)7?msgR!MfadVS8#Z1*)@cb>xI=+1x+FLLa zxz}7IF?`BH7~YyCrez%7@SdcX0(uw5)odM7KmK~y;y;j&{5rCwjhwf;yE`&UrJ#%p z*klw>dBayBB~FkSo03F91X0$mAF-*^VLPj0?!cuPA+eIkdy>P9gj(sVypm?q+8dG5 z_3E?J`51Au%K#6vy;zrZq0-3l0ZsO4=%RJD9H01G!(5l9jfbrOBvcvF^v@_baw!?3 zu?IV~@g@aLTgp}^YoPhJuMV+of6OY!w5ekR5l0p1Ko`f~uS zF~E8Qi1OZ&5ndk`7JD<7PbJFg3K0#j!f|`>$$$UB*`LrywzMLecD9LVpZY@wMRhq_ zyQqh6HTOqvHRUGzH4y-k@!cUi=%<~2S`YGr{7V{%2j8pz4R23^9y2J>m!$-Ja`^n$ zd}&Z#dL+|>V3hh8CP<3iL;Qxe@Q=TCT3fQfB1ElA#dD(e1fBzoX#{`JIzL}RK5rCna$%9OC?hJSV zWCNXD)=8H%7nF`OA0F;81^^wZpSGZ{xbVn81I(cnhYBEA-UFM0w&|Z1g+6JAD?R<& z)TALW3Lhjtj`XYCcTDZIQ-$PPb0A#WWtDj|b8C(F@+Mz!80UQdkL-XJzv^J6i49qI zpkU}TNA%!M#weCqQXS%yuiV29WIBnV_774L7?zUEC_{n->Hg~D7`Q!?GWg-z7}v$( zUQi#wh3o#>0QQvCe*#}0#=nw6aWDm2ur{^cX6R{Yfxlh7-Veb7@wA6v*^SvhfBBE_ zaeyIz+3$Q{M=(%>mDBVo^$muo@h87BoHUs-3@(D}-5%Ke5&UCJp#FNqDhJ#Uuyt7) zG+eWS)L%c?Y9C`a;r#rceGyW2*tjP3A7~H^bYRe1or;29m^;~Q;CDbxEB5QwUkvUa zFkBV_va}W}j=u@{`j@=fubX|McmG%p6VD#@Lphlzu(JuOMV+M^|Dv4jR%^Yt zKNLU#qw{pS+HSMspFcey+?XhUmm8$NpneS8!KlZ68E?(%Al4%x8I~FC!dT$*JLv7c zm`doTbsOwK=>N#{6GqpH@j56XSK-B0KB~6R1uevqf0EtACqiO)$4V~o6G+W}>-rdG za8h@KgC^k$qv%n`C%aP;nTy`#1mNe!`3@FOmG+(53G;%f7trUu&CNDTp1a_ z8B$uLyGy!;MnFOkkWN8Bx@dkgZ(pwvfQ%9f4Le?U#7xzII|7DKDMEny8B!0# z%lrO5GX=fE$C?l2>DIvULjY%Y?ZmaIOBwIve`r`fz0wy;BujD~wJCspTLeatD+Dyk zWqwbub>{oVaL^>!doVgBZTUx?rGkLj%ry0X!^^x5uo@QU$OR5lO7OBScmFKUpAt8l zQ0OqvyV%WJZaPZ!zXkyMCV0T2KWMRPVj^|nH8Oh{OXIvL$CW`0l9Gcu%l7Aqw~bZ8 z&&saNZ+t+z61BIRA}~3!*Y4J`RDhY~Oh0#{KpVhPaBoD>t?SZ$I9lE?=1)|nivd0j zn~YF^@WdA&n_t!1*E%k0AV0s{`D+`TYraRUGJueqC1tGgyHcgNKU=5!H`IaNB)Sx1 zqN_mj_g;h?174hqemn)~b{Bjq+PXdO8iR*nqVqOk8o>5EFe+DMwnDREK(9b}*O(v3 zt0iWA(*%EQ7mcp*iMU1?lI=jvlbnF4HltbwFt`Z7InJ028?~>C34hVmxT z_)53O93YYa)NNn(dsBX{j}&=cEdRZd#@D{rk`3&?dO@lV{EgI}-qOT_PGF~l?f3~Q z6J+I|uif_Aq1;A+{dt%Wc~A{`8Z&-N?}tsCFRryr=x&49Q&gDrKA~zZnxwyfdLd56 zR`l4fIuJ!W>(DS?Wiq)^@w3plvj5q9&Rc}vvg@wpi}E4+2W;e^59By!#&y6^_3*P{ zTnkZtmgK2ku&2+L2Qm*bR|7&=aw5k&M>&L<4-=J7E2BhSquwo^UR1T5T>U-?rpXc3 zS#7V=^7s;6&zX)K2oGLfU;+yBRC)=25A}5Rj}fBMT$Z&Rmf;o@DHEY5fAa>Rib2Q# zK9A`83~?o!xC}cl+Xv4V8oly4fEmYA{lW_HQ}Du%KEtkh&lYhWE?vVuVIfj^a|Ebc z{3-zYj*{6|Tt@w-CLh-1$worTM`e{~!$97a1d1yI)!6GYiX(*SoZvJvzMQmuH-pOa znEL8f2hCy`*5X6YN5Id<1$+@p!Tj5nuxdx-O{x8(9%twN&eTN?%><p!(kUIJHynXiWYs!B*64VqdM8NOdUJylh!nW$7I|mBfd+!2Zp$p)^ zMlHj`zagw*9fFC^lXb`YgTCjiB7M#z*ME4p+@2LNQ1B7f?Yvul<}?Ym71a)vZm*?q zH7E%Eh*`}(^Ea+xbPWLU-IBAeR>2D?BdNQ?`7%+Mo%z8~bYHj#$^$>ad@wrP*^%RK zW1bMLixZVH(PQ4$0lKMk)ma_5FH_DN3%qJ5dOM*pzOp(%>*_xM7($O0tC^~pVqr)e zK-_)7kZKbRd$$dbB_ajjTU4K42t8N%&&Mh3fji4{tN*|mXbUC<6k4WZ0v~{D7>(=K zi%b|LBCmllUjP6rk&`)jgwbjt2vwpdYptzZL9G#I@dY~tNN5!W(ZR*tYqSj}fS$J; z(yN%j38y!o!HiVgU_BE^m%S}mYoO%U3^bP>{XZRmZFzuT(TeT?)*5{SRo~8HLMLh& zz&8mp|0O4Xkn05fL78Mx%n)nRy62{k@syW$SjWN>HEiC0&{-1y$#IK^X}3wU>o48w zBL*<5fLxg|Sr??Y3@D3e>NYZ>k<;F2sqpch5b56}7M%>_P#oD*VC;ttAmVWK5_%#H z3BOP&a*pk``!&N=*m1yAMTE)v0D`BLPNVb=Vi zBT~jQ7L(=IeAlw$8enA{{rGhv6^0NXD;I>OGQDZ)c~kJAx0t9St>)l=K+^?4!f?)^ zBQ!GrRMP6|$9z07_WQMODntp5MO9tszuqZ?{5|t<^jxE(fCh|C40G=@%RKifkVM9* z((b-Ec&Ik{>Yu`doXqrZ;Xp_D5I7hWGGRcMsO6b*ptpS+pFUl7^XpwQ?WQDB#?+eA zYpaK~0xs1@y6%ISssMj;R7+yPGB1$cyD8+ZJUTLxVZi@?k+m*huiGyosd1QEV78MH zOn5w^)rXWqgIzcQr2eTtEsM^sWv@IyckH_#JeL4#fMELb_(0N}1%}OYy@3E*iJ<#m zhC-rpt4#j1Y%jFOM(%yL4?C2|CD77SehP7D`7g~nphvw z4KBHDZ0F$ciORXN7|B1F<2y7?!@Sh#+ZcE%)AP{8#AK`6eNs%nW!WpYp`k&%JFDP3@t zYx!{vv*e@uT7t;xR5THz$A<{=(;LsXi=(DjR%&h$vuqc3pK2bsMDOg_|JslVDtT`t z?9d;HCw@FG=$|)?1vJR>0806#CbcNtgL0mcG1DdQC5bVApVPC{psZ*jTcM)XYe#^a z1h4yU>=LPz1VyX94Xa`IKEg?Eub)P5#|Z9 zZ0k7eJf6^b`t+$t{A-5&-O@S)cU3 zJlK2=6K#O$y;9m=uRc2))F$K#w_kxBcGZy-c}DcD+~<3kjCt5;VpxhkN!s^Umhlb z7hhC0H4o|Qg02F)ejaq>NcuJaa-ZLxEie_Wpa(~1ZIwxIwpb~8s>tbC`n-z*hw93V zAcOyllso^;TQG)O3e2sD8=D&&+dp<|4>P~Cx~_YCU-qtiRX2jCaI(vUFLxsZ!v8ZO26qj4g-K51zsE22`+R*^ zjmXCnfx!6nqrhx;YE541?2-PX-3#)9LtzZ-q_8=l(heg-)#KU_$WO8bxr7uzrR>oE z_;2h4a}vHl$T^>36WmSzR9SrK;_Dn$2UK{G2IyG=`N;^4uZUP8rC;>(8MW>bz)aJB z5gi8SCDiE!-vMJ_mhd7fPru(4fDS44@bNzc3EGwg;X?}bz08>tDA?}|Ub~2n1t@z4 z6a)d;-%=S4!6XNGYrW1Z3bvR=%kbm6%CjNZQ#R0lmv;kH&kP_#^FkOf;o=!$j^4m> zE`#Vjpq}z3zdmt?z$sIR>)kqjU0hsjbjHoieeiQLW0U4*BDKWleS;OC(X|2ogDiMx zWT7R#z(tBGPHqD)!m3vF;~8)jeCY8PKbk}#KzH$<)zp1Q9m8ps`sD9*xNhw)f8Az+!2g4)9H@{ zTBbjMg6ytG(!Jws=QV|f2@9eb+Ez{_it?=id7tZ?<|71fTU65O`EVJy0*N!w0N@Zf zqj>Lw`a~>|mtS*yGmDrk#pFngRHDW8uL+ED0A>E@!nbKE;5**HL{NcTMlo(LW2Jd$ z$Gm>M#I#fMHDxrJ+H}wO-&ugS07RxXe|;?qk^(2zlJwR^7l@});b$xN z=zcP*W!N2+4BiyaOe2I9d1EX#+swS^!1jS`w-KtoY21(ChIh%+`%W58wDSt_S7Mt=$fu+9r<$iwhdZ27Y={T%n7@P!aayWV&` zyA;xaY(`9KO2^8)nCK6x(g1J8sK;iq=Bk)`s4BP#4>Z?GYLHG@riElFz?W|}m6DyE zl;~(81xbo-fZ1Re5UpSkNnH_4Ar`t@V-h7JeWtuO--!M5`{8ivpqk6YmrSd(J>YFw zFO_!tKKJwlA28DnE}Y3A?mvpJqiyQ=UNj>{PTTDymZ9_#F%`M&v#TW*P^m*?(<_3Z zQyxr+!?kI*C7izAO`m?kVCVT0;r!a%)xwy)Tjif8qZeV$91=}J&eOJWo6EG5B3HzD zC{kb8eC#v#H%<`|eKJbD8iQMzV?z6`F0_GIn$#Ra39B*$3ydL~x^G)NVR5-pOxpMB zm>Gmdv79w|vF_2u(#~NOoiAI0>}|uw=Z27dt&GlUypd)krg?P zD4j3YABgg_VaKgUp)$+@?(K%n)?(yfu|XntaTr%gT~r6A%Y0wl$GoKW6d*RTFSsuN zd2mN{2z8Zq`QE1ZYjE}dtRWag#L0tMHL!Hx>%KKwdv@mK81RhIbn*PoiqAUU#Uo>5 zt~gw^Oddsbb#+98V9WIo~?MsD-eB5H_z6sB`nE}MaB0itA@Fi>n6Ep~3Y2%Zw z&myD850dbXr!b4Hy=D=E`>@O&O^LhsV%&1-39nwgg7XHQs=a;tcEmDl*=d;d_b*~w z8b)R;%0XNC4Enb;Z<)jqTE|*hL^t(+D7*Yz5Wal6-tRM#ktnu%F!Y{$C`mm{)cuoW z80ZP{)PM#@7qhRbKbiDn?_YCA=`h(!YNmg>trSl!7wh=3H90gg6)0dTBmT`OM z6d9&?dUS$8{UH0T5z9n&V`mG7!(0AOMpayk?}|nNw;PDxx^}xPBN+K0*f+D!fvW!L zr}_>OODn5-%R$Iv-K>wxkWCtqC(0p3kn=XYFJ+R7uCjN3XMDSFGMvW#pCs@n6!k)) zNy!IHAQIjO1C>-}gS}zc%FnmP3&Pa&&0?A3GU+%t>`#1u1DAwr!1iCgNLbWylb?-= zF_hLbMkErk+|etS`y1JOc<9Jpng5MX^ZZ2npL2a{ddc1P>o} zFdH8!Mv#73=Xge{$cr&pQ>ybY9VfQLUvGo&8T5Wdn|Y-Gs6d&PAqr^QezclNI_Q6NxDM7j-oD z>yYx=hX< z$|?^}lX)1oI8jTVeMrjoQOUXk?&IVW=Vplb#K6MIOYT|amkGEtS>hJp?*E>2mIh!@ zaOPMQVXsNGM@UN+dpc} z#wUhRU5kgp!$`DaJNlZ|k!5S;p*>6n7|-iJrul=M&1mG*l)hm4{cX0#z^Gte2ZjwQ z)nQ0&EM|+vXAscCu`~=9z1$aC;_ow%AGW&|ZJ}J~H8ww6tn=LcOjpsj$p#AwY{;KgV27Wju;|gGlzu0TzfN89by9*QZOr&6y)-s zU(2K04}f#-O2An!hEaeosZSe3j5xewvp6K;pgJ$sJ^wW|u#+dZ&0TxdOGk~_`0j_m z^Py)OdG}36Kivd{AVZVl#IaP)^Z$D?TJTU1(R}Pf(Uz8$_0O8i;!nTr)^y;DthlU~ z)vkj{ir}w-%Rq<5qBBoQCV}X&R~uB|UGu&6I1;{m*gz~)?&H3f<{b|g7nhH-C=f&o zp^Nc;D`H`h!3>cPt@xpSLg~MGB%$O}JeN=0mA-X7Sm5{2m2sMqvvm^Rkt@(O#RmUJBj~8=_&jEcR(~_{ap*l-ndfH-hiUo=j|6$bj zs&r-*I$ro+GaEcYhn}jc8lW^(*-vz`7eRqEiI|9xG#Rkkpi_#2E+u{(=^vT9=2PW= z{C?};_tHJN&6gxaFh0!bM8A1l!0Wr8m=h`27nN>qB@%riw}D&Xwi2Jp3QLnzb%zY4>n=zj@3;GQ?_+g=)&wz=8_ zL@6!9IZTI<>xzu-8ohjbBMzED6UgHH2qS1~!~_~6STvWfXMKW zC^UYhE%{wOL+Gh64%f~IQm#&69{;~YwaV>r=2&N`{b)Jr@@uiEQ0!kO-fPzTfm3)TQC-Ng!6}tNi{&tp!nTq;*b_WV3A|3Ath0D=RJ7JkB-Wphq9v03W{!1XCGy z>|1=+JTkO5D%Sfny*iK1#nBKm4$2BgVO+c7HQ;xArzin2NFG~}mk1~ai&^-Vs`_ON z?>B8NOprGZfQm&f4Mf*GDh#Kt)jT=GGK(bZO|bYJ)U!w}@FF*H}*rHJh|Fovvdze$R!B#_D?o5MRXa`h(SXA>Vq36(XutNU{BmL08 z)ka!t8GQaEw69J#L0w9NdM$FCNzqBrYRluTt4{wh>i~`=BA5@8}>na zJq~p)&0wLhH%w@kO^|mCVkhs!rtKOWWOuGc&BFuJ!I;5*zwGchSBu4IGK)PINL9tU zPZmjvf(yV37Hhw^-qdxJlYf`ii7{=_oLmzS{$p62(BPOjsPMRfub@-gnI%`A1XR!% zvd8{arRk@3hd+T~zI**<`xgVhQz78@u5gqIUW5hhgV(4BS%96**}6!mcH;qm+l634 zpkeYHx_EYn-y7iO%Pltrf&FnYnIn;)8>=*z2NOx_t1`#bk|vokq$1Ud^(Kn`M%Zs# zt(g=tt`(rr1W6r$yveZ;8cb`e$05+<3$6+}&8P7l4rSxQ#P9K|f=_MHw1x4Y7|;YC z*xpmjaT8;gyfA{*?~IoSqr$;2^VB}a#b(G0zehD01d1UHQLY;upe(BXdxwu%?@ zbApkFXv*DA%Yg-WJ?3MCxx7rkZylNHTO<_r63em&DewOz)L>Ig_1`}|NKzZWX$MR| zj9cE|2y2oi>i$el&bo2pUE+WfypWLSgjYZMI-0shc-zL20vk9~Ees<^Ps=`y%bLtB=?r25XX~zNQxrofd6Jcr793}B5 zKqwx<2fTSilQS%a*S4;L&3^Ap&V7-f(tm#D-pVl<*&0FHyYB#<>OQiNJP9C%d|pn- z<&CG!X0aG?wVooO(1FFMg>HVw@X{8ix}dmUk0;YCVXihxeJn05_B`ZIGA>`GFhX-b zbHb2F9s-)x1*X#cG-}qK)n)Q9_RCkMwI8b>Fyb-WD52TwP1JT}m>L|RO8%~*tQ zLZ7~EoqFihy^%!(m@|YQ^LKL>ScsbDvBLSuJ4auoqB=U7ytMT`@6V+4Ghbky9aP_? zjKK9Bm;`_B%@+kg%qE5M6WI_~aOX_N#%|)}anaoQaG-G&T^HMDW5TEfZS41~dP!gY z#6u^@-{B|fTQ9yC#$k<`dkUf8+57s7*Zi%A?Up2EN~K+saX$+y2iArHkNfxp(T^az zjc}$UyW?1HZ-QYqu@yRaiauapLo!6nDnKSPS>96vhP>h zB_f8IF9R*L+@OFN0Cg_fDJ{u}|OB<_n&Xjm`cgw~bZyCwaoKdg3U z{o?sE;`WSxh-I)e01Z=Ht$Z91%m=W2r^tn6Owkg=NH*15ulcEL@E#@eH>Mz{cf4pL z*(Bgp@oXq$2>xE}p>q7E$PQjo3Ay+^^?M=KcZI>;rm1nex&R!_D{PW?Cb@ zVV?Uy&~CqctFE=EgWdv0f>RUR;%BX@Fk#GwU-ORIc=^bvagu_a=dE615CgiJWHX0_ zylIw|Y%6`N6uA4%(V7MS5W+vN>(tIi+)_Of`AV(xn<;DHg*|m-z|tGHhD1p;7X{`| z4UD5taO#2};ReAv405=V8pk1u)V~15@k*!}lK@A$CtumGFjCCNACwIeK?8 zCp3EXXUXUmiV@2@rU6$M_9yMXJ^^EItt%!dqYz`bS<8NJPJkGy&QfCW9 zJ*u)%892wgpd{yKays7$1&H%nJ$?1G+9i2qXja>sabozr(p&J6*t|2PR>?X{p`l|+ zXoL!v4IYf(qicjh6jWi%z+=p?-x(TvG!Q(6_ z4MhTB>aU?D7zf?=2rONP%&7;z*0)~$u(W1XEPgo~x7sZj+>jAsE;Q+det;HTIEafU zoG|l&4&6skcg|V|*`DANK;%jC5Y5=TnoA`5k}+O*AK2jLZM)rLB!RQgNSU;cEQ_ju zRak+!k{ro_iGKXYcnVyf5L!vI1e2LA*~2KjKjj+0ash+Xuo{&H*I))b>ado?cao*7 zcU@}-MlfuLfn!Jp>ptptHm&W4C&!A-ySAQnzNP!_Qq^`&A<^B;f_?mCj(=ko9sNf; z{?x-72+cnUxkv&aK^`JZxY3|qVw|Nm1eY;Ir_%h#GE61!c)QnG)1H#qX#82hELiyz z$@o4jI;nZRM$OGahoyUeL)Xo9fi&P`iNaWnm(=o0gpAYEKH|mPV%N%duU)>~K}RJ$ zK;q~(2KItMDMVA9G=N~4mM;MzS75<8gJ{GdashPX3xlVWV_Z6TSE_$WjB`&$LRLQy ziI}BFx`Fx$q~fp# zTpS~e3?OvPP`mJ$KpVC8CzaTNEP;0kuD*(DwLmn8u^Sj<5uTCMSzKMtZ-e8x5S1(3{ab#}6lz6)t6FXXWzYUh3SMLv z+Euec;p>NQOMrB=v|$$zFdEPPmM~9^jFc5grBD9uDP`0hY}E4B8#=PAjekUz9{^32 zrCo=!u@QP;9ICkXjt<@pbCQ_HYJ0VAJ?JA1W-B5O@!sv4(_ZF1q&Q#NF;);`_^CPE z_+(&hWj8iC1)=af6C22_F*{x@rmbi!hGD2d70#S-)IJINqIEZ&U#OYA7u2YUh$%76 zw>JKp>b`G!vKO^ArsL5iatgWK-Wg)PzyDL4bh{7MHytYmT9V+sGP@;j6aLswR#QTV z{+qj%bv-qjac5zgWuTs)ZT%f13ry9LRF)GWqE-N+qh8-U$g z4T-Xwdt%g^BWuknqh<;6GO41P+;uz^Q%QE=Ej8SIp_e|bT^xZw-0)T;KfbJ_pu|P5 zz7oh$=1oMl-5G?U%_|`9nCOk*pNkHN>ZM!nWtjR=Gd--daa)~2{zb3tnfk3((VnZp ziP}hfqTAGwLRgLXY?ECf#hc2jAmMoaE+?R>ARqMTCQV=?#?_KgXQ?97y5*m1syGmJ z_Q>&E&=WF*AM^*s^2)FbK~pXDyAe~Ap)==?-#>!DJ2|| zK(t_HAgM5E$+xdfu{__mJ!N|!I7HSy%dMhp*m;w{**^Ib}G&uW1BKVc)T;us`ABvHAFxuFkZ~*YT*^d3o zt$rYvXL`#c`jZ7O?}H&JeKL3rY?E(emaZFL=uDo3;?nZqKj4j%4eWrv)TW;#Iv&1l z0=?LhtDk2i#`H&{1`MPBR%bvRwg2u9!hJ25?=O8_C|o#t%fENfm8;$j!i3=V_`Ezj zuecCIe-3`@_8sLo#07~sCsjWyo9jd)3pgPg>G%~{RIW=Yn{LP}6CIBw!ON6CC?CoVpnRR;JPnwE zt>~;-cK_AQJ$%t`n~Hq5y`HmRB*cjo#6;Hu0dH~p{P;7=Jr6v3#uavNQyiTZ`mZeS zEc$~?ABh^8Az+r{3Ej&7^8C>%WWVcQ|3h*wqUM9S!{w<*@(3*Z<}lK26NN*XT|W_1J%GikVK^)s@q$q2T z3m_ihqR#L2WxY@FRK&osvlS_0I4Qm!*0xY5$tnqMiPd2!S0PUwGZqQh3is-=S)BS= z(NQ$OO#ih}GY@r#7KmsPoEDgJ4|&h(5?#kHcpq;1lc5NS@Z?ig2rhu3TFpVNPj9RS zb>HEou^axFsz6dP99d;1td1^K-hn#Z|49a{eC;|4YjU5yJc$h75T{7A6Z0Hg73)mu zr2J-y51_^ortSkYCMowQ5AIco8n@6b``pi?w^Y=o>)y2PsN1Qsw!4EG*;I16?~5hU zjlR428vsMqA0^Ie!)!r09R$BOO9eQTdws>@64!7r1}PKZa=AzzEE;rRGBBf-3WTFI zPu5EuTX#Pi&!rQS!{T*~i+8?TsXd`%|BPSHIRyQ=C_jU@_=n#-MT;X+m+C9(pzej| z!R37gk3mMpso4(&AMs3ld?`TdJWr?E8XXK>g4-m1~N=SlFOp4n9C4~4HFHg{d~5C|v$VG*OSnv1v$%_!MPmu|#Epw1c9pdNbq3-E`8fDg z$7p>YJwr=a2KNDpi8DdiU8o7Z?FUsfc9xyIxu3-kRSgior%4;&iG6aH!>aTKSe*^E zZIocQf6Txt1`*+XFJKY5UU4#N^Eldb!R3|f4d>2PvEQQsFaCHu3jm>gWvxB};1l+u zi%!%GZF(p%OD@9nKn@^#EMy#>}? znkDhV+aaFh0bD#3&$cOe!ML1spDE7Q7ZU^mkH$PL4C5`_vz-u?wiSpyN>>VshevZ6 z7HMCbM|b~ddN<5nLk>ZZEEu|ny>`JeGIYrf^eA=+Rkl|^N|YV;LZKy zU9L`3>?F;8U*DrvH&a6eL^4Q?|)9avD6( zek9g=@Gg1ZhE;hz^7xa@UeMCV@DTbQ`eXAcw8x$>0lcL^DXd=090JNI@6~VAH~qSi z57i-zA7>6RVQgi#vA&$=1dnqOvT*_6wx%C4k>UxK?h?R`smB+rkbb>XBgISY%l^S_ zIfAuWM03Zm039{Kpb7}kae8yBusFCF^OD^bXI|dJO#ukK0HZN zRSYSd_?i|i7n%XdhcrWkE+lybqE3+=c#u&Q$giORSv}*yuxK zuZT6%ZyOkh3a+&I9vSGRV%Dn<9*T&-W)iFQT{kOzfqepAhy&dIT)HSY1gtb` zG?I%wcyP~!B@5zfRIO8w5K)#87@&|LLp%idB6x78o6>EPao$|&TIZ{o z6EL}WYSL;aN6|U{-b$Z;1VT)}*f=VH7=p`&sHA!9EX##I(w_{PNR6{zS}8TcrIZOP z2RxLu?#QJA*IrwjfhRZZ-D^VPyCvZi*iPMSY6ZW(=W}mwZ&BM2m#sfVTcQl01p$m& za5!jXXIbC}ye}9_W3Zt(sis3~f}5TDCyP0f1g9i;&fX13AoEBY_lKc#4MI7Fra9s6 z$Hu7hdzZe-9YU#3GSD{*1!6-knQk5z+{ayX<}LTE66ELwKyXxt{~0+GhVAHWm^Q-M zhhWECGuhAvm`@3Q1YUW)C)=Z}==G2UfRn0seAS&YO$^u{@WI$r%X5!p?o~JYxLRW> zq&)L};A|~!TT4<`7u-MI*1;))tRJ3TUyc>V9V9g$ec+93Ry!toiC45Y7I{=EK8)RGzv`@}oTPSJPj!DzsKeqzArB)V3p|$-dS`^~ z3NXBLR0-t}PM-EdI3|dt+r2lbeA!65&<*3WaXsPJo1{L+M?F@`g;<9v6(|HTHllq4 zf63E|NL*MdR_573uze_o4dgQs>QO>fi`K{~S-kX4sSe}2R_2!V{*01`#Wr75qexO+Eny2y4B~jUWoBNCBfC2lK$tKtPbF#;(Hx`Pr&S zSh1HiqpZLDhS59!x|U|mBnyG^b<9LwE}y}Ik{gi$cc8e#lt;>ta6|aOAb7-g9Hh1T zoZx5WBhk1`E3eSVvu1od*HM+&+qteR|4#a}zI1)H>g*_^0$P}&yG)3(all_`BV?Kx z5n3OSA&-uY03??l1Ld$k3H?3#z7{$ADt2GPSU}LQ`+VC7k8nux zgcCJsQvJ%#ol(mGM}Y%^yZgOq-CRBh!5#>xz;aCH2gp#^aSO6qxe(5CrM`q36&fL; zbjab7WV`(+R!`efq|*f{ISfSIvGyllEc;-*j}xQdyrqmX)&v zO|8c8)ZeJPF78rDK8eyE8qB|5{?lk&N`$||l`5+L}cP+hfe7 zS|jeM{xQmN!moTE3OAPzYdH*JsZWG=P#}h1h3_(a%Yb!$8 z>M{6-5N*y%Ag;_+Z6UHk<`-qb+)UKm|6dg@ps^Uzexgx+Tk9UFn<3_nnilhd;-(7n z-i&lGE?%F0$E0KoKQWLCHbAwBOHFhTXuY=a2tNse)+8?`T@-sqT*}AE*@&&(JXeQM zO9(G$;UiNE9w{?z{pm*L?8bV>?BoD8*%O2^Emv!2_RCO5M11g`sx5{`eFBn)hdJ;d5Rx4KYy7&zu;{0dE!l#LBh(w z>g!WKT!#tQ&>$l0kiYzK>ep$s3{}LCZsUSxzNh>xn0$8&?g{<)MX2!ci@5Rw)oCw3 z)L4S&`Or+nx0*)g%LciK=FdMuX% z^*$ufc55XBCjHSE0lf&2K+@dWES>J~6uiLf!Mglj*~EqaKsAX~2Qd!1%-tSW0;cNP ziBL&<3v`s~gyXqS6u6++()a1@-|O$>T1zUL1>aS3HfX03#R1~G z%&Hc&o{tI8UFbwXm-|ejiH;E<3nJ9)UdAsMRRx1q#*Z zcfX*WzGZ5^OFX^w?z-u;I>@#vJ1SX{NVoFId;OftP&)CyT*L3Z{puwP)m0?@n(TM&Ub+Mp|0?j>Cv-Lg%i@2p(e(C*H~Q@1Gmqg&@@D^C-3 zDa!Y~M+ktfQFTCVTm*%)S#|<}Nfu>#fDSV6{M(lcH??=%U!(w))JSW=hLNPM9XNBn zAZ)&%ewxi{|gTY)lBLFX4K81C<&*1WJd|^&<$x0ETV}=JF$tasU_j2)!Y_D<``sCO#4wOLxh=!^C6J-f(2w8EaSUqcD~J9 z5K%Ry&nB-H!0(4&jIfRjePT1G41vofa@sO$?w+}f1xN6GC^<0zWaS5EsHpdN?O8p% z5NJ78Jp z4JNPC!piikP8(vN2$Xh}@%N7Jbpr1k&K&QRu}WNXw*aj}=RSS2P#XnzI-M(ho~O8i zbgKe2w_=eyT;j(V1G(Gu@T;KhP+V&k(GMSY2W3{CCD>_&^z}8rqXE+L#p&*BypFj~ zZ87b48Ka2AK-vZ*=~B>he#k>BIeU&~GSZG9T-?{_j7mXr%#TJz9bl5mLe;S|8ni}^ zdPKmxxjl(Yk4EiA^(X@zcb>ha47W$hzYOST3wN!8AKl#i0?3P`8$`Ys^?2LQINh!3 z08K{OX3<UrT|4r?%ZEZ(T^yU618Zkc ztK^-WCB3weJl10qb?1w|od9bl(GOEX;j5k6GTCFkJYY7LJiv2?El|pk?MFa^B%-J3 zZZPO7zVY-9%Q~baxX~jU2-qQR_OOw6_=oeynL^-#j#&n$?sEVcRaZeGvW5J)-yy27@s`PW8c>~T zV+?O=UWNdYUv;o%RZG#+I-3kR_o1)C8dzkK7{lX=!Ioh?U!TAFl@HUk+swt{wQL58 z!*D~`rNI2kVVco4HxI~Bw+FaU21l;3QLT@9 zx?j_JQqus)rnR`HWKyBL(kG*rRjj?Oe4^w)4ThZ2XjMeNnI7w{lJ()M&D?L zc!Nsh`_g3rT>in0$YVjoX=G4W@#Qo{+xss;J%&+R1RnIGG+~#QDm!(~5DHDeIoA^? z8JmlOYyEt>!2Z1;=o9Dn>CgCYx#<&{EeHCHwe$*axjD%3IRGM=E?r&nIW$B`GiUHtb>E&DHK^l>;9>Q(JjyQaqCoP$;&gcK@5t z7$-hMzcH7e>L+L3PPk0B+ju!dC-dm?E+bUahWqCE8gvFI&e~>>@d~U!_fMy0roQwI z`GaNob3pdGc$7!O7>7&#f=SMCl43%>>KR?R>s`C;sAa4rS6BRuOqM9YaGf9Rb!K_RDPj$Awjwo@3Qs+n?R!8ceRe?P@6|&M$gP5&%d}%X-#$J+g8z8) z0Th>u0--n4J>b>MzAYgXhgAcwJ|IKb7&cxG&xp z5Up-z-_maV-p(+fI8Ptw+U?oKaac3=a3w)X==m#0_p#cZ?oaVzVy*_Jso{!)G2brv zbMO~*EDeV>&EBMVTLD+0UXC5RY9w;n?Q2#P6Yz{DN90R+-aNmEG?a9a=f7=v&iTnh z-M88k^BjP3tM}@797VoTD4|Z)(v~gW8-7u^Ik)-?s({d9Uviejbq31Fg1td>Tb1tx z+#yQhia--XfQ8xFjhQ-%lL!#R1R2Q|G4pU-?w8Jm8X4=6^B)=}XE7%~? zU6RBEl4fC>(!7C9_4rr5kLVA{?pSeMkbpG+-DS<1NV+_D0yE$g8>2_l>A|ak3XHA< z@wnu*a8-DU2m!!B-gXPW;_IV`!@_c^&Wk?*T z{bD~_qMCpXfo|g0x0JCCgMEotfq`6s#}jn;LimWu#T=KhhCMBhL1A`t4#0iYh4R#g z;z1$oM2UUJ@3Uy!?F^M40RnCI9?-!gq-yK=5_roB>}P0iD85;)6F?j{e2cGTal903D4g z?9>ed>a_GhLhX2TFEr0I*hsrzC9+lvMh;p@8N8bx0reyz2*as`nX9Rqi2=}4E9qYf zsByy7`!9N{q$Mui9`BtJS2r=X`FrwAOlrc?*XLL-kz18p6>ESL?D5z@)OTP2|F#Iv zIDD2Tak!=CUGJmghxFx+C#}D}W$yhfsP5A*kcI7MvVnu75)#)Bd+rCx2&Q(w3_+&yRm_DVy)L8^+cN{z(bp;4$LuA0buT=-?F=Sf~ zrt|3B{`;uGKt7ap#qM<+A*Dhzc%U7MM8)l^{4#cC99VKJ0JRg_(Q3K2&f|4}e1End zfUIGxIMIq^iXm&WwKG=U4|t1i=#M`bj3R$8x+Yl)giTD}-ja2I$0+Vyr@O%hIBxzn z1crWHK2J1rFK_S4M|V(WWH5~)W7xQst{h2o{3P9uM&dD9n;)Hwq|3C663^!4I;Ef3 zkrVNQbWbbPP%2zVY zIb5H@5MGda)5xA?I#FCS2Os05EtNPemL@P)r(tgN-bLHh!XlJst6YfD=<7zzD7(g7PEYJV3sx0#>&}*wmIF?O8)_`y}0D7`IS)C<`#3kCtQa9UE8PU z2>p=Q&$7U5L@l-J7PA;($5V=<^XXW}dmjE;A9jX#O{-sY1c?qBlLOrq_$|<-jw=Y8 z7Tu04-Q{+Hsy@e4&nk7zz+LS^yjmsRESRSTimUq=wPu48?Q6)sFYXT+DIq@#%7V{r zE`dJ&18oCQG0!NIUSJBzO)7LX;F4>pjRSjYvyJYvpX7o7TML3D0_=);mP4q+O-9C) zx0G%{6K5hk;FW#9-s`dXdH)lhnrB(PRz()1zzjjv(q23$jToi3pGqzo2Mk_sY>az) zncIh#TGY1Pwh{)G+zMLc^yf#+BxfVwVq$4#Fz2PA3kGl~9U+y?aO~sJ^B*rF(6c!W za6Y}p1QVLQDjHJ>>#ErVl<}J}b|@|~63nlN9Q?Jfgpk@R~5jWb>L6uLK4_v$>@<<$=IbGG8yozj!zJ@|IS*6%?~z(?j|}NHnBM zLWJ5h-g+pu>hn{(uk-B`jNyWuXa7wRgR06 z`dpsYJA~>V-GeA-z#IoJzKk97i_8icniEDu#KjW3{u~r5XHSmVXPeDS13kF;d#g$O z?TJhMmyxdBxyBXX!BdOTd^C`FoO7k-B9Dzi=-`uzxIyq;X7c+O&h!6=wYQ3jW9y}2okC)Cm?AKPAtUsT@^q+k$vAdUh7iKzev5{^-zs|0X{-i z{a-D<#^&=SykWzhw$V`%O zDhiqOG*AFZLKX7{ps3^0!>X?kHTj((?;JXnEMG9VFW?tqx6fqLcfcYN3=8mKb@n}; zRj(&SS*ei$4jKVG&eH!KmdFSykBP$xMjiVB3PvPAjtBw5swN9jzUZ`5Bhf3aazjhO z6m>OT*fiSfR=qkU6!r@xXAJ4ZE%;?uI1ds8bewM(?C4V-y#ml!Q1zT;>$(uAP z4?=#o4FP_NpwBfn5XF7Qo$*RA_iey)3MZOy{GM^j>0JLspgt0eY1e9j1aL3W>6&sn zYT$a7p)IsSaqwJDi1&c&VEw}M9e0wOe@;|dYE1+ec@La?&*@X4A1*q>ccvkQ5!AA#} zBa6gS=>se@29`m-2{piPYVj%PjwiyZ#im^hpY~0D&3Sexvn4T((rrPELGIHyX{mi7Cr-IiO}h1NHtYKEy=7F z;8wk*7{7vrOOyj16sAZ@d&b%ifcAKO9?0cFN(uO{?G1TXFUyF|qVRwoasycOy2@5& zF$}EkDJpkhhx8+@tfU9aP)~Cf_vN4RF}|(Mddj6h?K(_2k>!&Cj&$FY87q7Tk~ssj z{qf^pUuRmC*ApAH4|}B>MaZj+7?{%Gy_n=WguXlt1V9xv=uNOE68-oSS1_+L6np>^ zt5*{NAjAahQU$H(+|QWe3eT=nUBC$BIt|`e!GbR-vI^1z@eHh;X#RJ#j?6BNLqGoL zgzy>lXA0Wbj*n6vB;CNhKwsOLBHFTkW1blIIUHz)1oyhv-yK78I`@Z*;LG-gV6&+) zVNVrQB3k0ii;u01Z%yL3X2%U2$XBdY!1eozuaR%W1zbP;&&+3P^sDoMOnUCO7UZ@= z6Hv|T)?Bz_s%oF0_}pmS}W>ZIaPP-|ID6d zA!)iUvYip{XJPvzDMlCa-CcJK=+aIwJt&QOHC^oXRmUUhW17U>eq++)pfA36*pHLb z+yVC{oEVs7L4}ws5`f$+PslPHS)r-w6Ib&a*k{+;<)Vz8?B#a9N5VcK{R9p@%hs?2 zEwR?8u`LaV943!eV?z8Rh{Sus)7!?tKw#LRbvOvI-;XoKAW%(Zc2a;NrGQuE^g?4A z4bHv3T2bLIEPv=2KKNOna{=1}cW%wlgM{~yHN~eR4>!35QygFvKQoQS<6ps6`_ycI zS;!{;ZYt={Z3ZRG*hUVD5ZPp5T_<}d111xz3a7(U4e)^chR|wgg z9kr&a9Kf9L5%3@{KUt6h0&Ui5{D}f#E^sLWViSHU=xn~rl9vX?8xN=*A;xNIIu0w4 zw1*}KcVIEB`JJ!LUbVNb(OCKefx;StlZiQlg%tGMU{yEAo^zNvK&{4m;aPsuKu4Os zld6!@lJbQCBz6$Lhm(}Ak55MlvYHJ1dW0{xvGlsBR{?-M#v)tL>#q<00> zlDUnW`#xo!(3Flxnh=zWz}m18*SUI70G5kY{R2RTwoo@&y$#2atvf{ht;J0_u(KBcJfI&!VYE&9(hta*=L*EY` zZ}Gz3<~ZHq*K+LXjXI80T_2j;@DGC`@hOAHKYZ*5jZ&=Rss5Q%ZJbDjWi0sx%O(-r zkbA9U5u9Hwgw1HeBI!#ATUZQLB@w_zn-PPZs|2Xaj(d4q^?9b1OFn>S;UXrX zn4zI)4W@6?g-+V)9>%RC3iHXKu^H1wAGkD~`l$xRxhAUo1JG9TY819DC%yvT zGzmQYQy_9_$MyE3uxR9eFw=WJrntV#w02N}0^|k;|H@NFNc7)ufDd&zcq`a?F$%~d zeaV7vk@}wsU?OOD2WiMMOJ8J;`Ed&Ng7U%**Oz$p8Z-eC@PgXzb zpjc$Qx*|rwK&JUbF!Zdlt~E_VG46Oog|JfRbRVQ;B|7>U0l#1r+~|^Ta?Xwker1l% zsYS0l(mF5L`D`e&MYi^WpU$-(I9ml7#dXg8yyni+OY;n4rLFFB`}5OQ)?SKi<*C)O zhwihOIa8uTZ&G|YL~R!TJ`3fbN`IJ z%Ej3FYs=8S@g-NWKMhdQvA`#haN1kH5}1#PMRSgFJt`5uGwaEThok=B94PcR!8ef) z4O>|q%RErd|IG_v?3eHe0|zD|&YUE4fENG4>4fhUZ|LT-YAOS+jdg2^;06o$Y$I)p z=I2BZWCU$xPBApM6)z)7YGTF_qZ>yAKqSG`_(;hC)P+Tp=ZW^3Y5$|=iCy#nr_xR* zMSVOFJ;H-IPb>82*MXTuKmREiYGcy|dDIT;7yD4!P=H0Ir2v6pPJf7Q$ z1s(}hNMblMQ5ql#tDo9c0Ng^~VVNCVZ5mDaPSraOscE;d-jO&OefT@7^|(3|=oMYM z@S6H?>Rykc*QJ6F=vcrXkH!bPwN?ciJ@c<{%J`E3K$%-hP;D=|F#`A*u{Had77R8u zPIf0Vq?T*NNAIXLpvPMs^EJs%tipF-JSY4 zBV32Hz1~f~G3bzuB;|J_Ti3&`)bFG~MLz07awP3OBooR#?I84wG`V#WFgX<$D{Y+C z*NvIwK1z6=II5P6-riuKkT64{=;7Lh_5Q08w`$JPbcAPkKTyIWOl|M%!~hbE?r$Bg zH1IAIEX_Z1f8zGucXYPuF+Y?HsL>U8@0TvZ+Cd=a=34{<1V28HpIY|(I#Xfbf4+VX z3S~4<$^^#F0f=)8Mu^>lTs$i9B)3jaRR;_DCtaYB59*sh_pk_sjgjxcnW5O6u ztn{fdfDO8B|6u*_UK!KQ9RU*-T4HPGFBxILx&BV1J2cA89q?NQLu>lCGvHi3G6NqC zd1b#f;E^T+>=|f@VLtcXlT$6~46~zho2Nw`Cno)_56^F7KP+5Fw}DnQF%@$>pHCLz zxhxIPd@>=uG+<> zG-P6#DM0`3D{c;whl|Uz`6g;#FBWur_1CxgP@uE}Wd#HQ@JnyDieO%k@`zjmD-5K` z7;gk>@~Kz>TJsQ)W7L4MoAeVfruor=RIIz?Y-rJNjL9JJ=DQIi0sE8p2f({3j=)<~ zdA`(jS@a3%0idZVg*Ywm`xOI0Zy$K4CMVDEnm%^XoCy?KoCw-mLwg*~E9W=k4oZZI zc$p!<$>#vwsekG=Ibhw{ETEekEJ6lUCueJNk>U|{Cqa++cLNsQC1p>NYr;JvyFV!#-21dWZX3YD7LV`mE zWwfgJ&y(Yvc6fb7n!VeQQBQdXgKrN%*sZja`~w4F`H$nIp=Yt@{v%_92t zSJ9EHONDIY3WRJnVthzdih&#YDguE1Ynj6oEZt4V9q_i3lKg4>zC9v?AcLMN=tMjs z@F;AhOF1|pYicy_fp17Bx5n!o*DmTKH748I4X*}mab2xwOoax{smb_wPpMk}NwN)q zoKD98CPx6!PxQ1EMzrU2l$IYkP6r%;wLp`6dpBS5fMf*yilV8B=J9&d)wPB>UjqiL%Uv>GdSS-RoC-$EzHQGd|vV1OM07LvF_BfWaUQ=oT_# ze08vP(f2(!OU_x_d6P3aCP=++Srf9Jym)oYy90m0@S)GbdWHW=%m2?aQ$!# z=5aWXMlYwRV2$rAuK8V6P=6MXnS%=l@PX?<>`xc9f#&>u$I;>U{riW_T!~4E=0C?!ccjep*k@-_){LA5QLUz#mA0i73eC@TorWg;c}nAzz_sT zPQW$pKuI{O*7&lC>v3?&1#Cw zK$sCqdq>*DivW%D&6(hWU-ttMI>?;ny~+Wmu@SHG%87LeIa%SXuHfmdz+Pt%7(UFm&E2mKWWm0Q^RY41JUm>N5@X`N$RX`eG zqDHW>0SG2-Wq^U(r^bgf20}Tp>_Dt@Z|=NB>SkVT@*~5>#%>;yP2V!}=gov!8?|5Q z{b5zWef5X};#}}}85RIsqP~EaSYK3;Zq@pS&Cy>hYRaE;%9Rl!ci_+SKkfv3KfJrH zC8au589na&?#Ka#OX`>MXa3B!t$`@*;&{MK{Bs+Vb_9op8jHxQ|2<<5*xUh+;ifz5 zA0d7-W;ZTuuLqHEjRf7nfjjXR+KxBVTRmqjr|r$wTm54mF{vL5^i-=5b_&@SD@Vq9Gk;86G3Q61InUFKDdna% zX4MNLL<`=j4hJ19jCcF;0nkLo4}N{VfzCp@m2P0yk^$3vkD1u6)c^#>B_VNFsCxxf zw<^=713Iz)dvBt{3qZbb-x}=_ai4~tz_=k z=L95(#>^ZfC|{yP1->iy$-4&k4;{)F=o$c8b2nQJ9pcE=ks0E?VCTsON-ZFVy!Q8i z)a6A++o(fmYAE1@MAk=%HC+tsKmI^e`9%=*E)SVN^HPQWF{xAr@bVvUAld+AO@goB zn=d*5?WL_B?0HWCknF=OG?4R*8FTNP#bevzj&?H=-^hzyyWwJ_{x)kgrW8=$jI_?{@x}k!qcq&=;bA9pHS0 z5b<$eH%d#{xUNOG0Uz^v*W6)MOTNr2FB{7+ezDa;IT)nMA?tc3gMlY}$b-p?%vw~I zf5nF}ERyACDh!NkZiD>DF(QDl?&mu(3+QO;pKfAgzk&;CLF;`z0yfMJ%|r@bc75Hh zR{gO*Ktc0_%^l#p7&V8xh!#$I@Bc=cFMfI}t-s`hc|s1Ge4*^*#QZWmJ~m2DU->GE zwOE5+$r*hiYE|ypq&tcreZcbJO|}49z$K zj8Qj43B$%+k*nVPgXrS(B|)vTMr!y@UMt?*@EPo`G{6>#bmo%-2~CGTBaR!a*3&sz z<}hpO+JWZd5gnfu1(ErsN_Vt@S|oWnW0oE zL%Ogp3`__lj`yQDu^Gn;z{Z^CeS1hu*$U$$IsOeijUOPv!G#a1?pG0+E_!c`-V?v+ zOG|)G`qKFHSEF=oE|N9MNmo@2!4FffHT1C%(%V zsLU-49i8h(9sW-zykKGAbI={Zh3pB5yrxDb8elkk-?5#~OOahY3!r&jo1jiSwMay$ z?)$$956bMMvCLw58UbOieN93jTSYTcT}8+X_NhZPs@RG3b*soOqy?upGLEy@%>ZtL zk{;Mpp^u&n-zxAAf4$Unf>xbT!r?b=jI6(+V|hHufchY98_VC2viG!g|4JtPQyC`U zajlLA-uHGOF1u_%##2R@92huJQv;B{KHxDJY(SQn_fZG7{l+1W8mc6_`U4Or*+>h+ z2SPu(Gpa+KBu3vIoLrFCRz4OmRi-`N>xSNp0c1}o5d42WJa5YO#=z=#hVLr@xF~@* zOEvM%wwE(3kB1J!FgO}~wUml*xAs%%TNXr!=9O!&#x?Sh9=*Ljtjh}4;uV*kk_UL$ifQTm=Q2~s z^tHM7dNcT}6#I2!3UjaX$TnxK_A?X1`)c%KHfGX;9o-3!w4e#`6WN5Mpl7GCG<`78 zsT$}s-|{5D!s2sqU_QPLmD;#|{1zfi(#C^0;6`xD&-J>J4`o4dG5ua3|iEG zFaxFUJUJ(jsSW@p1z^+A&s)O1XT^a50*%>ZN+d9u)6>(0OiZW@45-@11@05UXIu)Q zV_tMZo;|wCzfg|&>{369szU)@HyJPC1$1g^$zSl&=_v%f%{{`I)?OLu0N|Rs+M2;Y zKTojiT32}cH1R`-?geX;wqq$9MN)knJWMYb13jF9jKgh37Ugf2(`?RLk#$eo14FNt z7i+dr#b0~zpl~TPj9y+Rw-vADJBz$$Q4DwlGNi3vGJO@=6$33ZZF<}q9%imAv}tK} zn_~ZkTbeQ0+B+xaPm=6(b&JKm0xr>&qwt-zCcQ8bIWvTIS1F?2?ifo?Eeo2n{`hJu zz_?UdmM!Yllx?Y^5len%l9+~$Ih#h4pIoq7p>NB7M%;VvK&E3oADorY0bR%=qq;+iHvJJ_^D9_Ssl<3wTF&w5H)oO%hXmHBR;Z%W`VkNG^j6VmWNKuyF;Ix0b4+c4&&V;DnNx@Un8|J{Uz45y5fvt)} zv#cxk*;Q2Ob5`Lk9kh|&O}7m3nAeU1*5xit(+~KYkxRvYHHRzuB86{(*HVhmU?u7$Ci{_wA*$>I`NOEOmP$wRs)_G59J%Y8QM#IJnRaxE0 z$2kl~g<;?Xz<~28B%Yw*_;AtUDulrKNx6!nE3g1JPFz z2c$_6QN3|l<0!qCi)T2h$(tPBlqo6~XIqRqr#P$0*XNT~2)}0o_r=_>LBann1j`q~ zRGHhTPk+7QcAcnKY!hP{2}Z$k^(jUx=5~qVMe%3YV~Ik$VBiszQ<`QYN6S&{exo7p z%&?3m8TzDLH;LDf_2k-h#V{Lc7?Xgx%R!-QOA43K_9QX~6kkLkmnKAweO8@kRKN!F z{O%4;##=>I|2K~e-qITn_%9w)D*gF#OgoZX1|gP}y$E$W8ABz?9$IkK;De}qhy%Kh43 zi_z%W7gP>;)2ge!WQ`x_L0_Sm96bht*sG*mhxPwGZ7{LSGT3`8hwGmVc0=b7qu_Fq zNgxbFcl$rdj{cQ4_YQH9U>E!mhbYAqBpwKkC6??;rJ%^LzUzVd`oR&p3i~fK@r!6< zG%`Vcf?h;*jz8lrrK!Mg|Kd{er1+_+=CU`#w{OshUukd-a+WcEMWuqR_3_El1m~Y? zjj;T4@?*>$XJ=i_Y}P~Yr%Jos^yvN1Mp%ZtO^dZ^37Y3d27)YVP>Ra#;qxjo;#g_? zG0jFy9J>ZPeVD|fsM*~0Px#GSxv+c}P#T7ApG{$*$dhLSPsS+&Si~`IcV#Zf??rlC zxlXXElA%o_1^@E(Z_nbT4tOVI8*$@7s>wl;dI{ns?|;`{A=*bpK%rEN#H&wH$ubbO zYBRt^JKVYbKGZjWD3mC2f)Rwe~T>?Ich!wPKkj^+cAV}D%rA6W?)Ed7=(=am#ROKtJ<`h$7K z2D!HTk7l!8QE!c$-?R}qwiZ~mwWuv`uJS#UaLK1cHW4|n)`&G~q(Mh!oGgT8{by?85E z9@>TdDy8``*TV?E)n{bELWPXZ2W;ghjPSrPI~>wxapeNdptxj9k0y=;vy$vI%wfbV z1a@E{h}#Gf#NvE^cP@zW6;WnAUr~^gs$ymT2H=+GwO5xh8A6h|SZ2BpcRnUj4^NKM z8eB1EdpNf>?=HKwY|SIiGnr%;^ZM_aZp_fcaq{>Dwb}xRl#ii@fX z>%{`0O)2`#L8iRO9X$w4q!r00s)`ole%emP^z=mEV@P*{IR4OU_Bk_l3yD(J^lu2PI{@+>@Lj*+SmOwSkdFhF7Q`t`yRZn}) zbN;2iKIrznf*z^H<1c$onH)aC(WXUv6zDqNJa*7}wcqO}YjYuqgVze6%HiRLC7(f0 zj)KfP2R(+c`B^^^Ja(Q>F)=aD{Pw|wNoc32Mxw0!FroNu(InVKlKyOOZ(*a`PJ(?D#;&mQsDlQB2gj9&g`Nr%q36h8sB;JGD1_NPdWqo(g4 ze)B1SbEF}yd12}ua>I`7CjFpG3z8jFl=g-Y3{Jnl?ZCQPW}V!HXKwp^e!!l-ezay| z+t0*b=N>Qr@Uq5!D5Xx&c2-#e+q!*$0gFm7H8Mp_Ek;vNTyJHNEh_0#FH*14J)EL$ z@GEM!Aj@0m8;b&Y3ZuD-ePu+e9o5KPf@uec_hV1Yky7gZ;TLXFMI|FEitR<+6Vsn} zCc<*x?8j^UC~pl^ir9V?QK0pJ70C3l{l}jX?CQQHk^> zrLKv3QQc3UGW-0^;pW$^#(aTh$tL?`c%I#c5bW^NI2L$uT~JsBL2r89M@`w>d=>hD zzI29%n9tD=t^9n(^qZ{LlpfF;0;A0b)1~(a?zi}V7To#B;!VvgzV3hbmyh3@zZuq^ z(SQ@tuAFU*(7u;vpZ&^Ho{$%7HX;J!6ABLCoTVX_Tj5 zN0D6T_k)^kD*EZ4%JUuE7|u8RX@=bb0}hHo`_csso~(Pb-(IhFDbSBU;sZ=yx3K4u zQWYTzVH`Y}eAwkGQ;?5Yjr_yPT2-F42qq|BDv-W5oLB#njOh!kON!6fz^Av#hE2|G zaWf?^{?X!!F0CWWDy>lM2%b_2D&zisaLc0aL?n!|<2x@spXX{`D5|=B>3h&Rj)Fza zBMAZt{BPcoOYP-T{g)H6d;*w0|H@X7J)QlCnd@!?vlRy!l&gT($VFyFxo7{Ri1 zK(D`gt4EZP%-lzefp;UaVFz)0H(_iPg}HVcxjG2~GNjOr_`xr&y7dgd7qgI8*UE8cLMErDc^0YL4VSfwLbR-`KoS6bFRQLD;pD^; z8alA&E<%olpE%EPCB4Tr?D;=@vF<=b7@y6Pw3Gqez?-z0x6>__M;Dmk0A8Fedowbn zaz_mo(^0>iTO~LilTMrTL2TWDEb|Ip#Q0j+F-Jp|CQd~`sh%=L?{}cNqHsy}ByByO zir|pM7DMe>1W_}UFj!h*0zuc}<#%c~Z$A%24Hm-RV%$A-q{KBfCF*p!KhHosh`qlP zHpx<@y&8CAYE*3EBFax*4sbAYRf%8%{Zw`Y$SJqK{_lwf3S#F4%CC6%0g3XsyO~q1 z2zj{)n}pGFmOoPHyS@3o39gnxlEAnSr-5at0kbfb=O6a%igVG-y|A$+Ty4ac zG?!=d$6>|nuP8_xy+)E)J`D9OTeSmkYM;snw0_NkDwy0iPFCZq&?CP3S-Zez+Ec^5r=~{1bZN19noEq|j&TLJHezKtPIK?sTUL29j%aP4 z8H_j^m3}%4dFy>j^G{yEJmP^T6W!RL!QpPeTMRKAIkTc6n>dgw83CS_Nw04I?hIcl zU+gy%@U3Ru;gc|NWs6Boz8gyxPbnF-DHgqP8B1&p=Tg@7r8Aj*kG4GoyX-T34-e;P ztsglw2?yUpWcjWm;Prd^STmVwm)+~OUgKZOR_Z``)q^`b95KA@AL;B}$54I4nqn8z zu5eaerMA%E4014+-14|G)Uqm_YCdx!_F_$qjxL~ns?RU)(Q+Ad6mlbO|41ux&DmNv zbE+96AAiK*mIJ%y8#8%uQ$C)dQ>dm8YWRdJt0{BE(Cg4wFqMfKyZP#rSDm=13BRnR z6LAz?rBBzeCvzRp#tePbzGIbhA%-26jDLFTZCA89lkTw~9A|2CS zZ!aK}c8ABjz&@DsB=xi?MT{94*|soXu{dW%*-`ei_;WklS?etv*|MXde$jJ8PTXEY z)cSmKSgQb25G{S}hXi`OWz9+h=cMMj81Aua*9`-uBB|qv^vj*50)Kxa4;JUG74~u6 zR*gbaW->dyF*d*8IV-dw!n z6r}6GLD0#>E=R>lHg*xS19PCq1vp0B*j~9zo6?Zk9c@Jn9pjNed(j?*U%6+W`DMwg z3v3?A6O20~g4;yNZF3NxHQ|0U>$w>IVI4Eum-LPjtc}r|jjPSizd*+@Rxur$J(p|V zxY^B08%ZO-VJ@$viH~TR;=Vaqwl{Q$jmIRA)HnGFvz4Mop7fHRtc}Y|r1LtP-iX|X z#me)jMUQ%-a@a}R6|xF3(+{zEOuM&PiSj&>oj-otkJ||yqIw{Ec4#Fc3N;XZ&dON753)! z3{F+OL?&Z>i_w8j$f@5ge3^abw2kgdr0XozeE45vaRlWQB1YtlT%vMmR}x8TM2^Dd z)K^N!S$Kg0YBYBa`dB|kr&1QjKH_c-A$j(#p=McSH^~;fjMJ?NXqP?qO1x#8?X)>& z%P_yHsSg5H8MD_B1CfDx{OS~aaik%71Jifley`8gQA6g~ax>O+ne5b#q}tcqdM!je zc5QWvFVAS*{C1kq1)*rbSOZtKpmQWCX_wuJ_$It74c3y0Lb#w?O_;RDGUI@zkUlq^ zZ@W!zlj*>){P0$1_TcrDRrbT!0`LI&GPezP0e^3Y*f6}cE@hC*K}RIdUKWS}UHV%> zBdxpQ%wZZUy7`#rNlta{P2E7|r_0Ep=97v1-KDg~_WR|VA-SQ;AAC9OPE+57Tc*sv z08Q2M`lKavyFD284vCkh4$mW!2@GIJB96! zKc5Sv{8$@8XJlr-eJl(VwP#)Y`U!SUq_8%4Y$3crupI}n!`L8PWx5%uel%NnLH6Kq zr(`w$EUaxRGwAJ}BC+}BrH0c=F9{m_TE+Mjn#39P@Mc%2t!2KB4LJtDM8J%oZ%mib zpd%pl3Gf@18M)EK;#w8~Q+D8)j<|RC=3Vu@L{ccR0`xX&6xkO=S8ELy)DTT2ApK>j zpIh_z6sX&q2xB_Z_BoDojGVIIkF{Srdk^h{l}#qIrDY z%oq;h;=U^7-vI1Wk-~0 z8l(IEq%(~vH6JC)!$;-ZsK&b$}SK%pDBWd)jN*1?)f0_ z3#ShWs>WO*BHot>(Dz z%eSw+wNwe}>alHDcy-N5B0Dqf>BIv-FubY*ec-b*1|H&`jDzU8R7OsrzOV#;i_c`>ot%o93O+Y5-$Pd&SD`Ws2?^%Sq%@b3xlxtLkk?HSfa7 zn3%`jw;~I~HCL(b@pVDYB=vgv^{EtdI-EWj1vd9xYu%mn9~OHegw0%*Z4_Ywx=v8{ z2@T(CZORq3)I@m7Im@MpC((Dal+h+e@drx>YC#$S?}d1+X;4dth9P*|7vKI3FIMa zn~$8SHg&}E)?4axF!FH*eu!nVkc}A8XihL&-v^@}5ZyR6W&~22Vfx_^KHX5Heco|CEUa{8^3P3yMRj2UN+P*d%9mz zHCJ2O5m*W1SYzr~LH)@cUTUk(sX(BXv+Vwd>DRN(Ep3WX5yt`ti{Dl=di=^-%bQN3 zk{`|MPZ!kYP795gnuo=Yy-t%j$W+THP1{dl`&`Xe*$p2G#Yt}$G3q(3Vh_IjR9i@B zI87_47!N{QPcGj}D40G8Fb55r+r!@|_c`_?Qzc{X|T|qv(G8$>0Igv(ezGOTG zeidcUpd@?6l=f{5v!Sb98r|F~O)(`7@ocrn`!;fCsKKfrfhRoa?T(EXa;3|gfH$EM z!^2pmObLmAC!)g}o`6la=)7YHD>mL6l%^m;A2nO)jR`VvFYLAL64or(Y$G>l^$NcFZ)7=s40gXyOYTosC8{Qq%{2dUt0H_ zo>mC}fzfb8+`H!%rZoM!x z69drl zTp0R;I`;GOzq_IIx-_yU`KPdl0$%Xw4+C+jyTk1?hgx-tMH#;**&ec29iuLKDgsB; z!dh0ejxrD?rEqf>%&WYeQt}Nfw3A)6@R2eJ@z?Ss;1M<-9e~}j0y?^oF_q4N@a>Km|yFtVJ&2iZU*W1}p*_7uit|47=lMe64 zaVhC9jPosyGFbgm>gl7+wU;7}*53~=;Ul8%Rp%zoVUUjAl9a6SpS zU<0+Z=1p&(Ddkb@W4a^}2KyVrnm-^Z+Y zSgAZtjk2NM8{6|^$RZ$e_BalU5bb{FdRi}y5I{SWGpfMo`b_({#~+Nk%pFbe{%7wfrfQb`+?XeLyBe!tH2 zC$8>=VM#RZ}m=WWwCI@K4rjY*RZ9nppI-Th^sz6w9=3r z{&02S*ML#@D_Yt~Da+I+OBUXAjs>Wfi5jA)0R>#Lmm~}SW@nb|syst)3^iK5&dj66 zr)Pn74d$PpuA{G8uf43WQMPG5N|jMRi>yvp-dda1rA1_8HxEFV5Tpp?6kPrNts&4z zR3BUqffy!b&*V^d9U73MbeM&*k08QM|_x33`wFj!Jpi==J}9)inAkUhpF_AVxR9w{o+%rF(o^f314 zVc0l#k!OXT*PI!5yX}Hq=N);$uop~rS1@Oh*uW@d;9q9_sGIxlnOuGDXfRTz)@A8K z;=Y{nHs}L?g>A%{9IL%d8){|=P)w`w;Gn9m%gzs6<`PvZ)c^hIs%EONLrCaRkT7S) z?PB}dxjC{#Ow+PZ3u@fZVANUoj^&Bxn6vg>E44P&(=m7X)y`Hh&!3jrFrbCY4+X-$iw>pv#$5Kt%X3cX zIWi5C<$l~4yYFv`=9cgZ-a&dFC*9u`PfNL5Jx8*H6qh|n_lh-RlZ=R>aaSv4QwBHN z1=DD4eT|Gqr-4zSn)JJ*`~Q4llYsfY)2%8$!I<(NZ~Om#X#jq~uVHZ5h4laX zzu$30O#tu-sicsARqg-Aw7siO|34lARvUU%#2h48UTUms#>K`b9Kg7PX1%=plZEO- zUI-1Z*Vr|B3!6q3S@qt-GS7|KW8k3%$@CS!*$$79=PmkGy|JtwJc-wNM$=uom;E4nq#z<8^Ipa0mWvt9h_k zL|{1>+gnh!&aBx8fib_e<9X8IFh^3<3&ZQ&ZYi*lOZdR0gg%2^t>ifZtxfwSXHPrv z_B=$yRdF;}<@P4nqm3)W*Zaxm3Hkw7ES2om>}uiqikT;=E-EqQwI>EsXp`JD&j5$l zlP4{YlZj%kE@v-yDalRBn@bfvHtglk+p}PPMTzb*s7>}lwphSs`ow}oz z^&i~Q^rS3d^)JJs8PCIG6D2M;3nTmMJ{9qm`#Zt+F2OnI%zvM58y@Cdkr8+7{kr+f zzF1x)c$}|@iwE%xKPf!2x(!g~aV9X3-uSz)HjFKt1xKcvJ z_N6=5!YO&|>3!UIhjwpdDdY6{sbuR8PdUMMp*m&U)2q%RnRg{kL;QNKoCfa=i%1_^ z`e;A9>5ClVfkgY}2rr8b;hF$nH+^}s9VRMjB-g@doYc|Ix27$u7f$zAsP-ohsFGVF z1w#v&HQtrJ=^<`dv%k#Dp>=)1#q4pA+FpIfqo!!8{`<_EYWb@?@sVl|RA`pzV`Njx zm8=Ee-5gB2{ZCDfF0ljYPm4WN_mAO8rE3{7b=J^OnmmE-wBP&J*uB5G-#@-->CNiy z+Yfl(@8vq-|Mre(F4#VQnucQ0SHcff<{I33YYZOx_=S5m%aN|(G=j*A znsv>S)j534a&NLvIhcV2?PSHiG=WkqUq7Ah;j3(Hd!uZrCEH*_zmK z_sOGXrgy&ue>dJsY1aD+GTg3B`N_h)WA}g+_tpr7BwBHGS1no}+pE(Z4g@a$Lp@#l^s$nXwSHJzcoERc^@mmI7t zX*51WM7SL{IJsV1&~oo?vI^m&Q61xy@gCkq;S4KoUN4bve--r_MIh|{RH~GsP*6dX zytP`iaLFLk-twEPM2hN3-JkdRYt21;l3i-hjC1;t z2kY*R-SKip#d08Ov!`vXpK0RUuJYX}W_P2J3g1b7t}KVrmKigB>EoN9=AXySPx2Nw z46~=Y{ZCU1sCKk>%g&!KAj2QFOB7>SiZci3@bY}h%$Z>DZ16FWLi0H+NwuZ4MVp9U zjYf7MwmGaU>%9x~R%?>enolJgO%Ou2D<29fRARRn?#bCxR8nw;Ca%Vf`Gg>gBzTSc zjqE)S(ZcLXLNZ)X?^f*@hQ3iyKid+em$<=^a?aXxb`YS_aRnpIO3r%S(NIaGUKRXm z+jqy93qZ+Is9a1PXD7rzThpKBE}dSy7K&=jYF}vy4tIC4G1*XY9C!1{c)bDx?j4({ zo~Wzyvc0KMfB!JE9jn=6mcQ=Z!V%)KY^|mo+H|8OXWB;x%p14O?Q1K}_D2Ci9u8jx z1YWpjPZy`=YRYSg|F81C`YWzxX*WQECund9?(Tzo@BqQx1Hom0!3hL+cZU$%-CYL= znn8jO!5LgH`Oe9E?swMx5AOWdwQ5h-uG(GQz502&s95=9M8s(h3{D8S+y%+J(e(W8 zLtB=@^slbfmqlknvbr9+YlT#jy0Vs8KJ$}^q{3JUqzZ4|jdk6|y-vEo@IAEm_4Wg_ zeW7(cmR$HzV8dhN-H}PD5;i0+ZqH)C)*f|t1c-U_Rxs`22P(;u`b5UfV^lDKO{2Dl!AZyfZ$NuRAGIc)i;|WoBJcc zPD_B;NM9;yV5S+iJ;1#u7`eHl7erZ?*-;7yeeEkHU7u&KP+__c?uuW!V`SA5-QJgA zvz%9&edf9$#*oTN5L@aggvXDyCf%{4`-BRz5iEbgT~bmLCMri$w!FSJ7b|jpX!ABA z9`1IMJo$B3v2^~Oml)`J-4sE^@W}oMq6z{z7Iq5k$)ns|?G`9>hDOM~p``|jx-5*F z9QP2hMxV|OOK-k}n$ew{FlohIP589CRG$hInG0s9y^XKxigfCu+)J)Y)!@2}Q>&a| zSjPG8P1@t*u+@Ua$dv6BFG>`F)csvtHL z3rw8KeZhz{aJ@_`43-zk?x;+iDjA^NM{_+*@v8Wy0<;;F))`NhO zI&>pi^Hmx)>&EFqCDmac(slFlTm=AL@U`i9Gc|^;0{<2?lmLX!rp(E8cZ#pQhg|to zhFflRV^83{mZi_#j|MiZb5jX1T7EY;6xKgmdlz9;dbZcI7{`&VUI`WC+&ivvvYXsh z^f`7+SbnZSj?^KFMT#Rg{JPti9dkqcbrq}mizXpaL`Zyz2gu&+RDKEWa#vy|3ZKKq z@g<5iO#9-_P;DY*W}2#RR|LHkMuYg7G!vIu&z+;K6)|LWGPyIYLYnq=g+EQT5B=qF z=1`+sn_OL#nei7l=}qpY-|xx6TYe%{EBVRNv5k9XKs}r4uwrTMvLX5m%@Joer@9A0 z(jGJNtsWDO70+Zt^wp{0s!QNDQpx^XHmlKhvzXAZMtJ&(?qZxG>&hWK)zPitJMj-MjOv*?W*FT`2Df^ee^bx&uP_g|+9WGijD62xPItPIU zvDLtbf$HlucIRha;^bqR3EnUu8HeFX5qSG*3Mn{!*+%mgdJ+?9OVC_@xHjAvj``KV zm4oVbampbREXd$BT>ZKzWVbA^K*q+egT#mGd6WlaPc=(b<7H950UWL)F%b%0sVUQ& z-O|=CK^tP*_8v;xYid#78UZrBL=&)u7Ry8sHS}(6eHRy_6|#wyp%^)2n>K8j^UuuU zr~Xa8r{@EIO3A9`3_&{J**AfD$VUilcvRy9qt(gvii5f_TFI{TbHU8tB4pk@ZArdc zL2ARlZ-`4H35NOuvb|bJuzrESC17)VqM8_$HJ>1)dmHxiwl8#pUW3%&2C0${Stz1L z!k5dgZ;~{zj4Wjalr=1PP~ozVKZW|*ei91P9&wldYNo}&S|~M*LryEB=oa)fIA1-2 zfko@xG7h-l%~Pt>{b2|RCGpeTs~HLoOg;HcV=yUU*l*kzwR(tKB48Q?%jha(sio;< zpzPGbi0kr&QU&r{@Vj(R2ru8&V&mDmk)c`XFS~GyDyX90r<=( z#x0hc02;+#H7;h_B9NO*tILZ+z_c6--Gqhf2B|sS{sLX|4Ij>Wm}HvwZdPW_R;j8G zsW>S%N^J|P7tJxdCorkjDEn9C)mcq2aQD8AeB<^pkBmrKP-dmfDqqvqwC6kgJ(A%N zvPyc%?>@QrFBPJhu4O<5&Nu~^-u-tmB4Ym1Dph(<1BIW!)~(N_tf&ze<=iL?tFVnyYxk0n?Yn_~FvzDn6f(_nudoK<8omLiM%mAb}HJJ>H6uqPEX5(_Jq0UdadtiW~(I1k!8# zD!f7$dupSL9b50cCqw*t|}rAp>b6T zB_G?qdogMVEG06`** z9W|q|5`Z<$Vfys6oL`8(;W)B)nzbv6HE45DMYx@*s*^N>4s|oxo1c6(I@u9z{H14S zx|rC-KAHfF+lP=gnDPnEy!FPuo9W|tt6J~1I3nsAS}U%asImW{LgQmNaA+$HC_C~P zRq}WvT&nq2@;!NFhEOQrlyN7Ya=i6JujD|TF*P?cazlG0DtPbhN>aGiZKHkg2o7C_ zf4IQ5l}L7m(sig_b8#2GjKi|!bco1;D0uA2H;@4*pF#hO?09@kz{Y&~@Q}_~g2m!O z1y(Au>ntOyU4v4QZ+cN}t?z;|i^KEC)_y$`A@tPW5s4u>KFZc*nzn0Okd71m;b74= z*MTo|pWHXI?JLnD><*)R*!`1xj8j{PGGqq7&bTTn+6-J&QnLD)<$Z=tX>Q?oV2uy< zh^lYmk?!!!Lz10YLjjt}ufl1m6y}Y&yW@=>_hj{4=*j76t^g2?fTTrgE?XeWu-(@6 z6Ok+_bl)gewo)+R%7&jEMrCR7mHl96pWvWp8e*o#b-D4=%5Z0Zu7s1JF?E}~eWJY2 z?wlmOi34`U3^D?WIE6RZ>&C8x%d!MzAmn0LjnAfd+ywiE;Tr=LkVD$~P^g&ubri zf7frGe?PX^@d@SbXMPHUZhAMIA`!mA%?w}j@e$HBc*Ywy3oAiZ^dKPp%l+l40|_e8 zxY7bf*|B+qiti~#y`{?ME2;c`**Gh}b@YZR>cYtl-+rl5dm@B2)M4|@CC9D14UJ%l z-(YVq{oopqrbFn#E+VRZJBQte$+hE5lNP{G>6%BCc6OZN@i?79_&aBGyh+5=t}hb{ zsRQS}EU|j8j7>-5?ND%&k-XZ&RH<5ZCZU4y!4_7KcE!&-l^UHIuUmw%=PPa30$^mm zaVdr#(S9pD@!gUN*XNLiL{II`{nirGAH|(Fn0!0RWOqY6t`$Fr&(pGbqqG>-E?II| z7-&Hohx*eM*4y7{ET$>d=A;Hypc}#B6S|zczWrbZ-}8=3S{Yt#lkeK25vAo9G`tLP z$m&=S{PGRs3zYeW;wA{1_RXHVZ6lq_jomKKHQ`JX@u+7X)o=#P;i%)T>fXVC;rrxJ z!C|(@tv(rOohJJM!gD@Ut~=tBkMN zG|&+4>YDjL_9K@{SJPzQj?t^{QlAu#~oVP^d13aiZJYuCup@pmXmu4zo9mBlsCTWZ5m6|0GfKWJHc3sU8#wN zv-b7C)j@PeG99^JkQG@+;_$iWeQRT(-KZhG&ap@E)hZ|{#psFcsg<5c^1Up8U* z_V8jV6}V{gKI}n*UiS{G$}dI!PT_GBA;C0;p6vkXW;4M^?ifg{B6Ldte!S4Xzj_)y ze*Gw>tXKUWnaG8Lj=%Q=&72f2$su z&sd1OTut3E^!&ary?{$k4v_(=7dk6YY)1k~b3dEd<|n=INiWmxS9j_=k60V8_M ze#E2)ST6BqSqt_N%nC<_zaD$vbQil=6jf|NkkE2{3}$ba8HcN{xeH0TDRmXPGF+&# zE2c5F96B%>Mn4pnQ@e)lhBoz?lE#>l$HA zbnyR@U(uhze*>a@@1`1gu?O<;0RLKtn zT-Y*UQ0p5FZy4dJW4gnc33^rSX_TS89~-7?(-&{ROQ;b|id7zwLV`}oUKYwGj0oCMuWl0(0M?|~V#d8HC5@TJwu~<+!fiAXzuT&*amu}qrc)fNO^T1?cIK3?{*L-K zME(69rb^12Y-ih&4`~VVnwHr+_3tMH-^;gVZz&(vPufppAA3C1O=!32k6$;d0UcHY z{cJHn{h-mF#Nb}Zkl``LzRI8UBZ}){Z7%^sq1Ivz2dSqNkU+#~;rwtVg_&yN&Akl{ z@N_R_S!Q2ph``4WQ3MUcN=g(|3~51*omNceHaAQa@~$nmyg>X`7cGv*ZVMz#b26D+IUqX&i^Bi!DX5 zxy`Gt5jKF{WuiRUN{!mx)5|urkr<-q8gU=r*slcE7;yRkg7dY)wNK|_wgxe%NBA;m zh{N9*(`T6p&pmyhH+-OYy4ijQCt10f>ECC&7BBfpf*jDqWeNq-#E1$<6HULu zwi5MYbj@P%^P8+`=It1^zNjO$F}{<%jJ3Lj5^}8=R4RudJk-EV=p4^?!=Azq%{C&$ zOkW59PR&E2wszKBo|}Cdi32L8&P_yWjkZ0rolG5@{eoKcUX1gB4+rvLy$*h?bJtiT zTcuxRDXiAp+PT;=LgV;2KjaL~vk*#AU(u+((3D?lvd7=S5Sb#W%$2IdBECh?( z`C6oE7l&l{&X{gHq{QP9_Ihh6Z|6iaxr&u$FW)5;_EFe@c20gB;QQz%IFKxHX{SB$ zd#+5oW2oC7cKd^!ry}i6C3hkr$Z=1NDbog0u1~{7(A7F52~$-T~Q ze0*iIPNrG;p33#yqZRGdSLf8FDxm=+1+H&cE?Dj?Ru-DLo3ie--8guoHg7+RdPFW* z9Tg~QFen&|on?U#m4C|$c1TPQrrp;zU@EAh5^F^O9eD(yL$45ow!ZWM{RzP$LnWVG zf@2(On^>$gOz2n%()?4A&Da*lGmWe`p07tnMF6p%&NJvw3-+5O3)$>BuiotHjmuYv zX(+tc>Bz+GGRcH6p?9pt!~*kQM^bYxPX-K>(I1JVF(G+Pf(n3RbV9eIu0Z^ZrpeQ)W? znfJkN?#hJ;B@MTiS>6|5{2QCkaEz9myliG!El7Su*b(CRibHP@Yn!UfkIFsEl{MaH zIx;mG#!AJ8q*KyZkyVLYh(yekVU^Jx=+*?D12+jEG?-bs1D&G99Co)Pnn$c94^T++ zak?*Z#}`@NqC};xhyG%Cv;ibu8}P;NIY{+YXQ=oz$hBA-AgfhtbzzEEt}MN9h<(&z zM(LEzh;Rpo=iL@mpU%kHR5iC%rJJHK9>hT%aXY8K|>x14B zA*a#6c$v%X+A8@d#xaq zjS2gjp~2YnGCuwzDXd++KNzSF}qVCKN*REX?JubUx&GKx;bMA zEnSo=8VovgOftC8hy>2?!mk(U(4rJ0^7&l&@ zqLY<1_AM>A-Q$Gl{vOi*Z`8n_mLNRYj80pG;a7#f^rrtp26U$>i!tI)o?|E9B>cai z1+g#N6`vK_(Y0m%A*BBAZZh{?K69cJ*-X;@P1XHxghBV%vqI09zs31~_5E*n!T-M| z{33<7nZqj<_CRxQZ;Vu%6XaCp)`T2^J%7!&c{us9j)uw59;f^bi?Rv)pgO-Dr}cl_ zI7I|6PunGQqvFeN?$BdEd%O0)8>56=0E8h4o#$u}&cl0M#aH6*sm<<~qT zD{jYW`T_P%EQlZIwQmH=!XwXHT1E2!yJ(;J+kJVvCXMxD+`M1lsXr@e+>KDtgL zV}FU3vR^&Jig~c&2ZzyWYLDBM-WVo|TLzP! zBbMJ}q@F@}Wmfo7UoxYL`&47!m1bfv6Xmm$yO)AjevD6?EX(m zq@gi*NfK`2tTeprL4$E5q`z=un#DpW07OrNVg2zOIqpVJ;Zf-_z5Yg@__0J95=mG4 z(#M6%4LSn^vwb4vI6&-fW(T2fn6K^LMl=~Ifhmsm1h$or{!NU2<}H%KmFn{!hAYx) z|AhxRN{X#zpI&thdzAcWOsu-TtE*!Ozr%U*xSYY$e#yV0-}M=~9J4B*x76uLsKq(71^Q5l?1O=p$Q>dA{0sv3|`df6qwxP-dm?$AWutn7G&vv=uVQjAqSFwfrxE z-Km8=FM|=oVXdwrH9Pr@ct4>*w+=}j!f=5QJ2Wfyw%$dlfOk?*WHM(om6fHd(6fOk z^CAx(^7eZHVg-uw1&d|iei3>Y#*FzQ6W3DfHGb!l8?;QJCPwL-SDi;0+sZ`GcXCNjjgMlJ#wK`dQL1XWOq?R?wW_^U-xY-oQ!Q|{8`iu#;&?g0bzO_(xxW1jqZo=iC6<)%yZyS) ze*Ck$(&nmWjO(8dbMH?ARoNN#{|xdc?~uiyQ?oJwhx6bzpDBLRthE>c$h+1= zl0ZnSTJb)dEj4iA4`8aqR7RC>hVH%l2{z4ZG_eo0dRJ;etW(`cpn*Toyw6IpwBXiW z{7u=_kynMCcDf^iJoT!YYVP+fEg|FIX(4mxPlo1Z6HD{{>$+SPWP-LROQ}dQz2B&s zmZTL1ALQrj%oS*EmCXnvg={A^^?>OICVoe;N}_e_IP}DS#H5ztUC*>tq1($Efw3|aCB)kGrb4bkm@lhOb4qpq zd!>-BAVxH1f3R^VcdPDqhu`VeT~{3g2t&j=mgX zDx{G1ABo1E_EAl%JE7;H3UrB%D0T65D&h-8%dT~#z_}?1aEt7@nzJz$YQygC3L3O z6+%FL1=a71cDxhT1wD(I4oIYMPJP!f1j!cY$@6CHTHW$k!Rqm;IPUt4D$-%M+;9qu z`vgQLJgAoV`1mMBIG3cc*wbLzXHfZC#;!$v&c2T}3GIk}#PMI=3;2=h56igVp8TrV z`ky@Fk>ejd)nf)FN8ULc(>BV_O|G;W*+G3ijU-(7F_(y-QX(I+`e}+8-In(>%&%NY zR&2%Z4Z0qXI8@R#uelsGj11Udbst2hFIAp6TK3yiUaowyDghBjtIY?&CE7Nr9Uw`(NC zT-l<=QN;*+;Q8^O|B*QK13eSN0yDX;thVg?CNfuU|M-rui?j;85Qz~~3DFlXUXjX4 ziGM8pUa0$=BH07fTBZQ!XEuMG5ctOgya8&Qe;}Zlj4$D#T$c3f0OC@G&K(F%>7sWl zhrR1i!99To)4<>f5P9K^yfsIWlIB4D+XpI`nta-95ulSqlzdHe1Obj-(Vo=C34`a^Sc zRfqg^jEt$(UnG)<;OC-~nF5+L`B?ux?Q~DBTEnJ-q4y>ouQ^$q8Iy|DkK^OhtpXL; z1F$Z^El9#dnT+?m{&*3Njy#SfiMi^Zg|V_Hyq#&c$EbQN%D=PPAM9-MGm&Bxiba}w zwQquJ!2V_M^)xezE?I!Y^ml8aHgMI5Z08%Fw&`WhC+dy#X$@##Jd~us$_ogv_C!S> z!QX!f3!javxffj3=OJC2qNn_V{xM}s)wc0VjWCr%TUJd}ra<_|vX8d+@w=P|(eg2@ zpOBk`yirCjI;kGK48dzh%n7L*CrRQ1`pU%xWA{=YRo(3Uy^X|vUFiq&GuY+y zo7223+Ko>r=;Px~&PMpkzP=Gbn1s89+d%d-d>KRpRM$@)c;v+2LkZ8*FDx-JK_v%7 z`<*;N+T7>A<qDA&l5)1S>aOlblV1g$i^OcuSWR(xEJT3URX6NX~4i|;IH$i0lt8VJV% z!Zy<~1+vg~mA9u>1K{ShYR@}!4l+k)v3BtuH7x z6g)!BEv8$A2K=9CvL`~CdRliWNk?@lPkFUkUR+3(jW!a2jlEA-qo zGJ2Z7qscH{vBAHddpB}fkR~V?XSZf#(b)!Y^fVoFy&X$4x=yt8quW(Ey1ToGOK$j1 z`ajy$Sa9pTGUxZne_jF^bCEirLV(|0AnVjO8PCYPp(q63mzk{)0?9Hd^}`8($A9HvM8%g(?5j*E%OiYulW_`jvI%n>F=}uHjxMI9&z}TCNd9>Gx){xPfl7{s#3x@@c#gL_EFsc From c3ecde8ea3d07d757fe9aff82cb8e043f24ddaa2 Mon Sep 17 00:00:00 2001 From: marktwtn Date: Sat, 15 Feb 2020 10:11:46 +0800 Subject: [PATCH 19/22] docs: Add the steps of setting MAC address of DE10-Nano --- docs/board-de10-nano.md | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/docs/board-de10-nano.md b/docs/board-de10-nano.md index bc9e77c..5c2db11 100644 --- a/docs/board-de10-nano.md +++ b/docs/board-de10-nano.md @@ -25,7 +25,7 @@ Change the FPGA configuration mode switch as shown in the image\ -## Connect with the De10-Nano board +## Connect with the DE10-Nano board ### Hardware Please make sure the following list are well set or connected: - 5V DC Power Jack @@ -92,6 +92,23 @@ $ sudo minicom ``` Then enter the user account and the password to login. +### MAC address setting (optional) +For monitoring or using [Ansible Playbooks](https://docs.ansible.com/ansible/latest/user_guide/playbooks.html) on remote workers, +the IP address of them should be fixed. +The router can assign the IP address by detecting the hardware MAC address. +However, each time the **DE10-Nano** board is rebooted, the MAC address would be different. + +The steps to set the MAC address: +- Open the file `/etc/network/interfaces` +- Add the following text + ``` + auto eth0 + iface eth0 inet dhcp + hwaddress ether xx:xx:xx:xx:xx:xx + ``` + xx:xx:xx:xx:xx:xx is the assigned MAC address +- Reboot + ## Build and execute the remote worker ### Load the driver From 66a1cd6341f97995046e8029e968d10608f9d68b Mon Sep 17 00:00:00 2001 From: marktwtn Date: Wed, 4 Mar 2020 22:31:56 +0800 Subject: [PATCH 20/22] refactor: Replace port number with pre-defined macro --- src/remote_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/remote_common.c b/src/remote_common.c index 89234a2..fd5e138 100644 --- a/src/remote_common.c +++ b/src/remote_common.c @@ -74,7 +74,7 @@ bool connect_broker(amqp_connection_state_t *conn, const char *host_name) socket = amqp_tcp_socket_new(*conn); if (!socket) goto destroy_connection; - if (amqp_socket_open(socket, host, 5672) != AMQP_STATUS_OK) { + if (amqp_socket_open(socket, host, AMQP_PROTOCOL_PORT) != AMQP_STATUS_OK) { log_debug(0, "The rabbitmq broker of %s is closed\n", host); goto destroy_connection; } From 227974da9396901ad536a0d940192492762a8f1f Mon Sep 17 00:00:00 2001 From: marktwtn Date: Tue, 3 Mar 2020 17:27:14 +0800 Subject: [PATCH 21/22] feat: Change dcurl_init API to enable initialization configuration The dcurl_init API can pass a pointer to enable initialization configuration. Currently it only sets the hostname of the broker. If the passed pointer is NULL, the pre-defined default value would be used. The API document description and the test cases are modified as well. Close #220. --- jni/iri_pearldiver_exlib.c | 35 +++++++++++++++++++++++++++-------- src/dcurl.c | 7 ++++++- src/dcurl.h | 18 +++++++++++++++++- src/remote_interface.c | 2 +- src/remote_interface.h | 2 ++ src/remote_worker.c | 9 +++++---- tests/test-dcurl.c | 2 +- tests/test-multi-pow.c | 2 +- 8 files changed, 60 insertions(+), 17 deletions(-) diff --git a/jni/iri_pearldiver_exlib.c b/jni/iri_pearldiver_exlib.c index 1e8cab8..076982d 100644 --- a/jni/iri_pearldiver_exlib.c +++ b/jni/iri_pearldiver_exlib.c @@ -13,11 +13,32 @@ #include "../src/trinary.h" JNIEXPORT jboolean JNICALL -Java_com_iota_iri_crypto_PearlDiver_exlibInit(JNIEnv *env, jclass clazz) +Java_com_iota_iri_crypto_PearlDiver_exlibInit(JNIEnv *env, + jclass clazz, + jbyteArray broker_host, + jint broker_host_len) { - if (!dcurl_init()) - return JNI_FALSE; - return JNI_TRUE; + jboolean ret = JNI_TRUE; + + /* Get the Byte array from Java byte Array */ + jbyte *host = (*env)->GetByteArrayElements(env, broker_host, NULL); + + dcurl_config config; + config.broker_host = malloc(broker_host_len + 1); + if (!config.broker_host) { + ret = JNI_FALSE; + goto fail; + } + memcpy(config.broker_host, (char *) host, broker_host_len); + config.broker_host[broker_host_len] = '\0'; + + if (!dcurl_init(&config)) + ret = JNI_FALSE; + + free(config.broker_host); + +fail: + return ret; } JNIEXPORT jboolean JNICALL @@ -29,7 +50,7 @@ Java_com_iota_iri_crypto_PearlDiver_exlibSearch(JNIEnv *env, { jboolean ret = JNI_TRUE; - /*********** Get the Byte array from Java byte Array *************/ + /* Get the Byte array from Java byte Array */ jbyte *c_trits = (*env)->GetByteArrayElements(env, trits, NULL); trits_t *arg_trits = init_trits((int8_t *) c_trits, 8019); @@ -38,11 +59,10 @@ Java_com_iota_iri_crypto_PearlDiver_exlibSearch(JNIEnv *env, ret = JNI_FALSE; goto fail_input; } - /****************************************************************/ int8_t *result = dcurl_entry(arg_trytes->data, mwm, threads); - /************ Write result back Java byte array *****************/ + /* Write result back Java byte array */ trytes_t *ret_trytes = init_trytes(result, 2673); trits_t *ret_trits = trits_from_trytes(ret_trytes); if (!ret_trits) { @@ -50,7 +70,6 @@ Java_com_iota_iri_crypto_PearlDiver_exlibSearch(JNIEnv *env, goto fail_output; } (*env)->SetByteArrayRegion(env, trits, 0, 8019, ret_trits->data); - /****************************************************************/ fail_output: free(result); diff --git a/src/dcurl.c b/src/dcurl.c index 790fa18..c56e01d 100644 --- a/src/dcurl.c +++ b/src/dcurl.c @@ -71,7 +71,7 @@ extern remote_impl_context_t remote_context; static uv_sem_t notify_remote; #endif -bool dcurl_init() +bool dcurl_init(dcurl_config *config) { bool ret = false; @@ -107,6 +107,11 @@ bool dcurl_init() #endif #if defined(ENABLE_REMOTE) + if (!config) { + remote_context.broker_host = DEFAULT_BROKER_HOST; + } else { + remote_context.broker_host = config->broker_host; + } if (register_remote_context(&remote_context)) { runtime_caps |= CAP_REMOTE; ret |= true; diff --git a/src/dcurl.h b/src/dcurl.h index 8e8126a..3145cf3 100644 --- a/src/dcurl.h +++ b/src/dcurl.h @@ -23,16 +23,32 @@ * easily. */ +/*! The default value of the broker hostname */ +#define DEFAULT_BROKER_HOST "localhost" + +/** + * A structure representing the configuration of the initialization. + */ +typedef struct { + char *broker_host; /**< The broker hostname used in the remote mode */ +} dcurl_config; + /** * @brief dcurl initialization. * * Register the determined hardware into the list and initialize the * corresponding resource. + * @param [in] config + * @parblock + * The configuration of the initialization. + * + * NULL: Use default configuration. + * @endparblock * @return * - true: one of the initialization succeeded. * - false: all the initialization failed. */ -bool dcurl_init(); +bool dcurl_init(dcurl_config *config); /** * @brief dcurl destruction. diff --git a/src/remote_interface.c b/src/remote_interface.c index 6812179..7447cf5 100644 --- a/src/remote_interface.c +++ b/src/remote_interface.c @@ -159,7 +159,7 @@ static bool remote_init(remote_impl_context_t *remote_ctx) memset(remote_ctx->slots, 0, remote_ctx->num_max_thread * sizeof(bool)); for (int i = 0; i < CONN_MAX; i++) { - if (!connect_broker(&remote_ctx->conn[i], NULL)) + if (!connect_broker(&remote_ctx->conn[i], remote_ctx->broker_host)) goto fail_to_init; } if (!declare_queue(&remote_ctx->conn[0], 1, "incoming_queue")) diff --git a/src/remote_interface.h b/src/remote_interface.h index 456ea70..e25dd88 100644 --- a/src/remote_interface.h +++ b/src/remote_interface.h @@ -44,6 +44,8 @@ struct remote_impl_context_s { available */ int num_max_thread; int num_working_thread; + /* RabbitMQ broker hostname */ + char *broker_host; /* Functions of Implementation Context */ bool (*initialize)(remote_impl_context_t *remote_ctx); diff --git a/src/remote_worker.c b/src/remote_worker.c index 1a7055b..bccfdd1 100644 --- a/src/remote_worker.c +++ b/src/remote_worker.c @@ -24,7 +24,8 @@ int main(int argc, char *const *argv) amqp_connection_state_t conn; amqp_envelope_t envelope; - char *host_ip = NULL; + char *host = NULL; + dcurl_config config = {.broker_host = NULL}; /* Parse the command line options */ /* TODO: Support macOS since getopt_long() is GNU extension */ @@ -38,13 +39,13 @@ int main(int argc, char *const *argv) break; if (cmd_opt == 'b') { - host_ip = optarg; + host = optarg; } } - dcurl_init(); + dcurl_init(&config); - if (!connect_broker(&conn, host_ip)) + if (!connect_broker(&conn, host)) goto fail; if (!declare_queue(&conn, 1, "incoming_queue")) diff --git a/tests/test-dcurl.c b/tests/test-dcurl.c index d321268..861a72b 100644 --- a/tests/test-dcurl.c +++ b/tests/test-dcurl.c @@ -59,7 +59,7 @@ int main() for (int loop_count = 0; loop_count < LOOP_MAX; loop_count++) { /* test dcurl Implementation with mwm = 14 */ - dcurl_init(); + dcurl_init(NULL); int8_t *ret_trytes = dcurl_entry((int8_t *) transaction_trytes, mwm, 8); assert(ret_trytes); dcurl_destroy(); diff --git a/tests/test-multi-pow.c b/tests/test-multi-pow.c index 4a453be..1778403 100644 --- a/tests/test-multi-pow.c +++ b/tests/test-multi-pow.c @@ -79,7 +79,7 @@ int main() pthread_t threads[THREAD_MAX]; dcurl_item items[THREAD_MAX]; - dcurl_init(); + dcurl_init(NULL); for (int i = 0; i < THREAD_MAX; i++) { memcpy(items[i].input_trytes, transaction_trytes, TRANSACTION_TRYTES_LENGTH); From d493918bf16696d214d726e6f628fb2b0da9ea2a Mon Sep 17 00:00:00 2001 From: marktwtn Date: Thu, 5 Mar 2020 22:49:51 +0800 Subject: [PATCH 22/22] Release version v0.6.0 --- Doxyfile | 2 +- Makefile | 2 +- src/common.h | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Doxyfile b/Doxyfile index 6fe3a44..24a4a3e 100644 --- a/Doxyfile +++ b/Doxyfile @@ -2,7 +2,7 @@ # Project related configuration options #--------------------------------------------------------------------------- PROJECT_NAME = "dcurl" -PROJECT_NUMBER = 0.5.0 +PROJECT_NUMBER = 0.6.0 OUTPUT_DIRECTORY = docs OPTIMIZE_OUTPUT_FOR_C = YES #--------------------------------------------------------------------------- diff --git a/Makefile b/Makefile index 4f6e5aa..6f99b69 100644 --- a/Makefile +++ b/Makefile @@ -1,4 +1,4 @@ -VERSION = 0.5.0 +VERSION = 0.6.0 OUT ?= ./build SRC := src diff --git a/src/common.h b/src/common.h index 74fa362..6cd2b1e 100644 --- a/src/common.h +++ b/src/common.h @@ -15,7 +15,7 @@ #include #define __DCURL_MAJOR__ 0 -#define __DCURL_MINOR__ 5 +#define __DCURL_MINOR__ 6 #define __DCURL_PATCH__ 0 double diff_in_second(struct timespec t1, struct timespec t2);