/* * Authors: * Frolov Daniil <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 <memory.h> #include <assert.h> #include "dap_tsd.h" #include "dap_sign.h" #include "dap_common.h" #include "dap_chain_datum_decree.h" #include "dap_enc_base58.h" #include "dap_chain_common.h" #ifdef DAP_OS_UNIX #include <arpa/inet.h> #endif #ifdef WIN32 #include <winsock2.h> #include <ws2tcpip.h> #endif #define LOG_TAG "dap_chain_datum_decree" dap_sign_t *dap_chain_datum_decree_get_signs(dap_chain_datum_decree_t *a_decree, size_t* a_signs_size) { dap_return_val_if_fail(a_decree && a_signs_size, NULL); dap_sign_t *l_signs_section = (dap_sign_t*)(a_decree->data_n_signs + a_decree->header.data_size); *a_signs_size = a_decree->header.signs_size; return l_signs_section; } int dap_chain_datum_decree_get_fee(dap_chain_datum_decree_t *a_decree, uint256_t *a_fee_value) { dap_return_val_if_fail(a_decree && a_fee_value, -1); dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE); return l_tsd && l_tsd->size == sizeof(uint256_t) ? ( _dap_tsd_get_scalar(l_tsd, a_fee_value), 0 ) : 1; } int dap_chain_datum_decree_get_value(dap_chain_datum_decree_t *a_decree, uint256_t *a_value) { dap_return_val_if_fail(a_decree && a_value, -1); dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_VALUE); return l_tsd && l_tsd->size == sizeof(uint256_t) ? ( _dap_tsd_get_scalar(l_tsd, a_value), 0 ) : 1; } int dap_chain_datum_decree_get_fee_addr(dap_chain_datum_decree_t *a_decree, dap_chain_addr_t *a_fee_wallet) { dap_return_val_if_fail(a_decree && a_fee_wallet, -1); dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE_WALLET); return l_tsd && l_tsd->size == sizeof(dap_chain_addr_t) ? ( _dap_tsd_get_scalar(l_tsd, a_fee_wallet), 0 ) : 1; } dap_list_t *dap_chain_datum_decree_get_owners(dap_chain_datum_decree_t *a_decree, uint16_t *a_owners_num) { dap_return_val_if_fail(a_decree && a_owners_num, NULL); dap_list_t *l_ret = dap_tsd_find_all(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER); if (a_owners_num) *a_owners_num = (uint16_t)dap_list_length(l_ret); return l_ret; } int dap_chain_datum_decree_get_min_owners(dap_chain_datum_decree_t *a_decree, uint256_t *a_min_owners_num) { dap_return_val_if_fail(a_decree && a_min_owners_num, -1); dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER); return l_tsd && l_tsd->size == sizeof(uint256_t) ? ( _dap_tsd_get_scalar(l_tsd, a_min_owners_num), 0 ) : 1; } int dap_chain_datum_decree_get_hash(dap_chain_datum_decree_t *a_decree, dap_hash_fast_t *a_tx_hash) { dap_return_val_if_fail(a_decree && a_tx_hash, -1); dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HASH); return l_tsd && l_tsd->size == sizeof(dap_hash_fast_t) ? ( _dap_tsd_get_scalar(l_tsd, a_tx_hash), 0 ) : 1; } int dap_chain_datum_decree_get_stake_value(dap_chain_datum_decree_t *a_decree, uint256_t *a_stake_value) { dap_return_val_if_fail(a_decree && a_stake_value, -1); dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_VALUE); return l_tsd && l_tsd->size == sizeof(uint256_t) ? ( _dap_tsd_get_scalar(l_tsd, a_stake_value), 0 ) : 1; } int dap_chain_datum_decree_get_stake_signing_addr(dap_chain_datum_decree_t *a_decree, dap_chain_addr_t *a_signing_addr) { dap_return_val_if_fail(a_decree && a_signing_addr, -1); dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNING_ADDR); return l_tsd && l_tsd->size == sizeof(dap_chain_addr_t) ? ( _dap_tsd_get_scalar(l_tsd, a_signing_addr), 0 ) : 1; } int dap_chain_datum_decree_get_stake_signer_node_addr(dap_chain_datum_decree_t *a_decree, dap_chain_node_addr_t *a_node_addr) { dap_return_val_if_fail(a_decree && a_node_addr, -1); dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR); return l_tsd && l_tsd->size == sizeof(dap_chain_node_addr_t) ? ( _dap_tsd_get_scalar(l_tsd, a_node_addr), 0 ) : 1; } int dap_chain_datum_decree_get_stake_min_value(dap_chain_datum_decree_t *a_decree, uint256_t *a_min_value) { dap_return_val_if_fail(a_decree && a_min_value, -1); dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_VALUE); return l_tsd && l_tsd->size == sizeof(uint256_t) ? ( _dap_tsd_get_scalar(l_tsd, a_min_value), 0 ) : 1; } int dap_chain_datum_decree_get_stake_min_signers_count(dap_chain_datum_decree_t *a_decree, uint256_t *a_min_signers_count) { dap_return_val_if_fail(a_decree && a_min_signers_count, -1); dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_SIGNERS_COUNT); return l_tsd && l_tsd->size == sizeof(uint256_t) ? ( _dap_tsd_get_scalar(l_tsd, a_min_signers_count), 0 ) : 1; } int dap_chain_datum_decree_get_action(dap_chain_datum_decree_t *a_decree, uint8_t *a_action) { dap_return_val_if_fail(a_decree && a_action, -1); dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_ACTION); return l_tsd && l_tsd->size == sizeof(uint8_t) ? ( _dap_tsd_get_scalar(l_tsd, a_action), 0 ) : 1; } int dap_chain_datum_decree_get_signature_type(dap_chain_datum_decree_t *a_decree, uint32_t *a_signature_type) { dap_return_val_if_fail(a_decree && a_signature_type, -1); dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGNATURE_TYPE); return l_tsd && l_tsd->size == sizeof(uint32_t) ? ( _dap_tsd_get_scalar(l_tsd, a_signature_type), 0 ) : 1; } int dap_chain_datum_decree_get_ban_addr(dap_chain_datum_decree_t *a_decree, const char **a_addr) { dap_return_val_if_fail(a_decree && a_addr, -1); dap_tsd_t *l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HOST); if (!l_tsd) l_tsd = dap_tsd_find(a_decree->data_n_signs, a_decree->header.data_size, DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STRING); return l_tsd ? ( *a_addr = dap_tsd_get_string_const(l_tsd), !dap_strcmp(*a_addr, DAP_TSD_CORRUPTED_STRING) ) : 1; } void dap_chain_datum_decree_dump_json(json_object *a_json_out, dap_chain_datum_decree_t *a_decree, size_t a_decree_size, const char *a_hash_out_type) { char *l_type_str = ""; char l_tmp_buff[70]={0}; switch(a_decree->header.type) { case DAP_CHAIN_DATUM_DECREE_TYPE_COMMON: l_type_str = "DECREE_TYPE_COMMON"; break; case DAP_CHAIN_DATUM_DECREE_TYPE_SERVICE: l_type_str = "DECREE_TYPE_SERVICE"; break; default: l_type_str = "DECREE_TYPE_UNKNOWN"; } json_object_object_add(a_json_out, "type", json_object_new_string(l_type_str)); const char *l_subtype_str = dap_chain_datum_decree_subtype_to_str(a_decree->header.sub_type); json_object_object_add(a_json_out, "subtype", json_object_new_string(l_subtype_str)); json_object_object_add(a_json_out, "TSD", json_object_new_string("")); dap_tsd_t *l_tsd; size_t l_tsd_size; dap_tsd_iter(l_tsd, l_tsd_size, a_decree->data_n_signs, a_decree->header.data_size) { switch(l_tsd->type) { case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_VALUE: if (l_tsd->size > sizeof(uint256_t)){ json_object_object_add(a_json_out, "Value", json_object_new_string("WRONG SIZE")); break; } uint256_t l_value = uint256_0; _dap_tsd_get_scalar(l_tsd, &l_value); const char *l_value_str = dap_uint256_to_char(l_value, NULL); json_object_object_add(a_json_out, "Value", json_object_new_string(l_value_str)); break; case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGN: break; case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE: if (l_tsd->size > sizeof(uint256_t)){ json_object_object_add(a_json_out, "Fee", json_object_new_string("WRONG SIZE")); break; } uint256_t l_fee_value = uint256_0; _dap_tsd_get_scalar(l_tsd, &l_fee_value); const char *l_fee_value_str = dap_uint256_to_char(l_fee_value, NULL); json_object_object_add(a_json_out, "Fee", json_object_new_string(l_fee_value_str)); break; case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_OWNER: if (l_tsd->size < sizeof(dap_pkey_t)) { json_object_object_add(a_json_out, "Owner fingerprint", json_object_new_string("WRONG SIZE")); break; } dap_pkey_t *l_owner_pkey = /*DAP_NEW_STACK_SIZE(dap_pkey_t, l_tsd->size); memcpy(l_owner_pkey, l_tsd->data, l_tsd->size);*/ _dap_tsd_get_object(l_tsd, dap_pkey_t); json_object_object_add(a_json_out, "Owner fingerprint", json_object_new_string(dap_get_data_hash_str(l_owner_pkey->pkey, l_owner_pkey->header.size).s)); break; case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_MIN_OWNER: if (l_tsd->size > sizeof(uint256_t)){ json_object_object_add(a_json_out, "Owner min", json_object_new_string("WRONG SIZE")); break; } uint256_t l_owner_min = uint256_0; _dap_tsd_get_scalar(l_tsd, &l_owner_min); const char *l_owner_min_str = dap_uint256_to_char(l_owner_min, NULL); json_object_object_add(a_json_out, "Owner min", json_object_new_string(l_owner_min_str)); break; case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_FEE_WALLET: if (l_tsd->size > sizeof(dap_chain_addr_t)) { json_object_object_add(a_json_out, "Wallet for fee", json_object_new_string("WRONG SIZE")); break; } dap_chain_addr_t *l_addr_fee_wallet = /*{ }; _dap_tsd_get_scalar(l_tsd, &l_addr_fee_wallet);*/ _dap_tsd_get_object(l_tsd, dap_chain_addr_t); json_object_object_add(a_json_out, "Wallet for fee", json_object_new_string(dap_chain_addr_to_str_static(l_addr_fee_wallet))); case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HASH: if (l_tsd->size > sizeof(dap_hash_fast_t)) { json_object_object_add(a_json_out, "Stake tx", json_object_new_string("WRONG SIZE")); break; } dap_hash_fast_t *l_stake_tx = /*{ }; _dap_tsd_get_scalar(l_tsd, &l_stake_tx);*/ _dap_tsd_get_object(l_tsd, dap_hash_fast_t); const char *l_stake_tx_hash = dap_strcmp(a_hash_out_type, "hex") ? dap_enc_base58_encode_hash_to_str_static(l_stake_tx) : dap_chain_hash_fast_to_str_static(l_stake_tx); json_object_object_add(a_json_out, "Stake tx", json_object_new_string(l_stake_tx_hash)); break; case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_VALUE: if (l_tsd->size > sizeof(uint256_t)){ json_object_object_add(a_json_out, "Stake value", json_object_new_string("WRONG SIZE")); break; } uint256_t l_stake_value = uint256_0; _dap_tsd_get_scalar(l_tsd, &l_stake_value); const char *l_stake_value_str = dap_uint256_to_char(l_stake_value, NULL); json_object_object_add(a_json_out, "Stake value", json_object_new_string(l_stake_value_str)); break; case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_SIGNING_ADDR: if (l_tsd->size > sizeof(dap_chain_addr_t)) { json_object_object_add(a_json_out, "Signing addr", json_object_new_string("WRONG SIZE")); break; } dap_chain_addr_t *l_stake_addr_signing = /*{ }; _dap_tsd_get_scalar(l_tsd, &l_stake_addr_signing);*/ _dap_tsd_get_object(l_tsd, dap_chain_addr_t); json_object_object_add(a_json_out, "Signing addr", json_object_new_string(dap_chain_addr_to_str_static(l_stake_addr_signing))); dap_chain_hash_fast_t l_pkey_signing = l_stake_addr_signing->data.hash_fast; const char *l_pkey_signing_str = dap_strcmp(a_hash_out_type, "hex") ? dap_enc_base58_encode_hash_to_str_static(&l_pkey_signing) : dap_chain_hash_fast_to_str_static(&l_pkey_signing); json_object_object_add(a_json_out, "Signing pkey fingerprint", json_object_new_string(l_pkey_signing_str)); break; case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_NODE_ADDR: if(l_tsd->size > sizeof(dap_chain_node_addr_t)){ json_object_object_add(a_json_out, "Node addr", json_object_new_string("WRONG SIZE")); break; } dap_chain_node_addr_t *l_node_addr = _dap_tsd_get_object(l_tsd, dap_chain_node_addr_t); sprintf(l_tmp_buff, NODE_ADDR_FP_STR, NODE_ADDR_FP_ARGS(l_node_addr)); json_object_object_add(a_json_out, "Node addr", json_object_new_string(l_tmp_buff)); break; case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_VALUE: if (l_tsd->size > sizeof(uint256_t)) { json_object_object_add(a_json_out, "Min value", json_object_new_string("WRONG SIZE")); break; } uint256_t l_min_value = uint256_0; _dap_tsd_get_scalar(l_tsd, &l_min_value); const char *l_min_value_str = dap_uint256_to_char(l_min_value, NULL); json_object_object_add(a_json_out, "Min value", json_object_new_string(l_min_value_str)); break; case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STAKE_MIN_SIGNERS_COUNT: if (l_tsd->size > sizeof(uint256_t)) { json_object_object_add(a_json_out, "Min signers count", json_object_new_string("WRONG SIZE")); break; } uint256_t l_min_signers_count = uint256_0; _dap_tsd_get_scalar(l_tsd, &l_min_signers_count); const char *l_min_signers_count_str = dap_uint256_to_char(l_min_signers_count, NULL); json_object_object_add(a_json_out, "Min signers count", json_object_new_string(l_min_signers_count_str)); break; case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_HOST: case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_STRING: json_object_object_add(a_json_out, "Host address", json_object_new_string(dap_tsd_get_string(l_tsd))); break; case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_ACTION: if (l_tsd->size != sizeof(uint8_t)) { json_object_object_add(a_json_out, "Action", json_object_new_string("WRONG SIZE")); break; } uint8_t l_action = 0; _dap_tsd_get_scalar(l_tsd, &l_action); json_object_object_add(a_json_out, "tAction", l_action ? json_object_new_string("add (enable)") : json_object_new_string("delete (disable)")); break; case DAP_CHAIN_DATUM_DECREE_TSD_TYPE_SIGNATURE_TYPE: if (l_tsd->size != sizeof(uint32_t)) { json_object_object_add(a_json_out, "Signature type", json_object_new_string("WRONG SIZE")); break; } uint32_t l_type = 0; _dap_tsd_get_scalar(l_tsd, &l_type); dap_sign_type_t l_sign_type = { .type = l_type }; json_object_object_add(a_json_out, "Signature type", json_object_new_string(dap_sign_type_to_str(l_sign_type))); break; default: json_object_object_add(a_json_out, "UNKNOWN_TYPE_TSD_SECTION", json_object_new_string("")); break; } } dap_chain_datum_decree_certs_dump_json(a_json_out, a_decree->data_n_signs + a_decree->header.data_size, a_decree->header.signs_size, a_hash_out_type); } void dap_chain_datum_decree_certs_dump_json(json_object * a_json_out, byte_t * a_signs, size_t a_certs_size, const char *a_hash_out_type) { json_object_object_add(a_json_out, "signatures", json_object_new_string("")); if (!a_certs_size) { json_object_object_add(a_json_out, "Cert status", json_object_new_string("NONE")); return; } json_object* json_arr_certs_out = json_object_new_array(); size_t l_offset = 0; for (int i = 1; l_offset < (a_certs_size); i++) { json_object* json_obj_sign = json_object_new_object(); dap_sign_t *l_sign = (dap_sign_t *) (a_signs + l_offset); l_offset += dap_sign_get_size(l_sign); if (l_sign->header.sign_size == 0) { json_object_object_add(json_obj_sign, "sign status", json_object_new_string("CORRUPTED - 0 size signature")); json_object_array_add(json_arr_certs_out, json_obj_sign); continue; } dap_chain_hash_fast_t l_pkey_hash = {0}; if (dap_sign_get_pkey_hash(l_sign, &l_pkey_hash) == false) { json_object_object_add(json_obj_sign, "sign status", json_object_new_string("CORRUPTED - can't calc hash")); json_object_array_add(json_arr_certs_out, json_obj_sign); continue; } const char *l_hash_str = dap_strcmp(a_hash_out_type, "hex") ? dap_enc_base58_encode_hash_to_str_static(&l_pkey_hash) : dap_chain_hash_fast_to_str_static(&l_pkey_hash); json_object_object_add(json_obj_sign, "sign #", json_object_new_uint64(i)); json_object_object_add(json_obj_sign, "hash", json_object_new_string(l_hash_str)); json_object_object_add(json_obj_sign, "type", json_object_new_string(dap_sign_type_to_str(l_sign->header.type))); json_object_object_add(json_obj_sign, "sign size", json_object_new_uint64(l_sign->header.sign_size)); json_object_array_add(json_arr_certs_out, json_obj_sign); } json_object_object_add(a_json_out,"SIGNS", json_arr_certs_out); } dap_chain_datum_decree_t *dap_chain_datum_decree_new(dap_chain_net_id_t a_net_id, dap_chain_id_t a_chain_id, dap_chain_cell_id_t a_cell_id, size_t a_total_tsd_size) { dap_chain_datum_decree_t *l_decree = NULL; DAP_NEW_Z_SIZE_RET_VAL(l_decree, dap_chain_datum_decree_t, sizeof(dap_chain_datum_decree_t) + a_total_tsd_size, NULL, NULL); l_decree->decree_version = DAP_CHAIN_DATUM_DECREE_VERSION; l_decree->header.ts_created = dap_time_now(); l_decree->header.type = DAP_CHAIN_DATUM_DECREE_TYPE_COMMON; l_decree->header.common_decree_params.net_id = a_net_id; l_decree->header.common_decree_params.chain_id = a_chain_id; l_decree->header.common_decree_params.cell_id = a_cell_id; l_decree->header.data_size = a_total_tsd_size; return l_decree; } dap_chain_datum_decree_t *dap_chain_datum_decree_sign_in_cycle(dap_cert_t **a_certs, dap_chain_datum_decree_t *a_datum_decree, size_t a_certs_count, size_t *a_total_sign_count) { size_t l_cur_sign_offset = a_datum_decree->header.data_size + a_datum_decree->header.signs_size; size_t l_total_signs_size = a_datum_decree->header.signs_size, l_total_sign_count = 0; for(size_t i = 0; i < a_certs_count; i++) { dap_sign_t * l_sign = dap_cert_sign(a_certs[i], a_datum_decree, sizeof(dap_chain_datum_decree_t) + a_datum_decree->header.data_size, 0); if (!l_sign) { log_it(L_ERROR, "Decree signing failed"); DAP_DELETE(a_datum_decree); return NULL; } size_t l_sign_size = dap_sign_get_size(l_sign); a_datum_decree = DAP_REALLOC(a_datum_decree, sizeof(dap_chain_datum_decree_t) + l_cur_sign_offset + l_sign_size); if (!a_datum_decree) { log_it(L_CRITICAL, "%s", c_error_memory_alloc); DAP_DELETE(l_sign); return NULL; } memcpy(a_datum_decree->data_n_signs + l_cur_sign_offset, l_sign, l_sign_size); DAP_DELETE(l_sign); l_total_signs_size += l_sign_size; l_cur_sign_offset += l_sign_size; a_datum_decree->header.signs_size = l_total_signs_size; log_it(L_DEBUG,"<-- Signed with '%s'", a_certs[i]->name); l_total_sign_count++; } if (a_total_sign_count) *a_total_sign_count = l_total_sign_count; return a_datum_decree; }