Renamed proc namespace.

This commit is contained in:
ravinsp
2020-06-05 22:08:38 +05:30
parent 3aed949032
commit 9ee09bebb7
7 changed files with 104 additions and 97 deletions

View File

@@ -37,7 +37,7 @@ add_executable(hpcore
src/crypto.cpp
src/conf.cpp
src/hplog.cpp
src/proc.cpp
src/sc.cpp
src/bill/corebill.cpp
src/hpfs/h32.cpp
src/hpfs/hpfs.cpp

View File

@@ -90,7 +90,7 @@ Code is divided into subsystems via namespaces.
**crypto::** Handles cryptographic activities. Wraps libsodium and offers convenience functions.
**proc::** Handles contract process execution and managing user/SC I/O and npl I/O. Makes use of **usr** and **p2p**.
**sc::** Handles smart contract process execution and managing user/SC I/O and npl I/O. Makes use of **usr**, **p2p** and **hpfs**.
**usr::** Handles user connections. Makes use of **crypto** and **comm**.

View File

@@ -9,7 +9,7 @@
#include "../p2p/peer_session_handler.hpp"
#include "../hplog.hpp"
#include "../crypto.hpp"
#include "../proc.hpp"
#include "../sc.hpp"
#include "../hpfs/h32.hpp"
#include "../hpfs/hpfs.hpp"
#include "ledger_handler.hpp"
@@ -735,9 +735,9 @@ namespace cons
// Send any output from the previous consensus round to locally connected users.
dispatch_user_outputs(cons_prop);
proc::contract_bufmap_t useriobufmap;
sc::contract_bufmap_t useriobufmap;
proc::contract_iobuf_pair nplbufpair;
sc::contract_iobuf_pair nplbufpair;
nplbufpair.inputs.splice(nplbufpair.inputs.end(), ctx.candidate_npl_messages);
feed_user_inputs_to_contract_bufmap(useriobufmap, cons_prop);
@@ -826,12 +826,12 @@ namespace cons
* @param bufmap The contract bufmap which needs to be populated with inputs.
* @param cons_prop The proposal that achieved consensus.
*/
void feed_user_inputs_to_contract_bufmap(proc::contract_bufmap_t &bufmap, const p2p::proposal &cons_prop)
void feed_user_inputs_to_contract_bufmap(sc::contract_bufmap_t &bufmap, const p2p::proposal &cons_prop)
{
// Populate the buf map with all currently connected users regardless of whether they have inputs or not.
// This is in case the contract wanted to emit some data to a user without needing any input.
for (const std::string &pubkey : cons_prop.users)
bufmap.try_emplace(pubkey, proc::contract_iobuf_pair());
bufmap.try_emplace(pubkey, sc::contract_iobuf_pair());
for (const std::string &hash : cons_prop.hash_inputs)
{
@@ -852,7 +852,7 @@ namespace cons
std::string inputtofeed;
inputtofeed.swap(cand_input.input);
proc::contract_iobuf_pair &bufpair = bufmap[cand_input.userpubkey];
sc::contract_iobuf_pair &bufpair = bufmap[cand_input.userpubkey];
bufpair.inputs.push_back(std::move(inputtofeed));
// Remove the input from the candidate set because we no longer need it.
@@ -867,7 +867,7 @@ namespace cons
* for the next consensus round.
* @param bufmap The contract bufmap containing the outputs produced by the contract.
*/
void extract_user_outputs_from_contract_bufmap(proc::contract_bufmap_t &bufmap)
void extract_user_outputs_from_contract_bufmap(sc::contract_bufmap_t &bufmap)
{
for (auto &[pubkey, bufpair] : bufmap)
{
@@ -902,12 +902,12 @@ namespace cons
* @param time_now The time that must be passed on to the contract.
* @param useriobufmap The contract bufmap which holds user I/O buffers.
*/
int run_contract_binary(const int64_t time_now, proc::contract_bufmap_t &useriobufmap, proc::contract_iobuf_pair &nplbufpair)
int run_contract_binary(const int64_t time_now, sc::contract_bufmap_t &useriobufmap, sc::contract_iobuf_pair &nplbufpair)
{
// todo:implement exchange of hpsc bufs
proc::contract_iobuf_pair hpscbufpair;
return proc::exec_contract(
proc::contract_exec_args(time_now, useriobufmap, nplbufpair, hpscbufpair),
sc::contract_iobuf_pair hpscbufpair;
return sc::exec_contract(
sc::contract_exec_args(time_now, useriobufmap, nplbufpair, hpscbufpair),
ctx.curr_state_hash);
}

View File

@@ -3,7 +3,7 @@
#include "../pchheader.hpp"
#include "../util.hpp"
#include "../proc.hpp"
#include "../sc.hpp"
#include "../p2p/p2p.hpp"
#include "../usr/user_input.hpp"
#include "../hpfs/h32.hpp"
@@ -148,13 +148,13 @@ void dispatch_user_outputs(const p2p::proposal &cons_prop);
void check_state(vote_counter &votes);
void feed_user_inputs_to_contract_bufmap(proc::contract_bufmap_t &bufmap, const p2p::proposal &cons_prop);
void feed_user_inputs_to_contract_bufmap(sc::contract_bufmap_t &bufmap, const p2p::proposal &cons_prop);
void extract_user_outputs_from_contract_bufmap(proc::contract_bufmap_t &bufmap);
void extract_user_outputs_from_contract_bufmap(sc::contract_bufmap_t &bufmap);
void broadcast_npl_output(std::string &output);
int run_contract_binary(const int64_t time_now, proc::contract_bufmap_t &useriobufmap, proc::contract_iobuf_pair &nplbufpair);
int run_contract_binary(const int64_t time_now, sc::contract_bufmap_t &useriobufmap, sc::contract_iobuf_pair &nplbufpair);
template <typename T>
void increment(std::map<T, int32_t> &counter, const T &candidate);

View File

@@ -6,7 +6,7 @@
#include "util.hpp"
#include "conf.hpp"
#include "crypto.hpp"
#include "proc.hpp"
#include "sc.hpp"
#include "hplog.hpp"
#include "usr/usr.hpp"
#include "p2p/p2p.hpp"
@@ -67,7 +67,7 @@ void deinit()
usr::deinit();
p2p::deinit();
cons::deinit();
proc::deinit();
sc::deinit();
hpfs::deinit();
hplog::deinit();
}

View File

@@ -4,45 +4,12 @@
#include "fbschema/common_helpers.hpp"
#include "fbschema/p2pmsg_container_generated.h"
#include "fbschema/p2pmsg_content_generated.h"
#include "proc.hpp"
#include "sc.hpp"
#include "hpfs/hpfs.hpp"
namespace proc
namespace sc
{
constexpr size_t OUTPUT_READ_BUF_SIZE = 64 * 1024; //64KB
// Enum used to differenciate pipe fds maintained for SC I/O pipes.
enum FDTYPE
{
// Used by Smart Contract to read input sent by Hot Pocket
SCREAD = 0,
// Used by Hot Pocket to write input to the smart contract.
HPWRITE = 1,
// Used by Hot Pocket to read output from the smart contract.
HPREAD = 2,
// Used by Smart Contract to write output back to Hot Pocket.
SCWRITE = 3
};
// Map of user pipe fds (map key: user public key)
contract_fdmap_t userfds;
// Pipe fds for NPL <--> messages.
std::vector<int> nplfds;
// Pipe fds for HP <--> messages.
std::vector<int> hpscfds;
// Holds the contract process id (if currently executing).
pid_t contract_pid;
// Holds the hpfs rw process id (if currently executing).
pid_t hpfs_pid;
// Thread to collect contract outputs while contract is running.
std::thread output_fetcher_thread;
bool should_deinit = false;
execution_context ctx;
/**
* Executes the contract process and passes the specified arguments.
@@ -55,34 +22,34 @@ namespace proc
return -1;
// Setup io pipes and feed all inputs to them.
create_iopipes_for_fdmap(userfds, args.userbufs);
create_iopipes(nplfds, !args.nplbuff.inputs.empty());
create_iopipes(hpscfds, !args.hpscbufs.inputs.empty());
create_iopipes_for_fdmap(ctx.userfds, args.userbufs);
create_iopipes(ctx.nplfds, !args.nplbuff.inputs.empty());
create_iopipes(ctx.hpscfds, !args.hpscbufs.inputs.empty());
int ret = 0;
const pid_t pid = fork();
if (pid > 0)
{
// HotPocket process.
contract_pid = pid;
ctx.contract_pid = pid;
// Close all fds unused by HP process.
close_unused_fds(true);
// Start the contract output collection thread.
output_fetcher_thread = std::thread(fetch_outputs, std::ref(args));
ctx.output_fetcher_thread = std::thread(fetch_outputs, std::ref(args));
// Write the inputs into the contract process.
if (feed_inputs(args) != 0)
goto failure;
// Wait for child process (contract process) to complete execution.
const int presult = await_process_execution(contract_pid);
contract_pid = 0;
const int presult = await_process_execution(ctx.contract_pid);
ctx.contract_pid = 0;
LOG_DBG << "Contract process ended.";
// Wait for the output collection thread to gracefully stop.
output_fetcher_thread.join();
ctx.output_fetcher_thread.join();
if (presult != 0)
{
@@ -139,9 +106,9 @@ namespace proc
ret = -1;
success:
cleanup_fdmap(userfds);
cleanup_vectorfds(hpscfds);
cleanup_vectorfds(nplfds);
cleanup_fdmap(ctx.userfds);
cleanup_vectorfds(ctx.hpscfds);
cleanup_vectorfds(ctx.nplfds);
return ret;
}
@@ -168,10 +135,10 @@ namespace proc
int start_hpfs_rw_session()
{
LOG_DBG << "Starting hpfs rw session...";
if (hpfs::start_fs_session(hpfs_pid, conf::ctx.state_rw_dir, "rw", true) == -1)
if (hpfs::start_fs_session(ctx.hpfs_pid, conf::ctx.state_rw_dir, "rw", true) == -1)
return -1;
LOG_DBG << "hpfs rw session started. pid:" << hpfs_pid;
LOG_DBG << "hpfs rw session started. pid:" << ctx.hpfs_pid;
}
/**
@@ -183,11 +150,11 @@ namespace proc
if (hpfs::get_hash(state_hash, conf::ctx.state_rw_dir, "/") == -1)
return -1;
LOG_DBG << "Stopping hpfs rw session... pid:" << hpfs_pid;
if (util::kill_process(hpfs_pid, true) == -1)
LOG_DBG << "Stopping hpfs rw session... pid:" << ctx.hpfs_pid;
if (util::kill_process(ctx.hpfs_pid, true) == -1)
return -1;
hpfs_pid = 0;
ctx.hpfs_pid = 0;
LOG_DBG << "hpfs rw session stopped.";
return 0;
}
@@ -215,12 +182,12 @@ namespace proc
os << "{\"version\":\"" << util::HP_VERSION
<< "\",\"pubkey\":\"" << conf::cfg.pubkeyhex
<< "\",\"ts\":" << args.timestamp
<< ",\"hpfd\":[" << hpscfds[FDTYPE::SCREAD] << "," << hpscfds[FDTYPE::SCWRITE]
<< ",\"hpfd\":[" << ctx.hpscfds[FDTYPE::SCREAD] << "," << ctx.hpscfds[FDTYPE::SCWRITE]
<< "],\"usrfd\":{";
fdmap_json_to_stream(userfds, os);
fdmap_json_to_stream(ctx.userfds, os);
os << "},\"nplfd\":[" << nplfds[FDTYPE::SCREAD] << "," << nplfds[FDTYPE::SCWRITE]
os << "},\"nplfd\":[" << ctx.nplfds[FDTYPE::SCREAD] << "," << ctx.nplfds[FDTYPE::SCWRITE]
<< "],\"unl\":[";
for (auto nodepk = conf::cfg.unl.begin(); nodepk != conf::cfg.unl.end(); nodepk++)
@@ -276,7 +243,7 @@ namespace proc
}
// Write any verified (consensus-reached) user inputs to user pipes.
if (write_contract_fdmap_inputs(userfds, args.userbufs) != 0)
if (write_contract_fdmap_inputs(ctx.userfds, args.userbufs) != 0)
{
LOG_ERR << "Failed to write user inputs to contract.";
return -1;
@@ -289,14 +256,14 @@ namespace proc
{
while (true)
{
if (should_deinit)
if (ctx.should_deinit)
break;
const int hpsc_npl_res = read_contract_hp_npl_outputs(args);
if (hpsc_npl_res == -1)
return -1;
const int user_res = read_contract_fdmap_outputs(userfds, args.userbufs);
const int user_res = read_contract_fdmap_outputs(ctx.userfds, args.userbufs);
if (user_res == -1)
{
LOG_ERR << "Error reading user outputs from the contract.";
@@ -304,7 +271,7 @@ namespace proc
}
// If no bytes were read after contract finished execution, exit the read loop.
if (hpsc_npl_res == 0 && user_res == 0 && contract_pid == 0)
if (hpsc_npl_res == 0 && user_res == 0 && ctx.contract_pid == 0)
break;
util::sleep(20);
@@ -319,13 +286,13 @@ namespace proc
*/
int write_contract_hp_npl_inputs(const contract_exec_args &args)
{
if (write_iopipe(hpscfds, args.hpscbufs.inputs) != 0)
if (write_iopipe(ctx.hpscfds, args.hpscbufs.inputs) != 0)
{
LOG_ERR << "Error writing HP inputs to SC";
return -1;
}
if (write_npl_iopipe(nplfds, args.nplbuff.inputs) != 0)
if (write_npl_iopipe(ctx.nplfds, args.nplbuff.inputs) != 0)
{
LOG_ERR << "Error writing NPL inputs to SC";
return -1;
@@ -342,14 +309,14 @@ namespace proc
*/
int read_contract_hp_npl_outputs(const contract_exec_args &args)
{
const int hpsc_res = read_iopipe(hpscfds, args.hpscbufs.output);
const int hpsc_res = read_iopipe(ctx.hpscfds, args.hpscbufs.output);
if (hpsc_res == -1)
{
LOG_ERR << "Error reading HP output from the contract.";
return -1;
}
const int npl_res = read_iopipe(nplfds, args.nplbuff.output);
const int npl_res = read_iopipe(ctx.nplfds, args.nplbuff.output);
if (npl_res == -1)
{
LOG_ERR << "Error reading NPL output from the contract.";
@@ -361,7 +328,7 @@ namespace proc
/**
* Common helper function to write json output of fdmap to given ostream.
* @param fdmap Any pubkey->fdlist map. (eg. userfds, nplfds)
* @param fdmap Any pubkey->fdlist map. (eg. ctx.userfds, ctx.nplfds)
* @param os An output stream.
*/
void fdmap_json_to_stream(const contract_fdmap_t &fdmap, std::ostringstream &os)
@@ -456,7 +423,7 @@ namespace proc
/**
* Common function to close any open fds in the map after an error.
* @param fdmap Any pubkey->fdlist map. (eg. userfds, nplfds)
* @param fdmap Any pubkey->fdlist map. (eg. ctx.userfds, ctx.nplfds)
*/
void cleanup_fdmap(contract_fdmap_t &fdmap)
{
@@ -664,12 +631,12 @@ namespace proc
void close_unused_fds(const bool is_hp)
{
close_unused_vectorfds(is_hp, hpscfds);
close_unused_vectorfds(is_hp, ctx.hpscfds);
close_unused_vectorfds(is_hp, nplfds);
close_unused_vectorfds(is_hp, ctx.nplfds);
// Loop through user fds.
for (auto &[pubkey, fds] : userfds)
for (auto &[pubkey, fds] : ctx.userfds)
close_unused_vectorfds(is_hp, fds);
}
@@ -718,16 +685,16 @@ namespace proc
*/
void deinit()
{
should_deinit = true;
ctx.should_deinit = true;
if (contract_pid > 0)
util::kill_process(contract_pid, true);
if (ctx.contract_pid > 0)
util::kill_process(ctx.contract_pid, true);
if (hpfs_pid > 0)
util::kill_process(hpfs_pid, true);
if (ctx.hpfs_pid > 0)
util::kill_process(ctx.hpfs_pid, true);
if (output_fetcher_thread.joinable())
output_fetcher_thread.join();
if (ctx.output_fetcher_thread.joinable())
ctx.output_fetcher_thread.join();
}
} // namespace proc
} // namespace sc

View File

@@ -9,9 +9,22 @@
/**
* Contains helper functions regarding POSIX process execution and IPC between HP and SC.
*/
namespace proc
namespace sc
{
// Enum used to differenciate pipe fds maintained for SC I/O pipes.
enum FDTYPE
{
// Used by Smart Contract to read input sent by Hot Pocket
SCREAD = 0,
// Used by Hot Pocket to write input to the smart contract.
HPWRITE = 1,
// Used by Hot Pocket to read output from the smart contract.
HPREAD = 2,
// Used by Smart Contract to write output back to Hot Pocket.
SCWRITE = 3
};
/**
* Represents list of inputs to the contract and the accumulated contract output for those inputs.
*/
@@ -66,6 +79,33 @@ namespace proc
}
};
/**
* Holds context information relating to contract execution environment.
*/
struct execution_context
{
// Map of user pipe fds (map key: user public key)
contract_fdmap_t userfds;
// Pipe fds for NPL <--> messages.
std::vector<int> nplfds;
// Pipe fds for HP <--> messages.
std::vector<int> hpscfds;
// Holds the contract process id (if currently executing).
pid_t contract_pid;
// Holds the hpfs rw process id (if currently executing).
pid_t hpfs_pid;
// Thread to collect contract outputs while contract is running.
std::thread output_fetcher_thread;
// Indicates that the deinit procedure has begun.
bool should_deinit = false;
};
int exec_contract(const contract_exec_args &args, hpfs::h32 &state_hash);
void deinit();
@@ -114,6 +154,6 @@ namespace proc
void cleanup_vectorfds(std::vector<int> &fds);
} // namespace proc
} // namespace sc
#endif