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 <<
";";
229 if (!
get(st, sfSignature))
255 return init + s.size();
258 for (
auto const& line : blob)
259 tokenStr += boost::algorithm::trim_copy(line);
266 if (r.
parse(tokenStr, token))
271 if (m.isString() && k.isString())
273 auto const key =
strUnHex(k.asString());
275 if (key && key->size() == 32)
284 JLOG(journal.
error())
285 <<
"Exception in " << __func__ <<
": " << ex.
what();
294 auto const iter =
map_.find(pk);
296 if (iter !=
map_.end() && !iter->second.revoked())
297 return iter->second.signingKey;
318 auto const iter =
map_.find(pk);
320 if (iter !=
map_.end() && !iter->second.revoked())
321 return iter->second.sequence;
330 auto const iter =
map_.find(pk);
332 if (iter !=
map_.end() && !iter->second.revoked())
333 return iter->second.domain;
342 auto const iter =
map_.find(pk);
344 if (iter !=
map_.end() && !iter->second.revoked())
345 return iter->second.serialized;
354 auto const iter =
map_.find(pk);
356 if (iter !=
map_.end())
357 return iter->second.revoked();
372 [
this, &m](
auto const& iter,
bool checkSignature,
auto const& lock)
376 "xrpl::ManifestCache::applyManifest::prewriteCheck : locked");
379 if (iter !=
map_.end() && m.
sequence <= iter->second.sequence)
391 iter->second.sequence);
395 if (checkSignature && !m.
verify())
397 if (
auto stream =
j_.
warn())
420 <<
": Master key already used as ephemeral key for "
431 <<
": is not revoked and the manifest has no "
432 "signing key. Hence, the manifest is "
444 <<
": Ephemeral key already used as ephemeral key for "
453 <<
to_string(m) <<
": Ephemeral key used as master key for "
481 if (
auto d = prewriteCheck(iter,
false, sl))
487 if (iter ==
map_.end())
489 if (
auto stream =
j_.
info())
496 map_.emplace(std::move(masterKey), std::move(m));
502 if (
auto stream =
j_.
info())
508 iter->second.sequence);
515 iter->second = std::move(m);
537 load(dbCon, dbTable);
539 if (!configManifest.
empty())
544 JLOG(
j_.
error()) <<
"Malformed validator_token in config";
550 JLOG(
j_.
warn()) <<
"Configured manifest revokes public key";
555 JLOG(
j_.
error()) <<
"Manifest in config was rejected";
560 if (!configRevocation.
empty())
564 configRevocation.
cbegin(),
565 configRevocation.
cend(),
568 return init + s.size();
571 for (
auto const& line : configRevocation)
572 revocationStr += boost::algorithm::trim_copy(line);
576 if (!mo || !mo->revoked() ||
579 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.