Skip to content

Commit

Permalink
Add new validator_info and manifest rpc methods
Browse files Browse the repository at this point in the history
Returns local validator details and specified manifest information
respectively. Folded and rebased on latest develop
  • Loading branch information
movitto authored and nbougalis committed Feb 11, 2020
1 parent 2f9edf4 commit 3578aca
Show file tree
Hide file tree
Showing 15 changed files with 457 additions and 18 deletions.
4 changes: 4 additions & 0 deletions Builds/CMake/RippledCore.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
#[===============================[
Expand Down
1 change: 1 addition & 0 deletions src/ripple/app/main/Application.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ class AcceptedLedger;
class LedgerMaster;
class LoadManager;
class ManifestCache;
class ValidatorKeys;
class NetworkOPs;
class OpenLedger;
class OrderBookDB;
Expand Down
24 changes: 24 additions & 0 deletions src/ripple/app/misc/Manifest.h
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,30 @@ class ManifestCache
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
Expand Down
36 changes: 36 additions & 0 deletions src/ripple/app/misc/impl/Manifest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
51 changes: 36 additions & 15 deletions src/ripple/net/impl/RPCCall.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,21 @@ class RPCParser
}
}

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);

Expand Down Expand Up @@ -203,6 +218,24 @@ class RPCParser
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)
{
Expand Down Expand Up @@ -764,21 +797,7 @@ class RPCParser
{
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);
Expand Down Expand Up @@ -1171,6 +1190,7 @@ class RPCParser
{ "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 },
Expand All @@ -1195,6 +1215,7 @@ class RPCParser
{ "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 },
Expand Down
5 changes: 5 additions & 0 deletions src/ripple/protocol/ErrorCodes.h
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down
16 changes: 13 additions & 3 deletions src/ripple/protocol/jss.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
2 changes: 2 additions & 0 deletions src/ripple/rpc/handlers/Handlers.h
Original file line number Diff line number Diff line change
Expand Up @@ -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&);
Expand Down Expand Up @@ -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
75 changes: 75 additions & 0 deletions src/ripple/rpc/handlers/Manifest.cpp
Original file line number Diff line number Diff line change
@@ -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
Loading

0 comments on commit 3578aca

Please sign in to comment.