Files
hpcore/src/main.cpp
2019-10-21 19:25:45 +05:30

205 lines
6.2 KiB
C++

/**
Entry point for HP Core
**/
// This will direct all boost exceptions to our error handler.
#define BOOST_NO_EXCEPTIONS
#include <cstdio>
#include <iostream>
#include <thread>
#include <unistd.h>
#include "util.hpp"
#include "conf.hpp"
#include "crypto.hpp"
#include "usr/usr.hpp"
#include "p2p/p2p.hpp"
#include "proc.hpp"
#include "hplog.hpp"
/**
* Parses CLI args and extracts hot pocket command and parameters given.
* HP command line accepts command and the contract directory(optional)
*/
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.
{
// We populate the global contract ctx with the detected command.
conf::ctx.command = argv[1];
// For run/new/rekey, contract directory argument must be specified.
if (conf::ctx.command == "run" || conf::ctx.command == "new" || conf::ctx.command == "rekey")
{
if (argc != 3)
{
std::cerr << "Contract directory not specified.\n";
}
else
{
// We inform the conf subsystem to populate the contract directory context values
// based on the directory argument from the command line.
conf::set_contract_dir_paths(argv[2]);
return 0;
}
}
else if (conf::ctx.command == "version")
{
if (argc == 2)
return 0;
}
}
// If all extractions fail display help message.
std::cerr << "Arguments mismatch.\n";
std::cout << "Usage:\n";
std::cout << "hpcore version\n";
std::cout << "hpcore <command> <contract dir> (command = run | new | rekey)\n";
std::cout << "Example: hpcore run ~/mycontract\n";
return -1;
}
/**
* Performs any cleanup on graceful application termination.
*/
void deinit()
{
usr::deinit();
hplog::deinit();
}
void signal_handler(int signum)
{
LOG_WARN << "Interrupt signal (" << signum << ") received.";
deinit();
exit(signum);
}
int main(int argc, char **argv)
{
// Extract the CLI args
// This call will populate conf::ctx
if (parse_cmd(argc, argv) != 0)
return -1;
if (conf::ctx.command == "version")
{
// Print the version
std::cout << util::HP_VERSION << std::endl;
}
else
{
// This block is about contract operations (new/rekey/run)
// All the contract operations will be executed on the contract directory specified
// in the command line args. 'parse_cmd()' above takes care of populating the contexual directory paths.
// For any contract opreation to execute, we should init the crypto subsystem.
if (crypto::init() != 0)
return -1;
if (conf::ctx.command == "new")
{
// This will create a new contract with all the required files.
if (conf::create_contract() != 0)
return -1;
}
else
{
if (conf::ctx.command == "rekey")
{
// This will generate new signing keys for the contract.
if (conf::rekey() != 0)
return -1;
}
else if (conf::ctx.command == "run")
{
// In order to host the contract we should init some required sub systems.
if (conf::init() != 0)
return -1;
hplog::init();
if (usr::init() != 0)
return -1;
if (p2p::init() != 0)
return -1;
// After initializing primary subsystems, register the SIGINT handler.
signal(SIGINT, signal_handler);
// This will start hosting the contract and start consensus rounds.
// TODO
while (true)
{
sleep(2);
// Test code to execute contract and collect outputs.
std::unordered_map<std::string, std::pair<std::string, std::string>> userbufs;
for (auto &[sid, user] : usr::users)
{
std::pair<std::string, std::string> bufpair;
std::string inputtosend;
inputtosend.swap(user.inbuffer);
bufpair.first = std::move(inputtosend);
userbufs.emplace(user.pubkey, std::move(bufpair));
}
std::pair<std::string, std::string> hpscbufpair;
hpscbufpair.first = "{msg:'Message from HP'}";
std::unordered_map<std::string, std::pair<std::string, std::string>> nplbufs;
for (int i = 0; i < 3; i++)
{
std::pair<std::string, std::string> bufpair;
nplbufs.emplace("aaa", std::move(bufpair));
}
proc::ContractExecArgs eargs(123123345, userbufs, nplbufs, hpscbufpair);
proc::exec_contract(eargs);
for (auto &[pubkey, bufpair] : userbufs)
{
if (!bufpair.second.empty())
{
// Find the user session id by the pubkey.
const std::string sessionid = usr::sessionids[pubkey];
// Find the user by session id.
auto itr = usr::users.find(sessionid);
const usr::connected_user &user = itr->second;
user.session->send(std::move(bufpair.second));
}
}
if (!hpscbufpair.second.empty())
LOG_DBG << "Message from SC: " << hpscbufpair.second;
userbufs.clear();
}
// Free resources.
deinit();
}
}
}
std::cout << "exited normally\n";
return 0;
}
/**
* Global exception handler for boost exceptions.
*/
void boost::throw_exception(std::exception const &e)
{
LOG_ERR << "Boost error:" << e.what();
exit(-1);
}