-
3509bc7c
dap_chain_datum.c 47.82 KiB
/*
* Authors:
* Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
* DeM Labs Inc. https://demlabs.net
* Kelvin Project https://github.com/kelvinblockchain
* Copyright (c) 2017-2018
* All rights reserved.
This file is part of DAP (Deus Applications Prototypes) the open source project
DAP (Deus Applicaions Prototypes) 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.
DAP 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 DAP based project. If not, see <http://www.gnu.org/licenses/>.
*/
#include <string.h>
#include "dap_common.h"
#include "dap_time.h"
#include "dap_chain_datum.h"
#include "dap_chain_datum_tx.h"
#include "dap_chain_datum_token.h"
#include "dap_chain_datum_tx_items.h"
#include "dap_chain_datum_decree.h"
#include "dap_chain_datum_anchor.h"
#include "dap_chain_datum_hashtree_roots.h"
#include "dap_enc_base58.h"
#define LOG_TAG "dap_chain_datum"
/**
* @brief dap_chain_datum_create
* @param a_type_id
* @param a_data
* @param a_data_size
* @return
*/
dap_chain_datum_t * dap_chain_datum_create(uint16_t a_type_id, const void * a_data, size_t a_data_size)
{
dap_chain_datum_t * l_datum = DAP_NEW_Z_SIZE(dap_chain_datum_t, sizeof(l_datum->header)+ a_data_size);
memcpy(l_datum->data, a_data, (uint32_t)a_data_size); // Compiler warning escape
l_datum->header.type_id = a_type_id;
l_datum->header.data_size = (uint32_t) a_data_size;
l_datum->header.version_id = DAP_CHAIN_DATUM_VERSION;
l_datum->header.ts_create =(uint64_t) time(NULL);
return l_datum;
}
void s_datum_token_dump_tsd(dap_string_t *a_str_out, dap_chain_datum_token_t *a_token, size_t a_token_size, const char *a_hash_out_type)
{
dap_tsd_t *l_tsd = dap_chain_datum_token_tsd_get(a_token, a_token_size);
if (l_tsd == NULL) {
dap_string_append_printf(a_str_out,"<CORRUPTED TSD SECTION>\n");
return;
}
size_t l_tsd_total_size = 0;
switch (a_token->type) {
case DAP_CHAIN_DATUM_TOKEN_TYPE_DECL:
switch (a_token->subtype) {
case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:
l_tsd_total_size = a_token->header_private_decl.tsd_total_size; break;
case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:
l_tsd_total_size = a_token->header_native_decl.tsd_total_size; break;
default: break;
} break;
case DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE:
switch (a_token->subtype) {
case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:
l_tsd_total_size = a_token->header_private_update.tsd_total_size; break;
case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE:
l_tsd_total_size = a_token->header_native_update.tsd_total_size; break;
default: break;
} break;
default: break;
}
size_t l_tsd_size = 0;
for (size_t l_offset = 0; l_offset < l_tsd_total_size; l_offset += l_tsd_size) {
l_tsd = (dap_tsd_t *) (((byte_t*)l_tsd) + l_tsd_size);
l_tsd_size = l_tsd ? dap_tsd_size(l_tsd) : 0;
if (l_tsd_size == 0) {
log_it(L_ERROR,"Wrong zero TSD size, exiting s_datum_token_dump_tsd()");
return;
} else if (l_tsd_size+l_offset > l_tsd_total_size) {
log_it(L_WARNING, "<CORRUPTED TSD> too big size %u when left maximum %zu",
l_tsd->size, l_tsd_total_size - l_offset);
return;
}
switch( l_tsd->type){
case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_SET_FLAGS:
dap_string_append_printf(a_str_out,"flags_set: ");
dap_chain_datum_token_flags_dump(a_str_out,
dap_tsd_get_scalar(l_tsd, uint16_t));
continue;
case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_UNSET_FLAGS:
dap_string_append_printf(a_str_out,"flags_unset: ");
dap_chain_datum_token_flags_dump(a_str_out,
dap_tsd_get_scalar(l_tsd, uint16_t));
continue;
case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY: { // 256
char *l_balance = dap_chain_balance_print(dap_tsd_get_scalar(l_tsd, uint256_t));
dap_string_append_printf(a_str_out, "total_supply: %s\n", l_balance);
DAP_DELETE(l_balance);
}
continue;
case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SUPPLY_OLD: {// 128
char *l_balance = dap_chain_balance_print(GET_256_FROM_128(dap_tsd_get_scalar(l_tsd, uint128_t)));
dap_string_append_printf(a_str_out, "total_supply: %s\n", l_balance);
DAP_DELETE(l_balance);
}
continue;
case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_SIGNS_VALID :
dap_string_append_printf(a_str_out,"total_signs_valid: %u\n",
dap_tsd_get_scalar(l_tsd, uint16_t) );
continue;
case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_ADD:
if(l_tsd->size >= sizeof(dap_pkey_t)){
char *l_hash_str;
dap_pkey_t *l_pkey = (dap_pkey_t*)l_tsd->data;
dap_hash_fast_t l_hf = {0};
if (!dap_pkey_get_hash(l_pkey, &l_hf)) {
dap_string_append_printf(a_str_out,"total_pkeys_add: <WRONG CALCULATION FINGERPRINT>\n");
} else {
if (!dap_strcmp(a_hash_out_type, "hex") || !dap_strcmp(a_hash_out_type, "content_hash"))
l_hash_str = dap_chain_hash_fast_to_str_new(&l_hf);
else
l_hash_str = dap_enc_base58_encode_hash_to_str(&l_hf);
dap_string_append_printf(a_str_out, "total_pkeys_add: %s\n", l_hash_str);
DAP_DELETE(l_hash_str);
}
} else
dap_string_append_printf(a_str_out,"total_pkeys_add: <WRONG SIZE %u>\n", l_tsd->size);
continue;
case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TOTAL_PKEYS_REMOVE:
if(l_tsd->size == sizeof(dap_chain_hash_fast_t) ){
char *l_hash_str = (!dap_strcmp(a_hash_out_type,"hex")|| !dap_strcmp(a_hash_out_type, "content_hash"))
? dap_chain_hash_fast_to_str_new((dap_chain_hash_fast_t*) l_tsd->data)
: dap_enc_base58_encode_hash_to_str((dap_chain_hash_fast_t*) l_tsd->data);
dap_string_append_printf(a_str_out,"total_pkeys_remove: %s\n", l_hash_str);
DAP_DELETE( l_hash_str );
}else
dap_string_append_printf(a_str_out,"total_pkeys_remove: <WRONG SIZE %u>\n", l_tsd->size);
continue;
case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DELEGATE_EMISSION_FROM_STAKE_LOCK: {
char *balance = NULL;
dap_chain_datum_token_tsd_delegate_from_stake_lock_t *l_tsd_section = dap_tsd_get_object(l_tsd, dap_chain_datum_token_tsd_delegate_from_stake_lock_t);
dap_string_append_printf(a_str_out, "ticker_token_from: %s\nemission_rate: %s\n",
l_tsd_section->ticker_token_from, (balance = dap_chain_balance_to_coins(l_tsd_section->emission_rate)));
DAP_DEL_Z(balance);
}continue;
case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_ADD :
dap_string_append_printf(a_str_out,"datum_type_allowed_add: %s\n",
dap_tsd_get_string_const(l_tsd) );
continue;
case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_ALLOWED_REMOVE :
dap_string_append_printf(a_str_out,"datum_type_allowed_remove: %s\n",
dap_tsd_get_string_const(l_tsd) );
continue;
case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_ADD :
dap_string_append_printf(a_str_out,"datum_type_blocked_add: %s\n",
dap_tsd_get_string_const(l_tsd) );
continue;
case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_DATUM_TYPE_BLOCKED_REMOVE:
dap_string_append_printf(a_str_out,"datum_type_blocked_remove: %s\n",
dap_tsd_get_string_const(l_tsd) );
continue;
case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_ADD:
dap_string_append_printf(a_str_out,"tx_sender_allowed_add: %s\n",
dap_tsd_get_string_const(l_tsd) );
continue;
case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_ALLOWED_REMOVE:
dap_string_append_printf(a_str_out,"tx_sender_allowed_remove: %s\n",
dap_tsd_get_string_const(l_tsd) );
continue;
case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_ADD:
dap_string_append_printf(a_str_out,"tx_sender_blocked_add: %s\n",
dap_tsd_get_string_const(l_tsd) );
continue;
case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_SENDER_BLOCKED_REMOVE:
dap_string_append_printf(a_str_out,"tx_sender_blocked_remove: %s\n",
dap_tsd_get_string_const(l_tsd) );
continue;
case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_ADD:
dap_string_append_printf(a_str_out,"tx_receiver_allowed_add: %s\n",
dap_tsd_get_string_const(l_tsd) );
continue;
case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_ALLOWED_REMOVE:
dap_string_append_printf(a_str_out,"tx_receiver_allowed: %s\n",
dap_tsd_get_string_const(l_tsd) );
continue;
case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_ADD:
dap_string_append_printf(a_str_out, "tx_receiver_blocked_add: %s\n",
dap_tsd_get_string_const(l_tsd) );
continue;
case DAP_CHAIN_DATUM_TOKEN_TSD_TYPE_TX_RECEIVER_BLOCKED_REMOVE:
dap_string_append_printf(a_str_out, "tx_receiver_blocked_remove: %s\n",
dap_tsd_get_string_const(l_tsd) );
continue;
default: dap_string_append_printf(a_str_out, "<0x%04hX>: <size %u>\n", l_tsd->type, l_tsd->size);
}
}
}
/**
* @brief _dap_chain_datum_tx_out_data
*
* @param a_datum
* @param a_ledger
* @param a_str_out
* @param a_hash_out_type
* @param save_processed_tx
* @param a_tx_hash_processed
* @param l_tx_num
*/
bool dap_chain_datum_dump_tx(dap_chain_datum_tx_t *a_datum,
const char *a_ticker,
dap_string_t *a_str_out,
const char *a_hash_out_type,
dap_hash_fast_t *a_tx_hash,
dap_chain_net_id_t a_net_id)
{
dap_time_t l_ts_create = (dap_time_t)a_datum->header.ts_created;
bool l_is_first = false;
dap_chain_tx_in_t *l_in_item = (dap_chain_tx_in_t *)dap_chain_datum_tx_item_get(a_datum, NULL, TX_ITEM_TYPE_IN, NULL);
if (l_in_item && dap_hash_fast_is_blank(&l_in_item->header.tx_prev_hash))
l_is_first = true;
char l_tmp_buf[70];
char *l_hash_str = dap_strcmp(a_hash_out_type, "hex")
? dap_enc_base58_encode_hash_to_str(a_tx_hash)
: dap_chain_hash_fast_to_str_new(a_tx_hash);
dap_string_append_printf(a_str_out, "transaction:%s hash %s\n TS Created: %s%s%s\n Items:\n",
l_is_first ? " (emit)" : "", l_hash_str, dap_ctime_r(&l_ts_create, l_tmp_buf),
a_ticker ? " Token ticker: " : "", a_ticker ? a_ticker : "");
DAP_DELETE(l_hash_str);
uint32_t l_tx_items_count = 0;
uint32_t l_tx_items_size = a_datum->header.tx_items_size;
dap_sign_t *l_sign_tmp;
dap_hash_fast_t *l_hash_tmp = NULL;
dap_pkey_t *l_pkey_tmp;
while (l_tx_items_count < l_tx_items_size) {
uint8_t *item = a_datum->tx_items + l_tx_items_count;
size_t l_item_tx_size = dap_chain_datum_item_tx_get_size(item);
switch(dap_chain_datum_tx_item_get_type(item)){
case TX_ITEM_TYPE_IN:
l_hash_tmp = &((dap_chain_tx_in_t*)item)->header.tx_prev_hash;
if (dap_hash_fast_is_blank(l_hash_tmp)) {
l_hash_str = dap_strdup("BLANK");
} else {
l_hash_str = dap_strcmp(a_hash_out_type, "hex")
? dap_enc_base58_encode_hash_to_str(l_hash_tmp)
: dap_chain_hash_fast_to_str_new(l_hash_tmp);
}
dap_string_append_printf(a_str_out, "\t IN:\nTx_prev_hash: %s\n"
"\t\t Tx_out_prev_idx: %u\n",
l_hash_str,
((dap_chain_tx_in_t*)item)->header.tx_out_prev_idx);
DAP_DELETE(l_hash_str);
break;
case TX_ITEM_TYPE_OUT_OLD: {
char *l_value_str = dap_chain_balance_to_coins(dap_chain_uint256_from(
((dap_chain_tx_out_old_t*)item)->header.value));
char *l_addr_str = dap_chain_addr_to_str(&((dap_chain_tx_out_old_t*)item)->addr);
dap_string_append_printf(a_str_out, "\t OUT OLD (64):\n"
"\t\t Value: %s (%"DAP_UINT64_FORMAT_U")\n"
"\t\t Address: %s\n",
l_value_str,
((dap_chain_tx_out_old_t*)item)->header.value,
l_addr_str);
DAP_DELETE(l_value_str);
DAP_DELETE(l_addr_str);
} break;
case TX_ITEM_TYPE_OUT: { // 256
char *l_value_str = dap_chain_balance_print(((dap_chain_tx_out_t*)item)->header.value);
char *l_coins_str = dap_chain_balance_to_coins(((dap_chain_tx_out_t*)item)->header.value);
char *l_addr_str = dap_chain_addr_to_str(&((dap_chain_tx_out_t*)item)->addr);
dap_string_append_printf(a_str_out, "\t OUT:\n"
"\t\t Value: %s (%s)\n"
"\t\t Address: %s\n",
l_coins_str,
l_value_str,
l_addr_str);
DAP_DELETE(l_value_str);
DAP_DELETE(l_coins_str);
DAP_DELETE(l_addr_str);
} break;
case TX_ITEM_TYPE_IN_EMS: {
l_hash_tmp = &((dap_chain_tx_in_ems_t*)item)->header.token_emission_hash;
l_hash_str = dap_strcmp(a_hash_out_type, "hex")
? dap_enc_base58_encode_hash_to_str(l_hash_tmp)
: dap_chain_hash_fast_to_str_new(l_hash_tmp);
dap_string_append_printf(a_str_out, "\t IN_EMS:\n"
"\t\t ticker: %s \n"
"\t\t token_emission_hash: %s\n"
"\t\t token_emission_chain_id: 0x%016"DAP_UINT64_FORMAT_x"\n",
((dap_chain_tx_in_ems_t*)item)->header.ticker,
l_hash_str,
((dap_chain_tx_in_ems_t*)item)->header.token_emission_chain_id.uint64);
DAP_DELETE(l_hash_str);
} break;
case TX_ITEM_TYPE_IN_EMS_EXT: {
l_hash_tmp = &((dap_chain_tx_in_ems_ext_t*)item)->header.ext_tx_hash;
l_hash_str = dap_strcmp(a_hash_out_type, "hex")
? dap_enc_base58_encode_hash_to_str(l_hash_tmp)
: dap_chain_hash_fast_to_str_new(l_hash_tmp);
dap_string_append_printf(a_str_out, "\t IN_EMS EXT:\n"
"\t\t Version: %u\n"
"\t\t Ticker: %s\n"
"\t\t Ext chain id: 0x%016"DAP_UINT64_FORMAT_x"\n"
"\t\t Ext net id: 0x%016"DAP_UINT64_FORMAT_x"\n"
"\t\t Ext tx hash: %s\n"
"\t\t Ext tx out idx: %u\n",
((dap_chain_tx_in_ems_ext_t*)item)->header.version,
((dap_chain_tx_in_ems_ext_t*)item)->header.ticker,
((dap_chain_tx_in_ems_ext_t*)item)->header.ext_chain_id.uint64,
((dap_chain_tx_in_ems_ext_t*)item)->header.ext_net_id.uint64,
l_hash_str,
((dap_chain_tx_in_ems_ext_t*)item)->header.ext_tx_out_idx);
DAP_DELETE(l_hash_str);
} break;
case TX_ITEM_TYPE_SIG: {
l_sign_tmp = dap_chain_datum_tx_item_sign_get_sig((dap_chain_tx_sig_t *)item);
dap_sign_get_information(l_sign_tmp, a_str_out, a_hash_out_type);
dap_chain_addr_t l_sender_addr;
dap_chain_addr_fill_from_sign(&l_sender_addr, l_sign_tmp, a_net_id);
const char *l_addr_str = dap_chain_addr_to_str(&l_sender_addr);
dap_string_append_printf(a_str_out, "\tSender addr: %s", l_addr_str);
DAP_DELETE(l_addr_str);
} break;
case TX_ITEM_TYPE_RECEIPT: {
char *l_value_str = dap_chain_balance_print(
((dap_chain_datum_tx_receipt_t*)item)->receipt_info.value_datoshi);
char *l_coins_str = dap_chain_balance_to_coins(
((dap_chain_datum_tx_receipt_t*)item)->receipt_info.value_datoshi);
dap_string_append_printf(a_str_out, "\t Receipt:\n"
"\t\t size: %"DAP_UINT64_FORMAT_U"\n"
"\t\t ext size: %"DAP_UINT64_FORMAT_U"\n"
"\t\t Info:"
"\t\t\t units: 0x%016"DAP_UINT64_FORMAT_x"\n"
"\t\t\t uid: 0x%016"DAP_UINT64_FORMAT_x"\n"
"\t\t\t units type: %s \n"
"\t\t\t value: %s (%s)\n",
((dap_chain_datum_tx_receipt_t*)item)->size,
((dap_chain_datum_tx_receipt_t*)item)->exts_size,
((dap_chain_datum_tx_receipt_t*)item)->receipt_info.units,
((dap_chain_datum_tx_receipt_t*)item)->receipt_info.srv_uid.uint64,
dap_chain_srv_unit_enum_to_str(((dap_chain_datum_tx_receipt_t*)item)->receipt_info.units_type.enm),
l_coins_str,
l_value_str);
if (((dap_chain_datum_tx_receipt_t*)item)->exts_size == sizeof(dap_sign_t) + sizeof(dap_sign_t)){
dap_sign_t *l_provider = DAP_NEW_Z(dap_sign_t);
if (!l_provider) {
log_it(L_CRITICAL, "Memory allocation error");
DAP_DELETE(l_value_str);
DAP_DELETE(l_coins_str);
return false;
}
memcpy(l_provider, ((dap_chain_datum_tx_receipt_t*)item)->exts_n_signs, sizeof(dap_sign_t));
dap_sign_t *l_client = DAP_NEW_Z(dap_sign_t);
if (!l_client) {
log_it(L_CRITICAL, "Memory allocation error");
DAP_DEL_Z(l_provider);
DAP_DELETE(l_value_str);
DAP_DELETE(l_coins_str);
return false;
}
memcpy(l_client,
((dap_chain_datum_tx_receipt_t*)item)->exts_n_signs + sizeof(dap_sign_t),
sizeof(dap_sign_t));
dap_string_append_printf(a_str_out, "Exts:\n"
" Provider:\n");
dap_sign_get_information(l_provider, a_str_out, a_hash_out_type);
dap_string_append_printf(a_str_out, " Client:\n");
dap_sign_get_information(l_client, a_str_out, a_hash_out_type);
} else if (((dap_chain_datum_tx_receipt_t*)item)->exts_size == sizeof(dap_sign_t)) {
dap_sign_t *l_provider = DAP_NEW_Z(dap_sign_t);
if (!l_provider) {
log_it(L_CRITICAL, "Memory allocation error");
DAP_DELETE(l_value_str);
DAP_DELETE(l_coins_str);
return false;
}
memcpy(l_provider, ((dap_chain_datum_tx_receipt_t*)item)->exts_n_signs, sizeof(dap_sign_t));
dap_string_append_printf(a_str_out, "Exts:\n"
" Provider:\n");
dap_sign_get_information(l_provider, a_str_out, a_hash_out_type);
}
DAP_DELETE(l_value_str);
DAP_DELETE(l_coins_str);
} break;
case TX_ITEM_TYPE_PKEY: {
l_pkey_tmp = (dap_pkey_t*)((dap_chain_tx_pkey_t*)item)->pkey;
dap_chain_hash_fast_t l_pkey_hash_tmp;
dap_hash_fast(l_pkey_tmp->pkey, l_pkey_tmp->header.size, &l_pkey_hash_tmp);
l_hash_str = dap_strcmp(a_hash_out_type, "hex")
? dap_enc_base58_encode_hash_to_str(&l_pkey_hash_tmp)
: dap_chain_hash_fast_to_str_new(&l_pkey_hash_tmp);
dap_string_append_printf(a_str_out, "\t PKey: \n"
"\t\t SIG type: %s\n"
"\t\t SIG size: %u\n"
"\t\t Sequence number: %u \n"
"\t\t Key: \n"
"\t\t\t Type: %s\n"
"\t\t\t Size: %u\n"
"\t\t\t Hash: %s\n",
dap_sign_type_to_str(((dap_chain_tx_pkey_t*)item)->header.sig_type),
((dap_chain_tx_pkey_t*)item)->header.sig_size,
((dap_chain_tx_pkey_t*)item)->seq_no,
dap_pkey_type_to_str(l_pkey_tmp->header.type),
l_pkey_tmp->header.size,
l_hash_str);
DAP_DELETE(l_hash_str);
} break;
case TX_ITEM_TYPE_TSD: {
dap_string_append_printf(a_str_out, "\t TSD data: \n"
"\t\t type: %d\n"
"\t\t size: %lu\n",
((dap_chain_tx_tsd_t*)item)->header.type,
((dap_chain_tx_tsd_t*)item)->header.size);
} break;
case TX_ITEM_TYPE_IN_COND:
l_hash_tmp = &((dap_chain_tx_in_cond_t*)item)->header.tx_prev_hash;
l_hash_str = dap_strcmp(a_hash_out_type, "hex")
? dap_enc_base58_encode_hash_to_str(l_hash_tmp)
: dap_chain_hash_fast_to_str_new(l_hash_tmp);
dap_string_append_printf(a_str_out, "\t IN COND:\n\t\tReceipt_idx: %u\n"
"\t\t Tx_prev_hash: %s\n"
"\t\t Tx_out_prev_idx: %u\n",
((dap_chain_tx_in_cond_t*)item)->header.receipt_idx,
l_hash_str,
((dap_chain_tx_in_cond_t*)item)->header.tx_out_prev_idx);
DAP_DELETE(l_hash_str);
break;
case TX_ITEM_TYPE_OUT_COND: {
char *l_value_str = dap_chain_balance_print(((dap_chain_tx_out_cond_t*)item)->header.value);
char *l_coins_str = dap_chain_balance_to_coins(((dap_chain_tx_out_cond_t*)item)->header.value);
dap_time_t l_ts_exp = ((dap_chain_tx_out_cond_t*)item)->header.ts_expires;
dap_string_append_printf(a_str_out, "\t OUT COND:\n"
"\t Header:\n"
"\t\t ts_expires: %s"
"\t\t value: %s (%s)\n"
"\t\t subtype: %s\n"
"\t\t uid: 0x%016"DAP_UINT64_FORMAT_x"\n",
l_ts_exp ? dap_ctime_r(&l_ts_exp, l_tmp_buf) : "never\n",
l_coins_str, l_value_str,
dap_chain_tx_out_cond_subtype_to_str(((dap_chain_tx_out_cond_t*)item)->header.subtype),
((dap_chain_tx_out_cond_t*)item)->header.srv_uid.uint64);
DAP_DELETE(l_value_str);
DAP_DELETE(l_coins_str);
switch (((dap_chain_tx_out_cond_t*)item)->header.subtype) {
case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_PAY: {
char *l_value_str = dap_chain_balance_print(((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.unit_price_max_datoshi);
char *l_coins_str = dap_chain_balance_to_coins(((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.unit_price_max_datoshi);
l_hash_tmp = &((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.pkey_hash;
l_hash_str = dap_strcmp(a_hash_out_type, "hex")
? dap_enc_base58_encode_hash_to_str(l_hash_tmp)
: dap_chain_hash_fast_to_str_new(l_hash_tmp);
dap_string_append_printf(a_str_out, "\t\t\t unit: 0x%08x\n"
"\t\t\t pkey: %s\n"
"\t\t\t max price: %s (%s)\n",
((dap_chain_tx_out_cond_t*)item)->subtype.srv_pay.unit.uint32,
l_hash_str,
l_coins_str,
l_value_str);
DAP_DELETE(l_hash_str);
DAP_DELETE(l_value_str);
DAP_DELETE(l_coins_str);
} break;
case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_POS_DELEGATE: {
dap_chain_node_addr_t *l_signer_node_addr = &((dap_chain_tx_out_cond_t*)item)->subtype.srv_stake_pos_delegate.signer_node_addr;
dap_chain_addr_t *l_signing_addr = &((dap_chain_tx_out_cond_t*)item)->subtype.srv_stake_pos_delegate.signing_addr;
char *l_addr_str = dap_chain_addr_to_str(l_signing_addr);
l_hash_tmp = &l_signing_addr->data.hash_fast;
l_hash_str = dap_strcmp(a_hash_out_type, "hex")
? dap_enc_base58_encode_hash_to_str(l_hash_tmp)
: dap_chain_hash_fast_to_str_new(l_hash_tmp);
dap_string_append_printf(a_str_out, "\t\t\t signing_addr: %s\n"
"\t\t\t with pkey hash %s\n"
"\t\t\t signer_node_addr: "NODE_ADDR_FP_STR"\n",
l_addr_str,
l_hash_str,
NODE_ADDR_FP_ARGS(l_signer_node_addr));
DAP_DELETE(l_addr_str);
DAP_DELETE(l_hash_str);
} break;
case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_XCHANGE: {
char *l_value_str = dap_chain_balance_print(((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_value);
char *l_coins_str = dap_chain_balance_to_coins(((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_value);
dap_string_append_printf(a_str_out, "\t\t\t net id: 0x%016"DAP_UINT64_FORMAT_x"\n"
"\t\t\t buy_token: %s\n"
"\t\t\t buy_value: %s (%s)\n",
((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_net_id.uint64,
((dap_chain_tx_out_cond_t*)item)->subtype.srv_xchange.buy_token,
l_coins_str,
l_value_str);
DAP_DELETE(l_value_str);
DAP_DELETE(l_coins_str);
} break;
case DAP_CHAIN_TX_OUT_COND_SUBTYPE_SRV_STAKE_LOCK: {
dap_time_t l_ts_exp = ((dap_chain_tx_out_cond_t*)item)->subtype.srv_stake_lock.time_unlock;
dap_string_append_printf(a_str_out, "\t\t\t time_unlock %s\n",
dap_ctime_r(&l_ts_exp, l_tmp_buf));
} break;
default: break;
}
} break;
case TX_ITEM_TYPE_OUT_EXT: {
char *l_value_str = dap_chain_balance_print(((dap_chain_tx_out_ext_t*)item)->header.value);
char *l_coins_str = dap_chain_balance_to_coins(((dap_chain_tx_out_ext_t*)item)->header.value);
char *l_addr_str = dap_chain_addr_to_str(&((dap_chain_tx_out_ext_t*)item)->addr);
dap_string_append_printf(a_str_out, "\t OUT EXT:\n"
"\t\t Addr: %s\n"
"\t\t Token: %s\n"
"\t\t Value: %s (%s)\n",
l_addr_str,
((dap_chain_tx_out_ext_t*)item)->token,
l_coins_str,
l_value_str);
DAP_DELETE(l_addr_str);
DAP_DELETE(l_value_str);
DAP_DELETE(l_coins_str);
} break;
default:
dap_string_append_printf(a_str_out, " This transaction have unknown item type \n");
break;
}
l_tx_items_count += l_item_tx_size;
// Freeze protection
if(!l_item_tx_size)
{
break;
}
}
dap_string_append_printf(a_str_out, "\n");
return true;
}
/**
* @brief dap_chain_net_dump_datum
* process datum verification process. Can be:
* if DAP_CHAIN_DATUM_TX, called dap_chain_ledger_tx_add_check
* if DAP_CHAIN_DATUM_TOKEN_DECL, called dap_chain_ledger_token_decl_add_check
* if DAP_CHAIN_DATUM_TOKEN_EMISSION, called dap_chain_ledger_token_emission_add_check
* @param a_str_out
* @param a_datum
*/
void dap_chain_datum_dump(dap_string_t *a_str_out, dap_chain_datum_t *a_datum, const char *a_hash_out_type, dap_chain_net_id_t a_net_id)
{
if( a_datum == NULL){
dap_string_append_printf(a_str_out,"==Datum is NULL\n");
return;
}
dap_hash_fast_t l_datum_hash;
dap_hash_fast(a_datum->data, a_datum->header.data_size, &l_datum_hash);
char *l_hash_str = dap_strcmp(a_hash_out_type, "hex")
? dap_enc_base58_encode_hash_to_str(&l_datum_hash)
: dap_chain_hash_fast_to_str_new(&l_datum_hash);
switch (a_datum->header.type_id) {
case DAP_CHAIN_DATUM_TOKEN_DECL: {
size_t l_token_size = a_datum->header.data_size;
dap_chain_datum_token_t * l_token = dap_chain_datum_token_read(a_datum->data, &l_token_size);
if(l_token_size < sizeof(dap_chain_datum_token_t)){
dap_string_append_printf(a_str_out,"==Datum has incorrect size. Only %zu, while at least %zu is expected\n",
l_token_size, sizeof(dap_chain_datum_token_t));
DAP_DEL_Z(l_token);
return;
}
dap_string_append_printf(a_str_out,"=== Datum Token Declaration ===\n");
dap_string_append_printf(a_str_out, "hash: %s\n", l_hash_str);
dap_string_append_printf(a_str_out, "ticker: %s\n", l_token->ticker);
dap_string_append_printf(a_str_out, "size: %zd\n", l_token_size);
dap_string_append_printf(a_str_out, "version: %d\n", l_token->version);
switch (l_token->type) {
case DAP_CHAIN_DATUM_TOKEN_TYPE_DECL: {
dap_string_append(a_str_out,"type: DECL\n");
switch (l_token->subtype) {
case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE:{
char *l_value_str = dap_chain_balance_print(l_token->total_supply);
dap_string_append(a_str_out,"subtype: PRIVATE\n");
dap_string_append_printf(a_str_out, "decimals: %d\n", l_token->header_private_decl.decimals);
dap_string_append_printf(a_str_out, "auth signs (valid/total) %u/%u\n", l_token->signs_valid, l_token->signs_total);
dap_string_append_printf(a_str_out, "total_supply: %s\n", l_value_str);
dap_string_append(a_str_out,"flags: ");
dap_chain_datum_token_flags_dump(a_str_out, l_token->header_private_update.flags);
s_datum_token_dump_tsd(a_str_out, l_token, l_token_size, a_hash_out_type);
size_t l_certs_field_size = l_token_size - sizeof(*l_token) - l_token->header_private_update.tsd_total_size;
dap_chain_datum_token_certs_dump(a_str_out, l_token->data_n_tsd + l_token->header_private_update.tsd_total_size,
l_certs_field_size, a_hash_out_type);
DAP_DEL_Z(l_value_str);
}break;
case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE: {
char *l_value_str = dap_chain_balance_print(l_token->total_supply);
dap_string_append(a_str_out, "subtype: CF20\n");
dap_string_append_printf(a_str_out, "decimals: %d\n", l_token->header_native_decl.decimals);
dap_string_append_printf(a_str_out, "auth signs (valid/total) %u/%u\n", l_token->signs_valid, l_token->signs_total);
dap_string_append_printf(a_str_out, "total_supply: %s\n", l_value_str);
dap_string_append(a_str_out, "flags: ");
dap_chain_datum_token_flags_dump(a_str_out, l_token->header_native_decl.flags);
s_datum_token_dump_tsd(a_str_out, l_token, l_token_size, a_hash_out_type);
size_t l_certs_field_size = l_token_size - sizeof(*l_token) - l_token->header_native_decl.tsd_total_size;
dap_chain_datum_token_certs_dump(a_str_out, l_token->data_n_tsd + l_token->header_native_decl.tsd_total_size,
l_certs_field_size, a_hash_out_type);
DAP_DEL_Z(l_value_str);
}break;
case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PUBLIC: {
char *l_premine_supply = dap_chain_balance_print(l_token->header_public.premine_supply);
dap_chain_addr_t l_premine_addr = l_token->header_public.premine_address;
char *l_premine_addr_str = dap_chain_addr_to_str(&l_premine_addr);
dap_string_append(a_str_out, "subtype: PUBLIC\n");
dap_string_append_printf(a_str_out, "premine_supply: %s", l_premine_supply);
dap_string_append_printf(a_str_out, "premine_address: %s", l_premine_addr_str);
dap_string_append(a_str_out, "flags: ");
dap_chain_datum_token_flags_dump(a_str_out, l_token->header_public.flags);
DAP_DELETE(l_premine_supply);
DAP_DELETE(l_premine_addr_str);
}break;
}
}break;
case DAP_CHAIN_DATUM_TOKEN_TYPE_UPDATE: {
dap_string_append(a_str_out,"type: UPDATE\n");
switch (l_token->subtype) {
case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_PRIVATE: {
char *l_value_str = dap_chain_balance_print(l_token->total_supply);
dap_string_append(a_str_out,"subtype: PRIVATE\n");
dap_string_append_printf(a_str_out, "decimals: %d\n", l_token->header_private_decl.decimals);
dap_string_append_printf(a_str_out, "auth signs (valid/total) %u/%u\n", l_token->signs_valid, l_token->signs_total);
dap_string_append_printf(a_str_out, "total_supply: %s\n", l_value_str);
dap_string_append(a_str_out,"flags: ");
dap_chain_datum_token_flags_dump(a_str_out, l_token->header_private_update.flags);
s_datum_token_dump_tsd(a_str_out, l_token, l_token_size, a_hash_out_type);
size_t l_certs_field_size = l_token_size - sizeof(*l_token) - l_token->header_private_update.tsd_total_size;
dap_chain_datum_token_certs_dump(a_str_out, l_token->data_n_tsd + l_token->header_private_update.tsd_total_size,
l_certs_field_size, a_hash_out_type);
DAP_DEL_Z(l_value_str);
}break;
case DAP_CHAIN_DATUM_TOKEN_SUBTYPE_NATIVE: {
char *l_value_str = dap_chain_balance_print(l_token->total_supply);
dap_string_append_printf(a_str_out,"subtype: CF20\n");
dap_string_append_printf(a_str_out, "decimals: %d\n", l_token->header_native_update.decimals);
dap_string_append_printf(a_str_out, "auth signs (valid/total) %u/%u\n", l_token->signs_valid, l_token->signs_total);
dap_string_append_printf(a_str_out, "total_supply: %s\n", l_value_str);
dap_string_append(a_str_out, "flags: ");
dap_chain_datum_token_flags_dump(a_str_out, l_token->header_native_update.flags);
s_datum_token_dump_tsd(a_str_out, l_token, l_token_size, a_hash_out_type);
size_t l_certs_field_size = l_token_size - sizeof(*l_token) - l_token->header_native_update.tsd_total_size;
dap_chain_datum_token_certs_dump(a_str_out, l_token->data_n_tsd + l_token->header_native_update.tsd_total_size,
l_certs_field_size, a_hash_out_type);
DAP_DEL_Z(l_value_str);
}break;
}
}break;
default:
dap_string_append(a_str_out,"type: UNKNOWN\n");
break;
}
if (l_token->subtype == DAP_CHAIN_DATUM_TOKEN_SUBTYPE_SIMPLE ) {
char *l_value_str = dap_chain_balance_print(l_token->total_supply);
dap_string_append(a_str_out, "subtype: SIMPLE\n");
dap_string_append_printf(a_str_out, "decimals: %d\n", l_token->header_simple.decimals);
dap_string_append_printf(a_str_out, "sign_total: %hu\n", l_token->signs_total );
dap_string_append_printf(a_str_out, "sign_valid: %hu\n", l_token->signs_valid );
dap_string_append_printf(a_str_out, "total_supply: %s\n", l_value_str);
size_t l_certs_field_size = l_token_size - sizeof(*l_token);
dap_chain_datum_token_certs_dump(a_str_out, l_token->data_n_tsd,
l_certs_field_size, a_hash_out_type);
DAP_DEL_Z(l_value_str);
}
DAP_DELETE(l_token);
} break;
case DAP_CHAIN_DATUM_TOKEN_EMISSION: {
size_t l_emisssion_size = a_datum->header.data_size;
dap_chain_datum_token_emission_t *l_emission = dap_chain_datum_emission_read(a_datum->data, &l_emisssion_size);
char *l_value_str = dap_chain_balance_print(l_emission->hdr.value_256);
char *l_coins_str = dap_chain_balance_to_coins(l_emission->hdr.value_256);
char *l_addr_str = dap_chain_addr_to_str(&(l_emission->hdr.address));
dap_string_append_printf(a_str_out, "emission: hash %s\n\t%s(%s) %s, type: %s, version: %d\n",
l_hash_str,
l_coins_str,
l_value_str,
l_emission->hdr.ticker,
c_dap_chain_datum_token_emission_type_str[l_emission->hdr.type],
l_emission->hdr.version);
dap_string_append_printf(a_str_out, " to addr: %s\n", l_addr_str);
DAP_DELETE(l_value_str);
DAP_DELETE(l_coins_str);
DAP_DELETE(l_addr_str);
switch (l_emission->hdr.type) {
case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_UNDEFINED:
break;
case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_AUTH:
dap_string_append_printf(a_str_out, " signs_count: %d\n", l_emission->data.type_auth.signs_count);
dap_string_append_printf(a_str_out, " tsd_total_size: %"DAP_UINT64_FORMAT_U"\n",
l_emission->data.type_auth.tsd_total_size);
if ( ( (void *) l_emission->tsd_n_signs + l_emission->data.type_auth.tsd_total_size) >
((void *) l_emission + l_emisssion_size) )
{
log_it(L_ERROR, "Illformed DATUM type %d, TSD section is out-of-buffer (%" DAP_UINT64_FORMAT_U " vs %zu)",
l_emission->hdr.type, l_emission->data.type_auth.tsd_total_size, l_emisssion_size);
dap_string_append_printf(a_str_out, " Skip incorrect or illformed DATUM");
break;
}
dap_chain_datum_token_certs_dump(a_str_out, l_emission->tsd_n_signs + l_emission->data.type_auth.tsd_total_size,
l_emission->data.type_auth.size - l_emission->data.type_auth.tsd_total_size, a_hash_out_type);
break;
case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_ALGO:
dap_string_append_printf(a_str_out, " codename: %s\n", l_emission->data.type_algo.codename);
break;
case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_ATOM_OWNER:
dap_string_append_printf(a_str_out, " value_start: %.0Lf(%"DAP_UINT64_FORMAT_U"), codename: %s\n",
dap_chain_datoshi_to_coins(l_emission->data.type_atom_owner.value_start),
l_emission->data.type_atom_owner.value_start,
l_emission->data.type_atom_owner.value_change_algo_codename
);
break;
case DAP_CHAIN_DATUM_TOKEN_EMISSION_TYPE_SMART_CONTRACT: {
char l_time_str[70];
char *l_addr = dap_chain_addr_to_str(&l_emission->data.type_presale.addr);
// get time of create datum
if(dap_time_to_str_rfc822(l_time_str, 71, l_emission->data.type_presale.lock_time) < 1)
l_time_str[0] = '\0';
dap_string_append_printf(a_str_out, " flags: 0x%x, lock_time: %s\n", l_emission->data.type_presale.flags, l_time_str);
dap_string_append_printf(a_str_out, " addr: %s\n", l_addr);
DAP_DELETE(l_addr);
}
break;
}
DAP_DELETE(l_emission);
} break;
case DAP_CHAIN_DATUM_TX: {
dap_chain_datum_tx_t *l_tx = (dap_chain_datum_tx_t *)a_datum->data;
dap_chain_datum_dump_tx(l_tx, NULL, a_str_out, a_hash_out_type, &l_datum_hash, a_net_id);
} break;
case DAP_CHAIN_DATUM_DECREE:{
dap_chain_datum_decree_t *l_decree = (dap_chain_datum_decree_t *)a_datum->data;
size_t l_decree_size = dap_chain_datum_decree_get_size(l_decree);
dap_string_append_printf(a_str_out,"=== Datum decree ===\n");
dap_string_append_printf(a_str_out, "hash: %s\n", l_hash_str);
dap_string_append_printf(a_str_out, "size: %zd\n", l_decree_size);
dap_chain_datum_decree_dump(a_str_out, l_decree, l_decree_size, a_hash_out_type);
} break;
case DAP_CHAIN_DATUM_ANCHOR:{
dap_chain_datum_anchor_t *l_anchor = (dap_chain_datum_anchor_t *)a_datum->data;
size_t l_anchor_size = sizeof(dap_chain_datum_anchor_t) + l_anchor->header.data_size + l_anchor->header.signs_size;
dap_string_append_printf(a_str_out,"=== Datum anchor ===\n");
dap_string_append_printf(a_str_out, "hash: %s\n", l_hash_str);
dap_string_append_printf(a_str_out, "size: %zd\n", l_anchor_size);
dap_hash_fast_t l_decree_hash = { };
dap_chain_datum_anchor_get_hash_from_data(l_anchor, &l_decree_hash);
//dap_chain_hash_fast_to_str(&l_decree_hash, l_decree_hash_str, 40);
char l_decree_hash_str[DAP_CHAIN_HASH_FAST_STR_SIZE];
dap_chain_hash_fast_to_str(&l_decree_hash, l_decree_hash_str, DAP_CHAIN_HASH_FAST_STR_SIZE);
dap_string_append_printf(a_str_out, "decree hash: %s\n", l_decree_hash_str);
dap_chain_datum_anchor_certs_dump(a_str_out, l_anchor->data_n_sign + l_anchor->header.data_size, l_anchor->header.signs_size, a_hash_out_type);
} break;
}
DAP_DELETE(l_hash_str);
}
json_object * dap_chain_datum_to_json(dap_chain_datum_t* a_datum){
json_object *l_object = json_object_new_object();
char *l_hash_data_str;
dap_get_data_hash_str_static(a_datum->data, a_datum->header.data_size, l_hash_data_str);
json_object *l_obj_data_hash = json_object_new_string(l_hash_data_str);
json_object *l_obj_version = json_object_new_int(a_datum->header.version_id);
json_object *l_obj_size = json_object_new_int(a_datum->header.data_size);
json_object *l_obj_ts_created = json_object_new_uint64(a_datum->header.ts_create);
json_object *l_obj_type = json_object_new_string(dap_chain_datum_type_id_to_str(a_datum->header.type_id));
json_object *l_obj_data;
switch (a_datum->header.type_id) {
case DAP_CHAIN_DATUM_TX:
l_obj_data = dap_chain_datum_tx_to_json((dap_chain_datum_tx_t*)a_datum->data);
break;
default:
l_obj_data = json_object_new_null();
break;
}
json_object_object_add(l_object, "version", l_obj_version);
json_object_object_add(l_object, "hash", l_obj_data_hash);
json_object_object_add(l_object, "data_size", l_obj_size);
json_object_object_add(l_object, "ts_created", l_obj_ts_created);
json_object_object_add(l_object, "type", l_obj_type);
json_object_object_add(l_object, "data", l_obj_data);
return l_object;
}