diff --git a/nano/core_test/rpc.cpp b/nano/core_test/rpc.cpp index c03b215d..f8775963 100644 --- a/nano/core_test/rpc.cpp +++ b/nano/core_test/rpc.cpp @@ -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); diff --git a/nano/lib/blocks.cpp b/nano/lib/blocks.cpp index 51f034a0..a1958ba6 100644 --- a/nano/lib/blocks.cpp +++ b/nano/lib/blocks.cpp @@ -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) diff --git a/nano/lib/blocks.hpp b/nano/lib/blocks.hpp index 759f0ba2..eb4f9b95 100644 --- a/nano/lib/blocks.hpp +++ b/nano/lib/blocks.hpp @@ -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; diff --git a/nano/node/rpc.cpp b/nano/node/rpc.cpp index a98651ab..2cd64b0e 100644 --- a/nano/node/rpc.cpp +++ b/nano/node/rpc.cpp @@ -820,9 +820,20 @@ void nano::rpc_handler::block_info () response_l.put ("balance", balance.convert_to ()); 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 ("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 ("pending", false); const bool source = request.get ("source", false); + const bool json_block_l = request.get ("json_block", false); + std::vector 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 ()); 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 ("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 ("representatives", false); const bool contents = request.get ("contents", true); + const bool json_block_l = request.get ("json_block", false); std::string root_text (request.get ("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 ("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 ("json_block", false); auto count (count_optional_impl ()); nano::uint256_union key (0); boost::optional hash_text (request.get_optional ("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);