-
fb7d6b3e
dap_chain_net_decree.c 23.72 KiB
/*
*
* 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_common.h"
#include "dap_sign.h"
#include "dap_pkey.h"
#include "dap_chain_common.h"
#include "dap_chain_net.h"
#include "dap_chain_net_decree.h"
#include "dap_chain_cs_esbocs.h"
#include "dap_chain_net_tx.h"
#include "dap_chain_net_srv_stake_pos_delegate.h"
#include "dap_http_ban_list_client.h"
#define LOG_TAG "chain_net_decree"
// private types definition
static struct decree_hh {
dap_hash_fast_t key;
bool is_applied;
bool wait_for_apply;
dap_chain_datum_decree_t *decree;
UT_hash_handle hh;
} *s_decree_hh = NULL;
// Private variable
// Private fuctions prototype
static bool s_verify_pkey (dap_sign_t *a_sign, dap_chain_net_t *a_net);
static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain_net_t *a_net, bool a_apply, bool a_load_mode);
static int s_service_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain_net_t *a_net, bool a_apply);
// Public functions
int dap_chain_net_decree_init(dap_chain_net_t *a_net)
{
size_t l_auth_certs_count = 0;
if (!a_net) {
log_it(L_WARNING,"Invalid arguments. a_net must be not NULL");
return -106;
}
dap_list_t *l_net_keys = NULL;
uint16_t l_count_verify = 0;
for (dap_chain_t *l_chain = a_net->pub.chains; l_chain; l_chain = l_chain->next) {
if (!l_chain->callback_get_poa_certs)
continue;
l_net_keys = l_chain->callback_get_poa_certs(l_chain, &l_auth_certs_count, &l_count_verify);
if (l_net_keys)
break;
}
if (!l_net_keys || !l_auth_certs_count) {
log_it(L_WARNING,"Certificates for net %s not found.", a_net->pub.name);
return -1;
}
dap_chain_net_decree_t *l_decree = NULL;
l_decree = DAP_NEW_Z(dap_chain_net_decree_t);
if (!l_decree) {
log_it(L_CRITICAL, "Out of memory");
return -2;
}
l_decree->min_num_of_owners = l_count_verify;
l_decree->num_of_owners = l_auth_certs_count;
l_decree->pkeys = l_net_keys;
a_net->pub.decree = l_decree;
return 0;
}
int dap_chain_net_decree_deinit(dap_chain_net_t *a_net)
{
dap_chain_net_decree_t *l_decree = a_net->pub.decree;
dap_list_free_full(l_decree->pkeys, NULL);
DAP_DELETE(l_decree);
struct decree_hh *l_decree_hh, *l_tmp;
HASH_ITER(hh, s_decree_hh, l_decree_hh, l_tmp) {
HASH_DEL(s_decree_hh, l_decree_hh);
if ( !dap_chain_find_by_id(l_decree_hh->decree->header.common_decree_params.net_id, l_decree_hh->decree->header.common_decree_params.chain_id)->is_mapped )
DAP_DELETE(l_decree_hh->decree);
DAP_DELETE(l_decree_hh);
}
return 0;
}
void dap_chain_net_decree_purge(dap_chain_net_t *a_net)
{
dap_chain_net_decree_deinit(a_net);
dap_chain_net_decree_init(a_net);
}
static int s_decree_verify(dap_chain_net_t *a_net, dap_chain_datum_decree_t *a_decree, size_t a_data_size, dap_chain_hash_fast_t *a_decree_hash, bool a_load_mode)
{
if (a_data_size < sizeof(dap_chain_datum_decree_t)) {
log_it(L_WARNING, "Decree size is too small");
return -120;
}
if (dap_chain_datum_decree_get_size(a_decree) != a_data_size) {
log_it(L_WARNING, "Decree size is invalid");
return -121;
}
if (a_decree->header.common_decree_params.net_id.uint64 != a_net->pub.id.uint64) {
log_it(L_WARNING, "Decree net id is invalid");
return -122;
}
struct decree_hh *l_decree_hh = NULL;
HASH_FIND(hh, s_decree_hh, a_decree_hash, sizeof(dap_hash_fast_t), l_decree_hh);
if (l_decree_hh && l_decree_hh->decree) {
log_it(L_WARNING, "Decree with hash %s is already present", dap_hash_fast_to_str_static(a_decree_hash));
return -123;
}
// Get pkeys sign from decree datum
size_t l_signs_size = 0;
//multiple signs reading from datum
dap_sign_t *l_signs_block = dap_chain_datum_decree_get_signs(a_decree, &l_signs_size);
if (!l_signs_size || !l_signs_block)
{
log_it(L_WARNING, "Decree data sign not found");
return -100;
}
// Find unique pkeys in pkeys set from previous step and check that number of signs > min
size_t l_num_of_unique_signs = 0;
dap_sign_t **l_unique_signs = dap_sign_get_unique_signs(l_signs_block, l_signs_size, &l_num_of_unique_signs);
if (!a_net->pub.decree) {
log_it(L_ERROR, "Decree module hasn't been initialized yet");
return -404;
}
uint16_t l_min_signs = a_net->pub.decree->min_num_of_owners;
if (l_num_of_unique_signs < l_min_signs) {
log_it(L_WARNING, "Not enough unique signatures, get %zu from %hu", l_num_of_unique_signs, l_min_signs);
return -106;
}
// Verify all keys and its signatures
uint16_t l_signs_size_for_current_sign = 0, l_signs_verify_counter = 0;
a_decree->header.signs_size = 0;
size_t l_verify_data_size = a_decree->header.data_size + sizeof(dap_chain_datum_decree_t);
for (size_t i = 0; i < l_num_of_unique_signs; i++) {
size_t l_sign_max_size = dap_sign_get_size(l_unique_signs[i]);
if (s_verify_pkey(l_unique_signs[i], a_net)) {
// 3. verify sign
if(!dap_sign_verify_all(l_unique_signs[i], l_sign_max_size, a_decree, l_verify_data_size))
l_signs_verify_counter++;
} else {
dap_hash_fast_t l_sign_pkey_hash = {0};
size_t l_pkey_size = 0;
uint8_t *l_pkey = dap_sign_get_pkey(l_unique_signs[i], &l_pkey_size);
dap_hash_fast(l_pkey, l_pkey_size, &l_sign_pkey_hash);
char *l_sign_hash_str = dap_hash_fast_to_str_new(&l_sign_pkey_hash);
log_it(L_WARNING, "Signature [%zu] %s failed public key verification.", i, l_sign_hash_str);
DAP_DELETE(l_sign_hash_str);
}
// Each sign change the sign_size field by adding its size after signing. So we need to change this field in header for each sign.
l_signs_size_for_current_sign += l_sign_max_size;
a_decree->header.signs_size = l_signs_size_for_current_sign;
}
a_decree->header.signs_size = l_signs_size;
// DAP_DELETE(l_signs_arr);
DAP_DELETE(l_unique_signs);
if (l_signs_verify_counter < l_min_signs) {
log_it(L_WARNING, "Not enough valid signatures, get %hu from %hu", l_signs_verify_counter, l_min_signs);
return -107;
}
// check tsd-section
int l_ret = 0;
switch(a_decree->header.type) {
case DAP_CHAIN_DATUM_DECREE_TYPE_COMMON:
l_ret = s_common_decree_handler(a_decree, a_net, false, a_load_mode);
break;
case DAP_CHAIN_DATUM_DECREE_TYPE_SERVICE:
l_ret = s_service_decree_handler(a_decree, a_net, false);
break;
default:
log_it(L_WARNING, "Decree type is undefined!");
l_ret = -100;
}
if (l_ret) {
log_it(L_WARNING, "TSD checking error. Decree verification failed");
return l_ret;
}
return 0;
}
int dap_chain_net_decree_verify(dap_chain_net_t *a_net, dap_chain_datum_decree_t *a_decree, size_t a_data_size, dap_chain_hash_fast_t *a_decree_hash)
{
return s_decree_verify(a_net, a_decree, a_data_size, a_decree_hash, false);
}
int dap_chain_net_decree_apply(dap_hash_fast_t *a_decree_hash, dap_chain_datum_decree_t *a_decree, dap_chain_t *a_chain)
{
int ret_val = 0;
dap_chain_net_t *l_net = NULL;
if (!a_decree_hash || !a_chain)
{
log_it(L_ERROR,"Invalid arguments.");
return -107;
}
l_net = dap_chain_net_by_id(a_chain->net_id);
if (!l_net || !l_net->pub.decree)
{
log_it(L_WARNING,"Decree is not inited!");
return -108;
}
struct decree_hh *l_decree_hh = NULL;
HASH_FIND(hh, s_decree_hh, a_decree_hash, sizeof(dap_hash_fast_t), l_decree_hh);
if (!l_decree_hh) {
l_decree_hh = DAP_NEW_Z(struct decree_hh);
if (!l_decree_hh) {
log_it(L_CRITICAL, "Memory allocation error");
return -1;
}
l_decree_hh->key = *a_decree_hash;
HASH_ADD(hh, s_decree_hh, key, sizeof(dap_hash_fast_t), l_decree_hh);
}
if (!a_decree) { // Processing anchor for decree
if (!l_decree_hh->decree) {
log_it(L_WARNING, "Decree with hash %s is not found", dap_hash_fast_to_str_static(a_decree_hash));
l_decree_hh->wait_for_apply = true;
return -110;
}
if (l_decree_hh->is_applied) {
log_it(L_WARNING, "Decree already applied");
return -111;
}
} else { // Process decree itself
if (l_decree_hh->decree) {
log_it(L_WARNING, "Decree with hash %s is already present", dap_hash_fast_to_str_static(a_decree_hash));
return -123;
}
l_decree_hh->decree = a_chain->is_mapped ? a_decree : DAP_DUP_SIZE(a_decree, dap_chain_datum_decree_get_size(a_decree));
if (a_decree->header.common_decree_params.chain_id.uint64 != a_chain->id.uint64 && !l_decree_hh->wait_for_apply)
// Apply it with corresponding anchor
return ret_val;
}
// Process decree
switch(l_decree_hh->decree->header.type) {
case DAP_CHAIN_DATUM_DECREE_TYPE_COMMON:
ret_val = s_common_decree_handler(l_decree_hh->decree, l_net, true, false);
break;
case DAP_CHAIN_DATUM_DECREE_TYPE_SERVICE:
ret_val = s_service_decree_handler(l_decree_hh->decree, l_net, true);
break;
default:
log_it(L_WARNING,"Decree type is undefined!");
ret_val = -100;
}
if (!ret_val) {
l_decree_hh->is_applied = true;
l_decree_hh->wait_for_apply = false;
} else
log_it(L_ERROR,"Decree applying failed!");
return ret_val;
}
int dap_chain_net_decree_load(dap_chain_datum_decree_t * a_decree, dap_chain_t *a_chain, dap_chain_hash_fast_t *a_decree_hash)
{
int ret_val = 0;
if (!a_chain || !a_decree) {
log_it(L_ERROR, "Bad arguments");
return -100;
}
dap_chain_net_t *l_net = dap_chain_net_by_id(a_chain->net_id);
if (!l_net->pub.decree) {
log_it(L_WARNING, "Decree is not inited!");
return -108;
}
size_t l_data_size = dap_chain_datum_decree_get_size(a_decree);
if ((ret_val = s_decree_verify(l_net, a_decree, l_data_size, a_decree_hash, true)) != 0) {
log_it(L_ERROR, "Decree verification failed!");
return ret_val;
}
return dap_chain_net_decree_apply(a_decree_hash, a_decree, a_chain);
}
int dap_chain_net_decree_reset_applied(dap_chain_t *a_chain, dap_chain_hash_fast_t *a_decree_hash)
{
if (!a_chain || !a_decree_hash)
return -1;
struct decree_hh* l_decree_hh = NULL;
HASH_FIND(hh, s_decree_hh, a_decree_hash, sizeof(dap_hash_fast_t), l_decree_hh);
if (!l_decree_hh)
return -2;
l_decree_hh->is_applied = false;
return 0;
}
dap_chain_datum_decree_t *dap_chain_net_decree_get_by_hash(dap_hash_fast_t *a_hash, bool *is_applied)
{
struct decree_hh* l_decree_hh = NULL;
HASH_FIND(hh, s_decree_hh, a_hash, sizeof(dap_hash_fast_t), l_decree_hh);
if (!l_decree_hh || !l_decree_hh->decree)
return NULL;
if (is_applied)
*is_applied = l_decree_hh->is_applied;
return l_decree_hh->decree;
}
// Private functions
static bool s_verify_pkey (dap_sign_t *a_sign, dap_chain_net_t *a_net)
{
for (dap_list_t *it = a_net->pub.decree->pkeys; it; it = it->next)
if (dap_pkey_compare_with_sign(it->data, a_sign))
return true;
return false;
}
static int s_common_decree_handler(dap_chain_datum_decree_t *a_decree, dap_chain_net_t *a_net, bool a_apply, bool a_load_mode)
{
uint256_t l_value;
uint32_t l_sign_type;
uint16_t l_owners_num;
uint8_t l_action;
dap_chain_addr_t l_addr = {};
dap_hash_fast_t l_hash = {};
dap_chain_node_addr_t l_node_addr = {};
dap_list_t *l_owners_list = NULL;
const char *l_ban_addr;
dap_return_val_if_fail(a_decree && a_net, -112);
switch (a_decree->header.sub_type)
{
case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_FEE:
if (dap_chain_datum_decree_get_fee_addr(a_decree, &l_addr)) {
if (dap_chain_addr_is_blank(&a_net->pub.fee_addr)) {
log_it(L_WARNING, "Fee wallet address not set.");
return -111;
} else
l_addr = a_net->pub.fee_addr;
}
if (dap_chain_datum_decree_get_fee(a_decree, &l_value)) {
log_it(L_WARNING,"Can't get fee value from decree.");
return -103;
}
if (!a_apply)
break;
if (!dap_chain_net_tx_set_fee(a_net->pub.id, l_value, l_addr))
log_it(L_ERROR, "Can't set fee value for network %s", a_net->pub.name);
break;
case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_OWNERS:
l_owners_list = dap_chain_datum_decree_get_owners(a_decree, &l_owners_num);
if (!l_owners_list){
log_it(L_WARNING,"Can't get ownners from decree.");
return -104;
}
if (!a_apply)
break;
a_net->pub.decree->num_of_owners = l_owners_num;
dap_list_free_full(a_net->pub.decree->pkeys, NULL);
a_net->pub.decree->pkeys = l_owners_list;
break;
case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_OWNERS_MIN:
if (dap_chain_datum_decree_get_min_owners(a_decree, &l_value)) {
log_it(L_WARNING, "Can't get min number of ownners from decree.");
return -105;
}
if (IS_ZERO_256(l_value) || compare256(l_value, GET_256_FROM_64(UINT16_MAX)) == 1) {
log_it(L_WARNING, "Illegal min number of owners %s", dap_uint256_to_char(l_value, NULL));
return -116;
}
if (!a_apply)
break;
a_net->pub.decree->min_num_of_owners = dap_uint256_to_uint64(l_value);
break;
case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_APPROVE:
if (dap_chain_datum_decree_get_hash(a_decree, &l_hash)){
log_it(L_WARNING,"Can't get tx hash from decree.");
return -105;
}
if (dap_chain_datum_decree_get_stake_value(a_decree, &l_value)){
log_it(L_WARNING,"Can't get stake value from decree.");
return -106;
}
if (dap_chain_datum_decree_get_stake_signing_addr(a_decree, &l_addr)){
log_it(L_WARNING,"Can't get signing address from decree.");
return -107;
}
if (dap_chain_datum_decree_get_stake_signer_node_addr(a_decree, &l_node_addr)){
log_it(L_WARNING,"Can't get signer node address from decree.");
return -108;
}
if (a_load_mode) {
assert(!a_apply);
break;
}
if (dap_chain_net_srv_stake_verify_key_and_node(&l_addr, &l_node_addr)) {
log_it(L_WARNING, "Key and node verification error");
return -109;
}
if (!a_apply)
break;
dap_chain_net_srv_stake_key_delegate(a_net, &l_addr, &l_hash, l_value, &l_node_addr);
break;
case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_INVALIDATE:
if (dap_chain_datum_decree_get_stake_signing_addr(a_decree, &l_addr)){
log_it(L_WARNING,"Can't get signing address from decree.");
return -105;
}
if (!a_apply)
break;
dap_chain_net_srv_stake_key_invalidate(&l_addr);
break;
case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_MIN_VALUE:
if (dap_chain_datum_decree_get_stake_min_value(a_decree, &l_value)){
log_it(L_WARNING,"Can't get min stake value from decree.");
return -105;
}
if (!a_apply)
break;
dap_chain_net_srv_stake_set_allowed_min_value(a_net->pub.id, l_value);
break;
case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_STAKE_MIN_VALIDATORS_COUNT:
if (dap_chain_datum_decree_get_stake_min_signers_count(a_decree, &l_value)){
log_it(L_WARNING,"Can't get min stake value from decree.");
return -105;
}
dap_chain_t *l_chain = dap_chain_find_by_id(a_net->pub.id, a_decree->header.common_decree_params.chain_id);
if (!l_chain) {
log_it(L_WARNING, "Specified chain not found");
return -106;
}
if (dap_strcmp(dap_chain_get_cs_type(l_chain), "esbocs")) {
log_it(L_WARNING, "Can't apply this decree to specified chain");
return -115;
}
if (!a_apply)
break;
dap_chain_esbocs_set_min_validators_count(l_chain, (uint16_t)dap_chain_uint256_to(l_value));
break;
case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_BAN: {
if (dap_chain_datum_decree_get_ban_addr(a_decree, &l_ban_addr)) {
log_it(L_WARNING, "Can't get ban address from decree.");
return -114;
}
if (dap_http_ban_list_client_check(l_ban_addr, NULL, NULL)) {
log_it(L_ERROR, "Can't ban addr %s: already banlisted", l_ban_addr);
return -112;
}
if (!a_apply)
break;
dap_hash_fast_t l_decree_hash = {0};
dap_hash_fast(a_decree, dap_chain_datum_decree_get_size(a_decree), &l_decree_hash);
dap_http_ban_list_client_add(l_ban_addr, l_decree_hash, a_decree->header.ts_created);
} break;
case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_UNBAN: {
if (dap_chain_datum_decree_get_ban_addr(a_decree, &l_ban_addr)) {
log_it(L_WARNING, "Can't get ban address from decree.");
return -114;
}
if (!dap_http_ban_list_client_check(l_ban_addr, NULL, NULL)) {
log_it(L_ERROR, "Can't ban addr %s: already banlisted", l_ban_addr);
return -112;
}
if (!a_apply)
break;
dap_http_ban_list_client_remove(l_ban_addr);
} break;
case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_REWARD: {
if (dap_chain_datum_decree_get_value(a_decree, &l_value)) {
log_it(L_WARNING,"Can't get value from decree.");
return -103;
}
dap_chain_t *l_chain = dap_chain_find_by_id(a_net->pub.id, a_decree->header.common_decree_params.chain_id);
if (!l_chain) {
log_it(L_WARNING, "Specified chain not found");
return -106;
}
if (dap_strcmp(dap_chain_get_cs_type(l_chain), "esbocs")) {
log_it(L_WARNING, "Can't apply this decree to specified chain");
return -115;
}
if (!a_apply)
break;
uint64_t l_cur_block_num = l_chain->callback_count_atom(l_chain);
dap_chain_net_add_reward(a_net, l_value, l_cur_block_num);
} break;
case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_MAX_WEIGHT: {
if (dap_chain_datum_decree_get_value(a_decree, &l_value)) {
log_it(L_WARNING,"Can't get value from decree.");
return -103;
}
dap_chain_t *l_chain = dap_chain_find_by_id(a_net->pub.id, a_decree->header.common_decree_params.chain_id);
if (!l_chain) {
log_it(L_WARNING, "Specified chain not found");
return -106;
}
if (dap_strcmp(dap_chain_get_cs_type(l_chain), "esbocs")) {
log_it(L_WARNING, "Can't apply this decree to specified chain");
return -115;
}
if (compare256(l_value, dap_chain_coins_to_balance("1.0")) >= 0) {
log_it(L_WARNING, "Percent must be lower than 100%%");
return -116;
}
if (!a_apply)
break;
dap_chain_net_srv_stake_set_percent_max(a_net->pub.id, l_value);
} break;
case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_CHECK_SIGNS_STRUCTURE: {
if (dap_chain_datum_decree_get_action(a_decree, &l_action)) {
log_it(L_WARNING,"Can't get action from decree.");
return -103;
}
dap_chain_t *l_chain = dap_chain_find_by_id(a_net->pub.id, a_decree->header.common_decree_params.chain_id);
if (!l_chain) {
log_it(L_WARNING, "Specified chain not found");
return -106;
}
if (dap_strcmp(dap_chain_get_cs_type(l_chain), "esbocs")) {
log_it(L_WARNING, "Can't apply this decree to specified chain");
return -115;
}
if (!a_apply)
break;
dap_chain_esbocs_set_signs_struct_check(l_chain, l_action);
} break;
case DAP_CHAIN_DATUM_DECREE_COMMON_SUBTYPE_EMERGENCY_VALIDATORS: {
if (dap_chain_datum_decree_get_action(a_decree, &l_action)) {
log_it(L_WARNING,"Can't get action from decree.");
return -103;
}
if (dap_chain_datum_decree_get_signature_type(a_decree, &l_sign_type)) {
log_it(L_WARNING,"Can't get signature type from decree.");
return -113;
}
if (dap_chain_datum_decree_get_hash(a_decree, &l_hash)){
log_it(L_WARNING,"Can't get validator hash from decree.");
return -105;
}
dap_chain_t *l_chain = dap_chain_find_by_id(a_net->pub.id, a_decree->header.common_decree_params.chain_id);
if (!l_chain) {
log_it(L_WARNING, "Specified chain not found");
return -106;
}
if (dap_strcmp(dap_chain_get_cs_type(l_chain), "esbocs")) {
log_it(L_WARNING, "Can't apply this decree to specified chain");
return -115;
}
if (!a_apply)
break;
dap_chain_esbocs_set_emergency_validator(l_chain, l_action, l_sign_type, &l_hash);
} break;
default:
return -1;
}
return 0;
}
static int s_service_decree_handler(dap_chain_datum_decree_t * a_decree, dap_chain_net_t *a_net, bool a_apply)
{
// size_t l_datum_data_size = ;
// dap_chain_net_srv_t * l_srv = dap_chain_net_srv_get(l_decree->header.srv_id);
// if(l_srv){
// if(l_srv->callbacks.decree){
// dap_chain_net_t * l_net = dap_chain_net_by_id(a_chain->net_id);
// l_srv->callbacks.decree(l_srv,l_net,a_chain,l_decree,l_datum_data_size);
// }
// }else{
// log_it(L_WARNING,"Decree for unknown srv uid 0x%016"DAP_UINT64_FORMAT_X , l_decree->header.srv_id.uint64);
// return -103;
// }
return 0;
}