diff --git a/README.md b/README.md index 2b1fed10..0fa53eb2 100644 --- a/README.md +++ b/README.md @@ -119,7 +119,8 @@ Accessing restricted API's -------------------------- You can restrict API's to particular users by specifying an `apiaccess` file in `config.ini`. Here is an example `apiaccess` file which allows -user `bytemaster` with password `supersecret` to access four different API's: +user `bytemaster` with password `supersecret` to access four different API's, while allowing any other user to access the three public API's +necessary to use the wallet: { "permission_map" : @@ -131,6 +132,14 @@ user `bytemaster` with password `supersecret` to access four different API's: "password_salt_b64" : "INDdM6iCi/8=", "allowed_apis" : ["database_api", "network_broadcast_api", "history_api", "network_node_api"] } + ], + [ + "*", + { + "password_hash_b64" : "*", + "password_salt_b64" : "*", + "allowed_apis" : ["database_api", "network_broadcast_api", "history_api"] + } ] ] } @@ -237,3 +246,16 @@ Questions The first and second number together identify the kind of thing you're talking about (`1.2` for accounts, `1.3` for assets). The third number identifies the particular thing. + +- How do I get the `network_add_nodes` command to work? Why is it so complicated? + + You need to follow the instructions in the "Accessing restricted API's" section to + allow a username/password access to the `network_node` API. Then you need + to pass the username/password to the `cli_wallet` on the command line or in a config file. + + It's set up this way so that the default configuration is secure even if the RPC port is + publicly accessible. It's fine if your `witness_node` allows the general public to query + the database or broadcast transactions (in fact, this is how the hosted web UI works). It's + less fine if your `witness_node` allows the general public to control which p2p nodes it's + connecting to. Therefore the API to add p2p connections needs to be set up with proper access + controls. diff --git a/libraries/app/application.cpp b/libraries/app/application.cpp index cf88be5a..70b2899a 100644 --- a/libraries/app/application.cpp +++ b/libraries/app/application.cpp @@ -286,8 +286,8 @@ namespace detail { graphene::time::now(); - if( _options->count("apiaccess") ) - _apiaccess = fc::json::from_file( _options->at("apiaccess").as() ) + if( _options->count("api-access") ) + _apiaccess = fc::json::from_file( _options->at("api-access").as() ) .as(); else { diff --git a/libraries/app/include/graphene/app/api.hpp b/libraries/app/include/graphene/app/api.hpp index 649eea3f..5bb36f65 100644 --- a/libraries/app/include/graphene/app/api.hpp +++ b/libraries/app/include/graphene/app/api.hpp @@ -480,12 +480,6 @@ namespace graphene { namespace app { /** * @brief Get status of all current connections to peers - * @brief Not reflected, thus not accessible to API clients. - * - * This function is registered to receive the applied_block - * signal from the chain database when a block is received. - * It then dispatches callbacks to clients who have requested - * to be notified when a particular txid is included in a block. */ std::vector get_connected_peers() const; diff --git a/libraries/net/include/graphene/net/config.hpp b/libraries/net/include/graphene/net/config.hpp index 3242658c..5273be0f 100644 --- a/libraries/net/include/graphene/net/config.hpp +++ b/libraries/net/include/graphene/net/config.hpp @@ -51,6 +51,14 @@ #define GRAPHENE_NET_MAXIMUM_QUEUED_MESSAGES_IN_BYTES (1024 * 1024) +/** + * When we receive a message from the network, we advertise it to + * our peers and save a copy in a cache were we will find it if + * a peer requests it. We expire out old items out of the cache + * after this number of blocks go by. + */ +#define GRAPHENE_NET_MESSAGE_CACHE_DURATION_IN_BLOCKS 30 + /** * We prevent a peer from offering us a list of blocks which, if we fetched them * all, would result in a blockchain that extended into the future. diff --git a/libraries/net/node.cpp b/libraries/net/node.cpp index 103eb54d..55005b86 100644 --- a/libraries/net/node.cpp +++ b/libraries/net/node.cpp @@ -120,7 +120,7 @@ namespace graphene { namespace net { class blockchain_tied_message_cache { private: - static const uint32_t cache_duration_in_blocks = 2; + static const uint32_t cache_duration_in_blocks = GRAPHENE_NET_MESSAGE_CACHE_DURATION_IN_BLOCKS; struct message_hash_index{}; struct message_contents_hash_index{}; diff --git a/libraries/wallet/include/graphene/wallet/wallet.hpp b/libraries/wallet/include/graphene/wallet/wallet.hpp index 590212fe..f4288d34 100644 --- a/libraries/wallet/include/graphene/wallet/wallet.hpp +++ b/libraries/wallet/include/graphene/wallet/wallet.hpp @@ -1299,6 +1299,9 @@ class wallet_api void dbg_make_mia(string creator, string symbol); void flood_network(string prefix, uint32_t number_of_transactions); + void network_add_nodes( const vector& nodes ); + vector< variant > network_get_connected_peers(); + /** * Used to transfer from one set of blinded balances to another */ @@ -1449,6 +1452,8 @@ FC_API( graphene::wallet::wallet_api, (dbg_make_uia) (dbg_make_mia) (flood_network) + (network_add_nodes) + (network_get_connected_peers) (set_key_label) (get_key_label) (get_public_key) diff --git a/libraries/wallet/wallet.cpp b/libraries/wallet/wallet.cpp index 672d546d..09d7ee29 100644 --- a/libraries/wallet/wallet.cpp +++ b/libraries/wallet/wallet.cpp @@ -1997,6 +1997,48 @@ public: create_asset(get_account(creator).name, symbol, 2, opts, bopts, true); } + void use_network_node_api() + { + if( _remote_net_node ) + return; + try + { + _remote_net_node = _remote_api->network_node(); + } + catch( const fc::exception& e ) + { + std::cerr << "\nCouldn't get network node API. You probably are not configured\n" + "to access the network API on the witness_node you are\n" + "connecting to. Please follow the instructions in README.md to set up an apiaccess file.\n" + "\n"; + throw(e); + } + } + + void network_add_nodes( const vector& nodes ) + { + use_network_node_api(); + for( const string& node_address : nodes ) + { + (*_remote_net_node)->add_node( fc::ip::endpoint::from_string( node_address ) ); + } + } + + vector< variant > network_get_connected_peers() + { + use_network_node_api(); + const auto peers = (*_remote_net_node)->get_connected_peers(); + vector< variant > result; + result.reserve( peers.size() ); + for( const auto& peer : peers ) + { + variant v; + fc::to_variant( peer, v ); + result.push_back( v ); + } + return result; + } + void flood_network(string prefix, uint32_t number_of_transactions) { try @@ -2065,6 +2107,7 @@ public: fc::api _remote_db; fc::api _remote_net_broadcast; fc::api _remote_hist; + optional< fc::api > _remote_net_node; flat_map _prototype_ops; @@ -2713,6 +2756,16 @@ void wallet_api::dbg_make_mia(string creator, string symbol) my->dbg_make_mia(creator, symbol); } +void wallet_api::network_add_nodes( const vector& nodes ) +{ + my->network_add_nodes( nodes ); +} + +vector< variant > wallet_api::network_get_connected_peers() +{ + return my->network_get_connected_peers(); +} + void wallet_api::flood_network(string prefix, uint32_t number_of_transactions) { FC_ASSERT(!is_locked()); diff --git a/programs/cli_wallet/main.cpp b/programs/cli_wallet/main.cpp index aa1a0585..ef3e4118 100644 --- a/programs/cli_wallet/main.cpp +++ b/programs/cli_wallet/main.cpp @@ -179,8 +179,9 @@ int main( int argc, char** argv ) for( auto& name_formatter : wapiptr->get_result_formatters() ) wallet_cli->format_result( name_formatter.first, name_formatter.second ); - boost::signals2::scoped_connection closed_connection(con->closed.connect([]{ + boost::signals2::scoped_connection closed_connection(con->closed.connect([=]{ cerr << "Server has disconnected us.\n"; + wallet_cli->stop(); })); (void)(closed_connection);