mirror of
https://github.com/EvernodeXRPL/hpcore.git
synced 2026-04-29 15:37:59 +00:00
User control messages. (#56)
This commit is contained in:
@@ -1,18 +1,37 @@
|
||||
#include "../pchheader.hpp"
|
||||
#include "../util.hpp"
|
||||
#include "../crypto.hpp"
|
||||
#include "../cons/cons.hpp"
|
||||
#include "../hplog.hpp"
|
||||
#include "usrmsg_helpers.hpp"
|
||||
|
||||
namespace jsonschema::usrmsg
|
||||
{
|
||||
|
||||
// User JSON message schema version
|
||||
constexpr const char* SCHEMA_VERSION = "0.1";
|
||||
|
||||
// Separators
|
||||
static const char *SEP_COMMA = "\",\"";
|
||||
static const char *SEP_COLON = "\":\"";
|
||||
constexpr const char* SEP_COMMA = "\",\"";
|
||||
constexpr const char* SEP_COLON = "\":\"";
|
||||
constexpr const char* SEP_COMMA_NOQUOTE = ",\"";
|
||||
constexpr const char* SEP_COLON_NOQUOTE = "\":";
|
||||
|
||||
// Message field names
|
||||
const char* const FLD_VERSION = "version";
|
||||
constexpr const char* FLD_TYPE = "type";
|
||||
constexpr const char* FLD_CHALLENGE = "challenge";
|
||||
constexpr const char* FLD_SIG = "sig";
|
||||
constexpr const char* FLD_PUBKEY = "pubkey";
|
||||
constexpr const char* FLD_INPUT = "input";
|
||||
constexpr const char* FLD_MAX_LED_SEQ = "max_ledger_seqno";
|
||||
constexpr const char* FLD_CONTENT = "content";
|
||||
constexpr const char* FLD_NONCE = "nonce";
|
||||
constexpr const char* FLD_LCL = "lcl";
|
||||
constexpr const char* FLD_LCL_SEQ = "lcl_seqno";
|
||||
|
||||
// Length of user random challenge bytes.
|
||||
static const size_t CHALLENGE_LEN = 16;
|
||||
const size_t CHALLENGE_LEN = 16;
|
||||
|
||||
/**
|
||||
* Constructs user challenge message json and the challenge string required for
|
||||
@@ -43,8 +62,8 @@ void create_user_challenge(std::string &msg, std::string &challengehex)
|
||||
// We do not use RapidJson here in favour of performance because this is a simple json message.
|
||||
|
||||
// Since we know the rough size of the challenge massage we reserve adequate amount for the holder.
|
||||
// Only Hot Pocket version number is variable length. Therefore message size is roughly 95 bytes
|
||||
// so allocating 128bits for heap padding.
|
||||
// Only Hot Pocket version number is variable length. Therefore message size is roughly 90 bytes
|
||||
// so allocating 128bytes for heap padding.
|
||||
msg.reserve(128);
|
||||
msg.append("{\"")
|
||||
.append(FLD_VERSION)
|
||||
@@ -61,6 +80,55 @@ void create_user_challenge(std::string &msg, std::string &challengehex)
|
||||
.append("\"}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a status response message.
|
||||
* @param msg String reference to copy the generated json message string into.
|
||||
*/
|
||||
void create_status_response(std::string &msg)
|
||||
{
|
||||
msg.reserve(128);
|
||||
msg.append("{\"")
|
||||
.append(FLD_TYPE)
|
||||
.append(SEP_COLON)
|
||||
.append(MSGTYPE_STAT_RESP)
|
||||
.append(SEP_COMMA)
|
||||
.append(FLD_LCL)
|
||||
.append(SEP_COLON)
|
||||
.append(cons::ctx.lcl)
|
||||
.append(SEP_COMMA)
|
||||
.append(FLD_LCL_SEQ)
|
||||
.append(SEP_COLON_NOQUOTE)
|
||||
.append(std::to_string(cons::ctx.led_seq_no))
|
||||
.append("}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a contract output container message.
|
||||
* @param msg String reference to copy the generated json message string into.
|
||||
* @param content The contract output content to be put in the message.
|
||||
*/
|
||||
void create_contract_output_container(std::string &msg, std::string_view content)
|
||||
{
|
||||
msg.reserve(128);
|
||||
msg.append("{\"")
|
||||
.append(FLD_TYPE)
|
||||
.append(SEP_COLON)
|
||||
.append(MSGTYPE_CONTRACT_OUTPUT)
|
||||
.append(SEP_COMMA)
|
||||
.append(FLD_LCL)
|
||||
.append(SEP_COLON)
|
||||
.append(cons::ctx.lcl)
|
||||
.append(SEP_COMMA)
|
||||
.append(FLD_LCL_SEQ)
|
||||
.append(SEP_COLON_NOQUOTE)
|
||||
.append(std::to_string(cons::ctx.led_seq_no))
|
||||
.append(SEP_COMMA_NOQUOTE)
|
||||
.append(FLD_CONTENT)
|
||||
.append(SEP_COLON)
|
||||
.append(content)
|
||||
.append("\"}");
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies the user challenge response with the original challenge issued to the user
|
||||
* and the user public key contained in the response.
|
||||
@@ -69,8 +137,7 @@ void create_user_challenge(std::string &msg, std::string &challengehex)
|
||||
* @param response The response bytes to verify. This will be parsed as json.
|
||||
* Accepted response format:
|
||||
* {
|
||||
* "version": "<protocol version>"
|
||||
* "type": "challenge_response",
|
||||
* "type": "challenge_resp",
|
||||
* "challenge": "<original hex challenge the user received>",
|
||||
* "sig": "<hex signature of the challenge>",
|
||||
* "pubkey": "<hex public key of the user>"
|
||||
@@ -136,7 +203,6 @@ int verify_user_challenge_response(std::string &extracted_pubkeyhex, std::string
|
||||
* @param d The json document holding the input container.
|
||||
* Accepted signed input container format:
|
||||
* {
|
||||
* "version": "<protocol version>"
|
||||
* "type": "contract_input",
|
||||
* "content": "<hex encoded input container message>",
|
||||
* "sig": "<hex encoded signature of the content>"
|
||||
@@ -176,12 +242,12 @@ int extract_signed_input_container(
|
||||
* Extract the individual components of a given input container json.
|
||||
* @param nonce The extracted nonce.
|
||||
* @param input The extracted input.
|
||||
* @param max_ledger_seqno The extracted max ledger sequence no.
|
||||
* @param max_ledger_seqno Themaxledgerseqno extracted max ledger sequence no.
|
||||
* @param contentjson The json string containing the input container message.
|
||||
* {
|
||||
* "nonce": "<random string with optional sorted order>",
|
||||
* "input": "<hex encoded contract input content>",
|
||||
* "maxledgerseqno": 4562712334
|
||||
* "max_ledger_seqno": 4562712334
|
||||
* }
|
||||
* @return 0 on succesful extraction. -1 on failure.
|
||||
*/
|
||||
@@ -213,9 +279,9 @@ int extract_input_container(std::string &nonce, std::string &input, uint64_t &ma
|
||||
// Convert hex input to binary.
|
||||
input.resize(inputhex.length() / 2);
|
||||
if (util::hex2bin(
|
||||
reinterpret_cast<unsigned char *>(input.data()),
|
||||
input.length(),
|
||||
inputhex) != 0)
|
||||
reinterpret_cast<unsigned char *>(input.data()),
|
||||
input.length(),
|
||||
inputhex) != 0)
|
||||
{
|
||||
LOG_DBG << "Contract input format invalid.";
|
||||
return -1;
|
||||
@@ -231,6 +297,11 @@ int extract_input_container(std::string &nonce, std::string &input, uint64_t &ma
|
||||
* Parses a json message sent by a user.
|
||||
* @param d RapidJson 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(rapidjson::Document &d, std::string_view message)
|
||||
@@ -245,13 +316,6 @@ int parse_user_message(rapidjson::Document &d, std::string_view message)
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check existence of msg type field.
|
||||
if (!d.HasMember(FLD_VERSION) || !d[FLD_VERSION].IsString())
|
||||
{
|
||||
LOG_DBG << "User json message 'version' missing or invalid.";
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Check existence of msg type field.
|
||||
if (!d.HasMember(FLD_TYPE) || !d[FLD_TYPE].IsString())
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user