-
36cd548c
dap_chain_common.h 10.85 KiB
/*
* Authors:
* Dmitriy A. Gearasimov <gerasimov.dmitriy@demlabs.net>
* DeM Labs Inc. https://demlabs.net https:/gitlab.com/demlabs
* 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/>.
*/
#pragma once
#include <stdint.h>
#include <stdio.h>
#include "dap_common.h"
#include "dap_math_ops.h"
#include "dap_enc_key.h"
#include "dap_pkey.h"
#include "dap_sign.h"
#include "dap_hash.h"
#include <json-c/json.h>
#include "dap_strfuncs.h"
#define DAP_CHAIN_ADDR_VERSION_CURRENT 1
#define DAP_CHAIN_ID_SIZE 8
#define DAP_CHAIN_SHARD_ID_SIZE 8
#define DAP_CHAIN_NET_ID_SIZE 8
#define DAP_CHAIN_NODE_ROLE_SIZE 4
#define DAP_CHAIN_HASH_SLOW_SIZE 32
#define DAP_CHAIN_TIMESTAMP_SIZE 8
#define DAP_CHAIN_TICKER_SIZE_MAX 10
#define DATOSHI_LD 1000000000.0L // Deprecated
#define DATOSHI_DEGREE 18
#define DATOSHI_POW 39
#define DATOSHI_POW256 (DATOSHI_POW * 2)
// Chain ID of the whole system
typedef union dap_chain_id {
uint8_t raw[DAP_CHAIN_ID_SIZE];
uint64_t uint64;
} DAP_ALIGN_PACKED dap_chain_id_t;
// Shard ID
typedef union dap_chain_cell_id {
uint8_t raw[DAP_CHAIN_SHARD_ID_SIZE];
uint64_t uint64;
} DAP_ALIGN_PACKED dap_chain_cell_id_t;
/**
* @struct Node address
*
*/
typedef union dap_chain_node_addr {
uint64_t uint64;
uint16_t words[sizeof(uint64_t)/2];
uint8_t raw[sizeof(uint64_t)]; // Access to selected octects
} DAP_ALIGN_PACKED dap_chain_node_addr_t;
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
#define NODE_ADDR_FP_STR "%04hX::%04hX::%04hX::%04hX"
#define NODE_ADDR_FP_ARGS(a) a->words[2],a->words[3],a->words[0],a->words[1]
#define NODE_ADDR_FPS_ARGS(a) &a->words[2],&a->words[3],&a->words[0],&a->words[1]
#define NODE_ADDR_FP_ARGS_S(a) a.words[2],a.words[3],a.words[0],a.words[1]
#define NODE_ADDR_FPS_ARGS_S(a) &a.words[2],&a.words[3],&a.words[0],&a.words[1]
#else
#define NODE_ADDR_FP_STR "%04hX::%04hX::%04hX::%04hX"
#define NODE_ADDR_FP_ARGS(a) a->words[3],a->words[2],a->words[1],a->words[0]
#define NODE_ADDR_FPS_ARGS(a) &a->words[3],&a->words[2],&a->words[1],&a->words[0]
#define NODE_ADDR_FP_ARGS_S(a) a.words[3],a.words[2],a.words[1],a.words[0]
#define NODE_ADDR_FPS_ARGS_S(a) &a.words[3],&a.words[2],&a.words[1],&a.words[0]
#endif
DAP_STATIC_INLINE bool dap_chain_node_addr_str_check(const char *a_addr_str) {
size_t l_str_len = dap_strlen(a_addr_str);
if (l_str_len == 22) {
for (int n =0; n < 22; n+= 6) {
if (!dap_is_xdigit(a_addr_str[n]) || !dap_is_xdigit(a_addr_str[n + 1]) ||
!dap_is_xdigit(a_addr_str[n + 2]) || !dap_is_xdigit(a_addr_str[n + 3])) {
return false;
}
}
for (int n = 4; n < 18; n += 6) {
if (a_addr_str[n] != ':' || a_addr_str[n + 1] != ':')
return false;
}
return true;
}
return false;
}
DAP_STATIC_INLINE int dap_chain_node_addr_from_str(dap_chain_node_addr_t *a_addr, const char *a_addr_str)
{
if (sscanf(a_addr_str, NODE_ADDR_FP_STR, NODE_ADDR_FPS_ARGS(a_addr)) == 4)
return 0;
if (sscanf(a_addr_str, "0x%016"DAP_UINT64_FORMAT_x, &a_addr->uint64) == 1)
return 0;
return -1;
}
DAP_STATIC_INLINE bool dap_chain_node_addr_not_null(dap_chain_node_addr_t * a_addr) { return a_addr->uint64 != 0; }
enum {
NODE_ROLE_ROOT_MASTER=0x00,
NODE_ROLE_ROOT=0x01,
NODE_ROLE_ARCHIVE=0x02,
NODE_ROLE_CELL_MASTER=0x10,
NODE_ROLE_MASTER = 0x20,
NODE_ROLE_FULL=0xf0,
NODE_ROLE_LIGHT=0xff
};
typedef union dap_chain_node_role{
uint32_t enums;
uint8_t raw[DAP_CHAIN_NODE_ROLE_SIZE];
} DAP_ALIGN_PACKED dap_chain_node_role_t;
typedef union dap_chain_net_id{
uint64_t uint64;
uint8_t raw[DAP_CHAIN_NET_ID_SIZE];
} DAP_ALIGN_PACKED dap_chain_net_id_t;
typedef union dap_chain_hash_slow{
uint8_t raw[DAP_CHAIN_HASH_SLOW_SIZE];
} dap_chain_hash_slow_t;
typedef enum dap_chain_hash_slow_kind {
HASH_GOLD = 0, HASH_SILVER, HASH_COPPER, HASH_USELESS = -1
} dap_chain_hash_slow_kind_t;
typedef struct dap_chain_addr{
uint8_t addr_ver; // 0 for default
dap_chain_net_id_t net_id; // Testnet, mainnet or alternet
dap_sign_type_t sig_type;
union {
//dap_chain_hash_fast_t hash;
struct {
uint8_t key_spend[sizeof(dap_chain_hash_fast_t)/2];
uint8_t key_view[sizeof(dap_chain_hash_fast_t)/2];
} DAP_ALIGN_PACKED key_sv;
uint8_t key[sizeof(dap_chain_hash_fast_t)];
uint8_t hash[sizeof(dap_chain_hash_fast_t)];
dap_chain_hash_fast_t hash_fast;
} DAP_ALIGN_PACKED data;
dap_chain_hash_fast_t checksum;
} DAP_ALIGN_PACKED dap_chain_addr_t;
#define DAP_CHAIN_NET_SRV_UID_SIZE 8
typedef union {
uint8_t raw[DAP_CHAIN_NET_SRV_UID_SIZE];
#if DAP_CHAIN_NET_SRV_UID_SIZE == 8
uint64_t raw_ui64[1];
uint64_t uint64;
#elif DAP_CHAIN_NET_SRV_UID_SIZE == 16
uint64_t raw_ui64[1];
uint128_t uint128;
#endif
} dap_chain_net_srv_uid_t;
extern const dap_chain_net_srv_uid_t c_dap_chain_net_srv_uid_null;
extern const dap_chain_cell_id_t c_dap_chain_cell_id_null;
extern const dap_chain_addr_t c_dap_chain_addr_blank;
enum dap_chain_srv_unit_enum {
SERV_UNIT_UNDEFINED = 0 ,
SERV_UNIT_MB = 0x00000001, // megabytes
SERV_UNIT_SEC = 0x00000002, // seconds
SERV_UNIT_DAY = 0x00000003, // days
SERV_UNIT_KB = 0x00000010, // kilobytes
SERV_UNIT_B = 0x00000011, // bytes
SERV_UNIT_PCS = 0x00000022 // pieces
};
typedef uint32_t dap_chain_srv_unit_enum_t;
DAP_STATIC_INLINE const char *dap_chain_srv_unit_enum_to_str(dap_chain_srv_unit_enum_t a_unit_enum)
{
switch (a_unit_enum) {
case SERV_UNIT_UNDEFINED: return "SERV_UNIT_UNDEFINED";
case SERV_UNIT_MB: return "SERV_UNIT_MB";
case SERV_UNIT_SEC: return "SERV_UNIT_SEC";
case SERV_UNIT_DAY: return "SERV_UNIT_DAY";
case SERV_UNIT_KB: return "SERV_UNIT_KB";
case SERV_UNIT_B: return "SERV_UNIT_B";
case SERV_UNIT_PCS: return "SERV_UNIT_PCS";
default: return "UNDEFINED";
}
}
typedef union {
uint8_t raw[4];
uint32_t uint32;
dap_chain_srv_unit_enum_t enm;
} DAP_ALIGN_PACKED dap_chain_net_srv_price_unit_uid_t;
enum dap_chain_tx_item_type {
TX_ITEM_TYPE_IN = 0x00, /// @brief Transaction: inputs
TX_ITEM_TYPE_OUT_OLD = 0x10, /// @brief Transaction: outputs
TX_ITEM_TYPE_OUT_EXT = 0x11,
TX_ITEM_TYPE_OUT = 0x12, // 256
TX_ITEM_TYPE_PKEY = 0x20,
TX_ITEM_TYPE_SIG = 0x30,
TX_ITEM_TYPE_IN_EMS = 0x40,
TX_ITEM_TYPE_IN_EMS_EXT = 0x41,
TX_ITEM_TYPE_IN_COND = 0x50, /// @brief Transaction: conditon inputs
TX_ITEM_TYPE_OUT_COND_OLD = 0x60, // Obsolete
TX_ITEM_TYPE_OUT_COND = 0x61, /// @brief Transaction: 256 bit conditon outputs
TX_ITEM_TYPE_RECEIPT = 0x70,
TX_ITEM_TYPE_TSD = 0x80,
TX_ITEM_TYPE_IN_ALL = 0xfd,
TX_ITEM_TYPE_OUT_ALL = 0xfe,
TX_ITEM_TYPE_ANY = 0xff
};
#define TX_ITEM_TYPE_UNKNOWN TX_ITEM_TYPE_ANY
typedef byte_t dap_chain_tx_item_type_t;
#ifdef __cplusplus
extern "C" {
#endif
size_t dap_chain_hash_slow_to_str(dap_chain_hash_slow_t * a_hash, char * a_str, size_t a_str_max);
char* dap_chain_addr_to_str(const dap_chain_addr_t *a_addr);
json_object *dap_chain_addr_to_json(const dap_chain_addr_t *a_addr);
dap_chain_addr_t* dap_chain_addr_from_str(const char *str);
bool dap_chain_addr_is_blank(const dap_chain_addr_t *a_addr);
DAP_STATIC_INLINE json_object *dap_chain_net_id_to_json(dap_chain_net_id_t a_net_id) {
return json_object_new_uint64(a_net_id.uint64);
}
dap_chain_net_srv_uid_t dap_chain_net_srv_uid_from_str(const char* a_str);
void dap_chain_addr_fill(dap_chain_addr_t *a_addr, dap_sign_type_t a_type, dap_chain_hash_fast_t *a_pkey_hash, dap_chain_net_id_t a_net_id);
int dap_chain_addr_fill_from_key(dap_chain_addr_t *a_addr, dap_enc_key_t *a_key, dap_chain_net_id_t a_net_id);
int dap_chain_addr_fill_from_sign(dap_chain_addr_t *a_addr, dap_sign_t *a_sign, dap_chain_net_id_t a_net_id);
int dap_chain_addr_check_sum(const dap_chain_addr_t *a_addr);
DAP_STATIC_INLINE bool dap_chain_addr_compare(const dap_chain_addr_t *a_addr1, const dap_chain_addr_t *a_addr2)
{
return !memcmp(a_addr1, a_addr2, sizeof(dap_chain_addr_t));
}
// Deprecated
DAP_STATIC_INLINE long double dap_chain_datoshi_to_coins(uint64_t a_count)
{
return (double)a_count / DATOSHI_LD;
}
// Deprecated
DAP_STATIC_INLINE uint64_t dap_chain_coins_to_datoshi(long double a_count)
{
return (uint64_t)(a_count * DATOSHI_LD);
}
DAP_STATIC_INLINE uint128_t dap_chain_uint128_from(uint64_t a_from)
{
return GET_128_FROM_64(a_from);
}
// 256
uint128_t dap_chain_uint128_from_uint256(uint256_t a_from);
// 256
DAP_STATIC_INLINE uint256_t dap_chain_uint256_from(uint64_t a_from)
{
return GET_256_FROM_64(a_from);
}
DAP_STATIC_INLINE uint256_t dap_chain_uint256_from_uint128(uint128_t a_from)
{
return GET_256_FROM_128(a_from);
}
uint64_t dap_chain_uint128_to(uint128_t a_from);
// 256
uint64_t dap_chain_uint256_to(uint256_t a_from);
char *dap_chain_balance_print(uint256_t a_balance);
char *dap_chain_balance_to_coins(uint256_t a_balance);
uint256_t dap_chain_balance_scan(const char *a_balance);
char *dap_cvt_uint256_to_str(uint256_t a_uint256);
uint256_t dap_cvt_str_to_uint256(const char *a_256bit_num);
uint256_t dap_chain_coins_to_balance(const char *a_coins);
/**
* @brief dap_chain_hash_to_str
* @param a_hash
* @return
*/
static inline char * dap_chain_hash_slow_to_str_new(dap_chain_hash_slow_t * a_hash)
{
const size_t c_hash_str_size = sizeof(*a_hash)*2 +1 /*trailing zero*/ +2 /* heading 0x */ ;
char * ret = DAP_NEW_Z_SIZE(char, c_hash_str_size);
dap_chain_hash_slow_to_str(a_hash,ret,c_hash_str_size);
return ret;
}
/**
* @brief dap_chain_hash_kind_check
* @param a_hash
* @details
*/
static inline dap_chain_hash_slow_kind_t dap_chain_hash_slow_kind_check(dap_chain_hash_slow_t * a_hash, const uint8_t a_valuable_head )
{
uint8_t i;
uint8_t l_hash_first = a_hash->raw[0];
uint8_t * l_hash_data = a_hash->raw;
for ( i = 1; i < a_valuable_head; ++i ){
if ( l_hash_data[i] != l_hash_first )
return HASH_USELESS;
}
if( l_hash_first == 0 )
return HASH_GOLD;
else
return HASH_SILVER;
}
#ifdef __cplusplus
}
#endif