Util helper func simplification. (#203)

This commit is contained in:
Ravin Perera
2020-12-23 21:49:13 +05:30
committed by GitHub
parent 8dc20bdab0
commit c25ebe66f4
17 changed files with 205 additions and 416 deletions

View File

@@ -32,11 +32,9 @@ namespace conf
// 2. Read and load the contract config into memory
// 3. Validate the loaded config values
contract_config cfg = {};
if (validate_contract_dir_paths() == -1 ||
read_config(cfg) == -1 ||
validate_config(cfg) == -1 ||
populate_runtime_config(cfg) == -1)
validate_config(cfg) == -1)
{
return -1;
}
@@ -55,7 +53,8 @@ namespace conf
return -1;
crypto::generate_signing_keys(cfg.node.public_key, cfg.node.private_key);
binpair_to_hex(cfg);
cfg.node.public_key_hex = util::to_hex(cfg.node.public_key);
cfg.node.private_key_hex = util::to_hex(cfg.node.private_key);
if (write_config(cfg) != 0)
return -1;
@@ -93,8 +92,10 @@ namespace conf
//We populate the in-memory struct with default settings and then save it to the file.
contract_config cfg = {};
crypto::generate_signing_keys(cfg.node.public_key, cfg.node.private_key);
binpair_to_hex(cfg);
cfg.node.public_key_hex = util::to_hex(cfg.node.public_key);
cfg.node.private_key_hex = util::to_hex(cfg.node.private_key);
cfg.hp_version = util::HP_VERSION;
@@ -119,14 +120,8 @@ namespace conf
cfg.user.port = 8080;
cfg.user.idle_timeout = 0;
#ifndef NDEBUG
cfg.log.loglevel_type = conf::LOG_SEVERITY::DEBUG;
cfg.log.loglevel = "dbg";
#else
cfg.log.loglevel_type = conf::LOG_SEVERITY::WARN;
cfg.log.loglevel = "inf";
#endif
cfg.log.loggers.emplace("console");
cfg.log.loggers.emplace("file");
@@ -240,126 +235,171 @@ namespace conf
return -1;
}
const jsoncons::json &node = d["node"];
cfg.node.pub_key_hex = node["public_key"].as<std::string>();
cfg.node.private_key_hex = node["private_key"].as<std::string>();
if (node["role"] == ROLE_OBSERVER)
cfg.node.role = ROLE::OBSERVER;
else if (node["role"] == ROLE_VALIDATOR)
cfg.node.role = ROLE::VALIDATOR;
else
// node
{
std::cerr << "Invalid mode. 'observer' or 'validator' expected.\n";
return -1;
}
const jsoncons::json &node = d["node"];
cfg.node.public_key_hex = node["public_key"].as<std::string>();
cfg.node.private_key_hex = node["private_key"].as<std::string>();
const jsoncons::json &contract = d["contract"];
cfg.contract.id = contract["id"].as<std::string>();
cfg.contract.version = contract["version"].as<std::string>();
if (cfg.contract.id.empty())
{
std::cerr << "Contract id not specified.\n";
return -1;
}
else if (cfg.contract.version.empty())
{
std::cerr << "Contract version not specified.\n";
return -1;
}
cfg.contract.unl.clear();
for (auto &nodepk : contract["unl"].array_range())
{
// Convert the public key hex of each node to binary and store it.
std::string bin_pubkey;
bin_pubkey.resize(crypto::PFXD_PUBKEY_BYTES);
if (util::hex2bin(
reinterpret_cast<unsigned char *>(bin_pubkey.data()),
bin_pubkey.length(),
nodepk.as<std::string_view>()) != 0)
// Convert the hex keys to binary.
cfg.node.public_key = util::to_bin(cfg.node.public_key_hex);
if (cfg.node.public_key.empty())
{
std::cerr << "Error decoding unl list.\n";
return -1;
}
cfg.contract.unl.emplace(bin_pubkey);
}
cfg.contract.bin_path = contract["bin_path"].as<std::string>();
cfg.contract.bin_args = contract["bin_args"].as<std::string>();
cfg.contract.roundtime = contract["roundtime"].as<uint16_t>();
if (contract["consensus"] != PUBLIC && contract["consensus"] != PRIVATE)
{
std::cerr << "Invalid consensus flag configured. Valid values: public|private\n";
return -1;
}
cfg.contract.is_consensus_public = contract["consensus"] == PUBLIC;
if (contract["npl"] != PUBLIC && contract["npl"] != PRIVATE)
{
std::cerr << "Invalid npl flag configured. Valid values: public|private\n";
return -1;
}
cfg.contract.is_npl_public = contract["npl"] == PUBLIC;
cfg.contract.appbill.mode = contract["appbill"]["mode"].as<std::string>();
cfg.contract.appbill.bin_args = contract["appbill"]["bin_args"].as<std::string>();
const jsoncons::json &mesh = d["mesh"];
cfg.mesh.port = mesh["port"].as<uint16_t>();
// Storing peers in unordered map keyed by the concatenated address:port and also saving address and port
// seperately to retrieve easily when handling peer connections.
std::vector<std::string> splitted_peers;
cfg.mesh.known_peers.clear();
for (auto &v : mesh["known_peers"].array_range())
{
const char *ipport_concat = v.as<const char *>();
// Split the address:port text into two
util::split_string(splitted_peers, ipport_concat, ":");
// Push the peer address and the port to peers set
if (splitted_peers.size() != 2)
{
std::cerr << "Invalid peer: " << ipport_concat << "\n";
std::cerr << "Error decoding hex public key.\n";
return -1;
}
peer_properties peer;
peer.ip_port.host_address = splitted_peers.front();
peer.ip_port.port = std::stoi(splitted_peers.back());
cfg.node.private_key = util::to_bin(cfg.node.private_key_hex);
if (cfg.node.private_key.empty())
{
std::cerr << "Error decoding hex private key.\n";
return -1;
}
cfg.mesh.known_peers.push_back(peer);
splitted_peers.clear();
if (node["role"] == ROLE_OBSERVER)
cfg.node.role = ROLE::OBSERVER;
else if (node["role"] == ROLE_VALIDATOR)
cfg.node.role = ROLE::VALIDATOR;
else
{
std::cerr << "Invalid mode. 'observer' or 'validator' expected.\n";
return -1;
}
startup_mode = cfg.node.role;
}
cfg.mesh.msg_forwarding = mesh["msg_forwarding"].as<bool>();
cfg.mesh.max_connections = mesh["max_connections"].as<uint16_t>();
cfg.mesh.max_known_connections = mesh["max_known_connections"].as<uint16_t>();
// If max_connections is greater than max_known_connections then show error and stop execution.
if (cfg.mesh.max_known_connections > cfg.mesh.max_connections)
// contract
{
std::cerr << "Invalid configuration values: mesh max_known_connections count should not exceed mesh max_connections." << '\n';
return -1;
const jsoncons::json &contract = d["contract"];
cfg.contract.id = contract["id"].as<std::string>();
cfg.contract.version = contract["version"].as<std::string>();
if (cfg.contract.id.empty())
{
std::cerr << "Contract id not specified.\n";
return -1;
}
else if (cfg.contract.version.empty())
{
std::cerr << "Contract version not specified.\n";
return -1;
}
cfg.contract.unl.clear();
for (auto &nodepk : contract["unl"].array_range())
{
// Convert the public key hex of each node to binary and store it.
const std::string bin_pubkey = util::to_bin(nodepk.as<std::string_view>());
if (bin_pubkey.empty())
{
std::cerr << "Error decoding unl list.\n";
return -1;
}
cfg.contract.unl.emplace(bin_pubkey);
}
cfg.contract.bin_path = contract["bin_path"].as<std::string>();
cfg.contract.bin_args = contract["bin_args"].as<std::string>();
cfg.contract.roundtime = contract["roundtime"].as<uint16_t>();
if (contract["consensus"] != PUBLIC && contract["consensus"] != PRIVATE)
{
std::cerr << "Invalid consensus flag configured. Valid values: public|private\n";
return -1;
}
cfg.contract.is_consensus_public = contract["consensus"] == PUBLIC;
if (contract["npl"] != PUBLIC && contract["npl"] != PRIVATE)
{
std::cerr << "Invalid npl flag configured. Valid values: public|private\n";
return -1;
}
cfg.contract.is_npl_public = contract["npl"] == PUBLIC;
cfg.contract.appbill.mode = contract["appbill"]["mode"].as<std::string>();
cfg.contract.appbill.bin_args = contract["appbill"]["bin_args"].as<std::string>();
// Populate runtime contract execution args.
if (!cfg.contract.bin_args.empty())
util::split_string(cfg.contract.runtime_binexec_args, cfg.contract.bin_args, " ");
cfg.contract.runtime_binexec_args.insert(cfg.contract.runtime_binexec_args.begin(), (cfg.contract.bin_path[0] == '/' ? cfg.contract.bin_path : util::realpath(ctx.contract_dir + "/bin/" + cfg.contract.bin_path)));
// Populate runtime app bill args.
if (!cfg.contract.appbill.bin_args.empty())
util::split_string(cfg.contract.appbill.runtime_args, cfg.contract.appbill.bin_args, " ");
cfg.contract.appbill.runtime_args.insert(cfg.contract.appbill.runtime_args.begin(), (cfg.contract.appbill.mode[0] == '/' ? cfg.contract.appbill.mode : util::realpath(ctx.contract_dir + "/bin/" + cfg.contract.appbill.mode)));
// Uncomment for docker-based execution.
// std::string volumearg;
// volumearg.append("type=bind,source=").append(ctx.state_dir).append(",target=/state");
// const char *dockerargs[] = {"/usr/bin/docker", "run", "--rm", "-i", "--mount", volumearg.data(), cfg.contract.bin_path.data()};
// cfg.contract.runtime_binexec_args.insert(cfg.contract.runtime_binexec_args.begin(), std::begin(dockerargs), std::end(dockerargs));
}
cfg.mesh.max_bytes_per_msg = mesh["max_bytes_per_msg"].as<uint64_t>();
cfg.mesh.max_bytes_per_min = mesh["max_bytes_per_min"].as<uint64_t>();
cfg.mesh.max_bad_msgs_per_min = mesh["max_bad_msgs_per_min"].as<uint64_t>();
cfg.mesh.max_bad_msgsigs_per_min = mesh["max_bad_msgsigs_per_min"].as<uint64_t>();
cfg.mesh.max_dup_msgs_per_min = mesh["max_dup_msgs_per_min"].as<uint64_t>();
cfg.mesh.idle_timeout = mesh["idle_timeout"].as<uint16_t>();
cfg.mesh.peer_discovery.interval = mesh["peer_discovery"]["interval"].as<uint16_t>();
cfg.mesh.peer_discovery.enabled = mesh["peer_discovery"]["enabled"].as<bool>();
const jsoncons::json &user = d["user"];
cfg.user.port = user["port"].as<uint16_t>();
cfg.user.max_connections = user["max_connections"].as<unsigned int>();
cfg.user.max_bytes_per_msg = user["max_bytes_per_msg"].as<uint64_t>();
cfg.user.max_bytes_per_min = user["max_bytes_per_min"].as<uint64_t>();
cfg.user.max_bad_msgs_per_min = user["max_bad_msgs_per_min"].as<uint64_t>();
cfg.user.idle_timeout = user["idle_timeout"].as<uint16_t>();
// mesh
{
const jsoncons::json &mesh = d["mesh"];
cfg.mesh.port = mesh["port"].as<uint16_t>();
// Storing peers in unordered map keyed by the concatenated address:port and also saving address and port
// seperately to retrieve easily when handling peer connections.
std::vector<std::string> splitted_peers;
cfg.mesh.known_peers.clear();
for (auto &v : mesh["known_peers"].array_range())
{
const char *ipport_concat = v.as<const char *>();
// Split the address:port text into two
util::split_string(splitted_peers, ipport_concat, ":");
const jsoncons::json &log = d["log"];
cfg.log.loglevel = log["loglevel"].as<std::string>();
cfg.log.loglevel_type = get_loglevel_type(cfg.log.loglevel);
cfg.log.loggers.clear();
for (auto &v : log["loggers"].array_range())
cfg.log.loggers.emplace(v.as<std::string>());
// Push the peer address and the port to peers set
if (splitted_peers.size() != 2)
{
std::cerr << "Invalid peer: " << ipport_concat << "\n";
return -1;
}
peer_properties peer;
peer.ip_port.host_address = splitted_peers.front();
peer.ip_port.port = std::stoi(splitted_peers.back());
cfg.mesh.known_peers.push_back(peer);
splitted_peers.clear();
}
cfg.mesh.msg_forwarding = mesh["msg_forwarding"].as<bool>();
cfg.mesh.max_connections = mesh["max_connections"].as<uint16_t>();
cfg.mesh.max_known_connections = mesh["max_known_connections"].as<uint16_t>();
// If max_connections is greater than max_known_connections then show error and stop execution.
if (cfg.mesh.max_known_connections > cfg.mesh.max_connections)
{
std::cerr << "Invalid configuration values: mesh max_known_connections count should not exceed mesh max_connections." << '\n';
return -1;
}
cfg.mesh.max_bytes_per_msg = mesh["max_bytes_per_msg"].as<uint64_t>();
cfg.mesh.max_bytes_per_min = mesh["max_bytes_per_min"].as<uint64_t>();
cfg.mesh.max_bad_msgs_per_min = mesh["max_bad_msgs_per_min"].as<uint64_t>();
cfg.mesh.max_bad_msgsigs_per_min = mesh["max_bad_msgsigs_per_min"].as<uint64_t>();
cfg.mesh.max_dup_msgs_per_min = mesh["max_dup_msgs_per_min"].as<uint64_t>();
cfg.mesh.idle_timeout = mesh["idle_timeout"].as<uint16_t>();
cfg.mesh.peer_discovery.interval = mesh["peer_discovery"]["interval"].as<uint16_t>();
cfg.mesh.peer_discovery.enabled = mesh["peer_discovery"]["enabled"].as<bool>();
}
// user
{
const jsoncons::json &user = d["user"];
cfg.user.port = user["port"].as<uint16_t>();
cfg.user.max_connections = user["max_connections"].as<unsigned int>();
cfg.user.max_bytes_per_msg = user["max_bytes_per_msg"].as<uint64_t>();
cfg.user.max_bytes_per_min = user["max_bytes_per_min"].as<uint64_t>();
cfg.user.max_bad_msgs_per_min = user["max_bad_msgs_per_min"].as<uint64_t>();
cfg.user.idle_timeout = user["idle_timeout"].as<uint16_t>();
}
// log
{
const jsoncons::json &log = d["log"];
cfg.log.loglevel = log["loglevel"].as<std::string>();
cfg.log.loglevel_type = get_loglevel_type(cfg.log.loglevel);
cfg.log.loggers.clear();
for (auto &v : log["loggers"].array_range())
cfg.log.loggers.emplace(v.as<std::string>());
}
return 0;
}
@@ -377,7 +417,7 @@ namespace conf
// Node configs.
jsoncons::ojson node_config;
node_config.insert_or_assign("public_key", cfg.node.pub_key_hex);
node_config.insert_or_assign("public_key", cfg.node.public_key_hex);
node_config.insert_or_assign("private_key", cfg.node.private_key_hex);
node_config.insert_or_assign("role", cfg.node.role == ROLE::OBSERVER ? ROLE_OBSERVER : ROLE_VALIDATOR);
// node_config.insert_or_assign("full_history", cfg.node.full_history);
@@ -390,13 +430,7 @@ namespace conf
jsoncons::ojson unl(jsoncons::json_array_arg);
for (const auto &nodepk : cfg.contract.unl)
{
std::string hex_pubkey;
util::bin2hex(
hex_pubkey,
reinterpret_cast<const unsigned char *>(nodepk.data()),
nodepk.length());
unl.push_back(hex_pubkey);
unl.push_back(util::to_hex(nodepk));
}
contract.insert_or_assign("unl", unl);
contract.insert_or_assign("bin_path", cfg.contract.bin_path);
@@ -481,73 +515,6 @@ namespace conf
return 0;
}
int populate_runtime_config(contract_config &parsed_cfg)
{
cfg = parsed_cfg;
startup_mode = cfg.node.role;
// Convert the hex keys to binary.
cfg.node.public_key.resize(crypto::PFXD_PUBKEY_BYTES);
if (util::hex2bin(
reinterpret_cast<unsigned char *>(cfg.node.public_key.data()),
cfg.node.public_key.length(),
cfg.node.pub_key_hex) != 0)
{
std::cerr << "Error decoding hex public key.\n";
return -1;
}
cfg.node.private_key.resize(crypto::PFXD_SECKEY_BYTES);
if (util::hex2bin(
reinterpret_cast<unsigned char *>(cfg.node.private_key.data()),
cfg.node.private_key.length(),
cfg.node.private_key_hex) != 0)
{
std::cerr << "Error decoding hex private key.\n";
return -1;
}
// Populate runtime contract execution args.
if (!cfg.contract.bin_args.empty())
util::split_string(cfg.contract.runtime_binexec_args, cfg.contract.bin_args, " ");
cfg.contract.runtime_binexec_args.insert(cfg.contract.runtime_binexec_args.begin(), (cfg.contract.bin_path[0] == '/' ? cfg.contract.bin_path : util::realpath(ctx.contract_dir + "/bin/" + cfg.contract.bin_path)));
// Populate runtime app bill args.
if (!cfg.contract.appbill.bin_args.empty())
util::split_string(cfg.contract.appbill.runtime_args, cfg.contract.appbill.bin_args, " ");
cfg.contract.appbill.runtime_args.insert(cfg.contract.appbill.runtime_args.begin(), (cfg.contract.appbill.mode[0] == '/' ? cfg.contract.appbill.mode : util::realpath(ctx.contract_dir + "/bin/" + cfg.contract.appbill.mode)));
// Uncomment for docker-based execution.
// std::string volumearg;
// volumearg.append("type=bind,source=").append(ctx.state_dir).append(",target=/state");
// const char *dockerargs[] = {"/usr/bin/docker", "run", "--rm", "-i", "--mount", volumearg.data(), cfg.contract.bin_path.data()};
// cfg.contract.runtime_binexec_args.insert(cfg.contract.runtime_binexec_args.begin(), std::begin(dockerargs), std::end(dockerargs));
return 0;
}
/**
* Decode current binary keys in 'cfg' and populate the it with hex keys.
*
* @return Always returns 0.
*/
int binpair_to_hex(contract_config &cfg)
{
util::bin2hex(
cfg.node.pub_key_hex,
reinterpret_cast<const unsigned char *>(cfg.node.public_key.data()),
cfg.node.public_key.length());
util::bin2hex(
cfg.node.private_key_hex,
reinterpret_cast<const unsigned char *>(cfg.node.private_key.data()),
cfg.node.private_key.length());
return 0;
}
/**
* Validates the 'cfg' struct for invalid values.
*
@@ -557,7 +524,7 @@ namespace conf
{
// Check for non-empty signing keys.
// We also check for key pair validity as well in the below code.
if (cfg.node.pub_key_hex.empty() || cfg.node.private_key_hex.empty())
if (cfg.node.public_key_hex.empty() || cfg.node.private_key_hex.empty())
{
std::cerr << "Signing keys missing. Run with 'rekey' to generate new keys.\n";
return -1;
@@ -602,8 +569,8 @@ namespace conf
//Sign and verify a sample message to ensure we have a matching signing key pair.
const std::string msg = "hotpocket";
const std::string sighex = crypto::sign_hex(msg, cfg.node.private_key_hex);
if (crypto::verify_hex(msg, sighex, cfg.node.pub_key_hex) != 0)
const std::string sig = crypto::sign(msg, cfg.node.private_key);
if (crypto::verify(msg, sig, cfg.node.public_key) != 0)
{
std::cerr << "Invalid signing keys. Run with 'rekey' to generate new keys.\n";
return -1;

View File

@@ -67,7 +67,7 @@ namespace conf
ROLE role = ROLE::OBSERVER; // Configured startup role of the contract (Observer/validator).
bool is_unl = false; // Indicate whether we are a unl node or not.
std::string pub_key_hex; // Contract hex public key
std::string public_key_hex; // Contract hex public key
std::string private_key_hex; // Contract hex private key
bool full_history = false; // Whether full history mode is on/off.
};
@@ -185,14 +185,10 @@ namespace conf
int write_config(const contract_config &cfg);
int populate_runtime_config(contract_config &parsed_cfg);
int validate_config(const contract_config &cfg);
int validate_contract_dir_paths();
int binpair_to_hex(contract_config &cfg);
void change_role(const ROLE role);
LOG_SEVERITY get_loglevel_type(std::string_view severity);

View File

@@ -273,7 +273,7 @@ namespace consensus
<< " ts:" << std::to_string(cp.time)
<< " lcl:" << cp.lcl.substr(0, 15)
<< " state:" << cp.state
<< " [from:" << ((cp.pubkey == conf::cfg.node.public_key) ? "self" : util::get_hex(cp.pubkey, 1, 5)) << "]"
<< " [from:" << ((cp.pubkey == conf::cfg.node.public_key) ? "self" : util::to_hex(cp.pubkey).substr(2, 10)) << "]"
<< "(" << std::to_string(cp.recv_timestamp > cp.sent_timestamp ? cp.recv_timestamp - cp.sent_timestamp : 0) << "ms)";
if (keep_candidate)

View File

@@ -28,10 +28,10 @@ namespace crypto
// Generate key pair using libsodium default algorithm.
// Currently using ed25519. So append prefix byte to represent that.
pubkey.resize(PFXD_PUBKEY_BYTES);
pubkey.resize(crypto_sign_ed25519_PUBLICKEYBYTES + 1);
pubkey[0] = KEYPFX_ed25519;
seckey.resize(PFXD_SECKEY_BYTES);
seckey.resize(crypto_sign_ed25519_SECRETKEYBYTES + 1);
seckey[0] = KEYPFX_ed25519;
crypto_sign_ed25519_keypair(
@@ -62,33 +62,6 @@ namespace crypto
return sig;
}
/**
* Returns the hex signature string for a message.
*
* @param msg Message bytes to sign.
* @param private_key_hex hex private key string.
* @return hex signature string.
*/
std::string sign_hex(std::string_view msg, std::string_view private_key_hex)
{
//Decode hex string and generate the signature using libsodium.
unsigned char private_key[PFXD_SECKEY_BYTES];
util::hex2bin(private_key, PFXD_SECKEY_BYTES, private_key_hex);
unsigned char sig[crypto_sign_ed25519_BYTES];
crypto_sign_ed25519_detached(
sig,
NULL,
reinterpret_cast<const unsigned char *>(msg.data()),
msg.length(),
private_key + 1); // +1 to skip prefix byte.
std::string sighex;
util::bin2hex(sighex, sig, crypto_sign_ed25519_BYTES);
return sighex;
}
/**
* Verifies the given signature bytes for the message.
*
@@ -106,31 +79,6 @@ namespace crypto
reinterpret_cast<const unsigned char *>(pubkey.data() + 1)); // +1 to skip prefix byte.
}
/**
* Verifies the given hex signature for the message.
*
* @param msg hex message string.
* @param sighex hex signature string.
* @param pubkeyhex hex public key.
* @return 0 for successful verification. -1 for failure.
*/
int verify_hex(std::string_view msg, std::string_view sighex, std::string_view pubkeyhex)
{
//Decode hex string and verify the signature using libsodium.
unsigned char decoded_pubkey[PFXD_PUBKEY_BYTES];
util::hex2bin(decoded_pubkey, PFXD_PUBKEY_BYTES, pubkeyhex);
unsigned char decoded_sig[crypto_sign_ed25519_BYTES];
util::hex2bin(decoded_sig, crypto_sign_ed25519_BYTES, sighex);
return crypto_sign_ed25519_verify_detached(
decoded_sig,
reinterpret_cast<const unsigned char *>(msg.data()),
msg.length(),
decoded_pubkey + 1); // +1 to skip prefix byte.
}
/**
* Generate random bytes of specified length.
*/
@@ -237,12 +185,7 @@ namespace crypto
uuid[6] = (uuid[8] & 0x0F) | 0x40;
uuid[8] = (uuid[8] & 0xBF) | 0x80;
std::string hex;
util::bin2hex(
hex,
reinterpret_cast<const unsigned char *>(rand_bytes.data()),
rand_bytes.length());
const std::string hex = util::to_hex(rand_bytes);
return hex.substr(0, 8) + "-" + hex.substr(8, 4) + "-" + hex.substr(12, 4) + "-" + hex.substr(16, 4) + "-" + hex.substr(20);
}

