Add Validator Manifests (RIPD-772):

A Validator Manifest allows validators to use a generated ed25519
secret key as a master key for generating new validator public/secret
key pairs. Using this mechanism, rippled instances trust the master
ed25519 public key instead of the now-ephemeral validator public key.

Through a new message and propagation scheme, this lets a validator
change its ephemeral public key without requiring that all rippled
instances on the network restart after maintaining the configuration
file.
This commit is contained in:
Josh Juran
2015-04-10 14:41:16 -07:00
committed by seelabs
parent 41a840e776
commit 0dd6b95ac2
17 changed files with 844 additions and 15 deletions

View File

@@ -28,6 +28,7 @@
#include <ripple/overlay/impl/PeerImp.h>
#include <ripple/overlay/impl/TMHello.h>
#include <ripple/peerfinder/make_Manager.h>
#include <ripple/protocol/STExchange.h>
#include <beast/ByteOrder.h>
#include <beast/crypto/base64.h>
#include <beast/http/rfc2616.h>
@@ -425,9 +426,47 @@ OverlayImpl::checkStopped ()
stopped();
}
static
void
prepareValidatorKeyManifests (ManifestCache& mc, beast::Journal const& journal)
{
auto const validator_keys = getConfig().section("validator_keys");
auto const validation_manifest = getConfig().section("validation_manifest");
if (! validator_keys.lines().empty())
{
for (auto const& line : validator_keys.lines())
{
mc.configValidatorKey (line, journal);
}
}
else
{
if (journal.warning)
journal.warning << "[validator_keys] is empty";
}
if (! validation_manifest.lines().empty())
{
std::string s;
for (auto const& line : validation_manifest.lines())
s += beast::rfc2616::trim(line);
s = beast::base64_decode(s);
mc.configManifest(std::move(s), journal);
}
else
{
if (journal.warning)
journal.warning << "No [validation_manifest] section in config";
}
}
void
OverlayImpl::onPrepare()
{
prepareValidatorKeyManifests (manifestCache_, journal_);
PeerFinder::Config config;
if (getConfig ().PEERS_MAX != 0)
@@ -576,6 +615,59 @@ OverlayImpl::onPeerDeactivate (Peer::id_t id,
m_publicKeyMap.erase(publicKey);
}
void
OverlayImpl::onManifests (Job&,
std::shared_ptr<protocol::TMManifests> const& inbox,
std::shared_ptr<PeerImp> const& from)
{
auto& hashRouter = getApp().getHashRouter();
auto const n = inbox->list_size();
auto const& journal = from->pjournal();
if (journal.debug) journal.debug
<< "TMManifest, " << n << (n == 1 ? " item" : " items");
protocol::TMManifests outbox;
for (std::size_t i = 0; i < n; ++i)
{
auto& s = inbox->list().Get(i).stobject();
uint256 const hash = getSHA512Half (s);
auto const result = manifestCache_.applyManifest (s, journal);
if (result == ManifestDisposition::accepted)
{
protocol::TMManifests outbox;
outbox.add_list()->set_stobject(s);
auto const msg = std::make_shared<Message>(outbox, protocol::mtMANIFESTS);
for_each( [&](std::shared_ptr<PeerImp> const& peer)
{
if (hashRouter.addSuppressionPeer (hash, peer->id()) && peer != from)
{
if (auto& j = peer->pjournal().warning)
j << "Forwarding manifest with hash " << hash;
peer->send(msg);
}
else if (peer != from)
{
if (auto& j = peer->pjournal().warning)
j << "Suppressed manifest with hash " << hash;
}
});
}
else
{
if (journal.info) journal.info
<< "Bad manifest #" << i + 1;
}
}
}
std::size_t
OverlayImpl::selectPeers (PeerSet& set, std::size_t limit,
std::function<bool(std::shared_ptr<Peer> const&)> score)