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:
		
					parent
					
						
							
								c926f0a6e0
							
						
					
				
			
			
				commit
				
					
						62914cc9e8
					
				
			
		
					 4 changed files with 159 additions and 33 deletions
				
			
		| 
						 | 
				
			
			@ -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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -820,10 +820,21 @@ 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));
 | 
			
		||||
 | 
			
		||||
			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
 | 
			
		||||
		{
 | 
			
		||||
			ec = nano::error_blocks::not_found;
 | 
			
		||||
| 
						 | 
				
			
			@ -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));
 | 
			
		||||
 | 
			
		||||
					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,10 +1188,20 @@ 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 ());
 | 
			
		||||
					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
 | 
			
		||||
				{
 | 
			
		||||
					ec = nano::error_rpc::block_create_requirements_state;
 | 
			
		||||
| 
						 | 
				
			
			@ -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))
 | 
			
		||||
| 
						 | 
				
			
			@ -1499,11 +1534,20 @@ void nano::rpc_handler::confirmation_info ()
 | 
			
		|||
				entry.put ("tally", tally.convert_to<std::string> ());
 | 
			
		||||
				total += tally;
 | 
			
		||||
				if (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)
 | 
			
		||||
				{
 | 
			
		||||
					std::multimap<nano::uint128_t, nano::account, std::greater<nano::uint128_t>> 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));
 | 
			
		||||
 | 
			
		||||
				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));
 | 
			
		||||
			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);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue