20 #include <ripple/app/misc/Manifest.h>
21 #include <ripple/basics/Log.h>
22 #include <ripple/basics/StringUtilities.h>
23 #include <ripple/basics/base64.h>
24 #include <ripple/basics/contract.h>
25 #include <ripple/core/DatabaseCon.h>
26 #include <ripple/json/json_reader.h>
27 #include <ripple/protocol/PublicKey.h>
28 #include <ripple/protocol/Sign.h>
29 #include <boost/algorithm/clamp.hpp>
30 #include <boost/algorithm/string/trim.hpp>
31 #include <boost/regex.hpp>
37 boost::optional<Manifest>
73 st.applyTemplate(manifestFormat);
91 auto const d = st.getFieldVL(
sfDomain);
93 m.
domain.
assign(
reinterpret_cast<char const*
>(d.data()), d.size());
100 bool const hasEphemeralSig = st.isFieldPresent(
sfSignature);
116 if (!hasEphemeralKey)
119 if (!hasEphemeralSig)
138 template <
class Stream>
146 s <<
"Manifest: " << action
152 template <
class Stream>
161 s <<
"Manifest: " << action
163 <<
";OldSeq: " << oldSeq <<
";";
202 boost::optional<Blob>
222 boost::optional<ValidatorToken>
234 return init + s.size();
237 for (
auto const& line : blob)
238 tokenStr += boost::algorithm::trim_copy(line);
245 if (r.
parse(tokenStr, token))
250 if (m.isString() && k.isString())
252 auto const key =
strUnHex(k.asString());
254 if (key && key->size() == 32)
271 auto const iter =
map_.find(pk);
273 if (iter !=
map_.end() && !iter->second.revoked())
274 return iter->second.signingKey;
291 boost::optional<std::uint32_t>
295 auto const iter =
map_.find(pk);
297 if (iter !=
map_.end() && !iter->second.revoked())
298 return iter->second.sequence;
303 boost::optional<std::string>
307 auto const iter =
map_.find(pk);
309 if (iter !=
map_.end() && !iter->second.revoked())
310 return iter->second.domain;
315 boost::optional<std::string>
319 auto const iter =
map_.find(pk);
321 if (iter !=
map_.end() && !iter->second.revoked())
322 return iter->second.serialized;
331 auto const iter =
map_.find(pk);
333 if (iter !=
map_.end())
334 return iter->second.revoked();
350 if (iter !=
map_.end() && m.
sequence <= iter->second.sequence)
364 iter->second.sequence);
374 if (
auto stream =
j_.
warn())
392 if (
auto stream =
j_.
warn())
396 if (iter ==
map_.end())
403 if (
auto stream =
j_.
info())
410 map_.emplace(std::move(masterKey), std::move(m));
418 if (
auto stream =
j_.
info())
424 iter->second.sequence);
431 iter->second = std::move(m);
444 std::string const sql =
"SELECT RawData FROM " + dbTable +
";";
446 soci::blob sociRawData(*db);
447 soci::statement st = (db->prepare << sql, soci::into(sociRawData));
452 convert(sociRawData, serialized);
457 JLOG(
j_.
warn()) <<
"Unverifiable manifest in db";
465 JLOG(
j_.
warn()) <<
"Malformed manifest in database";
477 load(dbCon, dbTable);
479 if (!configManifest.
empty())
484 JLOG(
j_.
error()) <<
"Malformed validator_token in config";
490 JLOG(
j_.
warn()) <<
"Configured manifest revokes public key";
495 JLOG(
j_.
error()) <<
"Manifest in config was rejected";
500 if (!configRevocation.
empty())
504 configRevocation.
cbegin(),
505 configRevocation.
cend(),
508 return init + s.size();
511 for (
auto const& line : configRevocation)
512 revocationStr += boost::algorithm::trim_copy(line);
516 if (!mo || !mo->revoked() ||
519 JLOG(
j_.
error()) <<
"Invalid validator key revocation in config";
537 soci::transaction tr(*db);
538 *db <<
"DELETE FROM " << dbTable;
540 "INSERT INTO " + dbTable +
" (RawData) VALUES (:rawData);";
541 for (
auto const& v :
map_)
545 if (!v.second.revoked() && !isTrusted(v.second.masterKey))
547 JLOG(
j_.
info()) <<
"Untrusted manifest in cache not saved to db";
554 soci::blob rawData(*db);
555 convert(v.second.serialized, rawData);
556 *db << sql, soci::use(rawData);
std::size_t size() const noexcept
Returns the number of bytes in the storage.
void save(DatabaseCon &dbCon, std::string const &dbTable, std::function< bool(PublicKey const &)> isTrusted)
Save cached manifests to database.
std::string domain
The domain, if one was specified in the manifest; empty otherwise.
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)
PublicKey getMasterKey(PublicKey const &pk) const
Returns ephemeral signing key's master public key.
const SField sfGeneric(access, 0)
boost::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
An immutable linear range of bytes.
const SF_UINT32 sfSequence
void convert(soci::blob &from, std::vector< std::uint8_t > &to)
Value get(UInt index, const Value &defaultValue) const
If the array contains at least index+1 elements, returns the element value, otherwise returns default...
PublicKey signingKey
The ephemeral key associated with this manifest.
std::string serialized
The manifest in serialized form.
PublicKey masterKey
The master key associated with this manifest.
bool verify() const
Returns true if manifest signature is valid.
const SF_VL sfSigningPubKey
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
std::uint8_t const * data() const noexcept
Return a pointer to beginning of the storage.
hash_map< PublicKey, Manifest > map_
Active manifests stored by master public key.
boost::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
Blob getFieldVL(SField const &field) const
Unserialize a JSON document into a Value.
bool empty() const noexcept
Return true if the byte range is empty.
bool revoked() const
Returns true if manifest revokes master key.
const SF_UINT16 sfVersion
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig, bool mustBeFullyCanonical)
Verify a signature on a message.
Integers of any length that is a multiple of 32-bits.
boost::optional< Blob > getSignature() const
Returns manifest signature.
Defines the fields and their attributes within a STObject.
LockedSociSession checkoutDb()
hash_map< PublicKey, PublicKey > signingToMasterKeys_
Master public keys stored by current ephemeral public key.
const SF_VL sfMasterSignature
bool revoked(PublicKey const &pk) const
Returns true if master key has been revoked in a manifest.
boost::optional< std::string > getManifest(PublicKey const &pk) const
Returns mainfest corresponding to a given public key.
std::string base64_decode(std::string const &data)
std::atomic< std::uint32_t > seq_
PublicKey getSigningKey(PublicKey const &pk) const
Returns master key's current signing key.
Blob getMasterSignature() const
Returns manifest master key signature.
@ invalid
Timely, but invalid signature.
@ accepted
Manifest is valid.
std::uint32_t sequence
The sequence number of this manifest.
@ stale
Sequence is too old.
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
boost::optional< Manifest > deserializeManifest(Slice s)
Constructs Manifest from serialized string.
boost::optional< ValidatorToken > loadValidatorToken(std::vector< std::string > const &blob)
Stream & logMftAct(Stream &s, std::string const &action, PublicKey const &pk, std::uint32_t seq)
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
uint256 hash() const
Returns hash of serialized manifest data.
bool isProperlyFormedTomlDomain(std::string const &domain)
Determines if the given string looks like a TOML-file hosting domain.
boost::optional< std::uint32_t > getSequence(PublicKey const &pk) const
Returns master key's current manifest sequence.
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.
ManifestDisposition applyManifest(Manifest m)
Add manifest to cache.
void set(const SOTemplate &)
boost::optional< std::string > getDomain(PublicKey const &pk) const
Returns domain claimed by a given public key.
T & get(EitherAmount &amt)
uint256 getHash(HashPrefix prefix) const