Interface to read patch config from c contract lib. (#223)

This commit is contained in:
Chalith Desaman
2021-01-18 14:38:39 +05:30
committed by GitHub
parent a816b9079b
commit cf02108576
4 changed files with 154 additions and 85 deletions

View File

@@ -53,14 +53,29 @@ int main(int argc, char **argv)
// printf("Received %.*s from %.*s", len, msg, HP_KEY_SIZE, sender);
// free(msg);
// Patch file update.
// struct patch_config patch = {};
// patch.version = "2.0";
// struct hp_unl_node unl[1] = {"ed65aac94e7287d461540523b8ce43b873fc97398bef1b42350feac72ad360b7f3"};
// patch.unl.list = unl;
// patch.unl.count = 1;
// patch.roundtime = 1000;
// hp_update_config(&patch);
// // Test code segment - Config file will be updated with below values.
// struct hp_config config = {};
// config.version = "2.0";
// config.consensus = "public";
// config.npl = "public";
// config.appbill.bin_args = "123";
// struct hp_unl_node unl[1] = {"ed726f9f536904b125bdca10bbdd1e66591b274799b92ac8bcfc75bf45d7da4c0f"};
// config.unl.list = unl;
// config.unl.count = 1;
// config.roundtime = 1000;
// hp_update_config(&config);
// // Test code segment - Get current config file values.
// struct hp_config *current_config = hp_get_config();
// if (current_config != NULL)
// {
// printf("\"version\": \"%s\"\n", current_config->version);
// printf("\"consensus\": \"%s\"\n", current_config->consensus);
// printf("\"npl\": \"%s\"\n", current_config->npl);
// printf("\"appbill_bin_args\": \"%s\"\n", current_config->appbill.bin_args);
// }
// // Returned hp_config struct memory should be freed after it's been used.
// hp_free_config(current_config);
hp_deinit_user_input_mmap();
hp_deinit_contract();
@@ -69,13 +84,13 @@ int main(int argc, char **argv)
void store_timestamp(const uint64_t timestamp)
{
int fd = open("exects.txt", O_RDWR | O_CREAT | O_APPEND);
int fd = open("exects.txt", O_RDWR | O_CREAT | O_APPEND, 0644);
if (fd > 0)
{
char tsbuf[20];
memset(tsbuf, 0, 20);
sprintf(tsbuf, "%lu\n", timestamp);
struct iovec vec[2] = {{(void *)"ts:", 4}, {(void *)tsbuf, 20}};
struct iovec vec[2] = {{(void *)"ts:", 3}, {(void *)tsbuf, strlen(tsbuf)}};
writev(fd, vec, 2);
close(fd);
}

View File

@@ -81,30 +81,26 @@
ptr = NULL; \
}
#define __HP_UPDATE_CONFIG_ERROR(msg) \
{ \
fprintf(stderr, "%s\n", msg); \
if (fd) \
close(fd); \
\
if (root) \
__HP_FREE(root); \
\
if (config) \
__hp_free_patch_config(&existing_patch); \
\
return -1; \
#define __HP_UPDATE_CONFIG_ERROR(msg) \
{ \
fprintf(stderr, "%s\n", msg); \
if (fd) \
close(fd); \
if (config) \
__hp_free_patch_config(existing_patch); \
\
return -1; \
}
/**
* dest - Pointer to destination pointer.
* dest - Destination pointer.
* src - Source pointer.
*/
#define __HP_STRING_COPY(dest, src) \
{ \
__HP_FREE(*dest); \
*dest = (char *)malloc(strlen(src) + 1); \
memcpy(*dest, src, strlen(src) + 1); \
__HP_FREE(dest); \
dest = (char *)malloc(strlen(src) + 1); \
memcpy(dest, src, strlen(src) + 1); \
}
struct hp_user_input
@@ -153,7 +149,7 @@ struct hp_appbill_config
char *bin_args;
};
struct patch_config
struct hp_config
{
char *version;
struct hp_unl_collection unl;
@@ -195,13 +191,16 @@ int hp_writev_user_msg(const struct hp_user *user, const struct iovec *bufs, con
int hp_write_npl_msg(const void *buf, const uint32_t len);
int hp_writev_npl_msg(const struct iovec *bufs, const int buf_count);
int hp_read_npl_msg(void *msg_buf, char *pubkey_buf, const int timeout);
int hp_update_config(const struct patch_config *config);
int hp_update_config(const struct hp_config *config);
struct hp_config *hp_get_config();
void hp_free_config(struct hp_config *config);
void __hp_parse_args_json(const struct json_object_s *object);
int __hp_write_control_msg(const void *buf, const uint32_t len);
void __hp_populate_patch_from_json_object(struct patch_config *config, struct json_object_s *object);
int __hp_write_to_patch_file(const int fd, const struct patch_config *config);
void __hp_free_patch_config(struct patch_config *patch_config);
void __hp_populate_patch_from_json_object(struct hp_config *config, const struct json_object_s *object);
int __hp_write_to_patch_file(const int fd, const struct hp_config *config);
struct hp_config *__hp_read_from_patch_file(const int fd);
void __hp_free_patch_config(struct hp_config *patch_config);
static struct __hp_contract __hpc = {};
@@ -438,18 +437,16 @@ int hp_read_npl_msg(void *msg_buf, char *pubkey_buf, const int timeout)
}
/**
* Update the params of the existing patch file.
* @param config Pointer to the updated patch config struct.
* Update the params of the existing config file.
* @param config Pointer to the updated config struct.
*/
int hp_update_config(const struct patch_config *config)
int hp_update_config(const struct hp_config *config)
{
struct hp_contract_context *cctx = __hpc.cctx;
struct json_value_s *root = NULL;
struct patch_config existing_patch = {};
if (cctx->readonly)
{
fprintf(stderr, "Config update not allowed in readonly mode.");
fprintf(stderr, "Config update not allowed in readonly mode.\n");
return -1;
}
const int fd = open(PATCH_FILE_PATH, O_RDWR);
@@ -458,23 +455,15 @@ int hp_update_config(const struct patch_config *config)
fprintf(stderr, "Error opening patch.cfg file.\n");
return -1;
}
char buf[4096];
const size_t len = read(fd, buf, sizeof(buf));
if (len == -1)
{
__HP_UPDATE_CONFIG_ERROR("Error when reading stdin.");
}
root = json_parse(buf, len);
if (root && root->type == json_type_object)
struct hp_config *existing_patch = __hp_read_from_patch_file(fd);
if (existing_patch != NULL)
{
struct json_object_s *object = (struct json_object_s *)root->payload;
__hp_populate_patch_from_json_object(&existing_patch, object);
if (config->version)
{
if (strlen(config->version) != 0)
{
__HP_STRING_COPY(&existing_patch.version, config->version);
__HP_STRING_COPY(existing_patch->version, config->version);
}
else
{
@@ -511,20 +500,20 @@ int hp_update_config(const struct patch_config *config)
}
}
}
__HP_FREE(existing_patch.unl.list);
existing_patch.unl.list = config->unl.count ? (struct hp_unl_node *)malloc(sizeof(struct hp_unl_node) * config->unl.count) : NULL;
memcpy(existing_patch.unl.list, config->unl.list, sizeof(struct hp_unl_node) * config->unl.count);
existing_patch.unl.count = config->unl.count;
__HP_FREE(existing_patch->unl.list);
existing_patch->unl.list = config->unl.count ? (struct hp_unl_node *)malloc(sizeof(struct hp_unl_node) * config->unl.count) : NULL;
memcpy(existing_patch->unl.list, config->unl.list, sizeof(struct hp_unl_node) * config->unl.count);
existing_patch->unl.count = config->unl.count;
}
if (config->bin_path)
__HP_STRING_COPY(&existing_patch.bin_path, config->bin_path);
__HP_STRING_COPY(existing_patch->bin_path, config->bin_path);
if (config->bin_args)
__HP_STRING_COPY(&existing_patch.bin_args, config->bin_args);
__HP_STRING_COPY(existing_patch->bin_args, config->bin_args);
if (config->roundtime)
existing_patch.roundtime = config->roundtime;
// if (config->roundtime)
// existing_patch->roundtime = config->roundtime;
if (config->consensus)
{
@@ -532,7 +521,7 @@ int hp_update_config(const struct patch_config *config)
{
__HP_UPDATE_CONFIG_ERROR("Invalid consensus flag. Valid values: public|private");
}
__HP_STRING_COPY(&existing_patch.consensus, config->consensus);
__HP_STRING_COPY(existing_patch->consensus, config->consensus);
}
if (config->npl)
@@ -541,32 +530,97 @@ int hp_update_config(const struct patch_config *config)
{
__HP_UPDATE_CONFIG_ERROR("Invalid npl flag. Valid values: public|private");
}
__HP_STRING_COPY(&existing_patch.npl, config->npl);
__HP_STRING_COPY(existing_patch->npl, config->npl);
}
if (config->appbill.mode)
__HP_STRING_COPY(&existing_patch.appbill.mode, config->appbill.mode);
__HP_STRING_COPY(existing_patch->appbill.mode, config->appbill.mode);
if (config->appbill.bin_args)
__HP_STRING_COPY(&existing_patch.appbill.bin_args, config->appbill.bin_args);
__HP_STRING_COPY(existing_patch->appbill.bin_args, config->appbill.bin_args);
if (__hp_write_to_patch_file(fd, &existing_patch) == -1)
if (__hp_write_to_patch_file(fd, existing_patch) == -1)
__HP_UPDATE_CONFIG_ERROR("Error writing updated config to patch.cfg file.");
__hp_free_patch_config(&existing_patch);
__hp_free_patch_config(existing_patch);
}
else
{
fprintf(stderr, "Error reading patch.cfg file.\n");
close(fd);
return -1;
}
close(fd);
__HP_FREE(root);
close(fd);
return 0;
}
/**
* Get the existing config file values.
* @return returns a pointer to a config structure, returns NULL on error.
*/
struct hp_config *hp_get_config()
{
const int fd = open(PATCH_FILE_PATH, O_RDONLY);
if (fd == -1)
{
fprintf(stderr, "Error opening patch.cfg file.\n");
return NULL;
}
struct hp_config *config = __hp_read_from_patch_file(fd);
if (config == NULL)
fprintf(stderr, "Error reading patch.cfg file.\n");
close(fd);
return config;
}
/**
* Frees the memory allocated for the config structure.
* @param config Pointer to the config to be freed.
*/
void hp_free_config(struct hp_config *config)
{
__hp_free_patch_config(config);
}
/**
* Read the values from the existing patch file.
* @param fd File discriptor of the patch.cfg file.
* @return returns a pointer to a patch_config structure, returns NULL on error.
*/
struct hp_config *__hp_read_from_patch_file(const int fd)
{
char buf[4096];
const size_t len = read(fd, buf, sizeof(buf));
if (len == -1)
return NULL;
struct json_value_s *root = json_parse(buf, len);
if (root && root->type == json_type_object)
{
struct json_object_s *object = (struct json_object_s *)root->payload;
// Create struct to populate json values.
struct hp_config *config;
// Allocate memory for the patch_config struct.
config = (struct hp_config *)malloc(sizeof(struct hp_config));
// malloc and populate values to the struct.
__hp_populate_patch_from_json_object(config, object);
__HP_FREE(root);
return config;
}
__HP_FREE(root);
return NULL;
}
/**
* Write values of the given patch config struct to the file discriptor given.
* @param fd File discriptor of the patch.cfg file.
* @param config Patch config structure.
*/
int __hp_write_to_patch_file(const int fd, const struct patch_config *config)
int __hp_write_to_patch_file(const int fd, const struct hp_config *config)
{
struct iovec iov_vec[4];
// {version: + newline + 4 spaces => 21;
@@ -630,7 +684,7 @@ int __hp_write_to_patch_file(const int fd, const struct patch_config *config)
* @param config Pointer to the patch config sturct to be populated.
* @param object Pointer to the json object.
*/
void __hp_populate_patch_from_json_object(struct patch_config *config, struct json_object_s *object)
void __hp_populate_patch_from_json_object(struct hp_config *config, const struct json_object_s *object)
{
const struct json_object_element_s *elem = object->start;
do
@@ -832,7 +886,7 @@ int __hp_write_control_msg(const void *buf, const uint32_t len)
* Free memory allocated for the given patch config struct.
* @param patch_config Pointer of patch config struct to be freed.
*/
void __hp_free_patch_config(struct patch_config *patch_config)
void __hp_free_patch_config(struct hp_config *patch_config)
{
__HP_FREE(patch_config->version);
__HP_FREE(patch_config->unl.list);
@@ -842,6 +896,7 @@ void __hp_free_patch_config(struct patch_config *patch_config)
__HP_FREE(patch_config->npl);
__HP_FREE(patch_config->appbill.mode);
__HP_FREE(patch_config->appbill.bin_args);
__HP_FREE(patch_config);
}
#endif

View File

@@ -48,6 +48,15 @@ const echoContract = async (ctx) => {
// })
// await ctx.unl.send("Hello");
// }
// Update patch config
// await ctx.updateConfig({
// version: "2.0",
// unl: [
// "edf3f3bff36e22d0e1c7abf791ca4900e717754443b8e861dcfbf1cd2bbd0f6159"
// ],
// consensus: "private"
// });
}
const hpc = new HotPocket.Contract();

View File

@@ -109,19 +109,11 @@ class PatchConfig {
let updatedUnl = [];
for (let pubKey of unl) {
// Pubkeys are validated against length, ed prefix and hex characters.
if (!pubKey.length)
throw "UNL pubKey not specified.";
else if (pubKey.length != 66)
throw "Invalid UNL pubKey specified. Invalid length.";
else if (!pubKey.startsWith("ed"))
throw "Invalid UNL pubKey specified. Invalid format.";
try {
let pubKeyBin = hexToUint8Array(pubKey.substring(2));
}
catch {
throw "Invalid UNL pubKey specified. Decode error.";
}
else if (!(/^(e|E)(d|D)[0-9a-fA-F]{64}$/g.test(pubKey)))
throw "Invalid UNL pubKey specified.";
updatedUnl.push(pubKey);
}
@@ -166,14 +158,15 @@ class PatchConfig {
// Saves the config changes to tha patch config.
saveChanges() {
// Property order is simmilar to the property order of the patch.cfg created by HP at the startup.
const config = {
version: this.#version,
unl: this.#unl,
bin_path: this.#binPath,
bin_args: this.#binArgs ? this.#binArgs : "",
roundtime: this.#roundtime,
consensus: this.#consensus,
npl: this.#npl,
unl: this.#unl,
appbill: {
mode: this.#appbillMode ? this.#appbillMode : "",
bin_args: this.#appbillBinArgs ? this.#appbillBinArgs : ""
@@ -181,7 +174,8 @@ class PatchConfig {
};
return new Promise((resolve, reject) => {
fs.writeFile(this.#patchConfigPath, JSON.stringify(config), (err) => {
// Format json to match with the patch.cfg json format created by HP at the startup.
fs.writeFile(this.#patchConfigPath, JSON.stringify(config, null, 4), (err) => {
if (err) reject(err);
else resolve();
});
@@ -538,10 +532,6 @@ const invokeCallback = async (callback, ...args) => {
}
}
const hexToUint8Array = (hexString) => {
return new Uint8Array(hexString.match(/.{1,2}/g).map(byte => parseInt(byte, 16)));
}
const errHandler = (err) => console.log(err);
module.exports = {