mirror of
https://github.com/EvernodeXRPL/hpcore.git
synced 2026-04-29 15:37:59 +00:00
JSON message parsing for contract control messages. (#166)
This commit is contained in:
@@ -39,6 +39,8 @@ add_executable(hpcore
|
||||
src/msg/fbuf/common_helpers.cpp
|
||||
src/msg/fbuf/p2pmsg_helpers.cpp
|
||||
src/msg/fbuf/ledger_helpers.cpp
|
||||
src/msg/json/controlmsg_json.cpp
|
||||
src/msg/controlmsg_parser.cpp
|
||||
src/msg/json/usrmsg_json.cpp
|
||||
src/msg/bson/usrmsg_bson.cpp
|
||||
src/msg/usrmsg_parser.cpp
|
||||
|
||||
@@ -196,7 +196,7 @@ int hp_init(hp_contract_func contract_func)
|
||||
__hp_free_contract_context(&ctx);
|
||||
|
||||
// Send termination control message.
|
||||
write(gctx.control_fd, "Terminated", 10);
|
||||
write(gctx.control_fd, "{\"type\":\"contract_end\"}", 24);
|
||||
close(gctx.control_fd);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -40,7 +40,7 @@ class HotPocketContract {
|
||||
}
|
||||
|
||||
#terminate = () => {
|
||||
this.#controlChannel.send("Terminated")
|
||||
this.#controlChannel.send(JSON.stringify({ type: "contract_end" }));
|
||||
this.#controlChannel.close();
|
||||
}
|
||||
}
|
||||
|
||||
16
src/msg/controlmsg_common.hpp
Normal file
16
src/msg/controlmsg_common.hpp
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef _HP_MSG_CONTROLMSG_COMMON_
|
||||
#define _HP_MSG_CONTROLMSG_COMMON_
|
||||
|
||||
#include "../pchheader.hpp"
|
||||
|
||||
namespace msg::controlmsg
|
||||
{
|
||||
// Message field names
|
||||
constexpr const char *FLD_TYPE = "type";
|
||||
|
||||
// Message types
|
||||
constexpr const char *MSGTYPE_CONTRACT_END = "contract_end";
|
||||
|
||||
} // namespace msg::controlmsg
|
||||
|
||||
#endif
|
||||
19
src/msg/controlmsg_parser.cpp
Normal file
19
src/msg/controlmsg_parser.cpp
Normal file
@@ -0,0 +1,19 @@
|
||||
#include "../pchheader.hpp"
|
||||
#include "json/controlmsg_json.hpp"
|
||||
#include "controlmsg_parser.hpp"
|
||||
|
||||
namespace jctlmsg = msg::controlmsg::json;
|
||||
|
||||
namespace msg::controlmsg
|
||||
{
|
||||
int controlmsg_parser::parse(std::string_view message)
|
||||
{
|
||||
return jctlmsg::parse_control_message(jsonDoc, message);
|
||||
}
|
||||
|
||||
int controlmsg_parser::extract_type(std::string &extracted_type) const
|
||||
{
|
||||
return jctlmsg::extract_type(extracted_type, jsonDoc);
|
||||
}
|
||||
|
||||
} // namespace msg::controlmsg
|
||||
20
src/msg/controlmsg_parser.hpp
Normal file
20
src/msg/controlmsg_parser.hpp
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef _HP_MSG_CONTROLMSG_PARSER_
|
||||
#define _HP_MSG_CONTROLMSG_PARSER_
|
||||
|
||||
#include "../pchheader.hpp"
|
||||
|
||||
namespace msg::controlmsg
|
||||
{
|
||||
class controlmsg_parser
|
||||
{
|
||||
jsoncons::json jsonDoc;
|
||||
|
||||
public:
|
||||
int parse(std::string_view message);
|
||||
|
||||
int extract_type(std::string &extracted_type) const;
|
||||
};
|
||||
|
||||
} // namespace msg::controlmsg
|
||||
|
||||
#endif
|
||||
58
src/msg/json/controlmsg_json.cpp
Normal file
58
src/msg/json/controlmsg_json.cpp
Normal file
@@ -0,0 +1,58 @@
|
||||
#include "../../pchheader.hpp"
|
||||
#include "../controlmsg_common.hpp"
|
||||
#include "controlmsg_json.hpp"
|
||||
|
||||
namespace msg::controlmsg::json
|
||||
{
|
||||
// JSON separators
|
||||
constexpr const char *SEP_COMMA = "\",\"";
|
||||
constexpr const char *SEP_COLON = "\":\"";
|
||||
constexpr const char *SEP_COMMA_NOQUOTE = ",\"";
|
||||
constexpr const char *SEP_COLON_NOQUOTE = "\":";
|
||||
|
||||
// Message types
|
||||
constexpr const char *MSGTYPE_HANDSHAKE_CHALLENGE = "handshake_challenge";
|
||||
|
||||
/**
|
||||
* Parses a json control message sent by the contract.
|
||||
* @param d Jsoncons document to which the parsed json should be loaded.
|
||||
* @param message The message to parse.
|
||||
* Accepted message format:
|
||||
* {
|
||||
* 'type': '<message type>'
|
||||
* ...
|
||||
* }
|
||||
* @return 0 on successful parsing. -1 for failure.
|
||||
*/
|
||||
int parse_control_message(jsoncons::json &d, std::string_view message)
|
||||
{
|
||||
try
|
||||
{
|
||||
d = jsoncons::json::parse(message, jsoncons::strict_json_parsing());
|
||||
}
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
LOG_DEBUG << "User json message parsing failed.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check existence of msg type field.
|
||||
if (!d.contains(msg::controlmsg::FLD_TYPE) || !d[msg::controlmsg::FLD_TYPE].is<std::string>())
|
||||
{
|
||||
LOG_DEBUG << "User json message 'type' missing or invalid.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the message 'type' value from the json document.
|
||||
*/
|
||||
int extract_type(std::string &extracted_type, const jsoncons::json &d)
|
||||
{
|
||||
extracted_type = d[msg::controlmsg::FLD_TYPE].as<std::string>();
|
||||
return 0;
|
||||
}
|
||||
|
||||
} // namespace msg::controlmsg::json
|
||||
17
src/msg/json/controlmsg_json.hpp
Normal file
17
src/msg/json/controlmsg_json.hpp
Normal file
@@ -0,0 +1,17 @@
|
||||
#ifndef _HP_MSG_JSON_CONTROLMSG_JSON_
|
||||
#define _HP_MSG_JSON_CONTROLMSG_JSON_
|
||||
|
||||
#include "../../pchheader.hpp"
|
||||
|
||||
/**
|
||||
* Parser helpers for smart contract control messages.
|
||||
*/
|
||||
namespace msg::controlmsg::json
|
||||
{
|
||||
int parse_control_message(jsoncons::json &d, std::string_view message);
|
||||
|
||||
int extract_type(std::string &extracted_type, const jsoncons::json &d);
|
||||
|
||||
} // namespace msg::controlmsg::json
|
||||
|
||||
#endif
|
||||
@@ -21,18 +21,18 @@ namespace msg::usrmsg::json
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs user challenge message json and the challenge string required for
|
||||
* initial user challenge handshake. This gets called when a user establishes
|
||||
* a web socket connection to HP.
|
||||
*
|
||||
* @param msg String reference to copy the generated json message string into.
|
||||
* Message format:
|
||||
* {
|
||||
* "type": "handshake_challenge",
|
||||
* "challenge": "<hex challenge string>"
|
||||
* }
|
||||
* @param challengehex String reference to copy the generated hex challenge string into.
|
||||
*/
|
||||
* Constructs user challenge message json and the challenge string required for
|
||||
* initial user challenge handshake. This gets called when a user establishes
|
||||
* a web socket connection to HP.
|
||||
*
|
||||
* @param msg String reference to copy the generated json message string into.
|
||||
* Message format:
|
||||
* {
|
||||
* "type": "handshake_challenge",
|
||||
* "challenge": "<hex challenge string>"
|
||||
* }
|
||||
* @param challengehex String reference to copy the generated hex challenge string into.
|
||||
*/
|
||||
void create_user_challenge(std::vector<uint8_t> &msg, std::string &challengehex)
|
||||
{
|
||||
// Use libsodium to generate the random challenge bytes.
|
||||
@@ -63,15 +63,15 @@ namespace msg::usrmsg::json
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a status response message.
|
||||
* @param msg String reference to copy the generated json message string into.
|
||||
* Message format:
|
||||
* {
|
||||
* "type": "stat_response",
|
||||
* "lcl": "<lcl id>",
|
||||
* "lcl_seqno": <integer>
|
||||
* }
|
||||
*/
|
||||
* Constructs a status response message.
|
||||
* @param msg String reference to copy the generated json message string into.
|
||||
* Message format:
|
||||
* {
|
||||
* "type": "stat_response",
|
||||
* "lcl": "<lcl id>",
|
||||
* "lcl_seqno": <integer>
|
||||
* }
|
||||
*/
|
||||
void create_status_response(std::vector<uint8_t> &msg, const uint64_t lcl_seq_no, std::string_view lcl)
|
||||
{
|
||||
msg.reserve(128);
|
||||
@@ -91,19 +91,19 @@ namespace msg::usrmsg::json
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a contract input status message.
|
||||
* @param msg String reference to copy the generated json message string into.
|
||||
* Message format:
|
||||
* {
|
||||
* "type": "contract_input_status",
|
||||
* "status": "<accepted|rejected>",
|
||||
* "reason": "<reson>",
|
||||
* "input_sig": "<hex sig of original input message>"
|
||||
* }
|
||||
* @param is_accepted Whether the original message was accepted or not.
|
||||
* @param reason Rejected reason. Empty if accepted.
|
||||
* @param input_sig Binary signature of the original input message which generated this result.
|
||||
*/
|
||||
* Constructs a contract input status message.
|
||||
* @param msg String reference to copy the generated json message string into.
|
||||
* Message format:
|
||||
* {
|
||||
* "type": "contract_input_status",
|
||||
* "status": "<accepted|rejected>",
|
||||
* "reason": "<reson>",
|
||||
* "input_sig": "<hex sig of original input message>"
|
||||
* }
|
||||
* @param is_accepted Whether the original message was accepted or not.
|
||||
* @param reason Rejected reason. Empty if accepted.
|
||||
* @param input_sig Binary signature of the original input message which generated this result.
|
||||
*/
|
||||
void create_contract_input_status(std::vector<uint8_t> &msg, std::string_view status, std::string_view reason, std::string_view input_sig)
|
||||
{
|
||||
std::string sighex;
|
||||
@@ -130,15 +130,15 @@ namespace msg::usrmsg::json
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a contract read response message.
|
||||
* @param msg String reference to copy the generated json message string into.
|
||||
* Message format:
|
||||
* {
|
||||
* "type": "contract_read_response",
|
||||
* "content": "<hex encoded contract output>"
|
||||
* }
|
||||
* @param content The contract binary output content to be put in the message.
|
||||
*/
|
||||
* Constructs a contract read response message.
|
||||
* @param msg String reference to copy the generated json message string into.
|
||||
* Message format:
|
||||
* {
|
||||
* "type": "contract_read_response",
|
||||
* "content": "<hex encoded contract output>"
|
||||
* }
|
||||
* @param content The contract binary output content to be put in the message.
|
||||
*/
|
||||
void create_contract_read_response_container(std::vector<uint8_t> &msg, std::string_view content)
|
||||
{
|
||||
std::string contenthex;
|
||||
@@ -160,17 +160,17 @@ namespace msg::usrmsg::json
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a contract output container message.
|
||||
* @param msg String reference to copy the generated json message string into.
|
||||
* Message format:
|
||||
* {
|
||||
* "type": "contract_output",
|
||||
* "lcl": "<lcl id>"
|
||||
* "lcl_seqno": <integer>,
|
||||
* "content": "<hex encoded contract output>"
|
||||
* }
|
||||
* @param content The contract binary output content to be put in the message.
|
||||
*/
|
||||
* Constructs a contract output container message.
|
||||
* @param msg String reference to copy the generated json message string into.
|
||||
* Message format:
|
||||
* {
|
||||
* "type": "contract_output",
|
||||
* "lcl": "<lcl id>"
|
||||
* "lcl_seqno": <integer>,
|
||||
* "content": "<hex encoded contract output>"
|
||||
* }
|
||||
* @param content The contract binary output content to be put in the message.
|
||||
*/
|
||||
void create_contract_output_container(std::vector<uint8_t> &msg, std::string_view content, const uint64_t lcl_seq_no, std::string_view lcl)
|
||||
{
|
||||
std::string contenthex;
|
||||
@@ -200,23 +200,23 @@ namespace msg::usrmsg::json
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the user handshake response with the original challenge issued to the user
|
||||
* and the user public key contained in the response.
|
||||
*
|
||||
* @param extracted_pubkeyhex The hex public key extracted from the response.
|
||||
* @param extracted_protocol The protocol code extracted from the response.
|
||||
* @param response The response bytes to verify. This will be parsed as json.
|
||||
* Accepted response format:
|
||||
* {
|
||||
* "type": "handshake_response",
|
||||
* "challenge": "<original hex challenge the user received>",
|
||||
* "sig": "<hex signature of the challenge>",
|
||||
* "pubkey": "<hex public key of the user>",
|
||||
* "protocol": "<json | bson>"
|
||||
* }
|
||||
* @param original_challenge The original hex challenge string issued to the user.
|
||||
* @return 0 if challenge response is verified. -1 if challenge not met or an error occurs.
|
||||
*/
|
||||
* Verifies the user handshake response with the original challenge issued to the user
|
||||
* and the user public key contained in the response.
|
||||
*
|
||||
* @param extracted_pubkeyhex The hex public key extracted from the response.
|
||||
* @param extracted_protocol The protocol code extracted from the response.
|
||||
* @param response The response bytes to verify. This will be parsed as json.
|
||||
* Accepted response format:
|
||||
* {
|
||||
* "type": "handshake_response",
|
||||
* "challenge": "<original hex challenge the user received>",
|
||||
* "sig": "<hex signature of the challenge>",
|
||||
* "pubkey": "<hex public key of the user>",
|
||||
* "protocol": "<json | bson>"
|
||||
* }
|
||||
* @param original_challenge The original hex challenge string issued to the user.
|
||||
* @return 0 if challenge response is verified. -1 if challenge not met or an error occurs.
|
||||
*/
|
||||
int verify_user_handshake_response(std::string &extracted_pubkeyhex, std::string &extracted_protocol,
|
||||
std::string_view response, std::string_view original_challenge)
|
||||
{
|
||||
@@ -268,7 +268,7 @@ namespace msg::usrmsg::json
|
||||
}
|
||||
|
||||
// Verify the challenge signature. We do this last due to signature verification cost.
|
||||
std::string_view pubkeysv = d[msg::usrmsg::FLD_PUBKEY].as<std::string_view >();
|
||||
std::string_view pubkeysv = d[msg::usrmsg::FLD_PUBKEY].as<std::string_view>();
|
||||
if (crypto::verify_hex(
|
||||
original_challenge,
|
||||
d[msg::usrmsg::FLD_SIG].as<std::string_view>(),
|
||||
@@ -285,23 +285,23 @@ namespace msg::usrmsg::json
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a json message sent by a user.
|
||||
* @param d Jsoncons document to which the parsed json should be loaded.
|
||||
* @param message The message to parse.
|
||||
* Accepted message format:
|
||||
* {
|
||||
* 'type': '<message type>'
|
||||
* ...
|
||||
* }
|
||||
* @return 0 on successful parsing. -1 for failure.
|
||||
*/
|
||||
* Parses a json message sent by a user.
|
||||
* @param d Jsoncons document to which the parsed json should be loaded.
|
||||
* @param message The message to parse.
|
||||
* Accepted message format:
|
||||
* {
|
||||
* 'type': '<message type>'
|
||||
* ...
|
||||
* }
|
||||
* @return 0 on successful parsing. -1 for failure.
|
||||
*/
|
||||
int parse_user_message(jsoncons::json &d, std::string_view message)
|
||||
{
|
||||
try
|
||||
{
|
||||
d = jsoncons::json::parse(message, jsoncons::strict_json_parsing());
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
LOG_DEBUG << "User json message parsing failed.";
|
||||
return -1;
|
||||
@@ -318,8 +318,8 @@ namespace msg::usrmsg::json
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the message 'type' value from the json document.
|
||||
*/
|
||||
* Extracts the message 'type' value from the json document.
|
||||
*/
|
||||
int extract_type(std::string &extracted_type, const jsoncons::json &d)
|
||||
{
|
||||
extracted_type = d[msg::usrmsg::FLD_TYPE].as<std::string>();
|
||||
@@ -327,17 +327,17 @@ namespace msg::usrmsg::json
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a contract read request message sent by user.
|
||||
*
|
||||
* @param extracted_content The content to be passed to the contract, extracted from the message.
|
||||
* @param d The json document holding the read request message.
|
||||
* Accepted signed input container format:
|
||||
* {
|
||||
* "type": "contract_read_request",
|
||||
* "content": "<hex encoded content to be passed to the contract>"
|
||||
* }
|
||||
* @return 0 on successful extraction. -1 for failure.
|
||||
*/
|
||||
* Extracts a contract read request message sent by user.
|
||||
*
|
||||
* @param extracted_content The content to be passed to the contract, extracted from the message.
|
||||
* @param d The json document holding the read request message.
|
||||
* Accepted signed input container format:
|
||||
* {
|
||||
* "type": "contract_read_request",
|
||||
* "content": "<hex encoded content to be passed to the contract>"
|
||||
* }
|
||||
* @return 0 on successful extraction. -1 for failure.
|
||||
*/
|
||||
int extract_read_request(std::string &extracted_content, const jsoncons::json &d)
|
||||
{
|
||||
if (!d.contains(msg::usrmsg::FLD_CONTENT))
|
||||
@@ -370,19 +370,19 @@ namespace msg::usrmsg::json
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts a signed input container message sent by user.
|
||||
*
|
||||
* @param extracted_input_container The input container extracted from the message.
|
||||
* @param extracted_sig The binary signature extracted from the message.
|
||||
* @param d The json document holding the input container.
|
||||
* Accepted signed input container format:
|
||||
* {
|
||||
* "type": "contract_input",
|
||||
* "input_container": "<hex encoded stringified json input container message>",
|
||||
* "sig": "<hex encoded signature of the content>"
|
||||
* }
|
||||
* @return 0 on successful extraction. -1 for failure.
|
||||
*/
|
||||
* Extracts a signed input container message sent by user.
|
||||
*
|
||||
* @param extracted_input_container The input container extracted from the message.
|
||||
* @param extracted_sig The binary signature extracted from the message.
|
||||
* @param d The json document holding the input container.
|
||||
* Accepted signed input container format:
|
||||
* {
|
||||
* "type": "contract_input",
|
||||
* "input_container": "<hex encoded stringified json input container message>",
|
||||
* "sig": "<hex encoded signature of the content>"
|
||||
* }
|
||||
* @return 0 on successful extraction. -1 for failure.
|
||||
*/
|
||||
int extract_signed_input_container(
|
||||
std::string &extracted_input_container, std::string &extracted_sig, const jsoncons::json &d)
|
||||
{
|
||||
@@ -417,18 +417,18 @@ namespace msg::usrmsg::json
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the individual components of a given input container json.
|
||||
* @param input The extracted input.
|
||||
* @param nonce The extracted nonce.
|
||||
* @param max_lcl_seqno The extracted max ledger sequence no.
|
||||
* @param contentjson The json string containing the input container message.
|
||||
* {
|
||||
* "input": "<hex encoded contract input content>",
|
||||
* "nonce": "<random string with optional sorted order>",
|
||||
* "max_lcl_seqno": <integer>
|
||||
* }
|
||||
* @return 0 on succesful extraction. -1 on failure.
|
||||
*/
|
||||
* Extract the individual components of a given input container json.
|
||||
* @param input The extracted input.
|
||||
* @param nonce The extracted nonce.
|
||||
* @param max_lcl_seqno The extracted max ledger sequence no.
|
||||
* @param contentjson The json string containing the input container message.
|
||||
* {
|
||||
* "input": "<hex encoded contract input content>",
|
||||
* "nonce": "<random string with optional sorted order>",
|
||||
* "max_lcl_seqno": <integer>
|
||||
* }
|
||||
* @return 0 on succesful extraction. -1 on failure.
|
||||
*/
|
||||
int extract_input_container(std::string &input, std::string &nonce, uint64_t &max_lcl_seqno, std::string_view contentjson)
|
||||
{
|
||||
jsoncons::json d;
|
||||
@@ -436,7 +436,7 @@ namespace msg::usrmsg::json
|
||||
{
|
||||
d = jsoncons::json::parse(contentjson, jsoncons::strict_json_parsing());
|
||||
}
|
||||
catch(const std::exception& e)
|
||||
catch (const std::exception &e)
|
||||
{
|
||||
LOG_DEBUG << "User input container json parsing failed.";
|
||||
return -1;
|
||||
|
||||
44
src/sc.cpp
44
src/sc.cpp
@@ -6,6 +6,8 @@
|
||||
#include "sc.hpp"
|
||||
#include "hpfs/hpfs.hpp"
|
||||
#include "msg/fbuf/p2pmsg_helpers.hpp"
|
||||
#include "msg/controlmsg_common.hpp"
|
||||
#include "msg/controlmsg_parser.hpp"
|
||||
|
||||
namespace sc
|
||||
{
|
||||
@@ -332,7 +334,7 @@ namespace sc
|
||||
while (!ctx.is_shutting_down)
|
||||
{
|
||||
// Atempt to read messages from contract (regardless of contract terminated or not).
|
||||
const int hpsc_read_res = read_contract_hp_outputs(ctx);
|
||||
const int hpsc_read_res = read_control_outputs(ctx);
|
||||
const int npl_read_res = ctx.args.readonly ? 0 : read_contract_npl_outputs(ctx);
|
||||
const int user_read_res = read_contract_fdmap_outputs(ctx.userfds, ctx.args.userbufs);
|
||||
|
||||
@@ -351,13 +353,13 @@ namespace sc
|
||||
if (npl_write_res == -1)
|
||||
break;
|
||||
|
||||
const int hpsc_write_res = write_contract_hp_inputs(ctx);
|
||||
if (hpsc_write_res == -1)
|
||||
const int control_write_res = write_control_inputs(ctx);
|
||||
if (control_write_res == -1)
|
||||
break;
|
||||
|
||||
// If no operation was performed during this iteration, wait for a small delay until the next iteration.
|
||||
// This means there were no queued messages from either side.
|
||||
if ((hpsc_read_res + npl_read_res + user_read_res + hpsc_write_res + hpsc_write_res) == 0)
|
||||
if ((hpsc_read_res + npl_read_res + user_read_res + control_write_res + control_write_res) == 0)
|
||||
util::sleep(20);
|
||||
}
|
||||
|
||||
@@ -398,7 +400,7 @@ namespace sc
|
||||
/**
|
||||
* Writes any hp input messages to the contract.
|
||||
*/
|
||||
int write_contract_hp_inputs(execution_context &ctx)
|
||||
int write_control_inputs(execution_context &ctx)
|
||||
{
|
||||
std::string control_msg;
|
||||
|
||||
@@ -474,20 +476,20 @@ namespace sc
|
||||
*
|
||||
* @return 0 if no bytes were read. 1 if bytes were read..
|
||||
*/
|
||||
int read_contract_hp_outputs(execution_context &ctx)
|
||||
int read_control_outputs(execution_context &ctx)
|
||||
{
|
||||
std::string output;
|
||||
const int hpsc_res = read_iosocket(false, ctx.hpscfds, output);
|
||||
if (hpsc_res == -1)
|
||||
const int res = read_iosocket(false, ctx.hpscfds, output);
|
||||
if (res == -1)
|
||||
{
|
||||
LOG_ERROR << "Error reading HP output from the contract.";
|
||||
LOG_ERROR << "Error reading control message from the contract.";
|
||||
}
|
||||
else if (hpsc_res > 0)
|
||||
else if (res > 0)
|
||||
{
|
||||
handle_control_msgs(ctx, output);
|
||||
handle_control_msg(ctx, output);
|
||||
}
|
||||
|
||||
return (hpsc_res > 0) ? 1 : 0;
|
||||
return (res > 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -498,19 +500,19 @@ namespace sc
|
||||
int read_contract_npl_outputs(execution_context &ctx)
|
||||
{
|
||||
std::string output;
|
||||
const int npl_res = read_iosocket(false, ctx.nplfds, output);
|
||||
const int res = read_iosocket(false, ctx.nplfds, output);
|
||||
|
||||
if (npl_res == -1)
|
||||
if (res == -1)
|
||||
{
|
||||
LOG_ERROR << "Error reading NPL output from the contract.";
|
||||
}
|
||||
else if (npl_res > 0)
|
||||
else if (res > 0)
|
||||
{
|
||||
// Broadcast npl messages once contract npl output is collected.
|
||||
broadcast_npl_output(output);
|
||||
}
|
||||
|
||||
return (npl_res > 0) ? 1 : 0;
|
||||
return (res > 0) ? 1 : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -825,13 +827,17 @@ namespace sc
|
||||
ctx.is_shutting_down = true;
|
||||
}
|
||||
|
||||
void handle_control_msgs(execution_context &ctx, std::string &msg)
|
||||
void handle_control_msg(execution_context &ctx, std::string_view msg)
|
||||
{
|
||||
if (msg == "Terminated")
|
||||
msg::controlmsg::controlmsg_parser parser;
|
||||
std::string type;
|
||||
if (parser.parse(msg) == -1 || parser.extract_type(type) == -1)
|
||||
return;
|
||||
|
||||
if (type == msg::controlmsg::MSGTYPE_CONTRACT_END)
|
||||
{
|
||||
ctx.termination_signaled = true;
|
||||
}
|
||||
msg.clear();
|
||||
}
|
||||
|
||||
} // namespace sc
|
||||
|
||||
@@ -151,11 +151,11 @@ namespace sc
|
||||
|
||||
void contract_monitor_loop(execution_context &ctx);
|
||||
|
||||
int write_contract_hp_inputs(execution_context &ctx);
|
||||
int write_control_inputs(execution_context &ctx);
|
||||
|
||||
int write_npl_messages(execution_context &ctx);
|
||||
|
||||
int read_contract_hp_outputs(execution_context &ctx);
|
||||
int read_control_outputs(execution_context &ctx);
|
||||
|
||||
int read_contract_npl_outputs(execution_context &ctx);
|
||||
|
||||
@@ -183,7 +183,7 @@ namespace sc
|
||||
|
||||
void stop(execution_context &ctx);
|
||||
|
||||
void handle_control_msgs(execution_context &ctx, std::string &msg);
|
||||
void handle_control_msg(execution_context &ctx, std::string_view msg);
|
||||
|
||||
} // namespace sc
|
||||
|
||||
|
||||
Reference in New Issue
Block a user