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

@@ -29,6 +29,7 @@
#include <ripple/basics/Time.h>
#include <ripple/core/Config.h>
#include <ripple/core/LoadFeeTrack.h>
#include <ripple/crypto/Base58.h>
#include <ripple/net/HTTPClient.h>
#include <ripple/protocol/JsonFields.h>
#include <beast/module/core/thread/DeadlineTimer.h>
@@ -90,6 +91,18 @@ strJoin (Iterator first, Iterator last, std::string strSeparator)
return ossValues.str ();
}
static
std::string
encodeCredential (AnyPublicKey const& pk, unsigned char type)
{
Blob buffer;
buffer.reserve(1 + pk.size());
buffer.push_back (type);
auto const data = pk.data();
buffer.insert (buffer.end(), data, data + pk.size());
return Base58::encodeWithCheck (buffer);
}
template <size_t I, class String>
void selectBlobsIntoStrings (
soci::session& s,
@@ -214,6 +227,7 @@ private:
// XXX Make this faster, make this the contents vector unsigned char or raw public key.
// XXX Contents needs to based on score.
hash_set<std::string> mUNL;
hash_map<AnyPublicKey, std::string> ephemeralValidatorKeys_;
boost::posix_time::ptime mtpScoreNext; // When to start scoring.
boost::posix_time::ptime mtpScoreStart; // Time currently started scoring.
@@ -244,6 +258,9 @@ public:
// Get update times and start fetching and scoring as needed.
void start();
void insertEphemeralKey (AnyPublicKey pk, std::string comment);
void deleteEphemeralKey (AnyPublicKey const& pk);
// Add a trusted node. Called by RPC or other source.
void nodeAddPublic (RippleAddress const& naNodePublic, ValidatorSource vsWhy, std::string const& strComment);
@@ -468,6 +485,22 @@ void UniqueNodeListImp::start()
//--------------------------------------------------------------------------
void UniqueNodeListImp::insertEphemeralKey (AnyPublicKey pk, std::string comment)
{
ScopedUNLLockType sl (mUNLLock);
ephemeralValidatorKeys_.insert (std::make_pair(std::move(pk), std::move(comment)));
}
void UniqueNodeListImp::deleteEphemeralKey (AnyPublicKey const& pk)
{
ScopedUNLLockType sl (mUNLLock);
ephemeralValidatorKeys_.erase (pk);
}
//--------------------------------------------------------------------------
// Add a trusted node. Called by RPC or other source.
void UniqueNodeListImp::nodeAddPublic (RippleAddress const& naNodePublic, ValidatorSource vsWhy, std::string const& strComment)
{
@@ -612,9 +645,17 @@ void UniqueNodeListImp::nodeScore()
bool UniqueNodeListImp::nodeInUNL (RippleAddress const& naNodePublic)
{
auto const& blob = naNodePublic.getNodePublic();
AnyPublicKey const pk (blob.data(), blob.size());
ScopedUNLLockType sl (mUNLLock);
return mUNL.end () != mUNL.find (naNodePublic.humanNodePublic ());
if (ephemeralValidatorKeys_.find (pk) != ephemeralValidatorKeys_.end())
{
return true;
}
return mUNL.find (naNodePublic.humanNodePublic()) != mUNL.end();
}
//--------------------------------------------------------------------------
@@ -883,6 +924,18 @@ Json::Value UniqueNodeListImp::getUnlJson()
ret.append (node);
}
ScopedUNLLockType sl (mUNLLock);
for (auto const& key : ephemeralValidatorKeys_)
{
Json::Value node (Json::objectValue);
node["publicKey"] = encodeCredential (key.first, VER_NODE_PUBLIC);
node["comment"] = key.second;
ret.append (node);
}
return ret;
}