Add new validator_info and manifest rpc methods

Returns local validator details and specified manifest information
respectively. Folded and rebased on latest develop
This commit is contained in:
Mo Morsi
2020-01-22 22:13:02 -05:00
committed by Nik Bougalis
parent 2f9edf495e
commit 3578acaf0b
15 changed files with 457 additions and 18 deletions

View File

@@ -650,6 +650,7 @@ else ()
src/ripple/rpc/handlers/LedgerRequest.cpp
src/ripple/rpc/handlers/LogLevel.cpp
src/ripple/rpc/handlers/LogRotate.cpp
src/ripple/rpc/handlers/Manifest.cpp
src/ripple/rpc/handlers/NoRippleCheck.cpp
src/ripple/rpc/handlers/OwnerInfo.cpp
src/ripple/rpc/handlers/PathFind.cpp
@@ -676,6 +677,7 @@ else ()
src/ripple/rpc/handlers/ValidationCreate.cpp
src/ripple/rpc/handlers/ValidatorListSites.cpp
src/ripple/rpc/handlers/Validators.cpp
src/ripple/rpc/handlers/ValidatorInfo.cpp
src/ripple/rpc/handlers/WalletPropose.cpp
src/ripple/rpc/impl/DeliveredAmount.cpp
src/ripple/rpc/impl/Handler.cpp
@@ -967,6 +969,7 @@ else ()
src/test/rpc/LedgerData_test.cpp
src/test/rpc/LedgerRPC_test.cpp
src/test/rpc/LedgerRequestRPC_test.cpp
src/test/rpc/ManifestRPC_test.cpp
src/test/rpc/NoRippleCheck_test.cpp
src/test/rpc/NoRipple_test.cpp
src/test/rpc/OwnerInfo_test.cpp
@@ -983,6 +986,7 @@ else ()
src/test/rpc/TransactionEntry_test.cpp
src/test/rpc/TransactionHistory_test.cpp
src/test/rpc/Tx_test.cpp
src/test/rpc/ValidatorInfo_test.cpp
src/test/rpc/ValidatorRPC_test.cpp
src/test/rpc/Version_test.cpp
#[===============================[

View File

@@ -53,6 +53,7 @@ class AcceptedLedger;
class LedgerMaster;
class LoadManager;
class ManifestCache;
class ValidatorKeys;
class NetworkOPs;
class OpenLedger;
class OrderBookDB;

View File

