mirror of
https://github.com/XRPLF/rippled.git
synced 2025-12-06 17:27:55 +00:00
Support UNLs with future effective dates:
* Creates a version 2 of the UNL file format allowing publishers to pre-publish the next UNL while the current one is still valid. * Version 1 of the UNL file format is still valid and backward compatible. * Also causes rippled to lock down if it has no valid UNLs, similar to being amendment blocked, except reversible. * Resolves #3548 * Resolves #3470
This commit is contained in:
@@ -46,6 +46,8 @@ class ShardArchiveHandler_test : public beast::unit_test::suite
|
||||
env.app().getIOService(),
|
||||
list,
|
||||
env.timeKeeper().now() + std::chrono::seconds{3600},
|
||||
// No future VLs
|
||||
{},
|
||||
ssl);
|
||||
}
|
||||
|
||||
|
||||
@@ -189,12 +189,20 @@ public:
|
||||
// Manage single-thread io_service for server.
|
||||
BasicApp worker{1};
|
||||
using namespace std::chrono_literals;
|
||||
NetClock::time_point const expiration{3600s};
|
||||
NetClock::time_point const validUntil{3600s};
|
||||
NetClock::time_point const validFrom2{validUntil - 60s};
|
||||
NetClock::time_point const validUntil2{validFrom2 + 3600s};
|
||||
auto server = make_TrustedPublisherServer(
|
||||
worker.get_io_service(), validators, expiration, false, 1, false);
|
||||
worker.get_io_service(),
|
||||
validators,
|
||||
validUntil,
|
||||
{{validFrom2, validUntil2}},
|
||||
false,
|
||||
1,
|
||||
false);
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Publisher list site unavailable
|
||||
// Publisher list site unavailable v1
|
||||
{
|
||||
// Publisher site information
|
||||
using namespace std::string_literals;
|
||||
@@ -261,11 +269,78 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
// Publisher list site unavailable v2
|
||||
{
|
||||
// Publisher site information
|
||||
using namespace std::string_literals;
|
||||
std::string siteURI =
|
||||
"http://"s + getEnvLocalhostAddr() + ":1234/validators2";
|
||||
|
||||
Env env{
|
||||
*this,
|
||||
envconfig([&](std::unique_ptr<Config> cfg) {
|
||||
cfg->section(SECTION_VALIDATOR_LIST_SITES).append(siteURI);
|
||||
cfg->section(SECTION_VALIDATOR_LIST_KEYS)
|
||||
.append(strHex(server->publisherPublic()));
|
||||
return cfg;
|
||||
}),
|
||||
};
|
||||
|
||||
env.app().validatorSites().start();
|
||||
env.app().validatorSites().join();
|
||||
|
||||
{
|
||||
auto const jrr = env.rpc("server_info")[jss::result];
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::info][jss::validator_list][jss::expiration] ==
|
||||
"unknown");
|
||||
}
|
||||
{
|
||||
auto const jrr = env.rpc("server_state")[jss::result];
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::state][jss::validator_list_expires].asInt() == 0);
|
||||
}
|
||||
{
|
||||
auto const jrr = env.rpc("validators")[jss::result];
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::validation_quorum].asUInt() ==
|
||||
std::numeric_limits<std::uint32_t>::max());
|
||||
BEAST_EXPECT(jrr[jss::local_static_keys].size() == 0);
|
||||
BEAST_EXPECT(jrr[jss::trusted_validator_keys].size() == 0);
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::validator_list][jss::expiration] == "unknown");
|
||||
|
||||
if (BEAST_EXPECT(jrr[jss::publisher_lists].size() == 1))
|
||||
{
|
||||
auto jp = jrr[jss::publisher_lists][0u];
|
||||
BEAST_EXPECT(jp[jss::available] == false);
|
||||
BEAST_EXPECT(jp[jss::list].size() == 0);
|
||||
BEAST_EXPECT(!jp.isMember(jss::seq));
|
||||
BEAST_EXPECT(!jp.isMember(jss::expiration));
|
||||
BEAST_EXPECT(!jp.isMember(jss::version));
|
||||
BEAST_EXPECT(
|
||||
jp[jss::pubkey_publisher] ==
|
||||
strHex(server->publisherPublic()));
|
||||
}
|
||||
BEAST_EXPECT(jrr[jss::signing_keys].size() == 0);
|
||||
}
|
||||
{
|
||||
auto const jrr = env.rpc("validator_list_sites")[jss::result];
|
||||
if (BEAST_EXPECT(jrr[jss::validator_sites].size() == 1))
|
||||
{
|
||||
auto js = jrr[jss::validator_sites][0u];
|
||||
BEAST_EXPECT(js[jss::refresh_interval_min].asUInt() == 5);
|
||||
BEAST_EXPECT(js[jss::uri] == siteURI);
|
||||
BEAST_EXPECT(js.isMember(jss::last_refresh_time));
|
||||
BEAST_EXPECT(js[jss::last_refresh_status] == "invalid");
|
||||
}
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------
|
||||
// Publisher list site available
|
||||
server->start();
|
||||
// Publisher list site available v1
|
||||
{
|
||||
server->start();
|
||||
|
||||
std::stringstream uri;
|
||||
uri << "http://" << server->local_endpoint() << "/validators";
|
||||
auto siteURI = uri.str();
|
||||
@@ -286,26 +361,31 @@ public:
|
||||
for (auto const& val : validators)
|
||||
startKeys.insert(calcNodeID(val.masterPublic));
|
||||
|
||||
env.app().validators().updateTrusted(startKeys);
|
||||
env.app().validators().updateTrusted(
|
||||
startKeys,
|
||||
env.timeKeeper().now(),
|
||||
env.app().getOPs(),
|
||||
env.app().overlay(),
|
||||
env.app().getHashRouter());
|
||||
|
||||
{
|
||||
auto const jrr = env.rpc("server_info")[jss::result];
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::info][jss::validator_list][jss::expiration] ==
|
||||
to_string(expiration));
|
||||
to_string(validUntil));
|
||||
}
|
||||
{
|
||||
auto const jrr = env.rpc("server_state")[jss::result];
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::state][jss::validator_list_expires].asUInt() ==
|
||||
expiration.time_since_epoch().count());
|
||||
validUntil.time_since_epoch().count());
|
||||
}
|
||||
{
|
||||
auto const jrr = env.rpc("validators")[jss::result];
|
||||
BEAST_EXPECT(jrr[jss::validation_quorum].asUInt() == 2);
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::validator_list][jss::expiration] ==
|
||||
to_string(expiration));
|
||||
to_string(validUntil));
|
||||
BEAST_EXPECT(jrr[jss::local_static_keys].size() == 0);
|
||||
|
||||
BEAST_EXPECT(
|
||||
@@ -334,7 +414,7 @@ public:
|
||||
BEAST_EXPECT(
|
||||
jp[jss::pubkey_publisher] ==
|
||||
strHex(server->publisherPublic()));
|
||||
BEAST_EXPECT(jp[jss::expiration] == to_string(expiration));
|
||||
BEAST_EXPECT(jp[jss::expiration] == to_string(validUntil));
|
||||
BEAST_EXPECT(jp[jss::version] == 1);
|
||||
}
|
||||
auto jsk = jrr[jss::signing_keys];
|
||||
@@ -361,6 +441,129 @@ public:
|
||||
}
|
||||
}
|
||||
}
|
||||
// Publisher list site available v2
|
||||
{
|
||||
std::stringstream uri;
|
||||
uri << "http://" << server->local_endpoint() << "/validators2";
|
||||
auto siteURI = uri.str();
|
||||
|
||||
Env env{
|
||||
*this,
|
||||
envconfig([&](std::unique_ptr<Config> cfg) {
|
||||
cfg->section(SECTION_VALIDATOR_LIST_SITES).append(siteURI);
|
||||
cfg->section(SECTION_VALIDATOR_LIST_KEYS)
|
||||
.append(strHex(server->publisherPublic()));
|
||||
return cfg;
|
||||
}),
|
||||
};
|
||||
|
||||
env.app().validatorSites().start();
|
||||
env.app().validatorSites().join();
|
||||
hash_set<NodeID> startKeys;
|
||||
for (auto const& val : validators)
|
||||
startKeys.insert(calcNodeID(val.masterPublic));
|
||||
|
||||
env.app().validators().updateTrusted(
|
||||
startKeys,
|
||||
env.timeKeeper().now(),
|
||||
env.app().getOPs(),
|
||||
env.app().overlay(),
|
||||
env.app().getHashRouter());
|
||||
|
||||
{
|
||||
auto const jrr = env.rpc("server_info")[jss::result];
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::info][jss::validator_list][jss::expiration] ==
|
||||
to_string(validUntil2));
|
||||
}
|
||||
{
|
||||
auto const jrr = env.rpc("server_state")[jss::result];
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::state][jss::validator_list_expires].asUInt() ==
|
||||
validUntil2.time_since_epoch().count());
|
||||
}
|
||||
{
|
||||
auto const jrr = env.rpc("validators")[jss::result];
|
||||
BEAST_EXPECT(jrr[jss::validation_quorum].asUInt() == 2);
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::validator_list][jss::expiration] ==
|
||||
to_string(validUntil2));
|
||||
BEAST_EXPECT(jrr[jss::local_static_keys].size() == 0);
|
||||
|
||||
BEAST_EXPECT(
|
||||
jrr[jss::trusted_validator_keys].size() ==
|
||||
expectedKeys.size());
|
||||
for (auto const& jKey : jrr[jss::trusted_validator_keys])
|
||||
{
|
||||
BEAST_EXPECT(expectedKeys.count(jKey.asString()) == 1);
|
||||
}
|
||||
|
||||
if (BEAST_EXPECT(jrr[jss::publisher_lists].size() == 1))
|
||||
{
|
||||
auto jp = jrr[jss::publisher_lists][0u];
|
||||
BEAST_EXPECT(jp[jss::available] == true);
|
||||
if (BEAST_EXPECT(jp[jss::list].size() == 2))
|
||||
{
|
||||
// check entries
|
||||
std::set<std::string> foundKeys;
|
||||
for (auto const& k : jp[jss::list])
|
||||
{
|
||||
foundKeys.insert(k.asString());
|
||||
}
|
||||
BEAST_EXPECT(foundKeys == expectedKeys);
|
||||
}
|
||||
BEAST_EXPECT(jp[jss::seq].asUInt() == 1);
|
||||
BEAST_EXPECT(
|
||||
jp[jss::pubkey_publisher] ==
|
||||
strHex(server->publisherPublic()));
|
||||
BEAST_EXPECT(jp[jss::expiration] == to_string(validUntil));
|
||||
BEAST_EXPECT(jp[jss::version] == 2);
|
||||
if (BEAST_EXPECT(jp.isMember(jss::remaining)) &&
|
||||
BEAST_EXPECT(jp[jss::remaining].isArray()) &&
|
||||
BEAST_EXPECT(jp[jss::remaining].size() == 1))
|
||||
{
|
||||
auto const& r = jp[jss::remaining][0u];
|
||||
if (BEAST_EXPECT(r[jss::list].size() == 2))
|
||||
{
|
||||
// check entries
|
||||
std::set<std::string> foundKeys;
|
||||
for (auto const& k : r[jss::list])
|
||||
{
|
||||
foundKeys.insert(k.asString());
|
||||
}
|
||||
BEAST_EXPECT(foundKeys == expectedKeys);
|
||||
}
|
||||
BEAST_EXPECT(r[jss::seq].asUInt() == 2);
|
||||
BEAST_EXPECT(
|
||||
r[jss::effective] == to_string(validFrom2));
|
||||
BEAST_EXPECT(
|
||||
r[jss::expiration] == to_string(validUntil2));
|
||||
}
|
||||
}
|
||||
auto jsk = jrr[jss::signing_keys];
|
||||
BEAST_EXPECT(jsk.size() == 2);
|
||||
for (auto const& val : validators)
|
||||
{
|
||||
BEAST_EXPECT(jsk.isMember(toStr(val.masterPublic)));
|
||||
BEAST_EXPECT(
|
||||
jsk[toStr(val.masterPublic)] ==
|
||||
toStr(val.signingPublic));
|
||||
}
|
||||
}
|
||||
{
|
||||
auto const jrr = env.rpc("validator_list_sites")[jss::result];
|
||||
if (BEAST_EXPECT(jrr[jss::validator_sites].size() == 1))
|
||||
{
|
||||
auto js = jrr[jss::validator_sites][0u];
|
||||
BEAST_EXPECT(js[jss::refresh_interval_min].asUInt() == 5);
|
||||
BEAST_EXPECT(js[jss::uri] == siteURI);
|
||||
BEAST_EXPECT(js[jss::last_refresh_status] == "accepted");
|
||||
// The actual time of the update will vary run to run, so
|
||||
// just verify the time is there
|
||||
BEAST_EXPECT(js.isMember(jss::last_refresh_time));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
||||
Reference in New Issue
Block a user