1#include <xrpl/basics/Log.h>
2#include <xrpl/basics/StringUtilities.h>
3#include <xrpl/basics/base64.h>
4#include <xrpl/json/json_reader.h>
5#include <xrpl/protocol/PublicKey.h>
6#include <xrpl/protocol/Sign.h>
7#include <xrpl/rdb/DatabaseCon.h>
8#include <xrpl/server/Manifest.h>
9#include <xrpl/server/Wallet.h>
11#include <boost/algorithm/string/trim.hpp>
24 return "Revocation Manifest " + mk;
27 Throw<std::runtime_error>(
"No SigningKey in manifest " + mk);
69 st.applyTemplate(manifestFormat);
72 if (st.isFieldPresent(sfVersion) && st.getFieldU16(sfVersion) != 0)
75 auto const pk = st.getFieldVL(sfPublicKey);
87 if (st.isFieldPresent(sfDomain))
89 auto const d = st.getFieldVL(sfDomain);
91 domain.
assign(
reinterpret_cast<char const*
>(d.data()), d.size());
97 bool const hasEphemeralKey = st.isFieldPresent(sfSigningPubKey);
98 bool const hasEphemeralSig = st.isFieldPresent(sfSignature);
114 if (!hasEphemeralKey)
117 if (!hasEphemeralSig)
120 auto const spk = st.getFieldVL(sfSigningPubKey);
128 if (*signingKey == masterKey)
135 return Manifest(serialized, masterKey, signingKey, seq, domain);
139 JLOG(journal.
error()) <<
"Exception in " << __func__ <<
": " << ex.
what();
144template <
class Stream>
152template <
class Stream>
157 <<
";OldSeq: " << oldSeq <<
";";
214 if (!
get(st, sfSignature))
237 return init + s.size();
240 for (
auto const& line : blob)
241 tokenStr += boost::algorithm::trim_copy(line);
248 if (r.
parse(tokenStr, token))
253 if (m.isString() && k.isString())
255 auto const key =
strUnHex(k.asString());
257 if (key && key->size() == 32)
266 JLOG(journal.
error()) <<
"Exception in " << __func__ <<
": " << ex.
what();
275 auto const iter =
map_.find(pk);
277 if (iter !=
map_.end() && !iter->second.revoked())
278 return iter->second.signingKey;
298 auto const iter =
map_.find(pk);
300 if (iter !=
map_.end() && !iter->second.revoked())
301 return iter->second.sequence;
310 auto const iter =
map_.find(pk);
312 if (iter !=
map_.end() && !iter->second.revoked())
313 return iter->second.domain;
322 auto const iter =
map_.find(pk);
324 if (iter !=
map_.end() && !iter->second.revoked())
325 return iter->second.serialized;
334 auto const iter =
map_.find(pk);
336 if (iter !=
map_.end())
337 return iter->second.revoked();
353 XRPL_ASSERT(lock.owns_lock(),
"xrpl::ManifestCache::applyManifest::prewriteCheck : locked");
356 if (iter !=
map_.end() && m.
sequence <= iter->second.sequence)
367 if (checkSignature && !m.
verify())
369 if (
auto stream =
j_.
warn())
390 JLOG(
j_.
warn()) <<
to_string(m) <<
": Master key already used as ephemeral key for "
401 <<
": is not revoked and the manifest has no "
402 "signing key. Hence, the manifest is "
411 JLOG(
j_.
warn()) <<
to_string(m) <<
": Ephemeral key already used as ephemeral key for "
430 if (
auto d = prewriteCheck(
map_.find(m.
masterKey),
true, sl))
445 if (
auto d = prewriteCheck(iter,
false, sl))
451 if (iter ==
map_.end())
453 if (
auto stream =
j_.
info())
460 map_.emplace(std::move(masterKey), std::move(m));
470 if (
auto stream =
j_.
info())
478 iter->second = std::move(m);
500 load(dbCon, dbTable);
502 if (!configManifest.
empty())
507 JLOG(
j_.
error()) <<
"Malformed validator_token in config";
513 JLOG(
j_.
warn()) <<
"Configured manifest revokes public key";
518 JLOG(
j_.
error()) <<
"Manifest in config was rejected";
523 if (!configRevocation.
empty())
527 configRevocation.
cbegin(),
528 configRevocation.
cend(),
532 for (
auto const& line : configRevocation)
533 revocationStr += boost::algorithm::trim_copy(line);
539 JLOG(
j_.
error()) <<
"Invalid validator key revocation in config";
Unserialize a JSON document into a Value.
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
Value get(UInt index, Value const &defaultValue) const
If the array contains at least index+1 elements, returns the element value, otherwise returns default...
A generic endpoint for log messages.
LockedSociSession checkoutDb()
std::atomic< std::uint32_t > seq_
bool load(DatabaseCon &dbCon, std::string const &dbTable, std::string const &configManifest, std::vector< std::string > const &configRevocation)
Populate manifest cache with manifests in database and config.
std::optional< PublicKey > getSigningKey(PublicKey const &pk) const
Returns master key's current signing key.
ManifestDisposition applyManifest(Manifest m)
Add manifest to cache.
std::optional< std::string > getDomain(PublicKey const &pk) const
Returns domain claimed by a given public key.
PublicKey getMasterKey(PublicKey const &pk) const
Returns ephemeral signing key's master public key.
hash_map< PublicKey, PublicKey > signingToMasterKeys_
Master public keys stored by current ephemeral public key.
std::optional< std::string > getManifest(PublicKey const &pk) const
Returns manifest corresponding to a given public key.
hash_map< PublicKey, Manifest > map_
Active manifests stored by master public key.
std::optional< std::uint32_t > getSequence(PublicKey const &pk) const
Returns master key's current manifest sequence.
void save(DatabaseCon &dbCon, std::string const &dbTable, std::function< bool(PublicKey const &)> const &isTrusted)
Save cached manifests to database.
bool revoked(PublicKey const &pk) const
Returns true if master key has been revoked in a manifest.
Defines the fields and their attributes within a STObject.
Blob getFieldVL(SField const &field) const
uint256 getHash(HashPrefix prefix) const
void set(SOTemplate const &)
An immutable linear range of bytes.
bool empty() const noexcept
Return true if the byte range is empty.
std::uint8_t const * data() const noexcept
Return a pointer to beginning of the storage.
std::size_t size() const noexcept
Returns the number of bytes in the storage.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Stream & logMftAct(Stream &s, std::string const &action, PublicKey const &pk, std::uint32_t seq)
void getManifests(soci::session &session, std::string const &dbTable, ManifestCache &mCache, beast::Journal j)
getManifests Loads a manifest from the wallet database and stores it in the cache.
void saveManifests(soci::session &session, std::string const &dbTable, std::function< bool(PublicKey const &)> const &isTrusted, hash_map< PublicKey, Manifest > const &map, beast::Journal j)
saveManifests Saves all given manifests to the database.
bool isProperlyFormedTomlDomain(std::string_view domain)
Determines if the given string looks like a TOML-file hosting domain.
std::string to_string(base_uint< Bits, Tag > const &a)
T get(Section const §ion, std::string const &name, T const &defaultValue=T{})
Retrieve a key/value pair from a section.
std::string base64_decode(std::string_view data)
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig) noexcept
Verify a signature on a message.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
std::optional< Manifest > deserializeManifest(Slice s, beast::Journal journal)
Constructs Manifest from serialized string.
std::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
std::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
std::optional< ValidatorToken > loadValidatorToken(std::vector< std::string > const &blob, beast::Journal journal=beast::Journal(beast::Journal::getNullSink()))
@ badMasterKey
The master key is not acceptable to us.
@ stale
Sequence is too old.
@ accepted
Manifest is valid.
@ badEphemeralKey
The ephemeral key is not acceptable to us.
@ invalid
Timely, but invalid signature.
static bool revoked(std::uint32_t sequence)
Returns true if manifest revokes master key.
PublicKey masterKey
The master key associated with this manifest.
std::string serialized
The manifest in serialized form.
Blob getMasterSignature() const
Returns manifest master key signature.
std::optional< Blob > getSignature() const
Returns manifest signature.
std::optional< PublicKey > signingKey
The ephemeral key associated with this manifest.
std::uint32_t sequence
The sequence number of this manifest.
bool revoked() const
Returns true if manifest revokes master key.
uint256 hash() const
Returns hash of serialized manifest data.
bool verify() const
Returns true if manifest signature is valid.