@@ -257,6 +257,30 @@ public:
PublicKey
getMasterKey (PublicKey const& pk) const;
/** Returns master key's current manifest sequence.
@return sequence corresponding to Master public key
if configured or boost::none otherwise
*/
boost::optional<std::uint32_t>
getSequence (PublicKey const& pk) const;
/** Returns domain claimed by a given public key
@return domain corresponding to Master public key
if present, otherwise boost::none
*/
boost::optional<std::string>
getDomain (PublicKey const& pk) const;
/** Returns mainfest corresponding to a given public key
@return manifest corresponding to Master public key
if present, otherwise boost::none
*/
boost::optional<std::string>
getManifest (PublicKey const& pk) const;
/** Returns `true` if master key has been revoked in a manifest.
@param pk Master public key

View File

@@ -309,6 +309,42 @@ ManifestCache::getMasterKey (PublicKey const& pk) const
return pk;
}
boost::optional<std::uint32_t>
ManifestCache::getSequence (PublicKey const& pk) const
{
std::lock_guard lock{read_mutex_};
auto const iter = map_.find (pk);
if (iter != map_.end () && !iter->second.revoked ())
return iter->second.sequence;
return boost::none;
}
boost::optional<std::string>
ManifestCache::getDomain (PublicKey const& pk) const
{
std::lock_guard lock{read_mutex_};
auto const iter = map_.find (pk);
if (iter != map_.end () && !iter->second.revoked ())
return iter->second.domain;
return boost::none;
}
boost::optional<std::string>
ManifestCache::getManifest (PublicKey const& pk) const
{
std::lock_guard lock{read_mutex_};
auto const iter = map_.find (pk);
if (iter != map_.end () && !iter->second.revoked ())
return iter->second.serialized;
return boost::none;
}
bool
ManifestCache::revoked (PublicKey const& pk) const
{

View File

@@ -145,6 +145,21 @@ private:
}
}
static bool validPublicKey (std::string const& strPk)
{
if (parseBase58<PublicKey> (TokenType::AccountPublic, strPk))
return true;
auto pkHex = strUnHex (strPk);
if (!pkHex)
return false;
if (!publicKeyType(makeSlice(*pkHex)))
return false;
return true;
}
private:
using parseFuncPtr = Json::Value (RPCParser::*) (Json::Value const& jvParams);
@@ -203,6 +218,24 @@ private:
return v;
}
Json::Value parseManifest (Json::Value const& jvParams)
{
if (jvParams.size () == 1)
{
Json::Value jvRequest (Json::objectValue);
std::string const strPk = jvParams[0u].asString ();
if (!validPublicKey (strPk))
return rpcError (rpcPUBLIC_MALFORMED);
jvRequest[jss::public_key] = strPk;
return jvRequest;
}
return rpcError (rpcINVALID_PARAMS);
}
// fetch_info [clear]
Json::Value parseFetchInfo (Json::Value const& jvParams)
{
@@ -764,21 +797,7 @@ private:
{
std::string const strPk = jvParams[0u].asString ();
bool const validPublicKey = [&strPk]{
if (parseBase58<PublicKey> (TokenType::AccountPublic, strPk))
return true;
auto pkHex = strUnHex (strPk);
if (!pkHex)
return false;
if (!publicKeyType(makeSlice(*pkHex)))
return false;
return true;
}();
if (!validPublicKey)
if (!validPublicKey(strPk))
return rpcError (rpcPUBLIC_MALFORMED);
Json::Value jvRequest (Json::objectValue);
@@ -1171,6 +1190,7 @@ public:
{ "ledger_request", &RPCParser::parseLedgerId, 1, 1 },
{ "log_level", &RPCParser::parseLogLevel, 0, 2 },
{ "logrotate", &RPCParser::parseAsIs, 0, 0 },
{ "manifest", &RPCParser::parseManifest, 1, 1 },
{ "owner_info", &RPCParser::parseAccountItems, 1, 2 },
{ "peers", &RPCParser::parseAsIs, 0, 0 },
{ "ping", &RPCParser::parseAsIs, 0, 0 },
@@ -1195,6 +1215,7 @@ public:
{ "tx_history", &RPCParser::parseTxHistory, 1, 1 },
{ "unl_list", &RPCParser::parseAsIs, 0, 0 },
{ "validation_create", &RPCParser::parseValidationCreate, 0, 1 },
{ "validator_info", &RPCParser::parseAsIs, 0, 0 },
{ "version", &RPCParser::parseAsIs, 0, 0 },
{ "wallet_propose", &RPCParser::parseWalletPropose, 0, 1 },
{ "internal", &RPCParser::parseInternal, 1, -1 },

View File

@@ -285,6 +285,11 @@ inline Json::Value expected_field_error (
return expected_field_error (std::string (name), type);
}
inline Json::Value not_validator_error ()
{
return make_param_error ("not a validator");
}
/** @} */
/** Returns `true` if the json contains an rpc error specification. */

View File

