mirror of
https://github.com/EvernodeXRPL/hpcore.git
synced 2026-04-29 15:37:59 +00:00
Usage of nonce hash for ledger hash generation (#375)
This commit is contained in:
committed by
GitHub
parent
0022bd51e5
commit
6a2384cd03
@@ -12,8 +12,7 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY build)
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror")
|
||||
|
||||
#-------hpcore-------
|
||||
|
||||
# -------hpcore-------
|
||||
add_subdirectory(src/killswitch)
|
||||
|
||||
add_executable(hpcore
|
||||
@@ -76,6 +75,7 @@ target_link_libraries(hpcore
|
||||
)
|
||||
|
||||
add_custom_command(TARGET hpcore POST_BUILD
|
||||
|
||||
# COMMAND strip ./build/hpcore
|
||||
COMMAND cp ./test/bin/hpws ./test/bin/hpfs ./build/
|
||||
)
|
||||
@@ -85,10 +85,10 @@ target_precompile_headers(hpcore PUBLIC src/pchheader.hpp)
|
||||
# Create docker image for local cluster testing from hpcore build output with 'make docker'
|
||||
# Requires docker to be runnable without 'sudo'
|
||||
add_custom_target(docker
|
||||
COMMAND mkdir -p ./test/local-cluster/bin
|
||||
COMMAND cp ./build/hpcore ./test/local-cluster/bin/
|
||||
COMMAND cp ./test/bin/libblake3.so ./test/bin/hpws ./test/bin/hpfs ./test/local-cluster/bin/
|
||||
COMMAND docker build -t hpcore:latest -t hpcore:0.6.1 -f ./test/local-cluster/Dockerfile ./test/local-cluster/bin/
|
||||
COMMAND mkdir -p ./test/local-cluster/bin
|
||||
COMMAND cp ./build/hpcore ./test/local-cluster/bin/
|
||||
COMMAND cp ./test/bin/libblake3.so ./test/bin/hpws ./test/bin/hpfs ./test/local-cluster/bin/
|
||||
COMMAND docker build -t hpcore:latest -t hpcore:0.6.3 -f ./test/local-cluster/Dockerfile ./test/local-cluster/bin/
|
||||
)
|
||||
set_target_properties(docker PROPERTIES EXCLUDE_FROM_ALL TRUE)
|
||||
add_dependencies(docker hpcore)
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "util/h32.hpp"
|
||||
#include "util/sequence_hash.hpp"
|
||||
#include "unl.hpp"
|
||||
#include "ledger/ledger_common.hpp"
|
||||
#include "ledger/ledger.hpp"
|
||||
#include "ledger/ledger_query.hpp"
|
||||
#include "consensus.hpp"
|
||||
@@ -24,7 +25,6 @@ namespace p2pmsg = msg::fbuf::p2pmsg;
|
||||
namespace consensus
|
||||
{
|
||||
constexpr float STAGE_THRESHOLD_RATIO[3] = {0.5, 0.65, 0.8};
|
||||
constexpr size_t ROUND_NONCE_SIZE = 64;
|
||||
constexpr const char *HPFS_SESSION_NAME = "ro_patch_file_to_hp";
|
||||
|
||||
// Max no. of time to get unreliable votes before we try heuristics to increase vote receiving reliability.
|
||||
@@ -242,11 +242,8 @@ namespace consensus
|
||||
*/
|
||||
void attempt_ledger_close()
|
||||
{
|
||||
std::map<util::h32, uint32_t> hash_votes; // Votes on the proposal hash.
|
||||
std::map<util::h32, const p2p::proposal> cp_root_hash; // Stores one of proposal to match its root hash.
|
||||
util::h32 majority_hash = util::h32_empty;
|
||||
|
||||
uint32_t stage3_prop_count = 0; // Keep track of the number of stage 3 proposals received.
|
||||
std::map<util::h32, std::vector<p2p::proposal>> proposal_groups; // Stores sets of proposals against grouped by their root hashes.
|
||||
uint32_t stage3_prop_count = 0; // Keep track of the number of stage 3 proposals received.
|
||||
|
||||
// Count votes of all stage 3 proposal hashes.
|
||||
for (const auto &[pubkey, cp] : ctx.candidate_proposals)
|
||||
@@ -254,11 +251,10 @@ namespace consensus
|
||||
if (cp.stage == 3)
|
||||
{
|
||||
stage3_prop_count++;
|
||||
increment(hash_votes, cp.root_hash);
|
||||
if (!cp_root_hash.count(cp.root_hash))
|
||||
cp_root_hash.try_emplace(cp.root_hash, cp);
|
||||
proposal_groups[cp.root_hash].push_back(cp);
|
||||
}
|
||||
}
|
||||
|
||||
// Threshold is devided by 100 to convert average to decimal.
|
||||
const uint32_t min_votes_required = ceil((conf::cfg.contract.consensus.threshold * unl::count()) / 100.0);
|
||||
if (stage3_prop_count < min_votes_required)
|
||||
@@ -270,12 +266,13 @@ namespace consensus
|
||||
|
||||
// Find the winning hash and no. of votes for it.
|
||||
uint32_t winning_votes = 0;
|
||||
for (const auto [hash, votes] : hash_votes)
|
||||
util::h32 winning_hash = util::h32_empty;
|
||||
for (const auto [hash, proposals] : proposal_groups)
|
||||
{
|
||||
if (votes > winning_votes)
|
||||
if (proposals.size() > winning_votes)
|
||||
{
|
||||
winning_votes = votes;
|
||||
majority_hash = hash;
|
||||
winning_votes = proposals.size();
|
||||
winning_hash = hash;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -285,20 +282,16 @@ namespace consensus
|
||||
return;
|
||||
}
|
||||
|
||||
const auto itr = cp_root_hash.find(majority_hash);
|
||||
if (itr == cp_root_hash.end())
|
||||
{
|
||||
LOG_ERROR << "No proposal matching the majority hash found.";
|
||||
return;
|
||||
}
|
||||
const p2p::proposal &majority_prop = itr->second;
|
||||
// Consensus reached. This is the winning set of proposals.
|
||||
std::vector<p2p::proposal> &winning_group = proposal_groups[winning_hash];
|
||||
|
||||
LOG_DEBUG << "Closing ledger with proposal:" << majority_prop.root_hash;
|
||||
p2p::proposal &winning_prop = winning_group.front();
|
||||
LOG_DEBUG << "Closing ledger with proposal:" << winning_prop.root_hash;
|
||||
|
||||
// Upon successful ledger close condition, update the ledger and execute the contract using the consensus proposal.
|
||||
consensed_user_map consensed_users;
|
||||
if (prepare_consensed_users(consensed_users, majority_prop) == -1 ||
|
||||
commit_consensus_results(majority_prop, consensed_users) == -1)
|
||||
if (prepare_consensed_users(consensed_users, winning_prop) == -1 ||
|
||||
commit_consensus_results(winning_prop, consensed_users) == -1)
|
||||
{
|
||||
LOG_ERROR << "Error occured when closing ledger";
|
||||
|
||||
@@ -919,7 +912,12 @@ namespace consensus
|
||||
p.last_primary_shard_id = last_primary_shard_id;
|
||||
p.last_raw_shard_id = last_raw_shard_id;
|
||||
p.time_config = CURRENT_TIME_CONFIG;
|
||||
crypto::random_bytes(p.nonce, ROUND_NONCE_SIZE);
|
||||
|
||||
// In stage 0 proposals, we calculate a random nonce from this node to contribute to the group nonce
|
||||
std::string rand_bytes;
|
||||
crypto::random_bytes(rand_bytes, ledger::ROUND_NONCE_SIZE);
|
||||
ctx.round_nonce = crypto::get_hash(rand_bytes);
|
||||
p.node_nonce = ctx.round_nonce;
|
||||
|
||||
// Populate the proposal with set of candidate user pubkeys.
|
||||
p.users.swap(ctx.candidate_users);
|
||||
@@ -940,19 +938,24 @@ namespace consensus
|
||||
{
|
||||
// The proposal to be emited at the end of this stage.
|
||||
p2p::proposal p;
|
||||
p.stage = ctx.stage;
|
||||
|
||||
// We always vote for our current information regardless of what other peers are saying.
|
||||
// If there's a fork condition we will either request shards or hpfs state from
|
||||
// our peers or we will halt depending on level of consensus on the sides of the fork.
|
||||
p.stage = ctx.stage;
|
||||
p.state_hash = state_hash;
|
||||
p.patch_hash = patch_hash;
|
||||
p.last_primary_shard_id = last_primary_shard_id;
|
||||
p.last_raw_shard_id = last_raw_shard_id;
|
||||
p.time_config = CURRENT_TIME_CONFIG;
|
||||
p.output_hash.resize(BLAKE3_OUT_LEN); // Default empty hash.
|
||||
p.node_nonce = ctx.round_nonce;
|
||||
|
||||
const uint64_t time_now = util::get_epoch_milliseconds();
|
||||
|
||||
// Collect ordered nonces from all proposals in order to calculate the group nonce.
|
||||
std::set<std::string> node_nonces;
|
||||
|
||||
// Vote for rest of the proposal fields by looking at candidate proposals.
|
||||
for (const auto &[pubkey, cp] : ctx.candidate_proposals)
|
||||
{
|
||||
@@ -961,9 +964,6 @@ namespace consensus
|
||||
if (time_now > cp.time && (time_now - cp.time) <= (conf::cfg.contract.consensus.roundtime * 2))
|
||||
increment(votes.time, cp.time);
|
||||
|
||||
// Vote for round nonce.
|
||||
increment(votes.nonce, cp.nonce);
|
||||
|
||||
// Vote for user pubkeys.
|
||||
for (const std::string &pubkey : cp.users)
|
||||
increment(votes.users, pubkey);
|
||||
@@ -975,8 +975,14 @@ namespace consensus
|
||||
|
||||
// Vote for contract output hash.
|
||||
increment(votes.output_hash, cp.output_hash);
|
||||
|
||||
if (ctx.stage == 3)
|
||||
node_nonces.emplace(cp.node_nonce.to_string_view());
|
||||
}
|
||||
|
||||
if (ctx.stage == 3)
|
||||
p.group_nonce = crypto::get_list_hash(node_nonces);
|
||||
|
||||
// Compute the stage tresholds using ratios.
|
||||
// Threshold is devided by 100 to convert average to decimal.
|
||||
const float stage_threshold = ((STAGE_THRESHOLD_RATIO[ctx.stage - 1] * conf::cfg.contract.consensus.threshold) / (STAGE_THRESHOLD_RATIO[2] * 100.0));
|
||||
@@ -1043,17 +1049,6 @@ namespace consensus
|
||||
if (p.time == 0)
|
||||
p.time = ctx.round_start_time;
|
||||
|
||||
// Round nonce is voted on a simple sorted (highest to lowest) and majority basis, since there will always be disagreement.
|
||||
uint32_t highest_nonce_vote = 0;
|
||||
for (const auto [nonce, numvotes] : votes.nonce)
|
||||
{
|
||||
if (numvotes > highest_nonce_vote)
|
||||
{
|
||||
highest_nonce_vote = numvotes;
|
||||
p.nonce = nonce;
|
||||
}
|
||||
}
|
||||
|
||||
return p;
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,6 @@ namespace consensus
|
||||
{
|
||||
// The map of proposals that are being collected as consensus stages are progressing.
|
||||
// peer public key is the key.
|
||||
// todo: having a queue of proposals against peer pubkey.
|
||||
std::unordered_map<std::string, const p2p::proposal> candidate_proposals;
|
||||
|
||||
// Set of user pubkeys that is said to be connected to the cluster. This will be cleared in each round.
|
||||
@@ -113,6 +112,7 @@ namespace consensus
|
||||
uint32_t stage_reset_wait_threshold = 0; // Minimum stage wait time to reset the stage.
|
||||
uint64_t round_boundry_offset = 0; // Time window boundry offset based on contract id.
|
||||
uint16_t unreliable_votes_attempts = 0; // No. of times we failed to get reliable votes continously.
|
||||
util::h32 round_nonce; // The random nonce generated by this node for this consensus round.
|
||||
|
||||
// Indicates whether we are inside a sync cycle or not. Sync cycle is considered to being when we first detect that we are out of sync
|
||||
// and considered to end when we detect to be in sync inside stage 1 of a round for the first time after we began a sync.
|
||||
@@ -132,7 +132,6 @@ namespace consensus
|
||||
struct vote_counter
|
||||
{
|
||||
std::map<uint64_t, uint32_t> time;
|
||||
std::map<std::string, uint32_t> nonce;
|
||||
std::map<std::string, uint32_t> lcl;
|
||||
std::map<std::string, uint32_t> users;
|
||||
std::map<std::string, uint32_t> inputs;
|
||||
@@ -145,7 +144,6 @@ namespace consensus
|
||||
void reset()
|
||||
{
|
||||
time.clear();
|
||||
nonce.clear();
|
||||
lcl.clear();
|
||||
users.clear();
|
||||
inputs.clear();
|
||||
|
||||
@@ -41,7 +41,7 @@ namespace ledger
|
||||
|
||||
/**
|
||||
* Perform ledger related initializations.
|
||||
*/
|
||||
*/
|
||||
int init()
|
||||
{
|
||||
// Setup the static genesis ledger fields.
|
||||
@@ -91,7 +91,7 @@ namespace ledger
|
||||
|
||||
/**
|
||||
* Perform deinit tasks related to ledger.
|
||||
*/
|
||||
*/
|
||||
void deinit()
|
||||
{
|
||||
ledger_sync_worker.deinit();
|
||||
@@ -247,6 +247,7 @@ namespace ledger
|
||||
data.emplace_back((char *)time_bytes, sizeof(time_bytes));
|
||||
data.push_back(proposal.state_hash.to_string_view());
|
||||
data.push_back(proposal.patch_hash.to_string_view());
|
||||
data.push_back(proposal.group_nonce.to_string_view());
|
||||
data.push_back(user_hash);
|
||||
data.push_back(input_hash);
|
||||
data.push_back(proposal.output_hash);
|
||||
@@ -268,9 +269,11 @@ namespace ledger
|
||||
data_hash,
|
||||
std::string(proposal.state_hash.to_string_view()),
|
||||
std::string(proposal.patch_hash.to_string_view()),
|
||||
std::string(proposal.group_nonce.to_string_view()),
|
||||
user_hash,
|
||||
input_hash,
|
||||
proposal.output_hash}; // Merkle root output hash.
|
||||
proposal.output_hash // Merkle root output hash.
|
||||
};
|
||||
|
||||
if (sqlite::insert_ledger_row(db, ledger) == -1)
|
||||
{
|
||||
@@ -703,7 +706,7 @@ namespace ledger
|
||||
* @param last_shard_id Struct which holds last shard data. (sequence number and hash).
|
||||
* @param shard_parent_dir Parent director vpath of the shards.
|
||||
* @return 0 on success. -1 on error.
|
||||
*/
|
||||
*/
|
||||
int get_last_shard_info(std::string_view session_name, util::sequence_hash &last_shard_id, const std::string &shard_parent_dir)
|
||||
{
|
||||
const std::string last_shard_seq_no_vpath = shard_parent_dir + SHARD_SEQ_NO_FILENAME;
|
||||
@@ -746,12 +749,12 @@ namespace ledger
|
||||
}
|
||||
|
||||
/**
|
||||
* Update max_shard.seq_no meta file with the given latest shard sequence number which can be used to identify last shard
|
||||
* Update max_shard.seq_no meta file with the given latest shard sequence number which can be used to identify last shard
|
||||
* sequence number in startup.
|
||||
* @param shard_parent_dir Shard's parent directory. (primary or raw).
|
||||
* @param last_shard_seq_no Last shard sequence number of the given parent.
|
||||
* @return Return -1 on error and 0 on success.
|
||||
*/
|
||||
*/
|
||||
int persist_max_shard_seq_no(const std::string &shard_parent_dir, const uint64_t last_shard_seq_no)
|
||||
{
|
||||
const std::string last_shard_seq_no_vpath = shard_parent_dir + SHARD_SEQ_NO_FILENAME;
|
||||
@@ -789,7 +792,7 @@ namespace ledger
|
||||
* @param root_hash The calculated root hash as of the given seq_no.
|
||||
* @param seq_no Ledger's sequence number.
|
||||
* @return Returns -1 on error and 0 on success.
|
||||
*/
|
||||
*/
|
||||
int get_root_hash_from_ledger(util::h32 &root_hash, const uint64_t seq_no)
|
||||
{
|
||||
sqlite3 *db = NULL;
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace ledger
|
||||
constexpr const char *RAW_OUTPUTS_FILE = "raw_outputs.blob";
|
||||
constexpr uint64_t PRIMARY_SHARD_SIZE = 262144; // 2^18 ledgers per shard.
|
||||
constexpr uint64_t RAW_SHARD_SIZE = 4096;
|
||||
constexpr size_t ROUND_NONCE_SIZE = 64;
|
||||
|
||||
/**
|
||||
* Holds an individual input for a user within a ledger.
|
||||
@@ -43,19 +44,24 @@ namespace ledger
|
||||
/**
|
||||
* Struct to hold ledger fields corresponding to sqlite table.
|
||||
* All the hashes are stored as 32 byte binary data.
|
||||
*/
|
||||
*/
|
||||
struct ledger_record
|
||||
{
|
||||
uint64_t seq_no = 0;
|
||||
uint64_t timestamp = 0;
|
||||
std::string ledger_hash;
|
||||
|
||||
// COntributing hashes.
|
||||
std::string prev_ledger_hash;
|
||||
std::string data_hash;
|
||||
std::string state_hash;
|
||||
std::string config_hash;
|
||||
std::string nonce;
|
||||
std::string user_hash;
|
||||
std::string input_hash;
|
||||
std::string output_hash;
|
||||
|
||||
// Raw data.
|
||||
std::optional<std::vector<ledger_user_input>> inputs;
|
||||
std::optional<std::vector<ledger_user_output>> outputs;
|
||||
};
|
||||
|
||||
@@ -35,8 +35,8 @@ namespace ledger::sqlite
|
||||
|
||||
constexpr const char *INSERT_INTO_LEDGER = "INSERT INTO ledger("
|
||||
"seq_no, time, ledger_hash, prev_ledger_hash, data_hash,"
|
||||
"state_hash, patch_hash, user_hash, input_hash, output_hash"
|
||||
") VALUES(?,?,?,?,?,?,?,?,?,?)";
|
||||
"state_hash, config_hash, nonce, user_hash, input_hash, output_hash"
|
||||
") VALUES(?,?,?,?,?,?,?,?,?,?,?)";
|
||||
constexpr const char *INSERT_INTO_USERS = "INSERT INTO users(ledger_seq_no, pubkey) VALUES(?,?)";
|
||||
constexpr const char *INSERT_INTO_USER_INPUTS = "INSERT INTO inputs(ledger_seq_no, pubkey, hash, nonce,"
|
||||
" blob_offset, blob_size) VALUES(?,?,?,?,?,?)";
|
||||
@@ -56,7 +56,7 @@ namespace ledger::sqlite
|
||||
* @param writable Whether the database must be opened in a writable mode or not.
|
||||
* @param journal Whether to enable db journaling or not.
|
||||
* @returns returns 0 on success, or -1 on error.
|
||||
*/
|
||||
*/
|
||||
int open_db(std::string_view db_name, sqlite3 **db, const bool writable, const bool journal)
|
||||
{
|
||||
int ret;
|
||||
@@ -84,7 +84,7 @@ namespace ledger::sqlite
|
||||
* @param callback Callback funcion which is called for each result row.
|
||||
* @param callback_first_arg First data argumat to be parced to the callback (void pointer).
|
||||
* @returns returns 0 on success, or -1 on error.
|
||||
*/
|
||||
*/
|
||||
int exec_sql(sqlite3 *db, std::string_view sql, int (*callback)(void *, int, char **, char **), void *callback_first_arg)
|
||||
{
|
||||
char *err_msg;
|
||||
@@ -118,7 +118,7 @@ namespace ledger::sqlite
|
||||
* @param table_name Table name to be created.
|
||||
* @param column_info Column info of the table.
|
||||
* @returns returns 0 on success, or -1 on error.
|
||||
*/
|
||||
*/
|
||||
int create_table(sqlite3 *db, std::string_view table_name, const std::vector<table_column_info> &column_info)
|
||||
{
|
||||
std::string sql;
|
||||
@@ -186,7 +186,7 @@ namespace ledger::sqlite
|
||||
* @param column_names_string Comma seperated string of colums (eg: "col_1,col_2,...").
|
||||
* @param value_strings Vector of comma seperated values (wrap in single quotes for TEXT type) (eg: ["r1val1,'r1val2',...", "r2val1,'r2val2',..."]).
|
||||
* @returns returns 0 on success, or -1 on error.
|
||||
*/
|
||||
*/
|
||||
int insert_rows(sqlite3 *db, std::string_view table_name, std::string_view column_names_string, const std::vector<std::string> &value_strings)
|
||||
{
|
||||
std::string sql;
|
||||
@@ -219,7 +219,7 @@ namespace ledger::sqlite
|
||||
* @param column_names_string Comma seperated string of colums (eg: "col_1,col_2,...").
|
||||
* @param value_string comma seperated values as per column order (wrap in single quotes for TEXT type) (eg: "r1val1,'r1val2',...").
|
||||
* @returns returns 0 on success, or -1 on error.
|
||||
*/
|
||||
*/
|
||||
int insert_row(sqlite3 *db, std::string_view table_name, std::string_view column_names_string, std::string_view value_string)
|
||||
{
|
||||
std::string sql;
|
||||
@@ -245,7 +245,7 @@ namespace ledger::sqlite
|
||||
* @param db Pointer to the db.
|
||||
* @param table_name Table name to be checked.
|
||||
* @returns returns true is exist, otherwise false.
|
||||
*/
|
||||
*/
|
||||
bool is_table_exists(sqlite3 *db, std::string_view table_name)
|
||||
{
|
||||
std::string sql;
|
||||
@@ -280,7 +280,7 @@ namespace ledger::sqlite
|
||||
* Closes a connection to a given databse.
|
||||
* @param db Pointer to the db.
|
||||
* @returns returns 0 on success, or -1 on error.
|
||||
*/
|
||||
*/
|
||||
int close_db(sqlite3 **db)
|
||||
{
|
||||
if (*db == NULL)
|
||||
@@ -300,7 +300,7 @@ namespace ledger::sqlite
|
||||
* Sets up a blank ledger database.
|
||||
* @param db Pointer to the db.
|
||||
* @returns returns 0 on success, or -1 on error.
|
||||
*/
|
||||
*/
|
||||
int initialize_ledger_db(sqlite3 *db)
|
||||
{
|
||||
const std::vector<table_column_info> columns{
|
||||
@@ -310,7 +310,8 @@ namespace ledger::sqlite
|
||||
table_column_info("prev_ledger_hash", COLUMN_DATA_TYPE::BLOB),
|
||||
table_column_info("data_hash", COLUMN_DATA_TYPE::BLOB),
|
||||
table_column_info("state_hash", COLUMN_DATA_TYPE::BLOB),
|
||||
table_column_info("patch_hash", COLUMN_DATA_TYPE::BLOB),
|
||||
table_column_info("config_hash", COLUMN_DATA_TYPE::BLOB),
|
||||
table_column_info("nonce", COLUMN_DATA_TYPE::BLOB),
|
||||
table_column_info("user_hash", COLUMN_DATA_TYPE::BLOB),
|
||||
table_column_info("input_hash", COLUMN_DATA_TYPE::BLOB),
|
||||
table_column_info("output_hash", COLUMN_DATA_TYPE::BLOB)};
|
||||
@@ -327,7 +328,7 @@ namespace ledger::sqlite
|
||||
* Sets up a blank ledger raw data database.
|
||||
* @param db Pointer to the db.
|
||||
* @returns returns 0 on success, or -1 on error.
|
||||
*/
|
||||
*/
|
||||
int initialize_ledger_raw_db(sqlite3 *db)
|
||||
{
|
||||
// Users table.
|
||||
@@ -383,8 +384,8 @@ namespace ledger::sqlite
|
||||
* @param db Pointer to the db.
|
||||
* @param version Version string to be placed in the table.
|
||||
* @returns returns 0 on success, or -1 on error.
|
||||
*
|
||||
*/
|
||||
*
|
||||
*/
|
||||
int create_hp_table(sqlite3 *db, std::string_view version)
|
||||
{
|
||||
const std::vector<table_column_info> column_info{
|
||||
@@ -405,7 +406,7 @@ namespace ledger::sqlite
|
||||
* @param db Pointer to the db.
|
||||
* @param ledger Ledger struct to be inserted.
|
||||
* @returns returns 0 on success, or -1 on error.
|
||||
*/
|
||||
*/
|
||||
int insert_ledger_row(sqlite3 *db, const ledger::ledger_record &ledger)
|
||||
{
|
||||
sqlite3_stmt *stmt;
|
||||
@@ -417,9 +418,10 @@ namespace ledger::sqlite
|
||||
BIND_H32_BLOB(5, ledger.data_hash) &&
|
||||
BIND_H32_BLOB(6, ledger.state_hash) &&
|
||||
BIND_H32_BLOB(7, ledger.config_hash) &&
|
||||
BIND_H32_BLOB(8, ledger.user_hash) &&
|
||||
BIND_H32_BLOB(9, ledger.input_hash) &&
|
||||
BIND_H32_BLOB(10, ledger.output_hash) &&
|
||||
BIND_H32_BLOB(8, ledger.nonce) &&
|
||||
BIND_H32_BLOB(9, ledger.user_hash) &&
|
||||
BIND_H32_BLOB(10, ledger.input_hash) &&
|
||||
BIND_H32_BLOB(11, ledger.output_hash) &&
|
||||
sqlite3_step(stmt) == SQLITE_DONE)
|
||||
{
|
||||
sqlite3_finalize(stmt);
|
||||
@@ -533,7 +535,7 @@ namespace ledger::sqlite
|
||||
* @param db Pointer to the db.
|
||||
* @param ledger Ledger structure to populate.
|
||||
* @returns 0 on success. -1 on failure.
|
||||
*/
|
||||
*/
|
||||
int get_last_ledger(sqlite3 *db, ledger::ledger_record &ledger)
|
||||
{
|
||||
sqlite3_stmt *stmt;
|
||||
@@ -557,7 +559,7 @@ namespace ledger::sqlite
|
||||
* @param seq_no Ledger sequence no. to search for.
|
||||
* @param ledger Ledger structure to populate.
|
||||
* @returns 1 if ledger found. 0 if ledger not found. -1 on failure.
|
||||
*/
|
||||
*/
|
||||
int get_ledger_by_seq_no(sqlite3 *db, const uint64_t seq_no, ledger::ledger_record &ledger)
|
||||
{
|
||||
sqlite3_stmt *stmt;
|
||||
@@ -669,9 +671,10 @@ namespace ledger::sqlite
|
||||
ledger.data_hash = GET_H32_BLOB(4);
|
||||
ledger.state_hash = GET_H32_BLOB(5);
|
||||
ledger.config_hash = GET_H32_BLOB(6);
|
||||
ledger.user_hash = GET_H32_BLOB(7);
|
||||
ledger.input_hash = GET_H32_BLOB(8);
|
||||
ledger.output_hash = GET_H32_BLOB(9);
|
||||
ledger.nonce = GET_H32_BLOB(7);
|
||||
ledger.user_hash = GET_H32_BLOB(8);
|
||||
ledger.input_hash = GET_H32_BLOB(9);
|
||||
ledger.output_hash = GET_H32_BLOB(10);
|
||||
}
|
||||
|
||||
ledger::ledger_user_input populate_user_input_from_sql_record(sqlite3_stmt *stmt)
|
||||
|
||||
@@ -59,7 +59,8 @@ table ProposalMsg {
|
||||
stage:uint8;
|
||||
time:uint64;
|
||||
time_config:uint32; // Contains unified value derived from (roundtime*100 + stage_slice)
|
||||
nonce: [ubyte];
|
||||
node_nonce: [ubyte];
|
||||
group_nonce: [ubyte];
|
||||
users:[ByteArray];
|
||||
input_hashes:[ByteArray];
|
||||
output_hash:[ubyte];
|
||||
|
||||
@@ -77,13 +77,16 @@ namespace msg::fbuf::p2pmsg
|
||||
return util::h32_empty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a hash using the consensus data fields of the proposal.
|
||||
*/
|
||||
const util::h32 hash_proposal_msg(const msg::fbuf::p2pmsg::ProposalMsg &msg)
|
||||
{
|
||||
flatbuf_hasher hasher;
|
||||
hasher.add(msg.stage());
|
||||
hasher.add(msg.time());
|
||||
hasher.add(msg.time_config());
|
||||
hasher.add(msg.nonce());
|
||||
hasher.add(msg.group_nonce());
|
||||
hasher.add(msg.users());
|
||||
hasher.add(msg.input_hashes());
|
||||
hasher.add(msg.output_hash());
|
||||
@@ -149,7 +152,8 @@ namespace msg::fbuf::p2pmsg
|
||||
p.recv_timestamp = util::get_epoch_milliseconds();
|
||||
p.time = msg.time();
|
||||
p.time_config = msg.time_config();
|
||||
p.nonce = flatbuf_bytes_to_sv(msg.nonce());
|
||||
p.node_nonce = flatbuf_bytes_to_sv(msg.node_nonce());
|
||||
p.group_nonce = flatbuf_bytes_to_sv(msg.group_nonce());
|
||||
p.stage = msg.stage();
|
||||
p.state_hash = flatbuf_bytes_to_sv(msg.state_hash());
|
||||
p.patch_hash = flatbuf_bytes_to_sv(msg.patch_hash());
|
||||
@@ -335,7 +339,7 @@ namespace msg::fbuf::p2pmsg
|
||||
hasher.add(p.stage);
|
||||
hasher.add(p.time);
|
||||
hasher.add(p.time_config);
|
||||
hasher.add(p.nonce);
|
||||
hasher.add(p.group_nonce);
|
||||
hasher.add(p.users);
|
||||
hasher.add(p.input_ordered_hashes);
|
||||
hasher.add(p.output_hash);
|
||||
@@ -412,7 +416,8 @@ namespace msg::fbuf::p2pmsg
|
||||
p.stage,
|
||||
p.time,
|
||||
p.time_config,
|
||||
sv_to_flatbuf_bytes(builder, p.nonce),
|
||||
hash_to_flatbuf_bytes(builder, p.node_nonce),
|
||||
hash_to_flatbuf_bytes(builder, p.group_nonce),
|
||||
stringlist_to_flatbuf_bytearrayvector(builder, p.users),
|
||||
stringlist_to_flatbuf_bytearrayvector(builder, p.input_ordered_hashes),
|
||||
sv_to_flatbuf_bytes(builder, p.output_hash),
|
||||
|
||||
@@ -954,15 +954,16 @@ struct ProposalMsg FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
VT_STAGE = 8,
|
||||
VT_TIME = 10,
|
||||
VT_TIME_CONFIG = 12,
|
||||
VT_NONCE = 14,
|
||||
VT_USERS = 16,
|
||||
VT_INPUT_HASHES = 18,
|
||||
VT_OUTPUT_HASH = 20,
|
||||
VT_OUTPUT_SIG = 22,
|
||||
VT_STATE_HASH = 24,
|
||||
VT_PATCH_HASH = 26,
|
||||
VT_LAST_PRIMARY_SHARD_ID = 28,
|
||||
VT_LAST_RAW_SHARD_ID = 30
|
||||
VT_NODE_NONCE = 14,
|
||||
VT_GROUP_NONCE = 16,
|
||||
VT_USERS = 18,
|
||||
VT_INPUT_HASHES = 20,
|
||||
VT_OUTPUT_HASH = 22,
|
||||
VT_OUTPUT_SIG = 24,
|
||||
VT_STATE_HASH = 26,
|
||||
VT_PATCH_HASH = 28,
|
||||
VT_LAST_PRIMARY_SHARD_ID = 30,
|
||||
VT_LAST_RAW_SHARD_ID = 32
|
||||
};
|
||||
const flatbuffers::Vector<uint8_t> *pubkey() const {
|
||||
return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_PUBKEY);
|
||||
@@ -994,11 +995,17 @@ struct ProposalMsg FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
bool mutate_time_config(uint32_t _time_config) {
|
||||
return SetField<uint32_t>(VT_TIME_CONFIG, _time_config, 0);
|
||||
}
|
||||
const flatbuffers::Vector<uint8_t> *nonce() const {
|
||||
return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_NONCE);
|
||||
const flatbuffers::Vector<uint8_t> *node_nonce() const {
|
||||
return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_NODE_NONCE);
|
||||
}
|
||||
flatbuffers::Vector<uint8_t> *mutable_nonce() {
|
||||
return GetPointer<flatbuffers::Vector<uint8_t> *>(VT_NONCE);
|
||||
flatbuffers::Vector<uint8_t> *mutable_node_nonce() {
|
||||
return GetPointer<flatbuffers::Vector<uint8_t> *>(VT_NODE_NONCE);
|
||||
}
|
||||
const flatbuffers::Vector<uint8_t> *group_nonce() const {
|
||||
return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_GROUP_NONCE);
|
||||
}
|
||||
flatbuffers::Vector<uint8_t> *mutable_group_nonce() {
|
||||
return GetPointer<flatbuffers::Vector<uint8_t> *>(VT_GROUP_NONCE);
|
||||
}
|
||||
const flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::p2pmsg::ByteArray>> *users() const {
|
||||
return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::p2pmsg::ByteArray>> *>(VT_USERS);
|
||||
@@ -1057,8 +1064,10 @@ struct ProposalMsg FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table {
|
||||
VerifyField<uint8_t>(verifier, VT_STAGE) &&
|
||||
VerifyField<uint64_t>(verifier, VT_TIME) &&
|
||||
VerifyField<uint32_t>(verifier, VT_TIME_CONFIG) &&
|
||||
VerifyOffset(verifier, VT_NONCE) &&
|
||||
verifier.VerifyVector(nonce()) &&
|
||||
VerifyOffset(verifier, VT_NODE_NONCE) &&
|
||||
verifier.VerifyVector(node_nonce()) &&
|
||||
VerifyOffset(verifier, VT_GROUP_NONCE) &&
|
||||
verifier.VerifyVector(group_nonce()) &&
|
||||
VerifyOffset(verifier, VT_USERS) &&
|
||||
verifier.VerifyVector(users()) &&
|
||||
verifier.VerifyVectorOfTables(users()) &&
|
||||
@@ -1100,8 +1109,11 @@ struct ProposalMsgBuilder {
|
||||
void add_time_config(uint32_t time_config) {
|
||||
fbb_.AddElement<uint32_t>(ProposalMsg::VT_TIME_CONFIG, time_config, 0);
|
||||
}
|
||||
void add_nonce(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> nonce) {
|
||||
fbb_.AddOffset(ProposalMsg::VT_NONCE, nonce);
|
||||
void add_node_nonce(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> node_nonce) {
|
||||
fbb_.AddOffset(ProposalMsg::VT_NODE_NONCE, node_nonce);
|
||||
}
|
||||
void add_group_nonce(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> group_nonce) {
|
||||
fbb_.AddOffset(ProposalMsg::VT_GROUP_NONCE, group_nonce);
|
||||
}
|
||||
void add_users(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::p2pmsg::ByteArray>>> users) {
|
||||
fbb_.AddOffset(ProposalMsg::VT_USERS, users);
|
||||
@@ -1146,7 +1158,8 @@ inline flatbuffers::Offset<ProposalMsg> CreateProposalMsg(
|
||||
uint8_t stage = 0,
|
||||
uint64_t time = 0,
|
||||
uint32_t time_config = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> nonce = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> node_nonce = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> group_nonce = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::p2pmsg::ByteArray>>> users = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<msg::fbuf::p2pmsg::ByteArray>>> input_hashes = 0,
|
||||
flatbuffers::Offset<flatbuffers::Vector<uint8_t>> output_hash = 0,
|
||||
@@ -1165,7 +1178,8 @@ inline flatbuffers::Offset<ProposalMsg> CreateProposalMsg(
|
||||
builder_.add_output_hash(output_hash);
|
||||
builder_.add_input_hashes(input_hashes);
|
||||
builder_.add_users(users);
|
||||
builder_.add_nonce(nonce);
|
||||
builder_.add_group_nonce(group_nonce);
|
||||
builder_.add_node_nonce(node_nonce);
|
||||
builder_.add_time_config(time_config);
|
||||
builder_.add_sig(sig);
|
||||
builder_.add_pubkey(pubkey);
|
||||
@@ -1180,7 +1194,8 @@ inline flatbuffers::Offset<ProposalMsg> CreateProposalMsgDirect(
|
||||
uint8_t stage = 0,
|
||||
uint64_t time = 0,
|
||||
uint32_t time_config = 0,
|
||||
const std::vector<uint8_t> *nonce = nullptr,
|
||||
const std::vector<uint8_t> *node_nonce = nullptr,
|
||||
const std::vector<uint8_t> *group_nonce = nullptr,
|
||||
const std::vector<flatbuffers::Offset<msg::fbuf::p2pmsg::ByteArray>> *users = nullptr,
|
||||
const std::vector<flatbuffers::Offset<msg::fbuf::p2pmsg::ByteArray>> *input_hashes = nullptr,
|
||||
const std::vector<uint8_t> *output_hash = nullptr,
|
||||
@@ -1191,7 +1206,8 @@ inline flatbuffers::Offset<ProposalMsg> CreateProposalMsgDirect(
|
||||
flatbuffers::Offset<msg::fbuf::p2pmsg::SequenceHash> last_raw_shard_id = 0) {
|
||||
auto pubkey__ = pubkey ? _fbb.CreateVector<uint8_t>(*pubkey) : 0;
|
||||
auto sig__ = sig ? _fbb.CreateVector<uint8_t>(*sig) : 0;
|
||||
auto nonce__ = nonce ? _fbb.CreateVector<uint8_t>(*nonce) : 0;
|
||||
auto node_nonce__ = node_nonce ? _fbb.CreateVector<uint8_t>(*node_nonce) : 0;
|
||||
auto group_nonce__ = group_nonce ? _fbb.CreateVector<uint8_t>(*group_nonce) : 0;
|
||||
auto users__ = users ? _fbb.CreateVector<flatbuffers::Offset<msg::fbuf::p2pmsg::ByteArray>>(*users) : 0;
|
||||
auto input_hashes__ = input_hashes ? _fbb.CreateVector<flatbuffers::Offset<msg::fbuf::p2pmsg::ByteArray>>(*input_hashes) : 0;
|
||||
auto output_hash__ = output_hash ? _fbb.CreateVector<uint8_t>(*output_hash) : 0;
|
||||
@@ -1205,7 +1221,8 @@ inline flatbuffers::Offset<ProposalMsg> CreateProposalMsgDirect(
|
||||
stage,
|
||||
time,
|
||||
time_config,
|
||||
nonce__,
|
||||
node_nonce__,
|
||||
group_nonce__,
|
||||
users__,
|
||||
input_hashes__,
|
||||
output_hash__,
|
||||
|
||||
@@ -44,7 +44,8 @@ namespace p2p
|
||||
uint64_t time = 0; // The descreet concensus time value that is voted on.
|
||||
uint8_t stage = 0; // The round-stage that this proposal belongs to.
|
||||
uint32_t time_config = 0; // Time config of the proposer.
|
||||
std::string nonce; // Random nonce that is used to reduce lcl predictability.
|
||||
util::h32 node_nonce; // The random nonce produced by a particular node for the current consensus round.
|
||||
util::h32 group_nonce; // The stage 3 canonical nonce (hash of all node nonces) which is used to salt the ledger.
|
||||
util::sequence_hash last_primary_shard_id;
|
||||
util::sequence_hash last_raw_shard_id;
|
||||
util::h32 state_hash; // Contract state hash.
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
|
||||
namespace util
|
||||
{
|
||||
|
||||
// blake3b hash is 32 bytes which we store as 4 quad words
|
||||
// Originally from https://github.com/codetsunami/file-ptracer/blob/master/merkle.cpp
|
||||
struct h32
|
||||
@@ -15,14 +14,17 @@ namespace util
|
||||
bool operator==(const h32 rhs) const;
|
||||
bool operator!=(const h32 rhs) const;
|
||||
void operator^=(const h32 rhs);
|
||||
std::string_view to_string_view() const;
|
||||
h32 &operator=(std::string_view sv);
|
||||
void operator^=(std::string_view sv);
|
||||
bool operator<(const h32 rhs) const;
|
||||
std::string_view to_string_view() const;
|
||||
|
||||
h32()
|
||||
{
|
||||
memset(data, 0, sizeof(data));
|
||||
data[0] = 0;
|
||||
data[1] = 0;
|
||||
data[2] = 0;
|
||||
data[3] = 0;
|
||||
}
|
||||
};
|
||||
extern h32 h32_empty;
|
||||
|
||||
@@ -6,13 +6,13 @@
|
||||
namespace version
|
||||
{
|
||||
// HotPocket version. Written to new configs and p2p/user messages.
|
||||
constexpr const char *HP_VERSION = "0.6.2";
|
||||
constexpr const char *HP_VERSION = "0.6.3";
|
||||
|
||||
// Minimum compatible config version (this will be used to validate configs).
|
||||
constexpr const char *MIN_CONFIG_VERSION = "0.6.2";
|
||||
constexpr const char *MIN_CONFIG_VERSION = "0.6.3";
|
||||
|
||||
// Ledger file storage version. All nodes in a cluster MUST use the same ledger version.
|
||||
constexpr const char *LEDGER_VERSION = "0.5.0";
|
||||
constexpr const char *LEDGER_VERSION = "0.6.3";
|
||||
|
||||
// Version header size in bytes when serialized in binary format. (applies to hp version as well as ledger version)
|
||||
// 2 bytes each for 3 version components. 2 bytes reserved.
|
||||
|
||||
@@ -14,7 +14,7 @@ fi
|
||||
|
||||
clusterloc=$(pwd)/hpcluster
|
||||
n=$1
|
||||
hpversion=0.6.1
|
||||
hpversion=0.6.3
|
||||
|
||||
let pubport=8080+$n
|
||||
let peerport=22860+$n
|
||||
|
||||
@@ -5,7 +5,7 @@ WINDOWSIZE=60 # size of window in seconds to examine for successful consensus ro
|
||||
PIPE=concon.pipe
|
||||
clusterloc=$(pwd)/hpcluster
|
||||
n=1
|
||||
hpversion=0.6.1
|
||||
hpversion=0.6.3
|
||||
let pubport=8080+$n
|
||||
while true; do
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
|
||||
clusterloc=$(pwd)/hpcluster
|
||||
n=1
|
||||
hpversion=0.6.1
|
||||
hpversion=0.6.3
|
||||
let pubport=8080+$n
|
||||
while true; do
|
||||
CONSENSUS="0"
|
||||
|
||||
@@ -15,7 +15,7 @@ fi
|
||||
dir=$(realpath $1)
|
||||
dirname=$(basename $dir)
|
||||
n=$1
|
||||
hpversion=0.6.1
|
||||
hpversion=0.6.3
|
||||
|
||||
let pubport=8080
|
||||
|
||||
|
||||
Reference in New Issue
Block a user