/* * Authors: * Daniil Frolov <daniil.frolov@demlabs.net> * DeM Labs Inc. https://demlabs.net * Copyright (c) 2020, All rights reserved. This file is part of CellFrame SDK the open source project CellFrame SDK is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. CellFrame SDK is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with any CellFrame SDK based project. If not, see <http://www.gnu.org/licenses/>. */ #include "dap_chain_datum_tx_voting.h" #include "dap_chain_common.h" #define LOG_TAG "datum_tx_voting" dap_chain_datum_tx_voting_params_t* dap_chain_voting_parse_tsd(dap_chain_datum_tx_t* a_tx) { if (!a_tx) return NULL; dap_chain_datum_tx_voting_params_t *l_voting_parms = DAP_NEW_Z(dap_chain_datum_tx_voting_params_t); char *l_buf_string; byte_t *l_item; size_t l_tx_item_size; TX_ITEM_ITER_TX(l_item, l_tx_item_size, a_tx) { if (*l_item != TX_ITEM_TYPE_TSD) continue; dap_tsd_t *l_tsd = (dap_tsd_t*)((dap_chain_tx_tsd_t*)l_item)->tsd; switch(l_tsd->type){ case VOTING_TSD_TYPE_QUESTION: l_buf_string = DAP_NEW_Z_SIZE(char, l_tsd->size + 1); l_voting_parms->voting_question = memcpy(l_buf_string, l_tsd->data, l_tsd->size); break; case VOTING_TSD_TYPE_ANSWER: l_buf_string = DAP_NEW_Z_SIZE(char, l_tsd->size + 1); l_voting_parms->answers_list = dap_list_append(l_voting_parms->answers_list, memcpy(l_buf_string, l_tsd->data, l_tsd->size)); l_voting_parms->answers_count++; break; case VOTING_TSD_TYPE_EXPIRE: l_voting_parms->voting_expire = *(dap_time_t*)l_tsd->data; break; case VOTING_TSD_TYPE_MAX_VOTES_COUNT: l_voting_parms->votes_max_count = *(uint64_t*)l_tsd->data; break; case VOTING_TSD_TYPE_DELEGATED_KEY_REQUIRED: l_voting_parms->delegate_key_required = *(bool*)l_tsd->data; break; case VOTING_TSD_TYPE_VOTE_CHANGING_ALLOWED: l_voting_parms->vote_changing_allowed = *(bool*)l_tsd->data; break; default: break; } } return l_voting_parms; } dap_chain_tx_tsd_t* dap_chain_datum_voting_question_tsd_create(const char* a_question_str, size_t str_len) { if (!a_question_str || !str_len) return NULL; dap_chain_tx_tsd_t* l_tsd = dap_chain_datum_tx_item_tsd_create((void*)a_question_str, VOTING_TSD_TYPE_QUESTION, str_len); return l_tsd; } dap_chain_tx_tsd_t* dap_chain_datum_voting_answer_tsd_create(const char* a_answer_str, size_t str_len) { if (!a_answer_str || !str_len) return NULL; dap_chain_tx_tsd_t* l_tsd = dap_chain_datum_tx_item_tsd_create((void*)a_answer_str, VOTING_TSD_TYPE_ANSWER, str_len); return l_tsd; } dap_chain_tx_tsd_t* dap_chain_datum_voting_expire_tsd_create(dap_time_t a_expire) { if (!a_expire) return NULL; dap_chain_tx_tsd_t* l_tsd = dap_chain_datum_tx_item_tsd_create(&a_expire, VOTING_TSD_TYPE_EXPIRE, sizeof(dap_time_t)); return l_tsd; } dap_chain_tx_tsd_t* dap_chain_datum_voting_max_votes_count_tsd_create(uint64_t a_max_count) { if (!a_max_count) return NULL; dap_chain_tx_tsd_t* l_tsd = dap_chain_datum_tx_item_tsd_create(&a_max_count, VOTING_TSD_TYPE_MAX_VOTES_COUNT, sizeof(uint64_t)); return l_tsd; } dap_chain_tx_tsd_t* dap_chain_datum_voting_delegated_key_required_tsd_create(bool a_delegated_key_required) { byte_t l_value = a_delegated_key_required; dap_chain_tx_tsd_t* l_tsd = dap_chain_datum_tx_item_tsd_create(&l_value, VOTING_TSD_TYPE_DELEGATED_KEY_REQUIRED, sizeof(byte_t)); return l_tsd; } dap_chain_tx_tsd_t* dap_chain_datum_voting_vote_changing_allowed_tsd_create(bool a_vote_changing_allowed) { byte_t l_value = a_vote_changing_allowed; dap_chain_tx_tsd_t* l_tsd = dap_chain_datum_tx_item_tsd_create(&l_value, VOTING_TSD_TYPE_VOTE_CHANGING_ALLOWED, sizeof(byte_t)); return l_tsd; } dap_chain_tx_tsd_t* dap_chain_datum_voting_vote_tx_cond_tsd_create(dap_chain_hash_fast_t a_tx_hash, int a_out_idx) { dap_chain_tx_voting_tx_cond_t l_temp = { .tx_hash = a_tx_hash, .out_idx = a_out_idx }; dap_chain_tx_tsd_t* l_tsd = dap_chain_datum_tx_item_tsd_create(&l_temp, VOTING_TSD_TYPE_VOTE_TX_COND, sizeof(dap_chain_tx_voting_tx_cond_t)); return l_tsd; } dap_chain_tx_voting_t *dap_chain_datum_tx_item_voting_create(void) { dap_chain_tx_voting_t * l_item = DAP_NEW_Z(dap_chain_tx_voting_t); l_item->type = TX_ITEM_TYPE_VOTING; return l_item; } const char *s_tx_voting_get_answer_text_by_idx(dap_chain_datum_tx_t *a_tx, uint64_t a_idx) { byte_t *l_item; size_t l_tx_item_size; dap_tsd_t *l_tsd; TX_ITEM_ITER_TX(l_item, l_tx_item_size, a_tx) { if ( *l_item != TX_ITEM_TYPE_TSD || ( l_tsd = (dap_tsd_t*)((dap_chain_tx_tsd_t*)l_item)->tsd, l_tsd->type != VOTING_TSD_TYPE_ANSWER ) || a_idx-- ) continue; char *l_ret = DAP_NEW_Z_SIZE(char, l_tsd->size + 1); return memcpy(l_ret, l_tsd->data, l_tsd->size); } return NULL; } json_object *dap_chain_datum_tx_item_voting_tsd_to_json(dap_chain_datum_tx_t* a_tx) { if (!a_tx) return NULL; json_object *l_object = json_object_new_object(), *l_answer_array_object = json_object_new_array(); byte_t *l_item; size_t l_tx_item_size; dap_tsd_t *l_tsd; TX_ITEM_ITER_TX(l_item, l_tx_item_size, a_tx) { if (*l_item != TX_ITEM_TYPE_TSD) continue; l_tsd = (dap_tsd_t*)((dap_chain_tx_tsd_t*)l_item)->tsd; switch(l_tsd->type) { case VOTING_TSD_TYPE_QUESTION: json_object_object_add(l_object, "question", json_object_new_string_len((char*)l_tsd->data, l_tsd->size)); break; case VOTING_TSD_TYPE_ANSWER: json_object_array_add(l_answer_array_object, json_object_new_string_len((char*)l_tsd->data, l_tsd->size)); break; case VOTING_TSD_TYPE_EXPIRE: json_object_object_add(l_object, "exired", json_object_new_uint64(*(uint64_t*)l_tsd->data)); break; case VOTING_TSD_TYPE_MAX_VOTES_COUNT: json_object_object_add(l_object, "maxVotes", json_object_new_uint64(*(uint64_t*)l_tsd->data)); break; case VOTING_TSD_TYPE_DELEGATED_KEY_REQUIRED: json_object_object_add(l_object, "delegateKeyRequired", json_object_new_boolean(*(bool*)l_tsd->data)); break; case VOTING_TSD_TYPE_VOTE_CHANGING_ALLOWED: json_object_object_add(l_object, "voteChangingAllowed", json_object_new_boolean(*(bool*)l_tsd->data)); break; default: break; } } json_object_object_add(l_object, "answers", l_answer_array_object); return l_object; } dap_chain_tx_vote_t *dap_chain_datum_tx_item_vote_create(dap_chain_hash_fast_t *a_voting_hash, uint64_t *a_answer_idx) { if (!a_voting_hash) return NULL; dap_chain_tx_vote_t * l_item = DAP_NEW_Z(dap_chain_tx_vote_t); l_item->type = TX_ITEM_TYPE_VOTE; l_item->answer_idx = *a_answer_idx; l_item->voting_hash = *a_voting_hash; return l_item; } const char *s_get_vote_answer_text(dap_hash_fast_t *a_vote, uint64_t a_idx, dap_ledger_t *a_ledger) { dap_chain_datum_tx_t *l_tx = dap_ledger_tx_find_by_hash(a_ledger, a_vote); if (!l_tx || !a_ledger) { return NULL; } return s_tx_voting_get_answer_text_by_idx(l_tx, a_idx); } json_object *dap_chain_datum_tx_item_vote_to_json(dap_chain_tx_vote_t *a_vote, dap_ledger_t *a_ledger) { json_object *l_object = json_object_new_object(); char *l_voting_hash_str = dap_hash_fast_to_str_new(&a_vote->voting_hash); json_object *l_voting_hash = json_object_new_string(l_voting_hash_str); DAP_DELETE(l_voting_hash_str); json_object *l_answer_idx = json_object_new_uint64(a_vote->answer_idx); const char *l_answer_text_str = s_get_vote_answer_text(&a_vote->voting_hash, a_vote->answer_idx, a_ledger); json_object *l_answer_text = NULL; if (!l_answer_text_str) { l_answer_text = json_object_new_string("{UNDEFINED}"); } else { l_answer_text = json_object_new_string(l_answer_text_str); DAP_DELETE(l_answer_text_str); } json_object_object_add(l_object, "votingHash", l_voting_hash); json_object_object_add(l_object, "answer_idx", l_answer_idx); json_object_object_add(l_object, "answer_text", l_answer_text); return l_object; }