@@ -202,16 +202,20 @@ JSS ( destination_amount ); // in: PathRequest, RipplePathFind
JSS ( destination_currencies ); // in: PathRequest, RipplePathFind
JSS ( destination_tag ); // in: PathRequest
// out: AccountChannels
JSS ( details ); // out: Manifest
JSS ( dir_entry ); // out: DirectoryEntryIterator
JSS ( dir_index ); // out: DirectoryEntryIterator
JSS ( dir_root ); // out: DirectoryEntryIterator
JSS ( directory ); // in: LedgerEntry
JSS ( domain ); // out: ValidatorInfo, Manifest
JSS ( drops ); // out: TxQ
JSS ( duration_us ); // out: NetworkOPs
JSS ( enabled ); // out: AmendmentTable
JSS ( engine_result ); // out: NetworkOPs, TransactionSign, Submit
JSS ( engine_result_code ); // out: NetworkOPs, TransactionSign, Submit
JSS ( engine_result_message ); // out: NetworkOPs, TransactionSign, Submit
JSS ( ephemeral_key ); // out: ValidatorInfo
// in/out: Manifest
JSS ( error ); // out: error
JSS ( errored );
JSS ( error_code ); // out: error
@@ -331,11 +335,14 @@ JSS ( local_txs ); // out: GetCounts
JSS ( local_static_keys ); // out: ValidatorList
JSS ( lowest_sequence ); // out: AccountInfo
JSS ( majority ); // out: RPC feature
JSS ( manifest ); // out: ValidatorInfo, Manifest
JSS ( marker ); // in/out: AccountTx, AccountOffers,
// AccountLines, AccountObjects,
// LedgerData
// in: BookOffers
JSS ( master_key ); // out: WalletPropose, NetworkOPs
JSS ( master_key ); // out: WalletPropose, NetworkOPs,
// ValidatorInfo
// in/out: Manifest
JSS ( master_seed ); // out: WalletPropose
JSS ( master_seed_hex ); // out: WalletPropose
JSS ( master_signature ); // out: pubManifest
@@ -412,7 +419,9 @@ JSS ( proxied ); // out: RPC ping
JSS ( pubkey_node ); // out: NetworkOPs
JSS ( pubkey_publisher ); // out: ValidatorList
JSS ( pubkey_validator ); // out: NetworkOPs, ValidatorList
JSS ( public_key ); // out: OverlayImpl, PeerImp, WalletPropose
JSS ( public_key ); // out: OverlayImpl, PeerImp, WalletPropose,
// ValidatorInfo
// in/out: Manifest
JSS ( public_key_hex ); // out: WalletPropose
JSS ( published_ledger ); // out: NetworkOPs
JSS ( publisher_lists ); // out: ValidatorList
@@ -431,6 +440,7 @@ JSS ( refresh_interval_min ); // out: ValidatorSites
JSS ( regular_seed ); // in/out: LedgerEntry
JSS ( remote ); // out: Logic.h
JSS ( request ); // RPC
JSS ( requested ); // out: Manifest
JSS ( reservations ); // out: Reservations
JSS ( reserve_base ); // out: NetworkOPs
JSS ( reserve_base_xrp ); // out: NetworkOPs
@@ -457,7 +467,7 @@ JSS ( send_currencies ); // out: AccountCurrencies
JSS ( send_max ); // in: PathRequest, RipplePathFind
JSS ( seq ); // in: LedgerEntry;
// out: NetworkOPs, RPCSub, AccountOffers,
// ValidatorList
// ValidatorList, ValidatorInfo, Manifest
JSS ( seqNum ); // out: LedgerToJson
JSS ( server_state ); // out: NetworkOPs
JSS ( server_state_duration_us ); // out: NetworkOPs

View File

@@ -57,6 +57,7 @@ Json::Value doLedgerHeader (RPC::JsonContext&);
Json::Value doLedgerRequest (RPC::JsonContext&);
Json::Value doLogLevel (RPC::JsonContext&);
Json::Value doLogRotate (RPC::JsonContext&);
Json::Value doManifest (RPC::JsonContext&);
Json::Value doNoRippleCheck (RPC::JsonContext&);
Json::Value doOwnerInfo (RPC::JsonContext&);
Json::Value doPathFind (RPC::JsonContext&);
@@ -86,6 +87,7 @@ Json::Value doValidationCreate (RPC::JsonContext&);
Json::Value doWalletPropose (RPC::JsonContext&);
Json::Value doValidators (RPC::JsonContext&);
Json::Value doValidatorListSites (RPC::JsonContext&);
Json::Value doValidatorInfo (RPC::JsonContext&);
} // ripple
#endif

View File

