diff --git a/src/conf.cpp b/src/conf.cpp index 7441f8cd..3aa2c859 100644 --- a/src/conf.cpp +++ b/src/conf.cpp @@ -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(); - cfg.node.private_key_hex = node["private_key"].as(); - 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(); + cfg.node.private_key_hex = node["private_key"].as(); - const jsoncons::json &contract = d["contract"]; - cfg.contract.id = contract["id"].as(); - cfg.contract.version = contract["version"].as(); - 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(bin_pubkey.data()), - bin_pubkey.length(), - nodepk.as()) != 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(); - cfg.contract.bin_args = contract["bin_args"].as(); - cfg.contract.roundtime = contract["roundtime"].as(); - 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(); - cfg.contract.appbill.bin_args = contract["appbill"]["bin_args"].as(); - - const jsoncons::json &mesh = d["mesh"]; - cfg.mesh.port = mesh["port"].as(); - // 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 splitted_peers; - cfg.mesh.known_peers.clear(); - for (auto &v : mesh["known_peers"].array_range()) - { - const char *ipport_concat = v.as(); - // 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(); - cfg.mesh.max_connections = mesh["max_connections"].as(); - cfg.mesh.max_known_connections = mesh["max_known_connections"].as(); - // 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(); + cfg.contract.version = contract["version"].as(); + 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()); + 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(); + cfg.contract.bin_args = contract["bin_args"].as(); + cfg.contract.roundtime = contract["roundtime"].as(); + + 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(); + cfg.contract.appbill.bin_args = contract["appbill"]["bin_args"].as(); + + // 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(); - cfg.mesh.max_bytes_per_min = mesh["max_bytes_per_min"].as(); - cfg.mesh.max_bad_msgs_per_min = mesh["max_bad_msgs_per_min"].as(); - cfg.mesh.max_bad_msgsigs_per_min = mesh["max_bad_msgsigs_per_min"].as(); - cfg.mesh.max_dup_msgs_per_min = mesh["max_dup_msgs_per_min"].as(); - cfg.mesh.idle_timeout = mesh["idle_timeout"].as(); - cfg.mesh.peer_discovery.interval = mesh["peer_discovery"]["interval"].as(); - cfg.mesh.peer_discovery.enabled = mesh["peer_discovery"]["enabled"].as(); - - const jsoncons::json &user = d["user"]; - cfg.user.port = user["port"].as(); - cfg.user.max_connections = user["max_connections"].as(); - cfg.user.max_bytes_per_msg = user["max_bytes_per_msg"].as(); - cfg.user.max_bytes_per_min = user["max_bytes_per_min"].as(); - cfg.user.max_bad_msgs_per_min = user["max_bad_msgs_per_min"].as(); - cfg.user.idle_timeout = user["idle_timeout"].as(); + // mesh + { + const jsoncons::json &mesh = d["mesh"]; + cfg.mesh.port = mesh["port"].as(); + // 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 splitted_peers; + cfg.mesh.known_peers.clear(); + for (auto &v : mesh["known_peers"].array_range()) + { + const char *ipport_concat = v.as(); + // 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(); - 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()); + // 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(); + cfg.mesh.max_connections = mesh["max_connections"].as(); + cfg.mesh.max_known_connections = mesh["max_known_connections"].as(); + // 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(); + cfg.mesh.max_bytes_per_min = mesh["max_bytes_per_min"].as(); + cfg.mesh.max_bad_msgs_per_min = mesh["max_bad_msgs_per_min"].as(); + cfg.mesh.max_bad_msgsigs_per_min = mesh["max_bad_msgsigs_per_min"].as(); + cfg.mesh.max_dup_msgs_per_min = mesh["max_dup_msgs_per_min"].as(); + cfg.mesh.idle_timeout = mesh["idle_timeout"].as(); + cfg.mesh.peer_discovery.interval = mesh["peer_discovery"]["interval"].as(); + cfg.mesh.peer_discovery.enabled = mesh["peer_discovery"]["enabled"].as(); + } + + // user + { + const jsoncons::json &user = d["user"]; + cfg.user.port = user["port"].as(); + cfg.user.max_connections = user["max_connections"].as(); + cfg.user.max_bytes_per_msg = user["max_bytes_per_msg"].as(); + cfg.user.max_bytes_per_min = user["max_bytes_per_min"].as(); + cfg.user.max_bad_msgs_per_min = user["max_bad_msgs_per_min"].as(); + cfg.user.idle_timeout = user["idle_timeout"].as(); + } + + // log + { + const jsoncons::json &log = d["log"]; + cfg.log.loglevel = log["loglevel"].as(); + 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()); + } 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(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(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(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(cfg.node.public_key.data()), - cfg.node.public_key.length()); - - util::bin2hex( - cfg.node.private_key_hex, - reinterpret_cast(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; diff --git a/src/conf.hpp b/src/conf.hpp index 46b005c5..4376f81f 100644 --- a/src/conf.hpp +++ b/src/conf.hpp @@ -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); diff --git a/src/consensus.cpp b/src/consensus.cpp index cef563a5..a9a2a4a6 100644 --- a/src/consensus.cpp +++ b/src/consensus.cpp @@ -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) diff --git a/src/crypto.cpp b/src/crypto.cpp index 00e30d7a..88d1bbfc 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -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(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(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(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(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); } diff --git a/src/crypto.hpp b/src/crypto.hpp index 2bc3d6d8..d3276a77 100644 --- a/src/crypto.hpp +++ b/src/crypto.hpp @@ -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); diff --git a/src/ledger.cpp b/src/ledger.cpp index a5d62f6a..4a21a5c2 100644 --- a/src/ledger.cpp +++ b/src/ledger.cpp @@ -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(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 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(binary_block_hash.data()), - binary_block_hash.size()); + const std::string block_hash = util::to_hex(binary_block_hash); return block_hash == supplied_hash; } diff --git a/src/main.cpp b/src/main.cpp index 04413629..d48bc0e3 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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 || diff --git a/src/msg/json/controlmsg_json.cpp b/src/msg/json/controlmsg_json.cpp index 1ae20c2a..d3ae835e 100644 --- a/src/msg/json/controlmsg_json.cpp +++ b/src/msg/json/controlmsg_json.cpp @@ -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 bin_pubkey; - bin_pubkey.resize(crypto::PFXD_PUBKEY_BYTES); - if (util::hex2bin( - reinterpret_cast(bin_pubkey.data()), - bin_pubkey.length(), - hex_pubkey) != -1) - { + const std::string bin_pubkey = util::to_bin(pkhex.as()); + if (!bin_pubkey.empty()) vec.emplace(bin_pubkey); - } } } diff --git a/src/msg/json/usrmsg_json.cpp b/src/msg/json/usrmsg_json.cpp index 504606d1..e2b364ee 100644 --- a/src/msg/json/usrmsg_json.cpp +++ b/src/msg/json/usrmsg_json.cpp @@ -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(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 &msg, std::string_view status, std::string_view reason, std::string_view input_sig) { - std::string sighex; - util::bin2hex(sighex, reinterpret_cast(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 pubkey_bytes; - pubkey_bytes.resize(crypto::PFXD_PUBKEY_BYTES); - util::hex2bin(reinterpret_cast(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 sig_bytes; - sig_bytes.resize(sig_hex.size() / 2); - util::hex2bin(reinterpret_cast(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(); - extracted_sig.resize(crypto_sign_ed25519_BYTES); - util::hex2bin(reinterpret_cast(extracted_sig.data()), extracted_sig.length(), sig_hex); - + extracted_sig = util::to_bin(sig_hex); return 0; } diff --git a/src/p2p/p2p.cpp b/src/p2p/p2p.cpp index 2fc6851a..32b774ff 100644 --- a/src/p2p/p2p.cpp +++ b/src/p2p/p2p.cpp @@ -74,8 +74,7 @@ namespace p2p } // Converting the binary pub key into hexadecimal string. - std::string pubkeyhex; - util::bin2hex(pubkeyhex, reinterpret_cast(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); diff --git a/src/sc.cpp b/src/sc.cpp index 26844d48..9562a654 100644 --- a/src/sc.cpp +++ b/src/sc.cpp @@ -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(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(pubkey.data()) + 1, // Skip key type prefix. - pubkey.length() - 1); - const std::vector &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. diff --git a/src/state/state_serve.cpp b/src/state/state_serve.cpp index 40499b11..d702f683 100644 --- a/src/state/state_serve.cpp +++ b/src/state/state_serve.cpp @@ -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(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()); diff --git a/src/unl.cpp b/src/unl.cpp index 3c2940b6..0b2a1987 100644 --- a/src/unl.cpp +++ b/src/unl.cpp @@ -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(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(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(); } } diff --git a/src/unl.hpp b/src/unl.hpp index cb3f1d47..4e663185 100644 --- a/src/unl.hpp +++ b/src/unl.hpp @@ -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 &new_list); int check_unl_sync_requests(); int check_unl_sync_responses(); diff --git a/src/usr/usr.cpp b/src/usr/usr.cpp index a510d284..2f7719c7 100644 --- a/src/usr/usr.cpp +++ b/src/usr/usr.cpp @@ -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(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 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(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(); diff --git a/src/util/util.cpp b/src/util/util.cpp index 0e3b01f9..b557abea 100644 --- a/src/util/util.cpp +++ b/src/util/util.cpp @@ -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(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(const_cast(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 buffer; ::realpath(path.c_str(), buffer.data()); diff --git a/src/util/util.hpp b/src/util/util.hpp index 748cf42a..b6fbb7d2 100644 --- a/src/util/util.hpp +++ b/src/util/util.hpp @@ -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();