View File

@@ -12,10 +12,6 @@ namespace crypto
// Prefix byte to append to ed25519 keys.
static unsigned char KEYPFX_ed25519 = 0xED;
// Prefixed public key bytes.
static size_t PFXD_PUBKEY_BYTES = crypto_sign_ed25519_PUBLICKEYBYTES + 1;
// Prefixed private key bytes.
static size_t PFXD_SECKEY_BYTES = crypto_sign_ed25519_SECRETKEYBYTES + 1;
int init();
@@ -23,12 +19,8 @@ namespace crypto
std::string sign(std::string_view msg, std::string_view seckey);
std::string sign_hex(std::string_view msg, std::string_view private_key_hex);
int verify(std::string_view msg, std::string_view sig, std::string_view pubkey);
int verify_hex(std::string_view msg, std::string_view sighex, std::string_view pubkeyhex);
void random_bytes(std::string &result, const size_t len);
std::string get_hash(std::string_view data);

View File

@@ -359,10 +359,7 @@ namespace ledger
const std::string lcl_hash = crypto::get_hash(ledger_str_buf);
// Get hex from binary hash.
std::string lcl_hash_hex;
util::bin2hex(lcl_hash_hex,
reinterpret_cast<const unsigned char *>(lcl_hash.data()),
lcl_hash.size());
const std::string lcl_hash_hex = util::to_hex(lcl_hash);
// Acquire lock so history request serving does not access the ledger while consensus is updating the ledger.
std::scoped_lock<std::mutex> ledger_lock(ctx.ledger_mutex);
@@ -829,10 +826,7 @@ namespace ledger
const std::string binary_block_hash = crypto::get_hash(block_buffer.data(), block_buffer.size());
// Get hex from binary hash.
std::string block_hash;
util::bin2hex(block_hash,
reinterpret_cast<const unsigned char *>(binary_block_hash.data()),
binary_block_hash.size());
const std::string block_hash = util::to_hex(binary_block_hash);
return block_hash == supplied_hash;
}

