Skip to content
Snippets Groups Projects
dap_chain_common.c 5.61 KiB
Newer Older
/*
 * 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_chain_sign.h"
#include "dap_chain_common.h"
#include "dap_hash.h"
#define LOG_TAG "chain_common"

/**
 * @brief dap_chain_hash_to_str
 * @param a_hash
 * @param a_str
 * @param a_str_max
 * @return
 */
size_t dap_chain_hash_slow_to_str(dap_chain_hash_slow_t * a_hash, char * a_str, size_t a_str_max)
    const size_t c_hash_str_size = sizeof(*a_hash) * 2 + 1 /*trailing zero*/+ 2 /* heading 0x */;
    if(a_str_max < c_hash_str_size) {
        log_it(L_ERROR, "String for hash too small, need %u but have only %u", c_hash_str_size, a_str_max);
    snprintf(a_str, 3, "0x");
    for(i = 0; i < sizeof(a_hash->raw); ++i)
        snprintf(a_str + i * 2 + 2, 3, "%02x", a_hash->raw[i]);
    a_str[c_hash_str_size] = '\0';
    return strlen(a_str);
}

/**
 * @brief dap_chain_hash_fast_to_str
 * @param a_hash
 * @param a_str
 * @param a_str_max
 * @return
 */
size_t dap_chain_hash_fast_to_str(dap_chain_hash_fast_t * a_hash, char * a_str, size_t a_str_max)
{
    const size_t c_hash_str_size = sizeof(*a_hash) * 2 + 1 /*trailing zero*/+ 2 /* heading 0x */;
    if(a_str_max < c_hash_str_size) {
        log_it(L_ERROR, "String for hash too small, need %u but have only %u", c_hash_str_size, a_str_max);
    }
    size_t i;
    snprintf(a_str, 3, "0x");
    for(i = 0; i < sizeof(a_hash->raw); ++i)
        snprintf(a_str + i * 2 + 2, 3, "%02x", a_hash->raw[i]);
    a_str[c_hash_str_size] = '\0';
    return strlen(a_str);
/**
 * @brief dap_chain_str_to_hash_fast_to_str
 * @param a_hash_str
 * @param a_hash
 * @return
 */
int dap_chain_str_to_hash_fast( const char * a_hash_str, dap_chain_hash_fast_t * a_hash)
{
    const size_t c_hash_str_size = sizeof(*a_hash) * 2 + 1 /*trailing zero*/+ 2 /* heading 0x */;
    size_t l_hash_str_len = strlen( a_hash_str);
    if ( l_hash_str_len == c_hash_str_size ){
        for (size_t l_offset = 2; l_offset < c_hash_str_size ; l_offset+=2 ){
            if ( ( sscanf(a_hash_str+l_offset,"%02hhx",a_hash->raw+l_offset-2) != 1) ||
                 ( sscanf(a_hash_str+l_offset,"%02hhX",a_hash->raw+l_offset-2) != 1)
                 )
                return -10* ((int) l_offset); // Wrong char
        }
        return  0;
    }else  // Wromg string len
        return -1;
}

char* dap_chain_addr_to_str(const dap_chain_addr_t *a_addr)
    size_t l_ret_size = DAP_ENC_BASE58_ENCODE_SIZE(sizeof(dap_chain_addr_t));
    char * l_ret = DAP_NEW_SIZE(char, l_ret_size);
    if(dap_enc_base58_encode(a_addr, sizeof(dap_chain_addr_t), l_ret) > 0)

/**
 * @brief dap_chain_str_to_addr
 * @param a_addr
 * @return
 */
dap_chain_addr_t* dap_chain_str_to_addr(const char *a_str)
    size_t l_str_len = (a_str) ? strlen(a_str) : 0;
    if(l_str_len <= 0)
    size_t l_ret_size = DAP_ENC_BASE58_DECODE_SIZE(l_str_len);
    dap_chain_addr_t * l_addr = DAP_NEW_Z_SIZE(dap_chain_addr_t, l_ret_size);
    if(dap_enc_base58_decode(a_str, l_addr) == sizeof(dap_chain_addr_t) &&
            dap_chain_addr_check_sum(l_addr)==1)
        return l_addr;
        DAP_DELETE(l_addr);

/**
 * @brief dap_chain_addr_fill
 * @param a_addr
 * @param a_key
 * @param a_net_id
 * @return
 */
void dap_chain_addr_fill(dap_chain_addr_t *a_addr, dap_enc_key_t *a_key, dap_chain_net_id_t *a_net_id)
{
    if(!a_addr || !a_key || !a_net_id)
        return;
    a_addr->addr_ver = DAP_CHAIN_ADDR_VERSION_CURRENT;
    a_addr->net_id.uint64 = a_net_id->uint64;
    a_addr->sig_type.raw = dap_chain_sign_type_from_key_type(a_key->type).raw;
    // key -> serialized key
    dap_chain_hash_fast_t l_hash_public_key;
    size_t l_pub_key_data_size;
    uint8_t *l_pub_key_data = dap_enc_key_serealize_pub_key(a_key, &l_pub_key_data_size);
    // serialized key -> key hash
    if(dap_hash_fast(l_pub_key_data, l_pub_key_data_size, &l_hash_public_key)==1)
        memcpy(a_addr->data.hash, l_hash_public_key.raw, sizeof(l_hash_public_key.raw));

    // calc checksum
    dap_hash_fast(a_addr, sizeof(dap_chain_addr_t) - sizeof(dap_chain_hash_fast_t), &a_addr->checksum);
}

/**
 * @brief dap_chain_addr_check_sum
 * @param a_addr
 * @return 1 Ok, -1 Invalid a_addr or checksum
 */
int dap_chain_addr_check_sum(const dap_chain_addr_t *a_addr)
{
    if(!a_addr)
        return -1;
    dap_chain_hash_fast_t l_checksum;
    // calc checksum
    dap_hash_fast(a_addr, sizeof(dap_chain_addr_t) - sizeof(dap_chain_hash_fast_t), &l_checksum);
    if(!memcmp(a_addr->checksum.raw, l_checksum.raw, sizeof(l_checksum.raw)))
        return 1;
    return -1;
}