Event subscription infrastructure and ledger events. (#319)

- Introduced event subscription infrastructure for users.
- Added ability to subscribe to ledger events.
- Updated client lib for event subscription support.
This commit is contained in:
Ravin Perera
2021-06-07 10:24:58 +05:30
committed by GitHub
parent a7b7f6c9de
commit cc11ebd7b3
16 changed files with 599 additions and 152 deletions

View File

@@ -151,10 +151,9 @@ namespace msg::usrmsg::json
{
const util::sequence_hash lcl_id = status::get_lcl_id();
const std::set<std::string> unl = status::get_unl();
const bool in_sync = status::is_in_sync();
const uint16_t msg_length = 406 + (69 * unl.size());
msg.reserve(msg_length);
msg.reserve(1024);
msg += "{\"";
msg += msg::usrmsg::FLD_TYPE;
msg += SEP_COLON;
@@ -172,21 +171,25 @@ namespace msg::usrmsg::json
msg += SEP_COLON;
msg += util::to_hex(lcl_id.hash.to_string_view());
msg += SEP_COMMA;
msg += msg::usrmsg::FLD_IN_SYNC;
msg += SEP_COLON_NOQUOTE;
msg += in_sync ? STR_TRUE : STR_FALSE;
msg += SEP_COMMA_NOQUOTE;
msg += msg::usrmsg::FLD_ROUND_TIME;
msg += SEP_COLON_NOQUOTE;
msg += std::to_string(conf::cfg.contract.roundtime);
msg += SEP_COMMA_NOQUOTE;
msg += msg::usrmsg::FLD_CONTARCT_EXECUTION_ENABLED;
msg += SEP_COLON_NOQUOTE;
msg += conf::cfg.contract.execute ? "true" : "false";
msg += conf::cfg.contract.execute ? STR_TRUE : STR_FALSE;
msg += SEP_COMMA_NOQUOTE;
msg += msg::usrmsg::FLD_READ_REQUESTS_ENABLED;
msg += SEP_COLON_NOQUOTE;
msg += conf::cfg.user.concurrent_read_reqeuests != 0 ? "true" : "false";
msg += conf::cfg.user.concurrent_read_reqeuests != 0 ? STR_TRUE : STR_FALSE;
msg += SEP_COMMA_NOQUOTE;
msg += msg::usrmsg::FLD_IS_FULL_HISTORY_NODE;
msg += SEP_COLON_NOQUOTE;
msg += conf::cfg.node.history == conf::HISTORY::FULL ? "true" : "false";
msg += conf::cfg.node.history == conf::HISTORY::FULL ? STR_TRUE : STR_FALSE;
msg += SEP_COMMA_NOQUOTE;
msg += msg::usrmsg::FLD_CURRENT_UNL;
msg += SEP_COLON_NOQUOTE;
@@ -451,7 +454,7 @@ namespace msg::usrmsg::json
}
/**
* Constructs unl list container message.
* Constructs unl change notification message.
* @param msg Buffer to construct the generated json message string into.
* Message format:
* {
@@ -460,7 +463,7 @@ namespace msg::usrmsg::json
* }
* @param unl_list The unl node pubkey list to be put in the message.
*/
void create_unl_list_container(std::vector<uint8_t> &msg, const ::std::set<std::string> &unl_list)
void create_unl_notification(std::vector<uint8_t> &msg, const ::std::set<std::string> &unl_list)
{
msg.reserve((69 * unl_list.size()) + 30);
msg += "{\"";
@@ -485,6 +488,64 @@ namespace msg::usrmsg::json
msg += "]}";
}
/**
* Constructs ledger created notification message.
* @param msg Buffer to construct the generated json message string into.
* Message format:
* {
* "type": "ledger_event",
* "event": "ledger_created",
* "ledger": { ... }
* }
* @param ledger The created ledger.
*/
void create_ledger_created_notification(std::vector<uint8_t> &msg, const ledger::ledger_record &ledger)
{
msg.reserve(1024);
msg += "{\"";
msg += msg::usrmsg::FLD_TYPE;
msg += SEP_COLON;
msg += msg::usrmsg::MSGTYPE_LEDGER_EVENT;
msg += SEP_COMMA;
msg += msg::usrmsg::FLD_EVENT;
msg += SEP_COLON;
msg += msg::usrmsg::LEDGER_EVENT_LEDGER_CREATED;
msg += SEP_COMMA;
msg += msg::usrmsg::FLD_LEDGER;
msg += "\":{";
populate_ledger_fields(msg, ledger);
msg += "}}";
}
/**
* Constructs sync status notification message.
* @param msg Buffer to construct the generated json message string into.
* Message format:
* {
* "type": "ledger_event",
* "event": "sync_status",
* "in_sync": true | false
* }
* @param in_sync Whether the node is in sync or not.
*/
void create_sync_status_notification(std::vector<uint8_t> &msg, const bool in_sync)
{
msg.reserve(128);
msg += "{\"";
msg += msg::usrmsg::FLD_TYPE;
msg += SEP_COLON;
msg += msg::usrmsg::MSGTYPE_LEDGER_EVENT;
msg += SEP_COMMA;
msg += msg::usrmsg::FLD_EVENT;
msg += SEP_COLON;
msg += msg::usrmsg::LEDGER_EVENT_SYNC_STATUS;
msg += SEP_COMMA;
msg += msg::usrmsg::FLD_IN_SYNC;
msg += SEP_COLON_NOQUOTE;
msg += in_sync ? STR_TRUE : STR_FALSE;
msg += "}";
}
/**
* Constructs a ledger query response.
* @param msg Buffer to construct the generated json message string into.
@@ -796,6 +857,51 @@ namespace msg::usrmsg::json
return 0;
}
/**
* Extract ledger event subscription request.
* @param channel Extracted subscription channel.
* @param enabled Whether the subscription is enabled or not.
* @param d The json document holding the subscription request.
* Accepted message format:
* {
* "type": "subscription",
* "channel": "unl_change" | "ledger_event",
* "enabled": true | false
* }
* @return 0 on successful extraction. -1 for failure.
*/
int extract_subscription_request(usr::NOTIFICATION_CHANNEL &channel, bool &enabled, const jsoncons::json &d)
{
if (!d.contains(msg::usrmsg::FLD_CHANNEL) || !d.contains(msg::usrmsg::FLD_ENABLED))
{
LOG_DEBUG << "User subscription request required fields missing.";
return -1;
}
if (!d[msg::usrmsg::FLD_CHANNEL].is<std::string>() || !d[msg::usrmsg::FLD_ENABLED].is<bool>())
{
LOG_DEBUG << "User subscription request invalid field values.";
return -1;
}
if (d[msg::usrmsg::FLD_CHANNEL] == msg::usrmsg::MSGTYPE_LEDGER_EVENT)
{
channel = usr::NOTIFICATION_CHANNEL::LEDGER_EVENT;
}
else if (d[msg::usrmsg::FLD_CHANNEL] == msg::usrmsg::MSGTYPE_UNL_CHANGE)
{
channel = usr::NOTIFICATION_CHANNEL::UNL_CHANGE;
}
else
{
LOG_DEBUG << "User subscription request invalid channel.";
return -1;
}
enabled = d[msg::usrmsg::FLD_ENABLED].as<bool>();
return 0;
}
/**
* Extract query information from a ledger query request.
* @param extracted_query Extracted query criteria.
@@ -880,7 +986,7 @@ namespace msg::usrmsg::json
if ((first == '\"' && last == '\"') ||
(first == '{' && last == '}') ||
(first == '[' && last == ']') ||
content == "true" || content == "false")
content == STR_TRUE || content == STR_FALSE)
return false;
// Check whether all characters are digits.
@@ -933,43 +1039,8 @@ namespace msg::usrmsg::json
{
const ledger::ledger_record &ledger = results[i];
msg += "{\"";
msg += msg::usrmsg::FLD_SEQ_NO;
msg += SEP_COLON_NOQUOTE;
msg += std::to_string(ledger.seq_no);
msg += SEP_COMMA_NOQUOTE;
msg += msg::usrmsg::FLD_TIMESTAMP;
msg += SEP_COLON_NOQUOTE;
msg += std::to_string(ledger.timestamp);
msg += SEP_COMMA_NOQUOTE;
msg += msg::usrmsg::FLD_HASH;
msg += SEP_COLON;
msg += util::to_hex(ledger.ledger_hash);
msg += SEP_COMMA;
msg += msg::usrmsg::FLD_PREV_HASH;
msg += SEP_COLON;
msg += util::to_hex(ledger.prev_ledger_hash);
msg += SEP_COMMA;
msg += msg::usrmsg::FLD_STATE_HASH;
msg += SEP_COLON;
msg += util::to_hex(ledger.state_hash);
msg += SEP_COMMA;
msg += msg::usrmsg::FLD_CONFIG_HASH;
msg += SEP_COLON;
msg += util::to_hex(ledger.config_hash);
msg += SEP_COMMA;
msg += msg::usrmsg::FLD_USER_HASH;
msg += SEP_COLON;
msg += util::to_hex(ledger.user_hash);
msg += SEP_COMMA;
msg += msg::usrmsg::FLD_INPUT_HASH;
msg += SEP_COLON;
msg += util::to_hex(ledger.input_hash);
msg += SEP_COMMA;
msg += msg::usrmsg::FLD_OUTPUT_HASH;
msg += SEP_COLON;
msg += util::to_hex(ledger.output_hash);
msg += "\"";
msg += "{";
populate_ledger_fields(msg, ledger);
// If raw inputs or outputs is not requested, we don't include that field at all in the response.
// Otherwise the field will always contain an array (empty array if no data).
@@ -994,6 +1065,47 @@ namespace msg::usrmsg::json
}
}
void populate_ledger_fields(std::vector<uint8_t> &msg, const ledger::ledger_record &ledger)
{
msg += "\"";
msg += msg::usrmsg::FLD_SEQ_NO;
msg += SEP_COLON_NOQUOTE;
msg += std::to_string(ledger.seq_no);
msg += SEP_COMMA_NOQUOTE;
msg += msg::usrmsg::FLD_TIMESTAMP;
msg += SEP_COLON_NOQUOTE;
msg += std::to_string(ledger.timestamp);
msg += SEP_COMMA_NOQUOTE;
msg += msg::usrmsg::FLD_HASH;
msg += SEP_COLON;
msg += util::to_hex(ledger.ledger_hash);
msg += SEP_COMMA;
msg += msg::usrmsg::FLD_PREV_HASH;
msg += SEP_COLON;
msg += util::to_hex(ledger.prev_ledger_hash);
msg += SEP_COMMA;
msg += msg::usrmsg::FLD_STATE_HASH;
msg += SEP_COLON;
msg += util::to_hex(ledger.state_hash);
msg += SEP_COMMA;
msg += msg::usrmsg::FLD_CONFIG_HASH;
msg += SEP_COLON;
msg += util::to_hex(ledger.config_hash);
msg += SEP_COMMA;
msg += msg::usrmsg::FLD_USER_HASH;
msg += SEP_COLON;
msg += util::to_hex(ledger.user_hash);
msg += SEP_COMMA;
msg += msg::usrmsg::FLD_INPUT_HASH;
msg += SEP_COLON;
msg += util::to_hex(ledger.input_hash);
msg += SEP_COMMA;
msg += msg::usrmsg::FLD_OUTPUT_HASH;
msg += SEP_COLON;
msg += util::to_hex(ledger.output_hash);
msg += "\"";
}
void populate_ledger_inputs(std::vector<uint8_t> &msg, const std::vector<ledger::ledger_user_input> &inputs)
{
msg += "[";