20#include <xrpld/app/misc/Manifest.h>
21#include <xrpld/app/rdb/Wallet.h>
22#include <xrpld/core/DatabaseCon.h>
24#include <xrpl/basics/Log.h>
25#include <xrpl/basics/StringUtilities.h>
26#include <xrpl/basics/base64.h>
27#include <xrpl/json/json_reader.h>
28#include <xrpl/protocol/PublicKey.h>
29#include <xrpl/protocol/Sign.h>
31#include <boost/algorithm/string/trim.hpp>
44 return "Revocation Manifest " + mk;
47 Throw<std::runtime_error>(
"No SigningKey in manifest " + mk);
89 st.applyTemplate(manifestFormat);
92 if (st.isFieldPresent(sfVersion) && st.getFieldU16(sfVersion) != 0)
95 auto const pk = st.getFieldVL(sfPublicKey);
107 if (st.isFieldPresent(sfDomain))
109 auto const d = st.getFieldVL(sfDomain);
111 domain.
assign(
reinterpret_cast<char const*
>(d.data()), d.size());
117 bool const hasEphemeralKey = st.isFieldPresent(sfSigningPubKey);
118 bool const hasEphemeralSig = st.isFieldPresent(sfSignature);
134 if (!hasEphemeralKey)
137 if (!hasEphemeralSig)
140 auto const spk = st.getFieldVL(sfSigningPubKey);
148 if (*signingKey == masterKey)
153 reinterpret_cast<char const*
>(s.
data()), s.
size());
156 return Manifest(serialized, masterKey, signingKey, seq, domain);
160 JLOG(journal.
error())
161 <<
"Exception in " << __func__ <<
": " << ex.
what();
166template <
class Stream>
174 s <<
"Manifest: " << action
180template <
class Stream>
189 s <<
"Manifest: " << action
191 <<
";OldSeq: " << oldSeq <<
";";
249 if (!
get(st, sfSignature))
275 return init + s.size();
278 for (
auto const& line : blob)
279 tokenStr += boost::algorithm::trim_copy(line);
286 if (r.
parse(tokenStr, token))
291 if (m.isString() && k.isString())
293 auto const key =
strUnHex(k.asString());
295 if (key && key->size() == 32)
304 JLOG(journal.
error())
305 <<
"Exception in " << __func__ <<
": " << ex.
what();
314 auto const iter =
map_.find(pk);
316 if (iter !=
map_.end() && !iter->second.revoked())
317 return iter->second.signingKey;
338 auto const iter =
map_.find(pk);
340 if (iter !=
map_.end() && !iter->second.revoked())
341 return iter->second.sequence;
350 auto const iter =
map_.find(pk);
352 if (iter !=
map_.end() && !iter->second.revoked())
353 return iter->second.domain;
362 auto const iter =
map_.find(pk);
364 if (iter !=
map_.end() && !iter->second.revoked())
365 return iter->second.serialized;
374 auto const iter =
map_.find(pk);
376 if (iter !=
map_.end())
377 return iter->second.revoked();
392 [
this, &m](
auto const& iter,
bool checkSignature,
auto const& lock)
396 "ripple::ManifestCache::applyManifest::prewriteCheck : locked");
399 if (iter !=
map_.end() && m.
sequence <= iter->second.sequence)
411 iter->second.sequence);
415 if (checkSignature && !m.
verify())
417 if (
auto stream =
j_.
warn())
440 <<
": Master key already used as ephemeral key for "
451 <<
": is not revoked and the manifest has no "
452 "signing key. Hence, the manifest is "
464 <<
": Ephemeral key already used as ephemeral key for "
473 <<
to_string(m) <<
": Ephemeral key used as master key for "
501 if (
auto d = prewriteCheck(iter,
false, sl))
507 if (iter ==
map_.end())
509 if (
auto stream =
j_.
info())
516 map_.emplace(std::move(masterKey), std::move(m));
522 if (
auto stream =
j_.
info())
528 iter->second.sequence);
535 iter->second = std::move(m);
557 load(dbCon, dbTable);
559 if (!configManifest.
empty())
564 JLOG(
j_.
error()) <<
"Malformed validator_token in config";
570 JLOG(
j_.
warn()) <<
"Configured manifest revokes public key";
575 JLOG(
j_.
error()) <<
"Manifest in config was rejected";
580 if (!configRevocation.
empty())
584 configRevocation.
cbegin(),
585 configRevocation.
cend(),
588 return init + s.size();
591 for (
auto const& line : configRevocation)
592 revocationStr += boost::algorithm::trim_copy(line);
596 if (!mo || !mo->revoked() ||
599 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.