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

View File

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

View File

@@ -257,6 +257,30 @@ public:
PublicKey PublicKey
getMasterKey (PublicKey const& pk) const; 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. /** Returns `true` if master key has been revoked in a manifest.
@param pk Master public key @param pk Master public key

View File

@@ -309,6 +309,42 @@ ManifestCache::getMasterKey (PublicKey const& pk) const
return pk; 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 bool
ManifestCache::revoked (PublicKey const& pk) const 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: private:
using parseFuncPtr = Json::Value (RPCParser::*) (Json::Value const& jvParams); using parseFuncPtr = Json::Value (RPCParser::*) (Json::Value const& jvParams);
@@ -203,6 +218,24 @@ private:
return v; 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] // fetch_info [clear]
Json::Value parseFetchInfo (Json::Value const& jvParams) Json::Value parseFetchInfo (Json::Value const& jvParams)
{ {
@@ -764,21 +797,7 @@ private:
{ {
std::string const strPk = jvParams[0u].asString (); std::string const strPk = jvParams[0u].asString ();
bool const validPublicKey = [&strPk]{ if (!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)
return rpcError (rpcPUBLIC_MALFORMED); return rpcError (rpcPUBLIC_MALFORMED);
Json::Value jvRequest (Json::objectValue); Json::Value jvRequest (Json::objectValue);
@@ -1171,6 +1190,7 @@ public:
{ "ledger_request", &RPCParser::parseLedgerId, 1, 1 }, { "ledger_request", &RPCParser::parseLedgerId, 1, 1 },
{ "log_level", &RPCParser::parseLogLevel, 0, 2 }, { "log_level", &RPCParser::parseLogLevel, 0, 2 },
{ "logrotate", &RPCParser::parseAsIs, 0, 0 }, { "logrotate", &RPCParser::parseAsIs, 0, 0 },
{ "manifest", &RPCParser::parseManifest, 1, 1 },
{ "owner_info", &RPCParser::parseAccountItems, 1, 2 }, { "owner_info", &RPCParser::parseAccountItems, 1, 2 },
{ "peers", &RPCParser::parseAsIs, 0, 0 }, { "peers", &RPCParser::parseAsIs, 0, 0 },
{ "ping", &RPCParser::parseAsIs, 0, 0 }, { "ping", &RPCParser::parseAsIs, 0, 0 },
@@ -1195,6 +1215,7 @@ public:
{ "tx_history", &RPCParser::parseTxHistory, 1, 1 }, { "tx_history", &RPCParser::parseTxHistory, 1, 1 },
{ "unl_list", &RPCParser::parseAsIs, 0, 0 }, { "unl_list", &RPCParser::parseAsIs, 0, 0 },
{ "validation_create", &RPCParser::parseValidationCreate, 0, 1 }, { "validation_create", &RPCParser::parseValidationCreate, 0, 1 },
{ "validator_info", &RPCParser::parseAsIs, 0, 0 },
{ "version", &RPCParser::parseAsIs, 0, 0 }, { "version", &RPCParser::parseAsIs, 0, 0 },
{ "wallet_propose", &RPCParser::parseWalletPropose, 0, 1 }, { "wallet_propose", &RPCParser::parseWalletPropose, 0, 1 },
{ "internal", &RPCParser::parseInternal, 1, -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); 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. */ /** 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_currencies ); // in: PathRequest, RipplePathFind
JSS ( destination_tag ); // in: PathRequest JSS ( destination_tag ); // in: PathRequest
// out: AccountChannels // out: AccountChannels
JSS ( details ); // out: Manifest
JSS ( dir_entry ); // out: DirectoryEntryIterator JSS ( dir_entry ); // out: DirectoryEntryIterator
JSS ( dir_index ); // out: DirectoryEntryIterator JSS ( dir_index ); // out: DirectoryEntryIterator
JSS ( dir_root ); // out: DirectoryEntryIterator JSS ( dir_root ); // out: DirectoryEntryIterator
JSS ( directory ); // in: LedgerEntry JSS ( directory ); // in: LedgerEntry
JSS ( domain ); // out: ValidatorInfo, Manifest
JSS ( drops ); // out: TxQ JSS ( drops ); // out: TxQ
JSS ( duration_us ); // out: NetworkOPs JSS ( duration_us ); // out: NetworkOPs
JSS ( enabled ); // out: AmendmentTable JSS ( enabled ); // out: AmendmentTable
JSS ( engine_result ); // out: NetworkOPs, TransactionSign, Submit JSS ( engine_result ); // out: NetworkOPs, TransactionSign, Submit
JSS ( engine_result_code ); // out: NetworkOPs, TransactionSign, Submit JSS ( engine_result_code ); // out: NetworkOPs, TransactionSign, Submit
JSS ( engine_result_message ); // 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 ( error ); // out: error
JSS ( errored ); JSS ( errored );
JSS ( error_code ); // out: error JSS ( error_code ); // out: error
@@ -331,11 +335,14 @@ JSS ( local_txs ); // out: GetCounts
JSS ( local_static_keys ); // out: ValidatorList JSS ( local_static_keys ); // out: ValidatorList
JSS ( lowest_sequence ); // out: AccountInfo JSS ( lowest_sequence ); // out: AccountInfo
JSS ( majority ); // out: RPC feature JSS ( majority ); // out: RPC feature
JSS ( manifest ); // out: ValidatorInfo, Manifest
JSS ( marker ); // in/out: AccountTx, AccountOffers, JSS ( marker ); // in/out: AccountTx, AccountOffers,
// AccountLines, AccountObjects, // AccountLines, AccountObjects,
// LedgerData // LedgerData
// in: BookOffers // 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 ); // out: WalletPropose
JSS ( master_seed_hex ); // out: WalletPropose JSS ( master_seed_hex ); // out: WalletPropose
JSS ( master_signature ); // out: pubManifest JSS ( master_signature ); // out: pubManifest
@@ -412,7 +419,9 @@ JSS ( proxied ); // out: RPC ping
JSS ( pubkey_node ); // out: NetworkOPs JSS ( pubkey_node ); // out: NetworkOPs
JSS ( pubkey_publisher ); // out: ValidatorList JSS ( pubkey_publisher ); // out: ValidatorList
JSS ( pubkey_validator ); // out: NetworkOPs, 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 ( public_key_hex ); // out: WalletPropose
JSS ( published_ledger ); // out: NetworkOPs JSS ( published_ledger ); // out: NetworkOPs
JSS ( publisher_lists ); // out: ValidatorList JSS ( publisher_lists ); // out: ValidatorList
@@ -431,6 +440,7 @@ JSS ( refresh_interval_min ); // out: ValidatorSites
JSS ( regular_seed ); // in/out: LedgerEntry JSS ( regular_seed ); // in/out: LedgerEntry
JSS ( remote ); // out: Logic.h JSS ( remote ); // out: Logic.h
JSS ( request ); // RPC JSS ( request ); // RPC
JSS ( requested ); // out: Manifest
JSS ( reservations ); // out: Reservations JSS ( reservations ); // out: Reservations
JSS ( reserve_base ); // out: NetworkOPs JSS ( reserve_base ); // out: NetworkOPs
JSS ( reserve_base_xrp ); // out: NetworkOPs JSS ( reserve_base_xrp ); // out: NetworkOPs
@@ -457,7 +467,7 @@ JSS ( send_currencies ); // out: AccountCurrencies
JSS ( send_max ); // in: PathRequest, RipplePathFind JSS ( send_max ); // in: PathRequest, RipplePathFind
JSS ( seq ); // in: LedgerEntry; JSS ( seq ); // in: LedgerEntry;
// out: NetworkOPs, RPCSub, AccountOffers, // out: NetworkOPs, RPCSub, AccountOffers,
// ValidatorList // ValidatorList, ValidatorInfo, Manifest
JSS ( seqNum ); // out: LedgerToJson JSS ( seqNum ); // out: LedgerToJson
JSS ( server_state ); // out: NetworkOPs JSS ( server_state ); // out: NetworkOPs
JSS ( server_state_duration_us ); // 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 doLedgerRequest (RPC::JsonContext&);
Json::Value doLogLevel (RPC::JsonContext&); Json::Value doLogLevel (RPC::JsonContext&);
Json::Value doLogRotate (RPC::JsonContext&); Json::Value doLogRotate (RPC::JsonContext&);
Json::Value doManifest (RPC::JsonContext&);
Json::Value doNoRippleCheck (RPC::JsonContext&); Json::Value doNoRippleCheck (RPC::JsonContext&);
Json::Value doOwnerInfo (RPC::JsonContext&); Json::Value doOwnerInfo (RPC::JsonContext&);
Json::Value doPathFind (RPC::JsonContext&); Json::Value doPathFind (RPC::JsonContext&);
@@ -86,6 +87,7 @@ Json::Value doValidationCreate (RPC::JsonContext&);
Json::Value doWalletPropose (RPC::JsonContext&); Json::Value doWalletPropose (RPC::JsonContext&);
Json::Value doValidators (RPC::JsonContext&); Json::Value doValidators (RPC::JsonContext&);
Json::Value doValidatorListSites (RPC::JsonContext&); Json::Value doValidatorListSites (RPC::JsonContext&);
Json::Value doValidatorInfo (RPC::JsonContext&);
} // ripple } // ripple
#endif #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 }, { "ledger_request", byRef (&doLedgerRequest), Role::ADMIN, NO_CONDITION },
{ "log_level", byRef (&doLogLevel), Role::ADMIN, NO_CONDITION }, { "log_level", byRef (&doLogLevel), Role::ADMIN, NO_CONDITION },
{ "logrotate", byRef (&doLogRotate), 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 }, { "noripple_check", byRef (&doNoRippleCheck), Role::USER, NO_CONDITION },
{ "owner_info", byRef (&doOwnerInfo), Role::USER, NEEDS_CURRENT_LEDGER }, { "owner_info", byRef (&doOwnerInfo), Role::USER, NEEDS_CURRENT_LEDGER },
{ "peers", byRef (&doPeers), Role::ADMIN, NO_CONDITION }, { "peers", byRef (&doPeers), Role::ADMIN, NO_CONDITION },
@@ -117,6 +118,7 @@ Handler const handlerArray[] {
{ "validation_create", byRef (&doValidationCreate), Role::ADMIN, NO_CONDITION }, { "validation_create", byRef (&doValidationCreate), Role::ADMIN, NO_CONDITION },
{ "validators", byRef (&doValidators), Role::ADMIN, NO_CONDITION }, { "validators", byRef (&doValidators), Role::ADMIN, NO_CONDITION },
{ "validator_list_sites", byRef (&doValidatorListSites), 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 }, { "wallet_propose", byRef (&doWalletPropose), Role::ADMIN, NO_CONDITION },
// Evented methods // Evented methods

View File

@@ -58,5 +58,7 @@
#include <ripple/rpc/handlers/LedgerRequest.cpp> #include <ripple/rpc/handlers/LedgerRequest.cpp>
#include <ripple/rpc/handlers/LogLevel.cpp> #include <ripple/rpc/handlers/LogLevel.cpp>
#include <ripple/rpc/handlers/LogRotate.cpp> #include <ripple/rpc/handlers/LogRotate.cpp>
#include <ripple/rpc/handlers/Manifest.cpp>
#include <ripple/rpc/handlers/NoRippleCheck.cpp> #include <ripple/rpc/handlers/NoRippleCheck.cpp>
#include <ripple/rpc/handlers/OwnerInfo.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/LedgerData_test.cpp>
#include <test/rpc/LedgerRPC_test.cpp> #include <test/rpc/LedgerRPC_test.cpp>
#include <test/rpc/LedgerRequestRPC_test.cpp> #include <test/rpc/LedgerRequestRPC_test.cpp>
#include <test/rpc/ManifestRPC_test.cpp>
#include <test/rpc/NoRipple_test.cpp> #include <test/rpc/NoRipple_test.cpp>
#include <test/rpc/NoRippleCheck_test.cpp> #include <test/rpc/NoRippleCheck_test.cpp>
#include <test/rpc/OwnerInfo_test.cpp> #include <test/rpc/OwnerInfo_test.cpp>
@@ -54,6 +55,7 @@
#include <test/rpc/Transaction_test.cpp> #include <test/rpc/Transaction_test.cpp>
#include <test/rpc/TransactionEntry_test.cpp> #include <test/rpc/TransactionEntry_test.cpp>
#include <test/rpc/TransactionHistory_test.cpp> #include <test/rpc/TransactionHistory_test.cpp>
#include <test/rpc/ValidatorInfo_test.cpp>
#include <test/rpc/Tx_test.cpp> #include <test/rpc/Tx_test.cpp>
#include <test/rpc/ValidatorRPC_test.cpp> #include <test/rpc/ValidatorRPC_test.cpp>
#include <test/rpc/Version_test.cpp> #include <test/rpc/Version_test.cpp>