20#include <xrpld/app/misc/Manifest.h>
21#include <xrpld/app/rdb/Wallet.h>
22#include <xrpld/core/DatabaseCon.h>
23#include <xrpl/basics/Log.h>
24#include <xrpl/basics/StringUtilities.h>
25#include <xrpl/basics/base64.h>
26#include <xrpl/json/json_reader.h>
27#include <xrpl/protocol/PublicKey.h>
28#include <xrpl/protocol/Sign.h>
30#include <boost/algorithm/string/trim.hpp>
43 return "Revocation Manifest " + mk;
46 Throw<std::runtime_error>(
"No SigningKey in manifest " + mk);
88 st.applyTemplate(manifestFormat);
91 if (st.isFieldPresent(sfVersion) && st.getFieldU16(sfVersion) != 0)
94 auto const pk = st.getFieldVL(sfPublicKey);
106 if (st.isFieldPresent(sfDomain))
108 auto const d = st.getFieldVL(sfDomain);
110 domain.
assign(
reinterpret_cast<char const*
>(d.data()), d.size());
116 bool const hasEphemeralKey = st.isFieldPresent(sfSigningPubKey);
117 bool const hasEphemeralSig = st.isFieldPresent(sfSignature);
133 if (!hasEphemeralKey)
136 if (!hasEphemeralSig)
139 auto const spk = st.getFieldVL(sfSigningPubKey);
147 if (*signingKey == masterKey)
152 reinterpret_cast<char const*
>(s.
data()), s.
size());
155 return Manifest(serialized, masterKey, signingKey, seq, domain);
159 JLOG(journal.
error())
160 <<
"Exception in " << __func__ <<
": " << ex.
what();
165template <
class Stream>
173 s <<
"Manifest: " << action
179template <
class Stream>
188 s <<
"Manifest: " << action
190 <<
";OldSeq: " << oldSeq <<
";";
248 if (!
get(st, sfSignature))
274 return init + s.size();
277 for (
auto const& line : blob)
278 tokenStr += boost::algorithm::trim_copy(line);
285 if (r.
parse(tokenStr, token))
290 if (m.isString() && k.isString())
292 auto const key =
strUnHex(k.asString());
294 if (key && key->size() == 32)
303 JLOG(journal.
error())
304 <<
"Exception in " << __func__ <<
": " << ex.
what();
313 auto const iter =
map_.find(pk);
315 if (iter !=
map_.end() && !iter->second.revoked())
316 return iter->second.signingKey;
337 auto const iter =
map_.find(pk);
339 if (iter !=
map_.end() && !iter->second.revoked())
340 return iter->second.sequence;
349 auto const iter =
map_.find(pk);
351 if (iter !=
map_.end() && !iter->second.revoked())
352 return iter->second.domain;
361 auto const iter =
map_.find(pk);
363 if (iter !=
map_.end() && !iter->second.revoked())
364 return iter->second.serialized;
373 auto const iter =
map_.find(pk);
375 if (iter !=
map_.end())
376 return iter->second.revoked();
391 [
this, &m](
auto const& iter,
bool checkSignature,
auto const& lock)
395 "ripple::ManifestCache::applyManifest::prewriteCheck : locked");
398 if (iter !=
map_.end() && m.
sequence <= iter->second.sequence)
410 iter->second.sequence);
414 if (checkSignature && !m.
verify())
416 if (
auto stream =
j_.
warn())
439 <<
": Master key already used as ephemeral key for "
450 <<
": is not revoked and the manifest has no "
451 "signing key. Hence, the manifest is "
463 <<
": Ephemeral key already used as ephemeral key for "
472 <<
to_string(m) <<
": Ephemeral key used as master key for "
500 if (
auto d = prewriteCheck(iter,
false, sl))
506 if (iter ==
map_.end())
508 if (
auto stream =
j_.
info())
515 map_.emplace(std::move(masterKey), std::move(m));
521 if (
auto stream =
j_.
info())
527 iter->second.sequence);
534 iter->second = std::move(m);
556 load(dbCon, dbTable);
558 if (!configManifest.
empty())
563 JLOG(
j_.
error()) <<
"Malformed validator_token in config";
569 JLOG(
j_.
warn()) <<
"Configured manifest revokes public key";
574 JLOG(
j_.
error()) <<
"Manifest in config was rejected";
579 if (!configRevocation.
empty())
583 configRevocation.
cbegin(),
584 configRevocation.
cend(),
587 return init + s.size();
590 for (
auto const& line : configRevocation)
591 revocationStr += boost::algorithm::trim_copy(line);
595 if (!mo || !mo->revoked() ||
598 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, const Value &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
uint256 getHash(HashPrefix prefix) const
void set(const SOTemplate &)
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.