diff --git a/Builds/VisualStudio2015/RippleD.vcxproj b/Builds/VisualStudio2015/RippleD.vcxproj
index 801636f4ed..2a5e8e6a91 100644
--- a/Builds/VisualStudio2015/RippleD.vcxproj
+++ b/Builds/VisualStudio2015/RippleD.vcxproj
@@ -3378,6 +3378,10 @@
True
True
+
+ True
+ True
+
True
True
diff --git a/Builds/VisualStudio2015/RippleD.vcxproj.filters b/Builds/VisualStudio2015/RippleD.vcxproj.filters
index ce0be76f50..8da166a6be 100644
--- a/Builds/VisualStudio2015/RippleD.vcxproj.filters
+++ b/Builds/VisualStudio2015/RippleD.vcxproj.filters
@@ -3837,6 +3837,9 @@
ripple\rpc\tests
+
+ ripple\rpc\tests
+
ripple\rpc\tests
diff --git a/src/ripple/app/misc/NetworkOPs.cpp b/src/ripple/app/misc/NetworkOPs.cpp
index c9dd1ce2fa..75dfc6128c 100644
--- a/src/ripple/app/misc/NetworkOPs.cpp
+++ b/src/ripple/app/misc/NetworkOPs.cpp
@@ -50,6 +50,7 @@
#include
#include
#include
+#include
#include
#include
#include
@@ -67,10 +68,12 @@
#include
#include
#include
+#include
#include
#include
#include
#include
+#include
#include
#include
#include
@@ -2021,6 +2024,30 @@ Json::Value NetworkOPsImp::getServerInfo (bool human, bool admin)
{
if (app_.config().VALIDATION_PUB.size ())
{
+ auto const& validation_manifest =
+ app_.config().section (SECTION_VALIDATION_MANIFEST);
+
+ if (! validation_manifest.lines().empty())
+ {
+ std::string s;
+ s.reserve (188);
+ for (auto const& line : validation_manifest.lines())
+ s += beast::rfc2616::trim(line);
+ if (auto mo = make_Manifest (beast::detail::base64_decode(s)))
+ {
+ Json::Value valManifest = Json::objectValue;
+ valManifest [jss::master_key] = toBase58 (
+ TokenType::TOKEN_NODE_PUBLIC,
+ mo->masterKey);
+ valManifest [jss::signing_key] = toBase58 (
+ TokenType::TOKEN_NODE_PUBLIC,
+ mo->signingKey);
+ valManifest [jss::seq] = Json::UInt (mo->sequence);
+
+ info[jss::validation_manifest] = valManifest;
+ }
+ }
+
info[jss::pubkey_validator] = toBase58 (
TokenType::TOKEN_NODE_PUBLIC,
app_.config().VALIDATION_PUB);
diff --git a/src/ripple/core/Config.h b/src/ripple/core/Config.h
index 5b61f827de..d13c4f8a05 100644
--- a/src/ripple/core/Config.h
+++ b/src/ripple/core/Config.h
@@ -196,7 +196,7 @@ public:
bool bSilent, bool bStandalone);
/**
- * Load the conig from the contents of the sting.
+ * Load the config from the contents of the string.
*
* @param fileContents String representing the config contents.
*/
diff --git a/src/ripple/overlay/impl/OverlayImpl.cpp b/src/ripple/overlay/impl/OverlayImpl.cpp
index 6c400dc630..5423dd78df 100644
--- a/src/ripple/overlay/impl/OverlayImpl.cpp
+++ b/src/ripple/overlay/impl/OverlayImpl.cpp
@@ -491,16 +491,16 @@ OverlayImpl::setupValidatorKeyManifests (BasicConfig const& config,
Throw (
"Unable to load keys from [" SECTION_VALIDATOR_KEYS "]");
- auto const validation_manifest =
+ auto const& validation_manifest =
config.section (SECTION_VALIDATION_MANIFEST);
if (! validation_manifest.lines().empty())
{
std::string s;
+ s.reserve (188);
for (auto const& line : validation_manifest.lines())
s += beast::rfc2616::trim(line);
- s = beast::detail::base64_decode(s);
- if (auto mo = make_Manifest (std::move (s)))
+ if (auto mo = make_Manifest (beast::detail::base64_decode(s)))
{
manifestCache_.configManifest (
std::move (*mo),
diff --git a/src/ripple/protocol/JsonFields.h b/src/ripple/protocol/JsonFields.h
index 01e2896672..87f1e01a03 100644
--- a/src/ripple/protocol/JsonFields.h
+++ b/src/ripple/protocol/JsonFields.h
@@ -417,6 +417,7 @@ JSS ( validated ); // out: NetworkOPs, RPCHelpers, AccountTx*
JSS ( validated_ledger ); // out: NetworkOPs
JSS ( validated_ledgers ); // out: NetworkOPs
JSS ( validation_key ); // out: ValidationCreate, ValidationSeed
+JSS ( validation_manifest ); // out: NetworkOPs
JSS ( validation_public_key ); // out: ValidationCreate, ValidationSeed
JSS ( validation_quorum ); // out: NetworkOPs
JSS ( validation_seed ); // out: ValidationCreate, ValidationSeed
diff --git a/src/ripple/rpc/tests/ServerInfo.test.cpp b/src/ripple/rpc/tests/ServerInfo.test.cpp
new file mode 100644
index 0000000000..0b6c723409
--- /dev/null
+++ b/src/ripple/rpc/tests/ServerInfo.test.cpp
@@ -0,0 +1,108 @@
+//------------------------------------------------------------------------------
+/*
+ This file is part of rippled: https://github.com/ripple/rippled
+ Copyright (c) 2012-2016 Ripple Labs Inc.
+
+ 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
+#include
+#include
+#include
+
+namespace ripple {
+
+namespace test {
+
+namespace validator {
+static auto const seed = "ss7t3J9dYentEFgKdPA3q6eyxtrLB";
+static auto const master_key =
+ "nHU4LxxrSQsRTKy5uZbX95eYowoamUEPCcWraxoiCNbtDaUr1V34";
+static auto const signing_key =
+ "n9LHPLA36SBky1YjbaVEApQQ3s9XcpazCgfAG7jsqBb1ugDAosbm";
+// Format manifest string to test trim()
+static auto const manifest =
+ " JAAAAAFxIe2FwblmJwz4pVYXHLJSzSBgIK7mpQuHNQ88CxW\n"
+ " \tjIN7q4nMhAuUTyasIhvj2KPfNRbmmIBnqNUzidgkKb244eP \n"
+ "\t794ZpMdkC+8l5n3R/CHP6SAwhYDOaqub0Cs2NjjewBnp1mf\n"
+ "\t 23rhAzdcjRuWzm0IT12eduZ0DwcF5Ng8rAelaYP1iT93ScE\t \t";
+static auto sequence = 1;
+}
+
+class ServerInfo_test : public beast::unit_test::suite
+{
+public:
+ static
+ std::unique_ptr
+ makeValidatorConfig()
+ {
+ auto p = std::make_unique();
+ boost::format toLoad(R"rippleConfig(
+[validation_manifest]
+%1%
+
+[validation_seed]
+%2%
+)rippleConfig");
+
+ p->loadFromString (boost::str (
+ toLoad % validator::manifest % validator::seed));
+
+ setupConfigForUnitTests(*p);
+
+ return p;
+ }
+
+ void testServerInfo()
+ {
+ using namespace test::jtx;
+
+ {
+ Env env(*this);
+ auto const result = env.rpc("server_info", "1");
+ expect (!result[jss::result].isMember (jss::error));
+ expect (result[jss::status] == "success");
+ expect (result[jss::result].isMember(jss::info));
+ }
+ {
+ Env env(*this, makeValidatorConfig());
+ auto const result = env.rpc("server_info", "1");
+ expect (!result[jss::result].isMember (jss::error));
+ expect (result[jss::status] == "success");
+ expect (result[jss::result].isMember(jss::info));
+ expect(result[jss::result][jss::info]
+ [jss::pubkey_validator] == validator::signing_key);
+ expect (result[jss::result][jss::info].isMember(
+ jss::validation_manifest));
+ expect (result[jss::result][jss::info][jss::validation_manifest]
+ [jss::master_key] == validator::master_key);
+ expect (result[jss::result][jss::info][jss::validation_manifest]
+ [jss::signing_key] == validator::signing_key);
+ expect (result[jss::result][jss::info][jss::validation_manifest]
+ [jss::seq] == validator::sequence);
+ }
+ }
+
+ void run ()
+ {
+ testServerInfo ();
+ }
+};
+
+BEAST_DEFINE_TESTSUITE(ServerInfo,app,ripple);
+
+} // test
+} // ripple
+
diff --git a/src/ripple/unity/rpcx.cpp b/src/ripple/unity/rpcx.cpp
index bc652aa6da..9635457ebc 100644
--- a/src/ripple/unity/rpcx.cpp
+++ b/src/ripple/unity/rpcx.cpp
@@ -102,5 +102,6 @@
#include
#include
#include
+#include
#include
#include