mirror of
https://github.com/EvernodeXRPL/hpcore.git
synced 2026-04-29 15:37:59 +00:00
Renamed proc namespace.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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**.
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user