/** Entry point for HP Core **/ // This will direct all boost exceptions to our error handler. #define BOOST_NO_EXCEPTIONS #include #include #include #include #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 = 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> userbufs; for (auto &[sid, user] : usr::users) { std::pair bufpair; std::string inputtosend; inputtosend.swap(user.inbuffer); bufpair.first = std::move(inputtosend); userbufs.emplace(user.pubkey, std::move(bufpair)); } std::pair hpscbufpair; hpscbufpair.first = "{msg:'Message from HP'}"; std::unordered_map> nplbufs; for (int i = 0; i < 3; i++) { std::pair 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); }