User control messages. (#56)

This commit is contained in:
Ravin Perera
2019-11-11 15:06:25 +05:30
committed by GitHub
parent 403f2e1b21
commit 39031c3157
10 changed files with 155 additions and 72 deletions

View File

@@ -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())
{