mirror of
https://github.com/EvernodeXRPL/hpcore.git
synced 2026-04-29 15:37:59 +00:00
Added version compatibility infrstructure.
This commit is contained in:
111
src/conf.cpp
111
src/conf.cpp
@@ -1,9 +1,6 @@
|
||||
#include <cstdio>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <rapidjson/document.h>
|
||||
#include <rapidjson/istreamwrapper.h>
|
||||
#include <rapidjson/ostreamwrapper.h>
|
||||
@@ -20,7 +17,39 @@ namespace conf
|
||||
ContractCtx ctx;
|
||||
ContractConfig cfg;
|
||||
|
||||
void load_config()
|
||||
// v1 < v2 -> -1
|
||||
// v1 == v2 -> 0
|
||||
// v1 > v2 -> +1
|
||||
int version_compare(std::string v1, std::string v2)
|
||||
{
|
||||
size_t i = 0, j = 0;
|
||||
while (i < v1.length() || j < v2.length())
|
||||
{
|
||||
int acc1 = 0, acc2 = 0;
|
||||
|
||||
while (i < v1.length() && v1[i] != '.')
|
||||
{
|
||||
acc1 = acc1 * 10 + (v1[i] - '0');
|
||||
i++;
|
||||
}
|
||||
while (j < v2.length() && v2[j] != '.')
|
||||
{
|
||||
acc2 = acc2 * 10 + (v2[j] - '0');
|
||||
j++;
|
||||
}
|
||||
|
||||
if (acc1 < acc2)
|
||||
return -1;
|
||||
if (acc1 > acc2)
|
||||
return +1;
|
||||
|
||||
++i;
|
||||
++j;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int load_config()
|
||||
{
|
||||
ifstream ifs(ctx.configFile);
|
||||
IStreamWrapper isw(ifs);
|
||||
@@ -28,6 +57,16 @@ void load_config()
|
||||
Document d;
|
||||
d.ParseStream(isw);
|
||||
|
||||
//Check contract version.
|
||||
string cfgVersion = d["version"].GetString();
|
||||
if (version_compare(cfgVersion, _HP_MIN_CONTRACT_VERSION_) == -1)
|
||||
{
|
||||
cerr << "Contract version too old. Minimum "
|
||||
<< _HP_MIN_CONTRACT_VERSION_ << " required. "
|
||||
<< cfgVersion << " found.\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
cfg.pubkeyb64 = d["pubkeyb64"].GetString();
|
||||
cfg.seckeyb64 = d["seckeyb64"].GetString();
|
||||
cfg.binary = d["binary"].GetString();
|
||||
@@ -47,6 +86,8 @@ void load_config()
|
||||
cfg.pubport = d["pubport"].GetInt();
|
||||
cfg.pubmaxsize = d["pubmaxsize"].GetInt();
|
||||
cfg.pubmaxcpm = d["pubmaxcpm"].GetInt();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void save_config()
|
||||
@@ -54,6 +95,7 @@ void save_config()
|
||||
Document d;
|
||||
d.SetObject();
|
||||
Document::AllocatorType &allocator = d.GetAllocator();
|
||||
d.AddMember("version", StringRef(_HP_VERSION_), allocator);
|
||||
d.AddMember("pubkeyb64", StringRef(cfg.pubkeyb64.c_str()), allocator);
|
||||
d.AddMember("seckeyb64", StringRef(cfg.seckeyb64.c_str()), allocator);
|
||||
d.AddMember("binary", StringRef(cfg.binary.c_str()), allocator);
|
||||
@@ -91,46 +133,21 @@ void save_config()
|
||||
d.Accept(writer);
|
||||
}
|
||||
|
||||
int parse_cmd(int argc, char **argv)
|
||||
void set_contract_dir_paths(string basedir)
|
||||
{
|
||||
if (argc == 3) //We get working dir as an arg anyway. So we need to check for 1+2 args.
|
||||
{
|
||||
string command(argv[1]);
|
||||
if (command == "run" || command == "new" || command == "rekey")
|
||||
{
|
||||
ctx.command = command;
|
||||
string dir = argv[2];
|
||||
if (dir[dir.size() - 1] == '/')
|
||||
dir = dir.substr(0, dir.size() - 1);
|
||||
if (basedir[basedir.size() - 1] == '/')
|
||||
basedir = basedir.substr(0, basedir.size() - 1);
|
||||
|
||||
ctx.contractDir = dir;
|
||||
ctx.configDir = dir + "/cfg";
|
||||
ctx.configFile = ctx.configDir + "/hp.cfg";
|
||||
ctx.histDir = dir + "/hist";
|
||||
ctx.stateDir = dir + "/state";
|
||||
ctx.binDir = dir + "/bin";
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "Invalid command. 'run | new | rekey' expected.\n";
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
cerr << "Argument count mismatch.\n";
|
||||
}
|
||||
|
||||
cout << "Usage: hpcore <command> <contract dir> (command = run | new |rekey)\n";
|
||||
cout << "Example: hpcore run ~/mycontract\n";
|
||||
|
||||
return 0;
|
||||
ctx.contractDir = basedir;
|
||||
ctx.configDir = basedir + "/cfg";
|
||||
ctx.configFile = ctx.configDir + "/hp.cfg";
|
||||
ctx.histDir = basedir + "/hist";
|
||||
ctx.stateDir = basedir + "/state";
|
||||
ctx.binDir = basedir + "/bin";
|
||||
}
|
||||
|
||||
int create_contract()
|
||||
{
|
||||
struct stat dirInfo;
|
||||
|
||||
if (boost::filesystem::exists(ctx.contractDir))
|
||||
{
|
||||
cerr << "Contract dir already exists.\n";
|
||||
@@ -153,9 +170,8 @@ int create_contract()
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rekey()
|
||||
int clear_keys()
|
||||
{
|
||||
//Clear the keys and save the config. crpyto::init will automatically init the keys.
|
||||
cfg.pubkeyb64 = "";
|
||||
cfg.seckeyb64 = "";
|
||||
save_config();
|
||||
@@ -163,23 +179,22 @@ int rekey()
|
||||
|
||||
int init(int argc, char **argv)
|
||||
{
|
||||
if (!parse_cmd(argc, argv))
|
||||
return 0;
|
||||
|
||||
if (ctx.command == "new")
|
||||
{
|
||||
if (!create_contract())
|
||||
return 0;
|
||||
load_config();
|
||||
}
|
||||
else if (ctx.command == "rekey")
|
||||
|
||||
if (!load_config())
|
||||
return 0;
|
||||
|
||||
if (ctx.command == "rekey")
|
||||
{
|
||||
load_config();
|
||||
rekey();
|
||||
//Clear the keys. crpyto::init will automatically init the keys.
|
||||
clear_keys();
|
||||
}
|
||||
else if (ctx.command == "run")
|
||||
{
|
||||
load_config();
|
||||
//TO DO: Contract run logic.
|
||||
}
|
||||
|
||||
|
||||
23
src/conf.h
23
src/conf.h
@@ -1,6 +1,14 @@
|
||||
#ifndef _HP_CONF_H_
|
||||
#define _HP_CONF_H_
|
||||
|
||||
//Hot Pocket version. Displayed on 'hotpocket version' and written to new contract configs.
|
||||
#define _HP_VERSION_ "0.1"
|
||||
//minimum compatible contract config version (this will be used to validate contract configs)
|
||||
#define _HP_MIN_CONTRACT_VERSION_ "0.1"
|
||||
//minimum compatible peer message version (this will be used to accept/reject incoming peer connections)
|
||||
//(Keeping this as int for effcient msg payload and comparison)
|
||||
#define _HP_MIN_PEERMSG_VERSION_ 1
|
||||
|
||||
#include <rapidjson/document.h>
|
||||
#include <vector>
|
||||
|
||||
@@ -23,10 +31,19 @@ struct ContractCtx
|
||||
|
||||
struct ContractConfig
|
||||
{
|
||||
/*
|
||||
Config elements which are only initialized in memory (these are not loaded from the config file)
|
||||
*/
|
||||
//public key bytes
|
||||
unsigned char *pubkey;
|
||||
//secret key bytes
|
||||
unsigned char *seckey;
|
||||
|
||||
/*
|
||||
Config elements which are loaded from the config file.
|
||||
*/
|
||||
string pubkeyb64;
|
||||
string seckeyb64;
|
||||
unsigned char* pubkey;
|
||||
unsigned char* seckey;
|
||||
string binary;
|
||||
string binargs;
|
||||
string listenip;
|
||||
@@ -42,7 +59,7 @@ struct ContractConfig
|
||||
extern ContractCtx ctx;
|
||||
extern ContractConfig cfg;
|
||||
int init(int argc, char **argv);
|
||||
void load_config();
|
||||
void set_contract_dir_paths(string basedir);
|
||||
void save_config();
|
||||
|
||||
} // namespace conf
|
||||
|
||||
63
src/main.cpp
63
src/main.cpp
@@ -9,26 +9,61 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
int parse_cmd(int argc, char **argv);
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
if (!(conf::init(argc, argv) && crypto::init()))
|
||||
{
|
||||
cerr << "Init error\n";
|
||||
if (!parse_cmd(argc, argv))
|
||||
return -1;
|
||||
|
||||
if (conf::ctx.command == "version")
|
||||
{
|
||||
cout << _HP_VERSION_ << endl;
|
||||
}
|
||||
|
||||
//Example sign and verification.
|
||||
string msg = "hotpocket";
|
||||
string sigb64 = crypto::sign_b64(msg);
|
||||
cout << "Message: " << msg << endl;
|
||||
cout << "Signature: " << sigb64 << endl;
|
||||
|
||||
bool isValid = crypto::verify_b64(msg, sigb64, conf::cfg.pubkeyb64);
|
||||
if (isValid)
|
||||
cout << "Signature verified.\n";
|
||||
else
|
||||
cout << "Invalid signature.\n";
|
||||
{
|
||||
bool initSuccess = conf::init(argc, argv) && crypto::init();
|
||||
if (!initSuccess)
|
||||
{
|
||||
cerr << "Init error\n";
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
cout << "exited normally\n";
|
||||
return 0;
|
||||
}
|
||||
|
||||
int parse_cmd(int argc, char **argv)
|
||||
{
|
||||
if (argc > 1) //We get working dir as an arg anyway. So we need to check for >1 args.
|
||||
{
|
||||
string command = argv[1];
|
||||
conf::ctx.command = command;
|
||||
if (command == "run" || command == "new" || command == "rekey")
|
||||
{
|
||||
if (argc != 3)
|
||||
{
|
||||
cerr << "Contract directory not specified.\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
conf::set_contract_dir_paths(argv[2]);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
else if (command == "version")
|
||||
{
|
||||
if (argc == 2)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
cerr << "Arguments mismatch.\n";
|
||||
cout << "Usage:\n";
|
||||
cout << "hpcore version\n";
|
||||
cout << "hpcore <command> <contract dir> (command = run | new | rekey)\n";
|
||||
cout << "Example: hpcore run ~/mycontract\n";
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user