From 150df0eabbfc680c984c37933892b16d793ce030 Mon Sep 17 00:00:00 2001 From: Chalith Desaman Date: Tue, 11 Jan 2022 13:41:33 +0530 Subject: [PATCH] Specify environment variables to contract binary (#355) --- examples/c_contract/hotpocket_contract.h | 12 +++++++++--- src/conf.cpp | 7 +++++++ src/conf.hpp | 2 ++ src/sc/sc.cpp | 10 ++++++++-- test/local-cluster/cluster-create.sh | 1 + 5 files changed, 27 insertions(+), 5 deletions(-) diff --git a/examples/c_contract/hotpocket_contract.h b/examples/c_contract/hotpocket_contract.h index c47fdb3e..a63e7227 100644 --- a/examples/c_contract/hotpocket_contract.h +++ b/examples/c_contract/hotpocket_contract.h @@ -158,6 +158,7 @@ struct hp_config struct hp_unl_collection unl; char *bin_path; char *bin_args; + char *environment; uint32_t roundtime; uint32_t stage_slice; char *consensus; @@ -584,6 +585,7 @@ void hp_free_config(struct hp_config *config) __HP_FREE(config->unl.list); __HP_FREE(config->bin_path); __HP_FREE(config->bin_args); + __HP_FREE(config->environment); __HP_FREE(config->consensus); __HP_FREE(config->npl); __HP_FREE(config->appbill.mode); @@ -737,7 +739,7 @@ int __hp_write_to_patch_file(const int fd, const struct hp_config *config) // Top-level field values. - const char *json_string = " \"bin_path\": \"%s\",\n \"bin_args\": \"%s\",\n \"roundtime\": %s,\n \"stage_slice\": %s,\n" + const char *json_string = " \"bin_path\": \"%s\",\n \"bin_args\": \"%s\",\n \"environment\": \"%s\",\n \"roundtime\": %s,\n \"stage_slice\": %s,\n" " \"consensus\": \"%s\",\n \"npl\": \"%s\",\n \"max_input_ledger_offset\": %s,\n"; char roundtime_str[16]; @@ -749,11 +751,11 @@ int __hp_write_to_patch_file(const int fd, const struct hp_config *config) char max_input_ledger_offset_str[16]; sprintf(max_input_ledger_offset_str, "%d", config->max_input_ledger_offset); - const size_t json_string_len = 149 + strlen(config->bin_path) + strlen(config->bin_args) + + const size_t json_string_len = 172 + strlen(config->bin_path) + strlen(config->bin_args) + strlen(config->environment) + strlen(roundtime_str) + strlen(stage_slice_str) + strlen(config->consensus) + strlen(config->npl) + strlen(max_input_ledger_offset_str); char json_buf[json_string_len]; - sprintf(json_buf, json_string, config->bin_path, config->bin_args, roundtime_str, stage_slice_str, config->consensus, config->npl, max_input_ledger_offset_str); + sprintf(json_buf, json_string, config->bin_path, config->bin_args, config->environment, roundtime_str, stage_slice_str, config->consensus, config->npl, max_input_ledger_offset_str); iov_vec[2].iov_base = json_buf; iov_vec[2].iov_len = json_string_len; @@ -844,6 +846,10 @@ void __hp_populate_patch_from_json_object(struct hp_config *config, const struct { __HP_ASSIGN_CHAR_PTR(config->bin_args, elem); } + else if (strcmp(k->string, "environment") == 0) + { + __HP_ASSIGN_CHAR_PTR(config->environment, elem); + } else if (strcmp(k->string, "roundtime") == 0) { const struct json_number_s *value = (struct json_number_s *)elem->value->payload; diff --git a/src/conf.cpp b/src/conf.cpp index 32aa2e70..e1b1f783 100644 --- a/src/conf.cpp +++ b/src/conf.cpp @@ -948,6 +948,7 @@ namespace conf jdoc.insert_or_assign("unl", unl); jdoc.insert_or_assign("bin_path", contract.bin_path); jdoc.insert_or_assign("bin_args", contract.bin_args); + jdoc.insert_or_assign("environment", contract.environment); jdoc.insert_or_assign("roundtime", contract.roundtime.load()); jdoc.insert_or_assign("stage_slice", contract.stage_slice.load()); jdoc.insert_or_assign("consensus", contract.is_consensus_public ? PUBLIC : PRIVATE); @@ -1045,6 +1046,7 @@ namespace conf contract.bin_path = jdoc["bin_path"].as(); contract.bin_args = jdoc["bin_args"].as(); + contract.environment = jdoc["environment"].as(); contract.roundtime = jdoc["roundtime"].as(); if (contract.roundtime < 1 || contract.roundtime > MAX_ROUND_TIME) @@ -1093,6 +1095,11 @@ namespace conf return -1; } + contract.runtime_env_args.clear(); + // Populate runtime environment args. + if (!contract.environment.empty()) + util::split_string(contract.runtime_env_args, contract.environment, " "); + contract.runtime_binexec_args.clear(); // Populate runtime contract execution args. if (!contract.bin_args.empty()) diff --git a/src/conf.hpp b/src/conf.hpp index 5f05b129..c2396b86 100644 --- a/src/conf.hpp +++ b/src/conf.hpp @@ -182,6 +182,7 @@ namespace conf std::set unl; // Unique node list (list of binary public keys). std::string bin_path; // Full path to the contract binary. std::string bin_args; // CLI arguments to pass to the contract binary. + std::string environment; // Environment variables to be passed into contract. std::atomic roundtime = 0; // Consensus round time in ms (max: 3,600,000). std::atomic stage_slice = 0; // Percentage slice of round time that stages 0,1,2 get (max: 33). bool is_consensus_public = false; // If true, consensus are broadcasted to non-unl nodes as well. @@ -192,6 +193,7 @@ namespace conf // Config element which are initialized in memory (This is not directly loaded from the config file) std::vector runtime_binexec_args; // Contract binary execution args used during runtime. + std::vector runtime_env_args; // Contract environment variables. }; struct user_config diff --git a/src/sc/sc.cpp b/src/sc/sc.cpp index 9ad47e3d..24f24dcc 100644 --- a/src/sc/sc.cpp +++ b/src/sc/sc.cpp @@ -210,6 +210,12 @@ namespace sc execv_args[j] = conf::cfg.contract.runtime_binexec_args[i].data(); execv_args[len - 1] = NULL; + len = conf::cfg.contract.runtime_env_args.size() + 1; + char *env_args[len]; + for (int i = 0; i < conf::cfg.contract.runtime_env_args.size(); i++) + env_args[i] = conf::cfg.contract.runtime_env_args[i].data(); + env_args[len - 1] = NULL; + if (chdir(ctx.working_dir.c_str()) == -1) { std::cerr << errno << ": Contract process chdir failed." << (ctx.args.readonly ? " (rdonly)" : "") << "\n"; @@ -224,8 +230,8 @@ namespace sc exit(1); } - execv(execv_args[0], execv_args); - std::cerr << errno << ": Contract process execv failed." << (ctx.args.readonly ? " (rdonly)" : "") << "\n"; + execve(execv_args[0], execv_args, env_args); + std::cerr << errno << ": Contract process execve failed." << (ctx.args.readonly ? " (rdonly)" : "") << "\n"; exit(1); } else diff --git a/test/local-cluster/cluster-create.sh b/test/local-cluster/cluster-create.sh index fedeca11..02a7835a 100755 --- a/test/local-cluster/cluster-create.sh +++ b/test/local-cluster/cluster-create.sh @@ -111,6 +111,7 @@ do id: '3c349abe-4d70-4f50-9fa6-018f1f2530ab', \ bin_path: '$binary', \ bin_args: '$binargs', \ + environment: '', \ roundtime: $roundtime, \ consensus: 'public', \ npl: 'public', \