@@ -0,0 +1,75 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2019 Dev Null Productions
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <ripple/app/main/Application.h>
#include <ripple/basics/base64.h>
#include <ripple/json/json_value.h>
#include <ripple/protocol/ErrorCodes.h>
#include <ripple/protocol/jss.h>
#include <ripple/rpc/Context.h>
namespace ripple {
Json::Value doManifest (RPC::JsonContext& context)
{
auto& params = context.params;
if (!params.isMember(jss::public_key))
return RPC::missing_field_error (jss::public_key);
auto const requested = params[jss::public_key].asString();
Json::Value ret;
ret[jss::requested] = requested;
auto const pk = parseBase58<PublicKey>(TokenType::NodePublic, requested);
if (!pk)
{
RPC::inject_error(rpcINVALID_PARAMS, ret);
return ret;
}
// first attempt to use params as ephemeral key,
// if this lookup succeeds master key will be returned,
// else pk will just be returned and we will assume that
// is master key anyways
auto const mk = context.app.validatorManifests().getMasterKey(*pk);
auto const ek = context.app.validatorManifests().getSigningKey(mk);
// if ephemeral key not found, we don't have specified manifest
if (ek == mk)
return ret;
if (auto const manifest = context.app.validatorManifests().getManifest(mk))
ret[jss::manifest] = base64_encode(*manifest);
Json::Value details;
details[jss::master_key] = toBase58(TokenType::NodePublic, mk);
details[jss::ephemeral_key] = toBase58(TokenType::NodePublic, ek);
if (auto const seq = context.app.validatorManifests().getSequence(mk))
details[jss::seq] = *seq;
if (auto const domain = context.app.validatorManifests().getDomain(mk))
details[jss::domain] = *domain;
ret[jss::details] = details;
return ret;
}
} // ripple

View File

@@ -0,0 +1,62 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2019 Dev Null Productions
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <ripple/app/misc/ValidatorKeys.h>
#include <ripple/app/main/Application.h>
#include <ripple/basics/base64.h>
#include <ripple/json/json_value.h>
#include <ripple/protocol/ErrorCodes.h>
#include <ripple/protocol/jss.h>
#include <ripple/rpc/Context.h>
namespace ripple {
Json::Value doValidatorInfo (RPC::JsonContext& context)
{
// return error if not configured as validator
if (context.app.getValidationPublicKey().empty())
return RPC::not_validator_error ();
Json::Value ret;
auto const pk = context.app.getValidationPublicKey();
// assume pk is ephemeral key, get master key
auto const mk = context.app.validatorManifests().getMasterKey(pk);
ret[jss::master_key] = toBase58(TokenType::NodePublic, mk);
// pk is maskter key, eg no ephemeral key, eg no manifest, just return
if (mk == pk)
return ret;
// lookup ephemeral key
auto const ek = context.app.validatorManifests().getSigningKey(mk);
ret[jss::ephemeral_key] = toBase58(TokenType::NodePublic, ek);
if (auto const manifest = context.app.validatorManifests().getManifest(mk))
ret[jss::manifest] = base64_encode(*manifest);
if (auto const seq = context.app.validatorManifests().getSequence(mk))
ret[jss::seq] = *seq;
if (auto const domain = context.app.validatorManifests().getDomain(mk))
ret[jss::domain] = *domain;
return ret;
}
} // ripple

View File

