1#include <xrpld/app/misc/Manifest.h>
2#include <xrpld/app/rdb/Wallet.h>
3#include <xrpld/core/DatabaseCon.h>
5#include <xrpl/basics/Log.h>
6#include <xrpl/basics/StringUtilities.h>
7#include <xrpl/basics/base64.h>
8#include <xrpl/json/json_reader.h>
9#include <xrpl/protocol/PublicKey.h>
10#include <xrpl/protocol/Sign.h>
12#include <boost/algorithm/string/trim.hpp>
25 return "Revocation Manifest " + mk;
28 Throw<std::runtime_error>(
"No SigningKey in manifest " + mk);
70 st.applyTemplate(manifestFormat);
73 if (st.isFieldPresent(sfVersion) && st.getFieldU16(sfVersion) != 0)
76 auto const pk = st.getFieldVL(sfPublicKey);
88 if (st.isFieldPresent(sfDomain))
90 auto const d = st.getFieldVL(sfDomain);
92 domain.
assign(
reinterpret_cast<char const*
>(d.data()), d.size());
98 bool const hasEphemeralKey = st.isFieldPresent(sfSigningPubKey);
99 bool const hasEphemeralSig = st.isFieldPresent(sfSignature);
115 if (!hasEphemeralKey)
118 if (!hasEphemeralSig)
121 auto const spk = st.getFieldVL(sfSigningPubKey);
129 if (*signingKey == masterKey)
134 reinterpret_cast<char const*
>(s.
data()), s.
size());
137 return Manifest(serialized, masterKey, signingKey, seq, domain);
141 JLOG(journal.
error())
142 <<
"Exception in " << __func__ <<
": " << ex.
what();
147template <
class Stream>
155 s <<
"Manifest: " << action
161template <
class Stream>
170 s <<
"Manifest: " << action
172 <<
";OldSeq: " << oldSeq <<
";";
230 if (!
get(st, sfSignature))
256 return init + s.size();
259 for (
auto const& line : blob)
260 tokenStr += boost::algorithm::trim_copy(line);
267 if (r.
parse(tokenStr, token))
272 if (m.isString() && k.isString())
274 auto const key =
strUnHex(k.asString());
276 if (key && key->size() == 32)
285 JLOG(journal.
error())
286 <<
"Exception in " << __func__ <<
": " << ex.
what();
295 auto const iter =
map_.find(pk);
297 if (iter !=
map_.end() && !iter->second.revoked())
298 return iter->second.signingKey;
319 auto const iter =
map_.find(pk);
321 if (iter !=
map_.end() && !iter->second.revoked())
322 return iter->second.sequence;
331 auto const iter =
map_.find(pk);
333 if (iter !=
map_.end() && !iter->second.revoked())
334 return iter->second.domain;
343 auto const iter =
map_.find(pk);
345 if (iter !=
map_.end() && !iter->second.revoked())
346 return iter->second.serialized;
355 auto const iter =
map_.find(pk);
357 if (iter !=
map_.end())
358 return iter->second.revoked();
373 [
this, &m](
auto const& iter,
bool checkSignature,
auto const& lock)
377 "ripple::ManifestCache::applyManifest::prewriteCheck : locked");
380 if (iter !=
map_.end() && m.
sequence <= iter->second.sequence)
392 iter->second.sequence);
396 if (checkSignature && !m.
verify())
398 if (
auto stream =
j_.
warn())
421 <<
": Master key already used as ephemeral key for "
432 <<
": is not revoked and the manifest has no "
433 "signing key. Hence, the manifest is "
445 <<
": Ephemeral key already used as ephemeral key for "
454 <<
to_string(m) <<
": Ephemeral key used as master key for "
482 if (
auto d = prewriteCheck(iter,
false, sl))
488 if (iter ==
map_.end())
490 if (
auto stream =
j_.
info())
497 map_.emplace(std::move(masterKey), std::move(m));
503 if (
auto stream =
j_.
info())
509 iter->second.sequence);
516 iter->second = std::move(m);
538 load(dbCon, dbTable);
540 if (!configManifest.
empty())
545 JLOG(
j_.
error()) <<
"Malformed validator_token in config";
551 JLOG(
j_.
warn()) <<
"Configured manifest revokes public key";
556 JLOG(
j_.
error()) <<
"Manifest in config was rejected";
561 if (!configRevocation.
empty())
565 configRevocation.
cbegin(),
566 configRevocation.
cend(),
569 return init + s.size();
572 for (
auto const& line : configRevocation)
573 revocationStr += boost::algorithm::trim_copy(line);
577 if (!mo || !mo->revoked() ||
580 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::optional< std::uint32_t > getSequence(PublicKey const &pk) const
Returns master key's current manifest sequence.
hash_map< PublicKey, PublicKey > signingToMasterKeys_
Master public keys stored by current ephemeral public key.
std::optional< std::string > getManifest(PublicKey const &pk) const
Returns mainfest corresponding to a given public key.
std::optional< PublicKey > getSigningKey(PublicKey const &pk) const
Returns master key's current signing key.
bool revoked(PublicKey const &pk) const
Returns true if master key has been revoked in a manifest.
ManifestDisposition applyManifest(Manifest m)
Add manifest to cache.
hash_map< PublicKey, Manifest > map_
Active manifests stored by master public key.
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::atomic< std::uint32_t > seq_
void save(DatabaseCon &dbCon, std::string const &dbTable, std::function< bool(PublicKey const &)> const &isTrusted)
Save cached manifests to database.
PublicKey getMasterKey(PublicKey const &pk) const
Returns ephemeral signing key's master public key.
std::optional< std::string > getDomain(PublicKey const &pk) const
Returns domain claimed by a given public key.
Defines the fields and their attributes within a STObject.
Blob getFieldVL(SField const &field) const
void set(SOTemplate const &)
uint256 getHash(HashPrefix prefix) 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.
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
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)
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 verify(PublicKey const &publicKey, Slice const &m, Slice const &sig, bool mustBeFullyCanonical=true) noexcept
Verify a signature on a message.
std::string base64_decode(std::string_view data)
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
Stream & logMftAct(Stream &s, std::string const &action, PublicKey const &pk, std::uint32_t seq)
@ 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.
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::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::optional< ValidatorToken > loadValidatorToken(std::vector< std::string > const &blob, beast::Journal journal)
bool isProperlyFormedTomlDomain(std::string_view domain)
Determines if the given string looks like a TOML-file hosting domain.
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.
std::string serialized
The manifest in serialized form.
std::uint32_t sequence
The sequence number of this manifest.
static bool revoked(std::uint32_t sequence)
Returns true if manifest revokes master key.
bool revoked() const
Returns true if manifest revokes master key.
bool verify() const
Returns true if manifest signature is valid.
uint256 hash() const
Returns hash of serialized manifest data.
std::optional< Blob > getSignature() const
Returns manifest signature.
std::optional< PublicKey > signingKey
The ephemeral key associated with this manifest.
Blob getMasterSignature() const
Returns manifest master key signature.
PublicKey masterKey
The master key associated with this manifest.