View File

@@ -197,7 +197,7 @@ int main(int argc, char **argv)
LOG_INFO << "Hot Pocket " << util::HP_VERSION;
LOG_INFO << "Role: " << (conf::cfg.node.role == conf::ROLE::OBSERVER ? "Observer" : "Validator");
LOG_INFO << "Public key: " << conf::cfg.node.pub_key_hex;
LOG_INFO << "Public key: " << conf::cfg.node.public_key_hex;
LOG_INFO << "Contract: " << conf::cfg.contract.id << " (" << conf::cfg.contract.version << ")";
if (ledger::init() == -1 ||

View File

@@ -78,18 +78,11 @@ namespace msg::controlmsg::json
if (!d.contains(field_name) || !d[field_name].is_array())
return;
for (const auto &v : d[field_name].array_range())
for (const auto &pkhex : d[field_name].array_range())
{
std::string_view hex_pubkey = v.as<std::string_view>();
std::string bin_pubkey;
bin_pubkey.resize(crypto::PFXD_PUBKEY_BYTES);
if (util::hex2bin(
reinterpret_cast<unsigned char *>(bin_pubkey.data()),
bin_pubkey.length(),
hex_pubkey) != -1)
{
const std::string bin_pubkey = util::to_bin(pkhex.as<std::string_view>());
if (!bin_pubkey.empty())
vec.emplace(bin_pubkey);
}
}
}

