Usage of nonce hash for ledger hash generation (#375)

This commit is contained in:
Kithmini Gunawardhana
2023-08-03 16:52:56 +05:30
committed by GitHub
parent 0022bd51e5
commit 6a2384cd03
16 changed files with 148 additions and 117 deletions

View File

@@ -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)

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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;

View File

@@ -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;
};

View File

@@ -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)

View File

@@ -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];

View File

@@ -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),

View File

@@ -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__,

View File

@@ -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.

View File

@@ -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;

View File

@@ -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.

View File

@@ -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

View File

@@ -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

View File

@@ -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"

View File

@@ -15,7 +15,7 @@ fi
dir=$(realpath $1)
dirname=$(basename $dir)
n=$1
hpversion=0.6.1
hpversion=0.6.3
let pubport=8080