- 
                Notifications
    
You must be signed in to change notification settings  - Fork 170
 
Design of RPC API methods
============================
The RPC API is defined by a set of JSON files in libraries/api
blockchain_api.jsonwallet_api.jsonnetwork_api.json
These files describe each RPC method, providing enough information to generate help, the C++ method signature, a C++ RPC client, and a C++ RPC server.
From those files, it generates:
- 
bts/api/common_api.hpp: the pure virtual interface listing each of the methods listed in the JSON files. - 
bts/rpc_stubs/common_api_client.hppandbts/rpc_stubs/common_api_client.hpp: a C++ implementation of the client-side RPC API. This code implements the common_api interface for talking to an out-of-process bitshares_client. This code is used bybts::rpc::rpc_client, which derives from the client stub class and adds a few functions to establish the RPC network connection. - 
bts/rpc_stubs/common_api_server.hppandbts/rpc_stubs/common_api_server.hpp: implements the server side of the RPC interface. The generated code takes care of converting the method arguments from JSON to the native C++ types, validating the parameters, dispatching to native method inbts::client::client, and then converting the result back to JSON. This code is used bybts::rpc::rpc_server, which derives from the server stub class and adds methods to accept RPC and HTTP-RPC connections. 
To add a new function to the JSON-RPC API.  I'll walk through the call I'm working on now,
network_set_allowed_peers.  The logic is already implemented in bts::net::node as
void set_allowed_peers(const std::vector<node_id_t>& allowed_peers).
- Implement the C++ call in 
bts::client::client. All RPC methods must be implemented in client with the same name as they have in JSON-RPC, so this method will add thenetwork_prefix and delegate the call to the node. You only need to add the implementation in the .cpp file. The method prototype in the header will be generated from the JSON. 
void client::network_set_allowed_peers(const std::vector<bts::net::node_id_t>& allowed_peers)
{
  my->_p2p_node->set_allowed_peers(allowed_peers);
}
- Add the function to the appropriate JSON file.  Since this is a network function, it goes
in 
network_api.json. Down in themethodssection, add a method description: 
{
  "method_name": "network_set_allowed_peers",
  "description": "Sets the list of peers this node is allowed to connect to",
  "return_type": "void",
  "parameters" :
    [
      {
        "name" : "allowed_peers",
        "type" : "node_id_list",
        "description" : "the list of allowable peers"
      }
    ],
  "prerequisites" : ["json_authenticated"],
  "detailed_description" : "This function sets the list of peers we're allowed to connect to. It is used during testing to force network splits or other weird topologies."
}
Some notes on the method description:
- 
descriptionshould be a short one-liner,detailed_description(if present) should be a longer description that will be appended to the shortdescriptionwhen we generate long-form help messages. - types like 
return_typeand thetypefield for each parameter can be one of the predefined types the generator knows about, or one of the types defined in thetypessection of the json file. The default types are:- 
void(only used for return values, a method that takes no parameters just has an empty parameter list) int16_tuint16_tint32_tuint32_tint64_tuint64_tstd::string- 
json_variant, which maps tofc::variant - 
json_object, which maps tofc::variant_object - 
json_variant_list, which maps tofc::variants - 
json_object_list, which maps tostd::vector<fc::variant_object> 
 - 
 - 
prerequisitescan be a list containing one or more of:"no_prerequisites""json_authenticated"- 
"wallet_open"(implies"json_authenticated") - 
"wallet_unlocked"(implies"wallet_open") "connected_to_network"
 - Since this is the first method to need the type 
node_id_list, we need to define it. In C++, it's a vector ofbts::net::node_id_t, and we don't know anything about those either. So first, let's define anode_idtype to the JSON generator. 
{
  "type_name" : "node_id",
  "cpp_parameter_type" : "const bts::net::node_id_t&",
  "cpp_return_type" : "bts::net::node_id_t",
  "cpp_include_file" : "bts/net/node.hpp",
  "default_example" : "TODO"
}
 A few notes on this:
 - the `type_name` should be something that makes sense to display in our API help.  So prefer
   names like `node_id_list` to `std::vector<bts::net::node_id_t>`.
 - `cpp_parameter_type` is how objects of this type are passed as a parameter to functions.
   usually this is by const reference to larger objects, or by value for integer types.
 - `cpp_return_type` is the type as it appers as a return value, or for instantiating on
   the stack.  Usually just the type name.
 - `cpp_include_file` - if you provide this, it will make sure this file is included in any
   generated files that reference this type.
 - `default_example` is an object of that type, in JSON form, that will be used in generating
   example calls in the documentation.
 Now that the base type is defined, I need to define what a list of that type looks like:
{
  "type_name" : "node_id_list",
  "container_type" : "array",
  "contained_type" : "node_id",
  "default_example" : "TODO"
}
A few notes on this:
- container_type can be "array" or "dictionary".
- array maps to std::vector and requires a contained_type
- dictionary maps to std::map, and requires a key_type and value_type
2. Build.
The command line interface (CLI) will automatically prompt for missing required parameters. For example, if the user types the command "unlock", the CLI will prompt the user to enter the required parameters "timeout" and "passphrase". A CLI command can be aborted during prompted entry by pressing without entering any data.
Currently the command-line interface recoognizes these special types when prompting for parameters:
- passphrase: this type should be used for any password that shouldn't be echoed to the console during prompted entry.
 - new_passphrase: this type should be used for any command that requires the user to specify a "new" password. In this case, the CLI will not echo the password AND it will prompt for the password twice to verify it's accurate entry.