@@ -90,6 +90,7 @@ Handler const handlerArray[] {
{ "ledger_request", byRef (&doLedgerRequest), Role::ADMIN, NO_CONDITION },
{ "log_level", byRef (&doLogLevel), Role::ADMIN, NO_CONDITION },
{ "logrotate", byRef (&doLogRotate), Role::ADMIN, NO_CONDITION },
{ "manifest", byRef (&doManifest), Role::ADMIN, NO_CONDITION },
{ "noripple_check", byRef (&doNoRippleCheck), Role::USER, NO_CONDITION },
{ "owner_info", byRef (&doOwnerInfo), Role::USER, NEEDS_CURRENT_LEDGER },
{ "peers", byRef (&doPeers), Role::ADMIN, NO_CONDITION },
@@ -117,6 +118,7 @@ Handler const handlerArray[] {
{ "validation_create", byRef (&doValidationCreate), Role::ADMIN, NO_CONDITION },
{ "validators", byRef (&doValidators), Role::ADMIN, NO_CONDITION },
{ "validator_list_sites", byRef (&doValidatorListSites), Role::ADMIN, NO_CONDITION },
{ "validator_info", byRef (&doValidatorInfo), Role::ADMIN, NO_CONDITION },
{ "wallet_propose", byRef (&doWalletPropose), Role::ADMIN, NO_CONDITION },
// Evented methods

View File

@@ -58,5 +58,7 @@
#include <ripple/rpc/handlers/LedgerRequest.cpp>
#include <ripple/rpc/handlers/LogLevel.cpp>
#include <ripple/rpc/handlers/LogRotate.cpp>
#include <ripple/rpc/handlers/Manifest.cpp>
#include <ripple/rpc/handlers/NoRippleCheck.cpp>
#include <ripple/rpc/handlers/OwnerInfo.cpp>
#include <ripple/rpc/handlers/ValidatorInfo.cpp>

View File

@@ -0,0 +1,85 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2020 Dev Null Productions, LLC
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <test/jtx.h>
#include <ripple/beast/unit_test.h>
#include <ripple/core/ConfigSections.h>
#include <ripple/protocol/jss.h>
#include <string>
namespace ripple {
namespace test {
class ManifestRPC_test : public beast::unit_test::suite
{
public:
void testErrors()
{
testcase ("Errors");
using namespace jtx;
Env env(*this);
{
// manifest with no public key
auto const info = env.rpc ("json", "manifest", "{ }");
BEAST_EXPECT(info[jss::result][jss::error_message] ==
"Missing field 'public_key'.");
}
{
// manifest with manlformed public key
auto const info = env.rpc ("json", "manifest", "{ \"public_key\": "
"\"abcdef12345\"}");
BEAST_EXPECT(info[jss::result][jss::error_message] ==
"Invalid parameters.");
}
}
void testLookup()
{
testcase ("Lookup");
using namespace jtx;
std::string const key =
"n949f75evCHwgyP4fPVgaHqNHxUVN15PsJEZ3B3HnXPcPjcZAoy7";
Env env{
*this,
envconfig([&key](std::unique_ptr<Config> cfg) {
cfg->section(SECTION_VALIDATORS).append(key);
return cfg;
})
};
{
auto const info = env.rpc ("json", "manifest", "{ \"public_key\": "
"\"" + key + "\"}");
BEAST_EXPECT(info[jss::result][jss::requested] == key);
BEAST_EXPECT(info[jss::result][jss::status] == "success");
}
}
void run() override
{
testErrors();
testLookup();
}
};
BEAST_DEFINE_TESTSUITE(ManifestRPC,rpc,ripple);
}
}

View File

@@ -0,0 +1,108 @@
//------------------------------------------------------------------------------
/*
This file is part of rippled: https://github.com/ripple/rippled
Copyright (c) 2020 Dev Null Productions, LLC
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
//==============================================================================
#include <test/jtx.h>
#include <ripple/beast/unit_test.h>
#include <ripple/core/ConfigSections.h>
#include <ripple/protocol/jss.h>
#include <string>
#include <vector>
namespace ripple {
namespace test {
class ValidatorInfo_test : public beast::unit_test::suite
{
public:
void testErrors()
{
testcase ("Errors");
using namespace jtx;
{
Env env(*this);
auto const info = env.rpc ("validator_info");
BEAST_EXPECT(info[jss::result][jss::error_message] ==
"not a validator");
}
}
void
testPrivileges()
{
using namespace test::jtx;
Env env{*this, envconfig(no_admin)};
auto const info = env.rpc ("validator_info")[jss::result];
BEAST_EXPECT(info.isNull());
}
void testLookup()
{
testcase ("Lookup");
using namespace jtx;
const std::vector<std::string> tokenBlob = {
" "
"eyJ2YWxpZGF0aW9uX3NlY3JldF9rZXkiOiI5ZWQ0NWY4NjYyNDFjYzE4YTI3NDdiNT\n",
" \tQzODdjMDYyNTkwNzk3MmY0ZTcxOTAyMzFmYWE5Mzc0NTdmYTlkYWY2IiwibWFuaWZl "
" \n",
"\tc3QiOiJKQUFBQUFGeEllMUZ0d21pbXZHdEgyaUNjTUpxQzlnVkZLaWxHZncxL3ZDeE"
"\n",
"\t "
"hYWExwbGMyR25NaEFrRTFhZ3FYeEJ3RHdEYklENk9NU1l1TTBGREFscEFnTms4U0tG\t "
"\t\n",
"bjdNTzJmZGtjd1JRSWhBT25ndTlzQUtxWFlvdUorbDJWMFcrc0FPa1ZCK1pSUzZQU2\n",
"hsSkFmVXNYZkFpQnNWSkdlc2FhZE9KYy9hQVpva1MxdnltR21WcmxIUEtXWDNZeXd1\n",
"NmluOEhBU1FLUHVnQkQ2N2tNYVJGR3ZtcEFUSGxHS0pkdkRGbFdQWXk1QXFEZWRGdj\n",
"VUSmEydzBpMjFlcTNNWXl3TFZKWm5GT3I3QzBrdzJBaVR6U0NqSXpkaXRROD0ifQ==\n"};
std::string const master_key = "nHBt9fsb4849WmZiCds4r5TXyBeQjqnH5kzPtqgMAQMgi39YZRPa";
std::string const ephemeral_key = "n9KsDYGKhABVc4wK5u3MnVhgPinyJimyKGpr9VJYuBaY8EnJXR2x";
std::string const manifest = "JAAAAAFxIe1FtwmimvGtH2iCcMJqC9gVFKilGfw1/vCxHXXLplc2GnMhAkE1agqXxBwDwDbID6OMSYuM0FDAlpAgNk8SKFn7MO2fdkcwRQIhAOngu9sAKqXYouJ+l2V0W+sAOkVB+ZRS6PShlJAfUsXfAiBsVJGesaadOJc/aAZokS1vymGmVrlHPKWX3Yywu6in8HASQKPugBD67kMaRFGvmpATHlGKJdvDFlWPYy5AqDedFv5TJa2w0i21eq3MYywLVJZnFOr7C0kw2AiTzSCjIzditQ8=";
Env env{
*this,
envconfig([&tokenBlob](std::unique_ptr<Config> cfg) {
cfg->section(SECTION_VALIDATOR_TOKEN).append(tokenBlob);
return cfg;
})
};
{
auto const info = env.rpc ("validator_info");
BEAST_EXPECT(info[jss::result][jss::status] == "success");
BEAST_EXPECT(info[jss::result][jss::seq] == 1);
BEAST_EXPECT(info[jss::result][jss::master_key] == master_key);
BEAST_EXPECT(info[jss::result][jss::manifest] == manifest);
BEAST_EXPECT(info[jss::result][jss::ephemeral_key] == ephemeral_key);
BEAST_EXPECT(info[jss::result][jss::domain] == "");
}
}
void run() override
{
testErrors();
testPrivileges();
testLookup();
}
};
BEAST_DEFINE_TESTSUITE(ValidatorInfo,rpc,ripple);
}
}

View File

@@ -39,6 +39,7 @@
#include <test/rpc/LedgerData_test.cpp>
#include <test/rpc/LedgerRPC_test.cpp>
#include <test/rpc/LedgerRequestRPC_test.cpp>
#include <test/rpc/ManifestRPC_test.cpp>
#include <test/rpc/NoRipple_test.cpp>
#include <test/rpc/NoRippleCheck_test.cpp>
#include <test/rpc/OwnerInfo_test.cpp>
@@ -54,6 +55,7 @@
#include <test/rpc/Transaction_test.cpp>
#include <test/rpc/TransactionEntry_test.cpp>
#include <test/rpc/TransactionHistory_test.cpp>
#include <test/rpc/ValidatorInfo_test.cpp>
#include <test/rpc/Tx_test.cpp>
#include <test/rpc/ValidatorRPC_test.cpp>
#include <test/rpc/Version_test.cpp>