RPC: option to render block as JSON (#1740)

* Option to render block as JSON in create_block

* Better local var name

* Add ptree serialization to all block types, support flag in block_info

* Add flag to other RPC's doing stringified blocks

* Add test for the json_block option
This commit is contained in:
cryptocode 2019-02-24 00:38:32 +01:00 committed by GitHub
commit 62914cc9e8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 159 additions and 33 deletions

View file

@ -3411,6 +3411,36 @@ TEST (rpc, account_info)
ASSERT_EQ (nano::test_genesis_key.pub.to_account (), representative2);
}
TEST (rpc, json_block)
{
nano::system system (24000, 1);
nano::keypair key;
system.wallet (0)->insert_adhoc (nano::test_genesis_key.prv);
system.wallet (0)->insert_adhoc (key.prv);
auto & node1 (*system.nodes[0]);
auto latest (system.nodes[0]->latest (nano::test_genesis_key.pub));
nano::send_block send (latest, key.pub, 100, nano::test_genesis_key.prv, nano::test_genesis_key.pub, node1.work_generate_blocking (latest));
system.nodes[0]->process (send);
nano::rpc rpc (system.io_ctx, *system.nodes[0], nano::rpc_config (true));
rpc.start ();
boost::property_tree::ptree request;
request.put ("action", "block_info");
request.put ("json_block", "true");
request.put ("hash", send.hash ().to_string ());
test_response response (request, rpc, system.io_ctx);
system.deadline_set (5s);
while (response.status == 0)
{
ASSERT_NO_ERROR (system.poll ());
}
ASSERT_EQ (200, response.status);
// Make sure contents contains a valid JSON subtree instread of stringified json
bool json_error{ false };
nano::send_block send_from_json (json_error, response.json.get_child ("contents"));
ASSERT_FALSE (json_error);
}
TEST (rpc, blocks_info)
{
nano::system system (24000, 1);

View file

@ -240,6 +240,14 @@ bool nano::send_block::deserialize (nano::stream & stream_a)
void nano::send_block::serialize_json (std::string & string_a) const
{
boost::property_tree::ptree tree;
serialize_json (tree);
std::stringstream ostream;
boost::property_tree::write_json (ostream, tree);
string_a = ostream.str ();
}
void nano::send_block::serialize_json (boost::property_tree::ptree & tree) const
{
tree.put ("type", "send");
std::string previous;
hashables.previous.encode_hex (previous);
@ -252,9 +260,6 @@ void nano::send_block::serialize_json (std::string & string_a) const
signature.encode_hex (signature_l);
tree.put ("work", nano::to_string_hex (work));
tree.put ("signature", signature_l);
std::stringstream ostream;
boost::property_tree::write_json (ostream, tree);
string_a = ostream.str ();
}
bool nano::send_block::deserialize_json (boost::property_tree::ptree const & tree_a)
@ -555,6 +560,14 @@ bool nano::open_block::deserialize (nano::stream & stream_a)
void nano::open_block::serialize_json (std::string & string_a) const
{
boost::property_tree::ptree tree;
serialize_json (tree);
std::stringstream ostream;
boost::property_tree::write_json (ostream, tree);
string_a = ostream.str ();
}
void nano::open_block::serialize_json (boost::property_tree::ptree & tree) const
{
tree.put ("type", "open");
tree.put ("source", hashables.source.to_string ());
tree.put ("representative", representative ().to_account ());
@ -563,9 +576,6 @@ void nano::open_block::serialize_json (std::string & string_a) const
signature.encode_hex (signature_l);
tree.put ("work", nano::to_string_hex (work));
tree.put ("signature", signature_l);
std::stringstream ostream;
boost::property_tree::write_json (ostream, tree);
string_a = ostream.str ();
}
bool nano::open_block::deserialize_json (boost::property_tree::ptree const & tree_a)
@ -792,6 +802,14 @@ bool nano::change_block::deserialize (nano::stream & stream_a)
void nano::change_block::serialize_json (std::string & string_a) const
{
boost::property_tree::ptree tree;
serialize_json (tree);
std::stringstream ostream;
boost::property_tree::write_json (ostream, tree);
string_a = ostream.str ();
}
void nano::change_block::serialize_json (boost::property_tree::ptree & tree) const
{
tree.put ("type", "change");
tree.put ("previous", hashables.previous.to_string ());
tree.put ("representative", representative ().to_account ());
@ -799,9 +817,6 @@ void nano::change_block::serialize_json (std::string & string_a) const
std::string signature_l;
signature.encode_hex (signature_l);
tree.put ("signature", signature_l);
std::stringstream ostream;
boost::property_tree::write_json (ostream, tree);
string_a = ostream.str ();
}
bool nano::change_block::deserialize_json (boost::property_tree::ptree const & tree_a)
@ -1075,6 +1090,14 @@ bool nano::state_block::deserialize (nano::stream & stream_a)
void nano::state_block::serialize_json (std::string & string_a) const
{
boost::property_tree::ptree tree;
serialize_json (tree);
std::stringstream ostream;
boost::property_tree::write_json (ostream, tree);
string_a = ostream.str ();
}
void nano::state_block::serialize_json (boost::property_tree::ptree & tree) const
{
tree.put ("type", "state");
tree.put ("account", hashables.account.to_account ());
tree.put ("previous", hashables.previous.to_string ());
@ -1086,9 +1109,6 @@ void nano::state_block::serialize_json (std::string & string_a) const
signature.encode_hex (signature_l);
tree.put ("signature", signature_l);
tree.put ("work", nano::to_string_hex (work));
std::stringstream ostream;
boost::property_tree::write_json (ostream, tree);
string_a = ostream.str ();
}
bool nano::state_block::deserialize_json (boost::property_tree::ptree const & tree_a)
@ -1367,6 +1387,14 @@ bool nano::receive_block::deserialize (nano::stream & stream_a)
void nano::receive_block::serialize_json (std::string & string_a) const
{
boost::property_tree::ptree tree;
serialize_json (tree);
std::stringstream ostream;
boost::property_tree::write_json (ostream, tree);
string_a = ostream.str ();
}
void nano::receive_block::serialize_json (boost::property_tree::ptree & tree) const
{
tree.put ("type", "receive");
std::string previous;
hashables.previous.encode_hex (previous);
@ -1378,9 +1406,6 @@ void nano::receive_block::serialize_json (std::string & string_a) const
signature.encode_hex (signature_l);
tree.put ("work", nano::to_string_hex (work));
tree.put ("signature", signature_l);
std::stringstream ostream;
boost::property_tree::write_json (ostream, tree);
string_a = ostream.str ();
}
bool nano::receive_block::deserialize_json (boost::property_tree::ptree const & tree_a)

View file

@ -76,6 +76,7 @@ public:
virtual nano::account representative () const;
virtual void serialize (nano::stream &) const = 0;
virtual void serialize_json (std::string &) const = 0;
virtual void serialize_json (boost::property_tree::ptree &) const = 0;
virtual void visit (nano::block_visitor &) const = 0;
virtual bool operator== (nano::block const &) const = 0;
virtual nano::block_type type () const = 0;
@ -115,6 +116,7 @@ public:
void serialize (nano::stream &) const override;
bool deserialize (nano::stream &);
void serialize_json (std::string &) const override;
void serialize_json (boost::property_tree::ptree &) const override;
bool deserialize_json (boost::property_tree::ptree const &);
void visit (nano::block_visitor &) const override;
nano::block_type type () const override;
@ -158,6 +160,7 @@ public:
void serialize (nano::stream &) const override;
bool deserialize (nano::stream &);
void serialize_json (std::string &) const override;
void serialize_json (boost::property_tree::ptree &) const override;
bool deserialize_json (boost::property_tree::ptree const &);
void visit (nano::block_visitor &) const override;
nano::block_type type () const override;
@ -205,6 +208,7 @@ public:
void serialize (nano::stream &) const override;
bool deserialize (nano::stream &);
void serialize_json (std::string &) const override;
void serialize_json (boost::property_tree::ptree &) const override;
bool deserialize_json (boost::property_tree::ptree const &);
void visit (nano::block_visitor &) const override;
nano::block_type type () const override;
@ -248,6 +252,7 @@ public:
void serialize (nano::stream &) const override;
bool deserialize (nano::stream &);
void serialize_json (std::string &) const override;
void serialize_json (boost::property_tree::ptree &) const override;
bool deserialize_json (boost::property_tree::ptree const &);
void visit (nano::block_visitor &) const override;
nano::block_type type () const override;
@ -306,6 +311,7 @@ public:
void serialize (nano::stream &) const override;
bool deserialize (nano::stream &);
void serialize_json (std::string &) const override;
void serialize_json (boost::property_tree::ptree &) const override;
bool deserialize_json (boost::property_tree::ptree const &);
void visit (nano::block_visitor &) const override;
nano::block_type type () const override;

View file

@ -820,9 +820,20 @@ void nano::rpc_handler::block_info ()
response_l.put ("balance", balance.convert_to<std::string> ());
response_l.put ("height", std::to_string (sideband.height));
response_l.put ("local_timestamp", std::to_string (sideband.timestamp));
std::string contents;
block->serialize_json (contents);
response_l.put ("contents", contents);
bool json_block_l = request.get<bool> ("json_block", false);
if (json_block_l)
{
boost::property_tree::ptree block_node_l;
block->serialize_json (block_node_l);
response_l.add_child ("contents", block_node_l);
}
else
{
std::string contents;
block->serialize_json (contents);
response_l.put ("contents", contents);
}
}
else
{
@ -891,6 +902,8 @@ void nano::rpc_handler::blocks_info ()
{
const bool pending = request.get<bool> ("pending", false);
const bool source = request.get<bool> ("source", false);
const bool json_block_l = request.get<bool> ("json_block", false);
std::vector<std::string> hashes;
boost::property_tree::ptree blocks;
auto transaction (node.store.tx_begin_read ());
@ -915,9 +928,20 @@ void nano::rpc_handler::blocks_info ()
entry.put ("balance", balance.convert_to<std::string> ());
entry.put ("height", std::to_string (sideband.height));
entry.put ("local_timestamp", std::to_string (sideband.timestamp));
std::string contents;
block->serialize_json (contents);
entry.put ("contents", contents);
if (json_block_l)
{
boost::property_tree::ptree block_node_l;
block->serialize_json (block_node_l);
entry.add_child ("contents", block_node_l);
}
else
{
std::string contents;
block->serialize_json (contents);
entry.put ("contents", contents);
}
if (pending)
{
bool exists (false);
@ -1164,9 +1188,19 @@ void nano::rpc_handler::block_create ()
}
nano::state_block state (pub, previous, representative, balance, link, prv, pub, work);
response_l.put ("hash", state.hash ().to_string ());
std::string contents;
state.serialize_json (contents);
response_l.put ("block", contents);
bool json_block_l = request.get<bool> ("json_block", false);
if (json_block_l)
{
boost::property_tree::ptree block_node_l;
state.serialize_json (block_node_l);
response_l.add_child ("block", block_node_l);
}
else
{
std::string contents;
state.serialize_json (contents);
response_l.put ("block", contents);
}
}
else
{
@ -1477,6 +1511,7 @@ void nano::rpc_handler::confirmation_info ()
{
const bool representatives = request.get<bool> ("representatives", false);
const bool contents = request.get<bool> ("contents", true);
const bool json_block_l = request.get<bool> ("json_block", false);
std::string root_text (request.get<std::string> ("root"));
nano::uint512_union root;
if (!root.decode_hex (root_text))
@ -1500,9 +1535,18 @@ void nano::rpc_handler::confirmation_info ()
total += tally;
if (contents)
{
std::string contents;
i->second->serialize_json (contents);
entry.put ("contents", contents);
if (json_block_l)
{
boost::property_tree::ptree block_node_l;
i->second->serialize_json (block_node_l);
entry.add_child ("contents", block_node_l);
}
else
{
std::string contents;
i->second->serialize_json (contents);
entry.put ("contents", contents);
}
}
if (representatives)
{
@ -3185,6 +3229,7 @@ void nano::rpc_handler::unchecked_clear ()
void nano::rpc_handler::unchecked_get ()
{
const bool json_block_l = request.get<bool> ("json_block", false);
auto hash (hash_impl ());
if (!ec)
{
@ -3196,9 +3241,19 @@ void nano::rpc_handler::unchecked_get ()
{
nano::unchecked_info info (i->second);
response_l.put ("modified_timestamp", std::to_string (info.modified));
std::string contents;
info.block->serialize_json (contents);
response_l.put ("contents", contents);
if (json_block_l)
{
boost::property_tree::ptree block_node_l;
info.block->serialize_json (block_node_l);
response_l.add_child ("contents", block_node_l);
}
else
{
std::string contents;
info.block->serialize_json (contents);
response_l.put ("contents", contents);
}
break;
}
}
@ -3212,6 +3267,7 @@ void nano::rpc_handler::unchecked_get ()
void nano::rpc_handler::unchecked_keys ()
{
const bool json_block_l = request.get<bool> ("json_block", false);
auto count (count_optional_impl ());
nano::uint256_union key (0);
boost::optional<std::string> hash_text (request.get_optional<std::string> ("key"));
@ -3230,12 +3286,21 @@ void nano::rpc_handler::unchecked_keys ()
{
boost::property_tree::ptree entry;
nano::unchecked_info info (i->second);
std::string contents;
info.block->serialize_json (contents);
entry.put ("key", nano::block_hash (i->first.key ()).to_string ());
entry.put ("hash", info.block->hash ().to_string ());
entry.put ("modified_timestamp", std::to_string (info.modified));
entry.put ("contents", contents);
if (json_block_l)
{
boost::property_tree::ptree block_node_l;
info.block->serialize_json (block_node_l);
entry.add_child ("contents", block_node_l);
}
else
{
std::string contents;
info.block->serialize_json (contents);
entry.put ("contents", contents);
}
unchecked.push_back (std::make_pair ("", entry));
}
response_l.add_child ("unchecked", unchecked);