View File

@@ -43,9 +43,7 @@ namespace msg::usrmsg::json
{
std::string challenge_bytes;
crypto::random_bytes(challenge_bytes, msg::usrmsg::CHALLENGE_LEN);
util::bin2hex(challenge,
reinterpret_cast<const unsigned char *>(challenge_bytes.data()),
msg::usrmsg::CHALLENGE_LEN);
challenge = util::to_hex(challenge_bytes);
// Construct the challenge msg json.
// We do not use jsoncons library here in favour of performance because this is a simple json message.
@@ -94,7 +92,7 @@ namespace msg::usrmsg::json
{
// Generate signature of challenge + contract id + contract version.
const std::string content = original_challenge + conf::cfg.contract.id + conf::cfg.contract.version;
const std::string sig_hex = crypto::sign_hex(content, conf::cfg.node.private_key_hex);
const std::string sig_hex = util::to_hex(crypto::sign(content, conf::cfg.node.private_key));
// Since we know the rough size of the challenge message we reserve adequate amount for the holder.
msg.reserve(1024);
@@ -109,7 +107,7 @@ namespace msg::usrmsg::json
msg += SEP_COMMA;
msg += msg::usrmsg::FLD_PUBKEY;
msg += SEP_COLON;
msg += conf::cfg.node.pub_key_hex;
msg += conf::cfg.node.public_key_hex;
msg += SEP_COMMA;
msg += msg::usrmsg::FLD_UNL;
msg += "\":[";
@@ -169,9 +167,6 @@ namespace msg::usrmsg::json
*/
void create_contract_input_status(std::vector<uint8_t> &msg, std::string_view status, std::string_view reason, std::string_view input_sig)
{
std::string sighex;
util::bin2hex(sighex, reinterpret_cast<const unsigned char *>(input_sig.data()), input_sig.length());
msg.reserve(256);
msg += "{\"";
msg += msg::usrmsg::FLD_TYPE;
@@ -188,7 +183,7 @@ namespace msg::usrmsg::json
msg += SEP_COMMA;
msg += msg::usrmsg::FLD_INPUT_SIG;
msg += SEP_COLON;
msg += sighex;
msg += util::to_hex(input_sig);
msg += "\"}";
}
@@ -404,20 +399,12 @@ namespace msg::usrmsg::json
// Verify the challenge signature. We do this last due to signature verification cost.
std::string_view pubkey_hex = d[msg::usrmsg::FLD_PUBKEY].as<std::string_view>();
std::string pubkey_bytes;
pubkey_bytes.resize(crypto::PFXD_PUBKEY_BYTES);
util::hex2bin(reinterpret_cast<unsigned char *>(pubkey_bytes.data()),
pubkey_bytes.size(),
pubkey_hex);
const std::string pubkey_bytes = util::to_bin(pubkey_hex);
std::string_view sig_hex = d[msg::usrmsg::FLD_SIG].as<std::string_view>();
std::string sig_bytes;
sig_bytes.resize(sig_hex.size() / 2);
util::hex2bin(reinterpret_cast<unsigned char *>(sig_bytes.data()),
sig_bytes.size(),
sig_hex);
const std::string sig_bytes = util::to_bin(sig_hex);
if (crypto::verify(original_challenge, sig_bytes, pubkey_bytes) != 0)
if (pubkey_bytes.empty() || sig_bytes.empty() || crypto::verify(original_challenge, sig_bytes, pubkey_bytes) != 0)
{
LOG_DEBUG << "User challenge response signature verification failed.";
return -1;
@@ -537,9 +524,7 @@ namespace msg::usrmsg::json
// Extract the hex signature and convert to binary.
const std::string_view sig_hex = d[msg::usrmsg::FLD_SIG].as<std::string_view>();
extracted_sig.resize(crypto_sign_ed25519_BYTES);
util::hex2bin(reinterpret_cast<unsigned char *>(extracted_sig.data()), extracted_sig.length(), sig_hex);
extracted_sig = util::to_bin(sig_hex);
return 0;
}

View File

@@ -74,8 +74,7 @@ namespace p2p
}
// Converting the binary pub key into hexadecimal string.
std::string pubkeyhex;
util::bin2hex(pubkeyhex, reinterpret_cast<const unsigned char *>(challenge_resp.pubkey.data()), challenge_resp.pubkey.length());
std::string pubkeyhex = util::to_hex(challenge_resp.pubkey);
const int res = challenge_resp.pubkey.compare(conf::cfg.node.public_key);

View File

@@ -258,7 +258,7 @@ namespace sc
std::ostringstream os;
os << "{\"version\":\"" << util::HP_VERSION
<< "\",\"pubkey\":\"" << conf::cfg.node.pub_key_hex
<< "\",\"pubkey\":\"" << conf::cfg.node.public_key_hex
<< "\",\"ts\":" << ctx.args.time
<< ",\"readonly\":" << (ctx.args.readonly ? "true" : "false");
@@ -437,11 +437,7 @@ namespace sc
{
if (npl_msg.lcl == ctx.args.lcl)
{
std::string pubkeyhex;
util::bin2hex(
pubkeyhex,
reinterpret_cast<const unsigned char *>(npl_msg.pubkey.data()),
npl_msg.pubkey.length());
const std::string pubkeyhex = util::to_hex(npl_msg.pubkey);
// Writing the public key to the contract's fd (Skip first byte for key type prefix).
if (write(writefd, pubkeyhex.data(), pubkeyhex.size()) == -1)
@@ -541,16 +537,10 @@ namespace sc
// Get the hex pubkey.
const std::string &pubkey = itr->first; // Pubkey in binary format.
std::string pubkeyhex;
util::bin2hex(
pubkeyhex,
reinterpret_cast<const unsigned char *>(pubkey.data()) + 1, // Skip key type prefix.
pubkey.length() - 1);
const std::vector<util::buffer_view> &user_inputs = user_bufmap.find(pubkey)->second.inputs;
// Write hex pubkey as key and output fd as first element of array.
os << "\"" << pubkeyhex << "\":["
os << "\"" << util::to_hex(pubkey) << "\":["
<< itr->second.scfd;
// Write input offsets into the same array.

View File

@@ -101,13 +101,7 @@ namespace state_serve
}
// Session id is in binary format. Converting to hex before printing.
std::string session_id_hex;
util::bin2hex(
session_id_hex,
reinterpret_cast<const unsigned char *>(session_id.data()),
session_id.length());
LOG_DEBUG << "Serving state request from [" << session_id_hex.substr(2, 10) << "]";
LOG_DEBUG << "Serving state request from [" << util::to_hex(session_id).substr(2, 10) << "]";
const msg::fbuf::p2pmsg::Content *content = msg::fbuf::p2pmsg::GetContent(request.data());

View File

@@ -163,13 +163,7 @@ namespace unl
os << ","; // Trailing comma separator for previous element.
// Convert binary pubkey into hex.
std::string pubkeyhex;
util::bin2hex(
pubkeyhex,
reinterpret_cast<const unsigned char *>(pk->data()),
pk->length());
os << "\"" << pubkeyhex << "\"";
os << "\"" << util::to_hex(*pk) << "\"";
}
os << "]";
json_list = os.str();
@@ -208,7 +202,7 @@ namespace unl
sync_ctx.target_unl = target_unl_hash;
sync_ctx.target_requested_on = 0;
sync_ctx.request_submissions = 0;
LOG_INFO << "unl sync: Syncing for target:" << hash_bin2hex(sync_ctx.target_unl).substr(0, 10) << " (current:" << hash_bin2hex(get_hash()).substr(0, 10) << ")";
LOG_INFO << "unl sync: Syncing for target:" << util::to_hex(sync_ctx.target_unl).substr(0, 10) << " (current:" << util::to_hex(get_hash()).substr(0, 10) << ")";
}
}
@@ -233,7 +227,7 @@ namespace unl
std::string target_pubkey;
p2p::send_message_to_random_peer(fbuf, target_pubkey);
LOG_DEBUG << "UNL list requested from [" << target_pubkey.substr(0, 10) << "]. Required unl hash:" << hash_bin2hex(sync_ctx.target_unl).substr(0, 10);
LOG_DEBUG << "UNL list requested from [" << target_pubkey.substr(0, 10) << "]. Required unl hash:" << util::to_hex(sync_ctx.target_unl).substr(0, 10);
sync_ctx.target_requested_on = time_now;
sync_ctx.request_submissions++;
}
@@ -278,16 +272,6 @@ namespace unl
LOG_INFO << "unl sync: Worker stopped.";
}
std::string hash_bin2hex(std::string_view hash)
{
// Get hex from binary hash.
std::string unl_hash_hex;
util::bin2hex(unl_hash_hex,
reinterpret_cast<const unsigned char *>(hash.data()),
hash.size());
return unl_hash_hex;
}
/**
* Process any unl sync requests received.
* @return Returns 0 if no requests were processed and returns 1 if atleast one request is served.
@@ -355,7 +339,7 @@ namespace unl
{
if (unl.requester_unl == sync_ctx.target_unl && verify_and_replace(unl.unl_list) != -1)
{
LOG_INFO << "unl sync: Sync complete. New unl:" << hash_bin2hex(sync_ctx.target_unl).substr(0, 10);
LOG_INFO << "unl sync: Sync complete. New unl:" << util::to_hex(sync_ctx.target_unl).substr(0, 10);
sync_ctx.clear_target();
}
}

View File

@@ -52,7 +52,6 @@ namespace unl
void set_sync_target(std::string_view target_unl_hash);
void send_unl_sync_request();
void unl_syncer_loop();
std::string hash_bin2hex(std::string_view hash);
int verify_and_replace(const std::set<std::string> &new_list);
int check_unl_sync_requests();
int check_unl_sync_responses();

View File

@@ -238,14 +238,8 @@ namespace usr
return -1;
}
// Decode hex pubkey and get binary pubkey. We are only going to keep
// the binary pubkey due to reduced memory footprint.
std::string pubkey;
pubkey.resize(pubkey_hex.length() / 2);
util::hex2bin(
reinterpret_cast<unsigned char *>(pubkey.data()),
pubkey.length(),
pubkey_hex);
// Decode hex pubkey and get binary pubkey.
const std::string pubkey = util::to_bin(pubkey_hex);
// Acquire user list lock.
std::scoped_lock<std::mutex> lock(ctx.users_mutex);
@@ -371,8 +365,7 @@ namespace usr
char option[] = "--check";
execv_args[len - 4] = option;
// add the hex encoded public key as the last parameter
std::string hexpubkey;
util::bin2hex(hexpubkey, reinterpret_cast<const unsigned char *>(pubkey.data()), pubkey.size());
std::string hexpubkey = util::to_hex(pubkey);
std::string inputsize = std::to_string(input_len);
execv_args[len - 3] = hexpubkey.data();
execv_args[len - 2] = inputsize.data();

View File

@@ -19,58 +19,22 @@ namespace util
return encoded_string;
}
/**
* Encodes provided bytes to hex string.
*
* @param encoded_string String reference to assign the hex encoded output.
* @param bin Bytes to encode.
* @param bin_len Bytes length.
* @return Always returns 0.
*/
int bin2hex(std::string &encoded_string, const unsigned char *bin, const size_t bin_len)
const std::string to_bin(const std::string_view hex)
{
// Allocate the target string.
encoded_string.resize(bin_len * 2);
std::string bin;
bin.resize(hex.size() / 2);
// Get encoded string.
sodium_bin2hex(
encoded_string.data(),
encoded_string.length() + 1, // + 1 because sodium writes ending '\0' character as well.
bin,
bin_len);
return 0;
}
/**
* Decodes provided hex string into bytes.
*
* @param decodedbuf Buffer to assign decoded bytes.
* @param decodedbuf_len Decoded buffer size.
* @param hex_str hex string to decode.
*/
int hex2bin(unsigned char *decodedbuf, const size_t decodedbuf_len, std::string_view hex_str)
{
const char *hex_end;
size_t bin_len;
if (sodium_hex2bin(
decodedbuf, decodedbuf_len,
hex_str.data(),
hex_str.length(),
reinterpret_cast<unsigned char *>(bin.data()), bin.size(),
hex.data(), hex.size(),
"", &bin_len, &hex_end))
{
return -1;
return ""; // Empty indicates error.
}
return 0;
}
std::string get_hex(std::string_view bin, const off_t skip, const size_t take)
{
std::string hex;
const size_t len = (take ? take : (bin.size() - skip));
bin2hex(hex, reinterpret_cast<unsigned char *>(const_cast<char *>(bin.data() + skip)), len);
return hex;
return bin;
}
/**
@@ -128,7 +92,7 @@ namespace util
}
// Provide a safe std::string overload for realpath
std::string realpath(const std::string &path)
const std::string realpath(const std::string &path)
{
std::array<char, PATH_MAX> buffer;
::realpath(path.c_str(), buffer.data());

View File

@@ -40,11 +40,7 @@ namespace util
const std::string to_hex(const std::string_view bin);
int bin2hex(std::string &encoded_string, const unsigned char *bin, const size_t bin_len);
int hex2bin(unsigned char *decoded, const size_t decoded_len, std::string_view hex_str);
std::string get_hex(std::string_view bin, const off_t skip = 0, const size_t take = 0);
const std::string to_bin(const std::string_view hex);
uint64_t get_epoch_milliseconds();
@@ -52,7 +48,7 @@ namespace util
int version_compare(const std::string &x, const std::string &y);
std::string realpath(const std::string &path);
const std::string realpath(const std::string &path);
void mask_signal();