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)
136 return Manifest(serialized, masterKey, signingKey, seq, domain);
140 JLOG(journal.
error()) <<
"Exception in " << __func__ <<
": " << ex.
what();
145template <
class Stream>
153template <
class Stream>
158 <<
";OldSeq: " << oldSeq <<
";";
215 if (!
get(st, sfSignature))
238 return init + s.size();
241 for (
auto const& line : blob)
242 tokenStr += boost::algorithm::trim_copy(line);
249 if (r.
parse(tokenStr, token))
254 if (m.isString() && k.isString())
256 auto const key =
strUnHex(k.asString());
258 if (key && key->size() == 32)
267 JLOG(journal.
error()) <<
"Exception in " << __func__ <<
": " << ex.
what();
276 auto const iter =
map_.find(pk);
278 if (iter !=
map_.end() && !iter->second.revoked())
279 return iter->second.signingKey;
299 auto const iter =
map_.find(pk);
301 if (iter !=
map_.end() && !iter->second.revoked())
302 return iter->second.sequence;
311 auto const iter =
map_.find(pk);
313 if (iter !=
map_.end() && !iter->second.revoked())
314 return iter->second.domain;
323 auto const iter =
map_.find(pk);
325 if (iter !=
map_.end() && !iter->second.revoked())
326 return iter->second.serialized;
335 auto const iter =
map_.find(pk);
337 if (iter !=
map_.end())
338 return iter->second.revoked();
354 XRPL_ASSERT(lock.owns_lock(),
"xrpl::ManifestCache::applyManifest::prewriteCheck : locked");
357 if (iter !=
map_.end() && m.
sequence <= iter->second.sequence)
368 if (checkSignature && !m.
verify())
370 if (
auto stream =
j_.
warn())
391 JLOG(
j_.
warn()) <<
to_string(m) <<
": Master key already used as ephemeral key for "
402 <<
": is not revoked and the manifest has no "
403 "signing key. Hence, the manifest is "
412 JLOG(
j_.
warn()) <<
to_string(m) <<
": Ephemeral key already used as ephemeral key for "
431 if (
auto d = prewriteCheck(
map_.find(m.
masterKey),
true, sl))
446 if (
auto d = prewriteCheck(iter,
false, sl))
452 if (iter ==
map_.end())
454 if (
auto stream =
j_.
info())
461 map_.emplace(std::move(masterKey), std::move(m));
471 if (
auto stream =
j_.
info())
479 iter->second = std::move(m);
501 load(dbCon, dbTable);
503 if (!configManifest.
empty())
508 JLOG(
j_.
error()) <<
"Malformed validator_token in config";
514 JLOG(
j_.
warn()) <<
"Configured manifest revokes public key";
519 JLOG(
j_.
error()) <<
"Manifest in config was rejected";
524 if (!configRevocation.
empty())
528 configRevocation.
cbegin(),
529 configRevocation.
cend(),
533 for (
auto const& line : configRevocation)
534 revocationStr += boost::algorithm::trim_copy(line);
540 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)
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< ValidatorToken > loadValidatorToken(std::vector< std::string > const &blob, beast::Journal journal)
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.
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::enable_if_t< std::is_same< T, char >::value||std::is_same< T, unsigned char >::value, Slice > makeSlice(std::array< T, N > const &a)
@ 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.