From c8df2e75ac1c7ae03a5e4c2cd3fcf5fc3ddd6508 Mon Sep 17 00:00:00 2001 From: Chalith Desaman Date: Mon, 28 Jun 2021 10:41:08 +0530 Subject: [PATCH] Added contract id to the instance create message (#19) --- examples/message-board/message-board.js | 16 +++++++++------- src/comm/comm_session.cpp | 2 +- src/crypto.cpp | 9 +++++++++ src/crypto.hpp | 2 ++ src/hp_manager.cpp | 19 ++++++++++++++----- src/hp_manager.hpp | 5 +++-- src/msg/json/msg_json.cpp | 15 +++++++++++++++ src/msg/msg_common.hpp | 2 ++ src/pchheader.hpp | 1 + 9 files changed, 56 insertions(+), 15 deletions(-) diff --git a/examples/message-board/message-board.js b/examples/message-board/message-board.js index 79cecb9..da0ef2c 100644 --- a/examples/message-board/message-board.js +++ b/examples/message-board/message-board.js @@ -46,10 +46,10 @@ const sendToAll = (msg) => { }); } -const askForContainerName = () => { +const askForInput = (label) => { return new Promise(resolve => { - rl.question('Container name? ', (containerName) => { - resolve(containerName); + rl.question(`${label}? `, (input) => { + resolve(input); }) }) } @@ -68,14 +68,16 @@ server.listen(8080, () => { else { switch (inp) { case 'create': + contractId = await askForInput('Contract ID'); sendToAll(JSON.stringify({ id: uuidv4(), type: 'create', - owner_pubkey: 'ed5cb83404120ac759609819591ef839b7d222c84f1f08b3012f490586159d2b50' + owner_pubkey: 'ed5cb83404120ac759609819591ef839b7d222c84f1f08b3012f490586159d2b50', + contract_id: contractId })); break; case 'destroy': - containerName = await askForContainerName(); + containerName = await askForInput('Container Name'); sendToAll(JSON.stringify({ id: uuidv4(), type: 'destroy', @@ -84,7 +86,7 @@ server.listen(8080, () => { })) break; case 'start': - containerName = await askForContainerName(); + containerName = await askForInput('Container Name'); sendToAll(JSON.stringify({ id: uuidv4(), type: 'start', @@ -93,7 +95,7 @@ server.listen(8080, () => { })) break; case 'stop': - containerName = await askForContainerName(); + containerName = await askForInput('Container Name'); sendToAll(JSON.stringify({ id: uuidv4(), type: 'stop', diff --git a/src/comm/comm_session.cpp b/src/comm/comm_session.cpp index f144f08..d7d352b 100644 --- a/src/comm/comm_session.cpp +++ b/src/comm/comm_session.cpp @@ -174,7 +174,7 @@ namespace comm return -1; id = msg.id; hp::instance_info info; - if (hp::create_new_instance(info, msg.pubkey) == -1) + if (hp::create_new_instance(info, msg.pubkey, msg.contract_id) == -1) return -1; std::string res; diff --git a/src/crypto.cpp b/src/crypto.cpp index f7af984..dbc10f6 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -60,4 +60,13 @@ namespace crypto 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); } + + const bool verify_uuid(const std::string &uuid) + { + if (uuid.empty() || uuid.length() != 36) + return false; + + const std::regex pattern("^[0-9A-Fa-f]{8}-[0-9A-Fa-f]{4}-4[0-9A-Fa-f]{3}-[89ABab][0-9A-Fa-f]{3}-[0-9A-Fa-f]{12}$"); + return std::regex_match(uuid, pattern); + } } \ No newline at end of file diff --git a/src/crypto.hpp b/src/crypto.hpp index e2749e5..8f34b4d 100644 --- a/src/crypto.hpp +++ b/src/crypto.hpp @@ -20,5 +20,7 @@ namespace crypto void generate_signing_keys(std::string &pubkey, std::string &seckey); const std::string generate_uuid(); + + const bool verify_uuid(const std::string &uuid); } #endif \ No newline at end of file diff --git a/src/hp_manager.cpp b/src/hp_manager.cpp index 35bb614..8005c55 100644 --- a/src/hp_manager.cpp +++ b/src/hp_manager.cpp @@ -131,12 +131,20 @@ namespace hp * Create a new instance of hotpocket. A new contract is created and then the docker images is run on that. * @param info Structure holding the generated instance info. * @param owner_pubkey Public key of the instance owner. + * @param contract_id Contract id to be configured. * @return 0 on success and -1 on error. */ - int create_new_instance(instance_info &info, std::string_view owner_pubkey) + int create_new_instance(instance_info &info, std::string_view owner_pubkey, const std::string &contract_id) { LOG_INFO << "Resources for instance - CPU: " << instance_resources.cpu_micro_seconds << " MicroS, RAM: " << instance_resources.mem_bytes << " Bytes, Storage: " << instance_resources.storage_bytes << " Bytes."; + // First check whether contract_id is valid uuid. + if (!crypto::verify_uuid(contract_id)) + { + LOG_ERROR << "Provided contract id is not a valid uuid."; + return -1; + } + ports instance_ports; if (!vacant_ports.empty()) { @@ -164,7 +172,7 @@ namespace hp std::string hpfs_log_level; bool is_full_history; - if (create_contract(username, contract_dir, owner_pubkey, instance_ports, info) == -1 || + if (create_contract(username, owner_pubkey, contract_id, contract_dir, instance_ports, info) == -1 || read_contract_cfg_values(contract_dir, hpfs_log_level, is_full_history) == -1 || hpfs::start_fs_processes(username, contract_dir, hpfs_log_level, is_full_history) == -1) { @@ -368,14 +376,16 @@ namespace hp /** * Creates a copy of default contract with the given name and the ports in the instance folder given in the config file. * @param username Name of the instance user. - * @param contract_dir Directory of the contract. * @param owner_pubkey Public key of the owner of the instance. + * @param contract_id Contract id to be configured. + * @param contract_dir Directory of the contract. * @param assigned_ports Assigned ports to the instance. * @param info Information of the created contract instance. * @return -1 on error and 0 on success. * */ - int create_contract(std::string_view username, std::string_view contract_dir, std::string_view owner_pubkey, const ports &assigned_ports, instance_info &info) + int create_contract(std::string_view username, std::string_view owner_pubkey, std::string_view contract_id, + std::string_view contract_dir, const ports &assigned_ports, instance_info &info) { // Creating a temporary directory to do the config manipulations before moved to the contract dir. // Folders inside /tmp directory will be cleaned after a reboot. So this will self cleanup folders @@ -431,7 +441,6 @@ namespace hp std::string pubkey, seckey; crypto::generate_signing_keys(pubkey, seckey); - const std::string contract_id = crypto::generate_uuid(); const std::string pubkey_hex = util::to_hex(pubkey); // Default hp.cfg configs. diff --git a/src/hp_manager.hpp b/src/hp_manager.hpp index c7f7655..e281c24 100644 --- a/src/hp_manager.hpp +++ b/src/hp_manager.hpp @@ -51,7 +51,7 @@ namespace hp int init(); void deinit(); void hp_monitor_loop(); - int create_new_instance(instance_info &info, std::string_view owner_pubkey); + int create_new_instance(instance_info &info, std::string_view owner_pubkey, const std::string &contract_id); int run_container(std::string_view username, std::string_view container_name, std::string_view contract_dir, const ports &assigned_ports, instance_info &info); int start_container(std::string_view container_name); int docker_start(std::string_view username, std::string_view container_name); @@ -59,7 +59,8 @@ namespace hp int stop_container(std::string_view container_name); int destroy_container(std::string_view container_name); void kill_all_containers(); - int create_contract(std::string_view username, std::string_view contract_dir, std::string_view owner_pubkey, const ports &assigned_ports, instance_info &info); + int create_contract(std::string_view username, std::string_view owner_pubkey, std::string_view contract_id, + std::string_view contract_dir, const ports &assigned_ports, instance_info &info); int write_json_file(const int fd, const jsoncons::ojson &d); int check_instance_status(std::string_view username, std::string_view container_name, std::string &status); int read_contract_cfg_values(std::string_view contract_dir, std::string &log_level, bool &is_full_history); diff --git a/src/msg/json/msg_json.cpp b/src/msg/json/msg_json.cpp index 614bd70..c19542e 100644 --- a/src/msg/json/msg_json.cpp +++ b/src/msg/json/msg_json.cpp @@ -109,6 +109,7 @@ namespace msg::json * { * "type": "create", * "owner_pubkey": "" + * "contract_id": "" * } * @return 0 on successful extraction. -1 for failure. */ @@ -116,6 +117,20 @@ namespace msg::json { if (extract_commons(msg.type, msg.id, msg.pubkey, d) == -1) return -1; + + if (!d.contains(msg::FLD_CONTRACT_ID)) + { + LOG_ERROR << "Field contract_id is missing."; + return -1; + } + + if (!d[msg::FLD_CONTRACT_ID].is()) + { + LOG_ERROR << "Invalid contract_id value."; + return -1; + } + + msg.contract_id = d[msg::FLD_CONTRACT_ID].as(); return 0; } diff --git a/src/msg/msg_common.hpp b/src/msg/msg_common.hpp index 15e4264..fa3f1d4 100644 --- a/src/msg/msg_common.hpp +++ b/src/msg/msg_common.hpp @@ -10,6 +10,7 @@ namespace msg std::string id; std::string type; std::string pubkey; + std::string contract_id; }; struct destroy_msg @@ -42,6 +43,7 @@ namespace msg constexpr const char *FLD_CONTENT = "content"; constexpr const char *FLD_PUBKEY = "owner_pubkey"; constexpr const char *FLD_CONTAINER_NAME = "container_name"; + constexpr const char *FLD_CONTRACT_ID = "contract_id"; constexpr const char *FLD_ID = "id"; // Message types diff --git a/src/pchheader.hpp b/src/pchheader.hpp index d391648..1134ffd 100644 --- a/src/pchheader.hpp +++ b/src/pchheader.hpp @@ -29,5 +29,6 @@ #include #include #include +#include #endif \ No newline at end of file