mirror of
https://github.com/EvernodeXRPL/hpcore.git
synced 2026-04-29 15:37:59 +00:00
Passed unl stats to contract. (#357)
This commit is contained in:
@@ -61,7 +61,7 @@ int main(int argc, char **argv)
|
||||
// struct hp_config *config = hp_get_config();
|
||||
// hp_set_config_string(&config->version, "2.0", 4);
|
||||
// config->round_limits.user_input_bytes = 1024;
|
||||
// struct hp_unl_node new_unl[2] = {{"ed726f9f536904b125bdca10bbdd1e66591b274799b92ac8bcfc75bf45d7da4c0f"},
|
||||
// struct hp_pubkey new_unl[2] = {{"ed726f9f536904b125bdca10bbdd1e66591b274799b92ac8bcfc75bf45d7da4c0f"},
|
||||
// {"ed3e63992d62804ea0c182e5b22fe43c4b652fbbf068ec7520f3020f4c3771416a"}};
|
||||
// hp_set_config_unl(config, new_unl, 2);
|
||||
// hp_update_config(config);
|
||||
|
||||
@@ -108,10 +108,15 @@ struct hp_user_inputs_collection
|
||||
size_t count;
|
||||
};
|
||||
|
||||
struct hp_pubkey
|
||||
{
|
||||
char data[HP_KEY_SIZE + 1]; // +1 for null char.
|
||||
};
|
||||
|
||||
// Represents a user that is connected to HP cluster.
|
||||
struct hp_user
|
||||
{
|
||||
char pubkey[HP_KEY_SIZE + 1]; // +1 for null char.
|
||||
struct hp_pubkey pubkey;
|
||||
int outfd;
|
||||
struct hp_user_inputs_collection inputs;
|
||||
};
|
||||
@@ -119,7 +124,8 @@ struct hp_user
|
||||
// Represents a node that's part of unl.
|
||||
struct hp_unl_node
|
||||
{
|
||||
char pubkey[HP_KEY_SIZE + 1]; // +1 for null char.
|
||||
struct hp_pubkey pubkey;
|
||||
uint64_t active_on;
|
||||
};
|
||||
|
||||
struct hp_users_collection
|
||||
@@ -129,6 +135,12 @@ struct hp_users_collection
|
||||
int in_fd;
|
||||
};
|
||||
|
||||
struct hp_pubkey_collection
|
||||
{
|
||||
struct hp_pubkey *list;
|
||||
size_t count;
|
||||
};
|
||||
|
||||
struct hp_unl_collection
|
||||
{
|
||||
struct hp_unl_node *list;
|
||||
@@ -155,7 +167,7 @@ struct hp_round_limits_config
|
||||
struct hp_config
|
||||
{
|
||||
char *version;
|
||||
struct hp_unl_collection unl;
|
||||
struct hp_pubkey_collection unl;
|
||||
char *bin_path;
|
||||
char *bin_args;
|
||||
char *environment;
|
||||
@@ -202,7 +214,7 @@ struct hp_config *hp_get_config();
|
||||
int hp_update_config(const struct hp_config *config);
|
||||
int hp_update_peers(const char *add_peers[], const size_t add_peers_count, const char *remove_peers[], const size_t remove_peers_count);
|
||||
void hp_set_config_string(char **config_str, const char *value, const size_t value_size);
|
||||
void hp_set_config_unl(struct hp_config *config, const struct hp_unl_node *new_unl, const size_t new_unl_count);
|
||||
void hp_set_config_unl(struct hp_config *config, const struct hp_pubkey *new_unl, const size_t new_unl_count);
|
||||
void hp_free_config(struct hp_config *config);
|
||||
|
||||
void __hp_parse_args_json(const struct json_object_s *object);
|
||||
@@ -493,20 +505,21 @@ int hp_update_config(const struct hp_config *config)
|
||||
{
|
||||
for (size_t i = 0; i < config->unl.count; i++)
|
||||
{
|
||||
const size_t pubkey_len = strlen(config->unl.list[i].pubkey);
|
||||
const char *pubkey = config->unl.list[i].data;
|
||||
const size_t pubkey_len = strlen(pubkey);
|
||||
if (pubkey_len == 0)
|
||||
__HP_UPDATE_CONFIG_ERROR("Unl pubkey cannot be empty.");
|
||||
|
||||
if (pubkey_len != HP_KEY_SIZE)
|
||||
__HP_UPDATE_CONFIG_ERROR("Unl pubkey invalid. Invalid length.");
|
||||
|
||||
if (config->unl.list[i].pubkey[0] != 'e' || config->unl.list[i].pubkey[1] != 'd')
|
||||
if (pubkey[0] != 'e' || pubkey[1] != 'd')
|
||||
__HP_UPDATE_CONFIG_ERROR("Unl pubkey invalid. Invalid format.");
|
||||
|
||||
// Checking the validity of hexadecimal portion. (without 'ed').
|
||||
for (size_t j = 2; j < HP_KEY_SIZE; j++)
|
||||
{
|
||||
const char current_char = config->unl.list[i].pubkey[j];
|
||||
const char current_char = pubkey[j];
|
||||
if ((current_char < 'A' || current_char > 'F') && (current_char < 'a' || current_char > 'f') && (current_char < '0' || current_char > '9'))
|
||||
__HP_UPDATE_CONFIG_ERROR("Unl pubkey invalid. Invalid character.");
|
||||
}
|
||||
@@ -564,13 +577,13 @@ void hp_set_config_string(char **config_str, const char *value, const size_t val
|
||||
/**
|
||||
* Populates the config unl list with the specified values.
|
||||
* @param config The config struct to populate the unl to.
|
||||
* @param new_unl Pointer to the new unl node array.
|
||||
* @param new_unl_count No. of entries in the new unl node array.
|
||||
* @param new_unl Pointer to array of unl pubkeys.
|
||||
* @param new_unl_count No. of entries in the new unl pubkey array.
|
||||
*/
|
||||
void hp_set_config_unl(struct hp_config *config, const struct hp_unl_node *new_unl, const size_t new_unl_count)
|
||||
void hp_set_config_unl(struct hp_config *config, const struct hp_pubkey *new_unl, const size_t new_unl_count)
|
||||
{
|
||||
const size_t mem_size = sizeof(struct hp_unl_node) * new_unl_count;
|
||||
config->unl.list = (struct hp_unl_node *)realloc(config->unl.list, mem_size);
|
||||
const size_t mem_size = sizeof(struct hp_pubkey) * new_unl_count;
|
||||
config->unl.list = (struct hp_pubkey *)realloc(config->unl.list, mem_size);
|
||||
memcpy(config->unl.list, new_unl, mem_size);
|
||||
config->unl.count = new_unl_count;
|
||||
}
|
||||
@@ -728,7 +741,7 @@ int __hp_write_to_patch_file(const int fd, const struct hp_config *config)
|
||||
strncpy(unl_buf + pos, "\n ", 9);
|
||||
pos += 9;
|
||||
unl_buf[pos++] = '"';
|
||||
strncpy(unl_buf + pos, config->unl.list[i].pubkey, HP_KEY_SIZE);
|
||||
strncpy(unl_buf + pos, config->unl.list[i].data, HP_KEY_SIZE);
|
||||
pos += HP_KEY_SIZE;
|
||||
unl_buf[pos++] = '"';
|
||||
}
|
||||
@@ -825,14 +838,14 @@ void __hp_populate_patch_from_json_object(struct hp_config *config, const struct
|
||||
const size_t unl_count = unl_array->length;
|
||||
|
||||
config->unl.count = unl_count;
|
||||
config->unl.list = unl_count ? (struct hp_unl_node *)malloc(sizeof(struct hp_unl_node) * unl_count) : NULL;
|
||||
config->unl.list = unl_count ? (struct hp_pubkey *)malloc(sizeof(struct hp_pubkey) * unl_count) : NULL;
|
||||
|
||||
if (unl_count > 0)
|
||||
{
|
||||
struct json_array_element_s *unl_elem = unl_array->start;
|
||||
for (int i = 0; i < unl_count; i++)
|
||||
{
|
||||
__HP_ASSIGN_STRING(config->unl.list[i].pubkey, unl_elem);
|
||||
__HP_ASSIGN_STRING(config->unl.list[i].data, unl_elem);
|
||||
unl_elem = unl_elem->next;
|
||||
}
|
||||
}
|
||||
@@ -981,7 +994,7 @@ void __hp_parse_args_json(const struct json_object_s *object)
|
||||
for (int i = 0; i < user_count; i++)
|
||||
{
|
||||
struct hp_user *user = &cctx->users.list[i];
|
||||
memcpy(user->pubkey, user_elem->name->string, HP_KEY_SIZE);
|
||||
memcpy(user->pubkey.data, user_elem->name->string, HP_KEY_SIZE);
|
||||
|
||||
if (user_elem->value->type == json_type_array)
|
||||
{
|
||||
@@ -1020,20 +1033,38 @@ void __hp_parse_args_json(const struct json_object_s *object)
|
||||
}
|
||||
else if (strcmp(k->string, "unl") == 0)
|
||||
{
|
||||
if (elem->value->type == json_type_array)
|
||||
// unl is an object with pubkeys as keys. Each key contains an object with that node statistics.
|
||||
if (elem->value->type == json_type_object)
|
||||
{
|
||||
const struct json_array_s *unl_array = (struct json_array_s *)elem->value->payload;
|
||||
const size_t unl_count = unl_array->length;
|
||||
const struct json_object_s *unl_obj = (struct json_object_s *)elem->value->payload;
|
||||
const size_t unl_count = unl_obj->length;
|
||||
|
||||
cctx->unl.count = unl_count;
|
||||
cctx->unl.list = unl_count ? (struct hp_unl_node *)malloc(sizeof(struct hp_unl_node) * unl_count) : NULL;
|
||||
|
||||
if (unl_count > 0)
|
||||
{
|
||||
struct json_array_element_s *unl_elem = unl_array->start;
|
||||
struct json_object_element_s *unl_elem = unl_obj->start;
|
||||
for (int i = 0; i < unl_count; i++)
|
||||
{
|
||||
__HP_ASSIGN_STRING(cctx->unl.list[i].pubkey, unl_elem);
|
||||
// Each element(key) is named by the pubkey.
|
||||
strncpy(cctx->unl.list[i].pubkey.data, unl_elem->name->string, unl_elem->name->string_size);
|
||||
|
||||
if (unl_elem->value->type == json_type_object)
|
||||
{
|
||||
const struct json_object_s *stat_obj = (struct json_object_s *)unl_elem->value->payload;
|
||||
struct json_object_element_s *stat_elem = stat_obj->start;
|
||||
do
|
||||
{
|
||||
const struct json_string_s *k = stat_elem->name;
|
||||
if (strcmp(k->string, "active_on") == 0)
|
||||
{
|
||||
__HP_ASSIGN_UINT64(cctx->unl.list[i].active_on, stat_elem);
|
||||
}
|
||||
stat_elem = stat_elem->next;
|
||||
} while (stat_elem);
|
||||
}
|
||||
|
||||
unl_elem = unl_elem->next;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -487,7 +487,7 @@ namespace consensus
|
||||
}
|
||||
|
||||
// Provide latest roundtime information to unl statistics.
|
||||
unl::update_time_config_stats(collected_proposals);
|
||||
unl::update_unl_stats(collected_proposals);
|
||||
|
||||
// Move collected propsals to candidate set of proposals.
|
||||
for (const auto &p : collected_proposals)
|
||||
|
||||
49
src/unl.cpp
49
src/unl.cpp
@@ -10,8 +10,14 @@
|
||||
*/
|
||||
namespace unl
|
||||
{
|
||||
std::map<std::string, uint32_t> list; // List of binary pubkeys of UNL and their latest reported time configs.
|
||||
std::string json_list; // Stringified json array of UNL. (To be fed into the contract args)
|
||||
struct node_stat
|
||||
{
|
||||
uint32_t time_config = 0; // Roundtime config of this node.
|
||||
uint64_t active_on = 0; // Latest timestamp we received a proposal from this node.
|
||||
};
|
||||
|
||||
std::map<std::string, node_stat> list; // List of binary pubkeys of UNL nodes and their statistics.
|
||||
std::string json_list; // Stringified json array of UNL. (To be fed into the contract args)
|
||||
std::shared_mutex unl_mutex;
|
||||
|
||||
/**
|
||||
@@ -81,18 +87,27 @@ namespace unl
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates unl pubkey-->time config information using the specified list of proposals.
|
||||
* Updates unl stats using the specified list of proposals.
|
||||
*/
|
||||
void update_time_config_stats(const std::list<p2p::proposal> &proposals)
|
||||
void update_unl_stats(const std::list<p2p::proposal> &proposals)
|
||||
{
|
||||
std::unique_lock lock(unl_mutex);
|
||||
bool changes_made = false;
|
||||
|
||||
for (const auto &p : proposals)
|
||||
{
|
||||
const auto itr = list.find(p.pubkey);
|
||||
if (itr != list.end())
|
||||
itr->second = p.time_config;
|
||||
{
|
||||
changes_made = true;
|
||||
itr->second.active_on = p.recv_timestamp;
|
||||
itr->second.time_config = p.time_config;
|
||||
}
|
||||
}
|
||||
|
||||
// Update the prepared json list which will be fed into contract args.
|
||||
if (changes_made)
|
||||
json_list = prepare_json_list();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,14 +127,14 @@ namespace unl
|
||||
for (auto itr = list.begin(); itr != list.end(); itr++)
|
||||
{
|
||||
// If time config is 0, attempt to get from peer connection (if available).
|
||||
if (itr->second == 0)
|
||||
if (itr->second.time_config == 0)
|
||||
{
|
||||
const auto peer_itr = p2p::ctx.peer_connections.find(itr->first);
|
||||
if (peer_itr != p2p::ctx.peer_connections.end())
|
||||
itr->second = peer_itr->second->reported_time_config;
|
||||
itr->second.time_config = peer_itr->second->reported_time_config;
|
||||
}
|
||||
|
||||
const uint32_t time_config = itr->second;
|
||||
const uint32_t time_config = itr->second.time_config;
|
||||
if (time_config > 0)
|
||||
time_config_votes[time_config]++;
|
||||
}
|
||||
@@ -167,7 +182,7 @@ namespace unl
|
||||
{
|
||||
if (list.count(pubkey) == 0)
|
||||
{
|
||||
list.emplace(pubkey, 0);
|
||||
list.emplace(pubkey, node_stat{});
|
||||
changes_made = true;
|
||||
}
|
||||
}
|
||||
@@ -176,7 +191,7 @@ namespace unl
|
||||
return false;
|
||||
|
||||
// Update the prepared json list which will be fed into contract args.
|
||||
json_list = prepare_json_list(conf::cfg.contract.unl);
|
||||
json_list = prepare_json_list();
|
||||
|
||||
// Update the own node's unl status.
|
||||
conf::cfg.node.is_unl = (list.count(conf::cfg.node.public_key) == 1);
|
||||
@@ -184,19 +199,21 @@ namespace unl
|
||||
return true; // Changes made.
|
||||
}
|
||||
|
||||
const std::string prepare_json_list(const std::set<std::string> &new_list)
|
||||
const std::string prepare_json_list()
|
||||
{
|
||||
std::ostringstream os;
|
||||
os << "[";
|
||||
for (auto pk = new_list.begin(); pk != new_list.end(); pk++)
|
||||
os << "{";
|
||||
for (auto node = list.begin(); node != list.end(); node++)
|
||||
{
|
||||
if (pk != new_list.begin())
|
||||
if (node != list.begin())
|
||||
os << ","; // Trailing comma separator for previous element.
|
||||
|
||||
// Convert binary pubkey into hex.
|
||||
os << "\"" << util::to_hex(*pk) << "\"";
|
||||
os << "\"" << util::to_hex(node->first) << "\":{"
|
||||
<< "\"active_on\":" << node->second.active_on
|
||||
<< "}";
|
||||
}
|
||||
os << "]";
|
||||
os << "}";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
|
||||
@@ -17,10 +17,10 @@ namespace unl
|
||||
bool exists(const std::string &bin_pubkey);
|
||||
int init();
|
||||
void update_unl_changes_from_patch();
|
||||
void update_time_config_stats(const std::list<p2p::proposal> &proposals);
|
||||
void update_unl_stats(const std::list<p2p::proposal> &proposals);
|
||||
uint32_t get_majority_time_config();
|
||||
bool merge_latest_unl_config();
|
||||
const std::string prepare_json_list(const std::set<std::string> &new_list);
|
||||
const std::string prepare_json_list();
|
||||
|
||||
} // namespace unl
|
||||
|
||||
|
||||
Reference in New Issue
Block a user