rippled
app/misc/impl/Manifest.cpp
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of rippled: https://github.com/ripple/rippled
4  Copyright (c) 2012, 2013 Ripple Labs Inc.
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #include <ripple/app/misc/Manifest.h>
21 #include <ripple/app/rdb/Wallet.h>
22 #include <ripple/basics/Log.h>
23 #include <ripple/basics/StringUtilities.h>
24 #include <ripple/basics/base64.h>
25 #include <ripple/basics/contract.h>
26 #include <ripple/beast/rfc2616.h>
27 #include <ripple/core/DatabaseCon.h>
28 #include <ripple/json/json_reader.h>
29 #include <ripple/protocol/PublicKey.h>
30 #include <ripple/protocol/Sign.h>
31 
32 #include <boost/algorithm/string/trim.hpp>
33 
34 #include <numeric>
35 #include <shared_mutex>
36 #include <stdexcept>
37 
38 namespace ripple {
39 
42 {
43  auto const mk = toBase58(TokenType::NodePublic, m.masterKey);
44 
45  if (m.revoked())
46  return "Revocation Manifest " + mk;
47 
48  return "Manifest " + mk + " (" + std::to_string(m.sequence) + ": " +
50 }
51 
54 {
55  if (s.empty())
56  return std::nullopt;
57 
58  static SOTemplate const manifestFormat{
59  // A manifest must include:
60  // - the master public key
62 
63  // - a signature with that public key
65 
66  // - a sequence number
68 
69  // It may, optionally, contain:
70  // - a version number which defaults to 0
72 
73  // - a domain name
75 
76  // - an ephemeral signing key that can be changed as necessary
78 
79  // - a signature using the ephemeral signing key, if it is present
81  };
82 
83  try
84  {
85  SerialIter sit{s};
86  STObject st{sit, sfGeneric};
87 
88  st.applyTemplate(manifestFormat);
89 
90  // We only understand "version 0" manifests at this time:
91  if (st.isFieldPresent(sfVersion) && st.getFieldU16(sfVersion) != 0)
92  return std::nullopt;
93 
94  auto const pk = st.getFieldVL(sfPublicKey);
95 
96  if (!publicKeyType(makeSlice(pk)))
97  return std::nullopt;
98 
99  Manifest m;
100  m.serialized.assign(reinterpret_cast<char const*>(s.data()), s.size());
101  m.masterKey = PublicKey(makeSlice(pk));
102  m.sequence = st.getFieldU32(sfSequence);
103 
104  if (st.isFieldPresent(sfDomain))
105  {
106  auto const d = st.getFieldVL(sfDomain);
107 
108  m.domain.assign(reinterpret_cast<char const*>(d.data()), d.size());
109 
111  return std::nullopt;
112  }
113 
114  bool const hasEphemeralKey = st.isFieldPresent(sfSigningPubKey);
115  bool const hasEphemeralSig = st.isFieldPresent(sfSignature);
116 
117  if (m.revoked())
118  {
119  // Revocation manifests should not specify a new signing key
120  // or a signing key signature.
121  if (hasEphemeralKey)
122  return std::nullopt;
123 
124  if (hasEphemeralSig)
125  return std::nullopt;
126  }
127  else
128  {
129  // Regular manifests should contain a signing key and an
130  // associated signature.
131  if (!hasEphemeralKey)
132  return std::nullopt;
133 
134  if (!hasEphemeralSig)
135  return std::nullopt;
136 
137  auto const spk = st.getFieldVL(sfSigningPubKey);
138 
139  if (!publicKeyType(makeSlice(spk)))
140  return std::nullopt;
141 
142  m.signingKey = PublicKey(makeSlice(spk));
143 
144  // The signing and master keys can't be the same
145  if (m.signingKey == m.masterKey)
146  return std::nullopt;
147  }
148 
149  return m;
150  }
151  catch (std::exception const& ex)
152  {
153  JLOG(journal.error())
154  << "Exception in " << __func__ << ": " << ex.what();
155  return std::nullopt;
156  }
157 }
158 
159 template <class Stream>
160 Stream&
162  Stream& s,
163  std::string const& action,
164  PublicKey const& pk,
165  std::uint32_t seq)
166 {
167  s << "Manifest: " << action
168  << ";Pk: " << toBase58(TokenType::NodePublic, pk) << ";Seq: " << seq
169  << ";";
170  return s;
171 }
172 
173 template <class Stream>
174 Stream&
176  Stream& s,
177  std::string const& action,
178  PublicKey const& pk,
179  std::uint32_t seq,
180  std::uint32_t oldSeq)
181 {
182  s << "Manifest: " << action
183  << ";Pk: " << toBase58(TokenType::NodePublic, pk) << ";Seq: " << seq
184  << ";OldSeq: " << oldSeq << ";";
185  return s;
186 }
187 
188 bool
190 {
191  STObject st(sfGeneric);
193  st.set(sit);
194 
195  // Signing key and signature are not required for
196  // master key revocations
198  return false;
199 
200  return ripple::verify(
202 }
203 
204 uint256
206 {
207  STObject st(sfGeneric);
209  st.set(sit);
210  return st.getHash(HashPrefix::manifest);
211 }
212 
213 bool
215 {
216  /*
217  The maximum possible sequence number means that the master key
218  has been revoked.
219  */
221 }
222 
225 {
226  STObject st(sfGeneric);
228  st.set(sit);
229  if (!get(st, sfSignature))
230  return std::nullopt;
231  return st.getFieldVL(sfSignature);
232 }
233 
234 Blob
236 {
237  STObject st(sfGeneric);
239  st.set(sit);
240  return st.getFieldVL(sfMasterSignature);
241 }
242 
245 {
246  try
247  {
248  std::string tokenStr;
249 
250  tokenStr.reserve(std::accumulate(
251  blob.cbegin(),
252  blob.cend(),
253  std::size_t(0),
254  [](std::size_t init, std::string const& s) {
255  return init + s.size();
256  }));
257 
258  for (auto const& line : blob)
259  tokenStr += boost::algorithm::trim_copy(line);
260 
261  tokenStr = base64_decode(tokenStr);
262 
263  Json::Reader r;
264  Json::Value token;
265 
266  if (r.parse(tokenStr, token))
267  {
268  auto const m = token.get("manifest", Json::Value{});
269  auto const k = token.get("validation_secret_key", Json::Value{});
270 
271  if (m.isString() && k.isString())
272  {
273  auto const key = strUnHex(k.asString());
274 
275  if (key && key->size() == 32)
276  return ValidatorToken{m.asString(), makeSlice(*key)};
277  }
278  }
279 
280  return std::nullopt;
281  }
282  catch (std::exception const& ex)
283  {
284  JLOG(journal.error())
285  << "Exception in " << __func__ << ": " << ex.what();
286  return std::nullopt;
287  }
288 }
289 
290 PublicKey
292 {
293  std::shared_lock lock{mutex_};
294  auto const iter = map_.find(pk);
295 
296  if (iter != map_.end() && !iter->second.revoked())
297  return iter->second.signingKey;
298 
299  return pk;
300 }
301 
302 PublicKey
304 {
305  std::shared_lock lock{mutex_};
306 
307  if (auto const iter = signingToMasterKeys_.find(pk);
308  iter != signingToMasterKeys_.end())
309  return iter->second;
310 
311  return pk;
312 }
313 
316 {
317  std::shared_lock lock{mutex_};
318  auto const iter = map_.find(pk);
319 
320  if (iter != map_.end() && !iter->second.revoked())
321  return iter->second.sequence;
322 
323  return std::nullopt;
324 }
325 
328 {
329  std::shared_lock lock{mutex_};
330  auto const iter = map_.find(pk);
331 
332  if (iter != map_.end() && !iter->second.revoked())
333  return iter->second.domain;
334 
335  return std::nullopt;
336 }
337 
340 {
341  std::shared_lock lock{mutex_};
342  auto const iter = map_.find(pk);
343 
344  if (iter != map_.end() && !iter->second.revoked())
345  return iter->second.serialized;
346 
347  return std::nullopt;
348 }
349 
350 bool
352 {
353  std::shared_lock lock{mutex_};
354  auto const iter = map_.find(pk);
355 
356  if (iter != map_.end())
357  return iter->second.revoked();
358 
359  return false;
360 }
361 
364 {
365  // Check the manifest against the conditions that do not require a
366  // `unique_lock` (write lock) on the `mutex_`. Since the signature can be
367  // relatively expensive, the `checkSignature` parameter determines if the
368  // signature should be checked. Since `prewriteCheck` is run twice (see
369  // comment below), `checkSignature` only needs to be set to true on the
370  // first run.
371  auto prewriteCheck =
372  [this, &m](auto const& iter, bool checkSignature, auto const& lock)
374  assert(lock.owns_lock());
375  (void)lock; // not used. parameter is present to ensure the mutex is
376  // locked when the lambda is called.
377  if (iter != map_.end() && m.sequence <= iter->second.sequence)
378  {
379  // We received a manifest whose sequence number is not strictly
380  // greater than the one we already know about. This can happen in
381  // several cases including when we receive manifests from a peer who
382  // doesn't have the latest data.
383  if (auto stream = j_.debug())
384  logMftAct(
385  stream,
386  "Stale",
387  m.masterKey,
388  m.sequence,
389  iter->second.sequence);
391  }
392 
393  if (checkSignature && !m.verify())
394  {
395  if (auto stream = j_.warn())
396  logMftAct(stream, "Invalid", m.masterKey, m.sequence);
398  }
399 
400  // If the master key associated with a manifest is or might be
401  // compromised and is, therefore, no longer trustworthy.
402  //
403  // A manifest revocation essentially marks a manifest as compromised. By
404  // setting the sequence number to the highest value possible, the
405  // manifest is effectively neutered and cannot be superseded by a forged
406  // one.
407  bool const revoked = m.revoked();
408 
409  if (auto stream = j_.warn(); stream && revoked)
410  logMftAct(stream, "Revoked", m.masterKey, m.sequence);
411 
412  // Sanity check: the master key of this manifest should not be used as
413  // the ephemeral key of another manifest:
414  if (auto const x = signingToMasterKeys_.find(m.masterKey);
415  x != signingToMasterKeys_.end())
416  {
417  JLOG(j_.warn()) << to_string(m)
418  << ": Master key already used as ephemeral key for "
419  << toBase58(TokenType::NodePublic, x->second);
420 
422  }
423 
424  if (!revoked)
425  {
426  // Sanity check: the ephemeral key of this manifest should not be
427  // used as the master or ephemeral key of another manifest:
428  if (auto const x = signingToMasterKeys_.find(m.signingKey);
429  x != signingToMasterKeys_.end())
430  {
431  JLOG(j_.warn())
432  << to_string(m)
433  << ": Ephemeral key already used as ephemeral key for "
434  << toBase58(TokenType::NodePublic, x->second);
435 
437  }
438 
439  if (auto const x = map_.find(m.signingKey); x != map_.end())
440  {
441  JLOG(j_.warn())
442  << to_string(m) << ": Ephemeral key used as master key for "
443  << to_string(x->second);
444 
446  }
447  }
448 
449  return std::nullopt;
450  };
451 
452  {
454  if (auto d =
455  prewriteCheck(map_.find(m.masterKey), /*checkSig*/ true, sl))
456  return *d;
457  }
458 
460  auto const iter = map_.find(m.masterKey);
461  // Since we released the previously held read lock, it's possible that the
462  // collections have been written to. This means we need to run
463  // `prewriteCheck` again. This re-does work, but `prewriteCheck` is
464  // relatively inexpensive to run, and doing it this way allows us to run
465  // `prewriteCheck` under a `shared_lock` above.
466  // Note, the signature has already been checked above, so it
467  // doesn't need to happen again (signature checks are somewhat expensive).
468  // Note: It's a mistake to use an upgradable lock. This is a recipe for
469  // deadlock.
470  if (auto d = prewriteCheck(iter, /*checkSig*/ false, sl))
471  return *d;
472 
473  bool const revoked = m.revoked();
474  // This is the first manifest we are seeing for a master key. This should
475  // only ever happen once per validator run.
476  if (iter == map_.end())
477  {
478  if (auto stream = j_.info())
479  logMftAct(stream, "AcceptedNew", m.masterKey, m.sequence);
480 
481  if (!revoked)
483 
484  auto masterKey = m.masterKey;
485  map_.emplace(std::move(masterKey), std::move(m));
487  }
488 
489  // An ephemeral key was revoked and superseded by a new key. This is
490  // expected, but should happen infrequently.
491  if (auto stream = j_.info())
492  logMftAct(
493  stream,
494  "AcceptedUpdate",
495  m.masterKey,
496  m.sequence,
497  iter->second.sequence);
498 
499  signingToMasterKeys_.erase(iter->second.signingKey);
500 
501  if (!revoked)
503 
504  iter->second = std::move(m);
505 
506  // Something has changed. Keep track of it.
507  seq_++;
508 
510 }
511 
512 void
514 {
515  auto db = dbCon.checkoutDb();
516  ripple::getManifests(*db, dbTable, *this, j_);
517 }
518 
519 bool
521  DatabaseCon& dbCon,
522  std::string const& dbTable,
523  std::string const& configManifest,
524  std::vector<std::string> const& configRevocation)
525 {
526  load(dbCon, dbTable);
527 
528  if (!configManifest.empty())
529  {
530  auto mo = deserializeManifest(base64_decode(configManifest));
531  if (!mo)
532  {
533  JLOG(j_.error()) << "Malformed validator_token in config";
534  return false;
535  }
536 
537  if (mo->revoked())
538  {
539  JLOG(j_.warn()) << "Configured manifest revokes public key";
540  }
541 
542  if (applyManifest(std::move(*mo)) == ManifestDisposition::invalid)
543  {
544  JLOG(j_.error()) << "Manifest in config was rejected";
545  return false;
546  }
547  }
548 
549  if (!configRevocation.empty())
550  {
551  std::string revocationStr;
552  revocationStr.reserve(std::accumulate(
553  configRevocation.cbegin(),
554  configRevocation.cend(),
555  std::size_t(0),
556  [](std::size_t init, std::string const& s) {
557  return init + s.size();
558  }));
559 
560  for (auto const& line : configRevocation)
561  revocationStr += boost::algorithm::trim_copy(line);
562 
563  auto mo = deserializeManifest(base64_decode(revocationStr));
564 
565  if (!mo || !mo->revoked() ||
566  applyManifest(std::move(*mo)) == ManifestDisposition::invalid)
567  {
568  JLOG(j_.error()) << "Invalid validator key revocation in config";
569  return false;
570  }
571  }
572 
573  return true;
574 }
575 
576 void
578  DatabaseCon& dbCon,
579  std::string const& dbTable,
580  std::function<bool(PublicKey const&)> const& isTrusted)
581 {
582  std::shared_lock lock{mutex_};
583  auto db = dbCon.checkoutDb();
584 
585  saveManifests(*db, dbTable, isTrusted, map_, j_);
586 }
587 } // namespace ripple
ripple::ManifestCache::mutex_
std::shared_mutex mutex_
Definition: Manifest.h:235
ripple::Slice::size
std::size_t size() const noexcept
Returns the number of bytes in the storage.
Definition: Slice.h:80
ripple::Manifest::domain
std::string domain
The domain, if one was specified in the manifest; empty otherwise.
Definition: Manifest.h:95
ripple::makeSlice
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)
Definition: Slice.h:241
std::string
STL class.
ripple::ManifestDisposition
ManifestDisposition
Definition: Manifest.h:191
ripple::ManifestCache::getMasterKey
PublicKey getMasterKey(PublicKey const &pk) const
Returns ephemeral signing key's master public key.
Definition: app/misc/impl/Manifest.cpp:303
std::exception
STL class.
ripple::sfGeneric
const SField sfGeneric(access, 0)
Definition: SField.h:327
ripple::loadValidatorToken
std::optional< ValidatorToken > loadValidatorToken(std::vector< std::string > const &blob, beast::Journal journal)
Definition: app/misc/impl/Manifest.cpp:244
ripple::Manifest
Definition: Manifest.h:80
ripple::Slice
An immutable linear range of bytes.
Definition: Slice.h:44
std::string::reserve
T reserve(T... args)
ripple::sfSequence
const SF_UINT32 sfSequence
ripple::HashPrefix::manifest
@ manifest
Manifest.
Json::Value::get
Value get(UInt index, const Value &defaultValue) const
If the array contains at least index+1 elements, returns the element value, otherwise returns default...
Definition: json_value.cpp:834
ripple::verify
bool verify(PublicKey const &publicKey, Slice const &m, Slice const &sig, bool mustBeFullyCanonical) noexcept
Verify a signature on a message.
Definition: PublicKey.cpp:272
ripple::Manifest::signingKey
PublicKey signingKey
The ephemeral key associated with this manifest.
Definition: Manifest.h:89
std::vector< unsigned char >
ripple::Manifest::serialized
std::string serialized
The manifest in serialized form.
Definition: Manifest.h:83
std::string::size
T size(T... args)
ripple::Manifest::masterKey
PublicKey masterKey
The master key associated with this manifest.
Definition: Manifest.h:86
ripple::Manifest::verify
bool verify() const
Returns true if manifest signature is valid.
Definition: app/misc/impl/Manifest.cpp:189
ripple::sfSigningPubKey
const SF_VL sfSigningPubKey
ripple::toBase58
std::string toBase58(AccountID const &v)
Convert AccountID to base58 checked string.
Definition: AccountID.cpp:104
ripple::Slice::data
std::uint8_t const * data() const noexcept
Return a pointer to beginning of the storage.
Definition: Slice.h:97
ripple::ValidatorToken
Definition: Manifest.h:180
beast::Journal::warn
Stream warn() const
Definition: Journal.h:327
ripple::ManifestCache::map_
hash_map< PublicKey, Manifest > map_
Active manifests stored by master public key.
Definition: Manifest.h:238
ripple::soeREQUIRED
@ soeREQUIRED
Definition: SOTemplate.h:35
ripple::ManifestDisposition::badEphemeralKey
@ badEphemeralKey
The ephemeral key is not acceptable to us.
std::function
ripple::STObject::getFieldVL
Blob getFieldVL(SField const &field) const
Definition: STObject.cpp:595
Json::Reader
Unserialize a JSON document into a Value.
Definition: json_reader.h:36
ripple::Slice::empty
bool empty() const noexcept
Return true if the byte range is empty.
Definition: Slice.h:69
ripple::Manifest::revoked
bool revoked() const
Returns true if manifest revokes master key.
Definition: app/misc/impl/Manifest.cpp:214
ripple::ManifestCache::save
void save(DatabaseCon &dbCon, std::string const &dbTable, std::function< bool(PublicKey const &)> const &isTrusted)
Save cached manifests to database.
Definition: app/misc/impl/Manifest.cpp:577
ripple::sfVersion
const SF_UINT16 sfVersion
ripple::publicKeyType
std::optional< KeyType > publicKeyType(Slice const &slice)
Returns the type of public key.
Definition: PublicKey.cpp:207
stdexcept
ripple::base_uint< 256 >
ripple::SOTemplate
Defines the fields and their attributes within a STObject.
Definition: SOTemplate.h:82
ripple::DatabaseCon::checkoutDb
LockedSociSession checkoutDb()
Definition: DatabaseCon.h:178
ripple::ManifestCache::signingToMasterKeys_
hash_map< PublicKey, PublicKey > signingToMasterKeys_
Master public keys stored by current ephemeral public key.
Definition: Manifest.h:241
ripple::ManifestDisposition::badMasterKey
@ badMasterKey
The master key is not acceptable to us.
ripple::PublicKey
A public key.
Definition: PublicKey.h:59
ripple::sfMasterSignature
const SF_VL sfMasterSignature
ripple::getManifests
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.
Definition: Wallet.cpp:42
ripple::soeOPTIONAL
@ soeOPTIONAL
Definition: SOTemplate.h:36
std::unique_lock
STL class.
ripple::Manifest::getSignature
std::optional< Blob > getSignature() const
Returns manifest signature.
Definition: app/misc/impl/Manifest.cpp:224
std::to_string
T to_string(T... args)
ripple::ManifestCache::revoked
bool revoked(PublicKey const &pk) const
Returns true if master key has been revoked in a manifest.
Definition: app/misc/impl/Manifest.cpp:351
ripple::base64_decode
std::string base64_decode(std::string const &data)
Definition: base64.cpp:245
beast::Journal::error
Stream error() const
Definition: Journal.h:333
beast::Journal::info
Stream info() const
Definition: Journal.h:321
ripple::ManifestCache::j_
beast::Journal j_
Definition: Manifest.h:234
ripple::ManifestCache::seq_
std::atomic< std::uint32_t > seq_
Definition: Manifest.h:243
std::accumulate
T accumulate(T... args)
ripple::SerialIter
Definition: Serializer.h:310
ripple::ManifestCache::getSigningKey
PublicKey getSigningKey(PublicKey const &pk) const
Returns master key's current signing key.
Definition: app/misc/impl/Manifest.cpp:291
beast::Journal
A generic endpoint for log messages.
Definition: Journal.h:58
std::uint32_t
ripple::Manifest::getMasterSignature
Blob getMasterSignature() const
Returns manifest master key signature.
Definition: app/misc/impl/Manifest.cpp:235
ripple::ManifestDisposition::invalid
@ invalid
Timely, but invalid signature.
ripple::ManifestCache::getSequence
std::optional< std::uint32_t > getSequence(PublicKey const &pk) const
Returns master key's current manifest sequence.
Definition: app/misc/impl/Manifest.cpp:315
ripple::ManifestDisposition::accepted
@ accepted
Manifest is valid.
ripple::Manifest::sequence
std::uint32_t sequence
The sequence number of this manifest.
Definition: Manifest.h:92
ripple::STObject
Definition: STObject.h:51
ripple::ManifestCache::getManifest
std::optional< std::string > getManifest(PublicKey const &pk) const
Returns mainfest corresponding to a given public key.
Definition: app/misc/impl/Manifest.cpp:339
ripple::ManifestCache::getDomain
std::optional< std::string > getDomain(PublicKey const &pk) const
Returns domain claimed by a given public key.
Definition: app/misc/impl/Manifest.cpp:327
ripple::ManifestDisposition::stale
@ stale
Sequence is too old.
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
std::vector::cbegin
T cbegin(T... args)
ripple::logMftAct
Stream & logMftAct(Stream &s, std::string const &action, PublicKey const &pk, std::uint32_t seq)
Definition: app/misc/impl/Manifest.cpp:161
Json::Reader::parse
bool parse(std::string const &document, Value &root)
Read a Value from a JSON document.
Definition: json_reader.cpp:74
ripple::DatabaseCon
Definition: DatabaseCon.h:81
ripple::sfSignature
const SF_VL sfSignature
ripple::Manifest::hash
uint256 hash() const
Returns hash of serialized manifest data.
Definition: app/misc/impl/Manifest.cpp:205
std::string::empty
T empty(T... args)
std::string::assign
T assign(T... args)
ripple::TokenType::NodePublic
@ NodePublic
std::optional
beast::Journal::debug
Stream debug() const
Definition: Journal.h:315
std::size_t
ripple::to_string
std::string to_string(Manifest const &m)
Format the specified manifest to a string for debugging purposes.
Definition: app/misc/impl/Manifest.cpp:41
ripple::isProperlyFormedTomlDomain
bool isProperlyFormedTomlDomain(std::string const &domain)
Determines if the given string looks like a TOML-file hosting domain.
std::vector::cend
T cend(T... args)
ripple::deserializeManifest
std::optional< Manifest > deserializeManifest(Slice s, beast::Journal journal)
Constructs Manifest from serialized string.
Definition: app/misc/impl/Manifest.cpp:53
numeric
std::numeric_limits::max
T max(T... args)
ripple::ManifestCache::load
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.
Definition: app/misc/impl/Manifest.cpp:520
ripple::sfDomain
const SF_VL sfDomain
ripple::ManifestCache::applyManifest
ManifestDisposition applyManifest(Manifest m)
Add manifest to cache.
Definition: app/misc/impl/Manifest.cpp:363
ripple::strUnHex
std::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
Definition: StringUtilities.h:50
shared_mutex
ripple::STObject::set
void set(const SOTemplate &)
Definition: STObject.cpp:100
ripple::saveManifests
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.
Definition: Wallet.cpp:90
std::string::data
T data(T... args)
ripple::sfPublicKey
const SF_VL sfPublicKey
ripple::soeDEFAULT
@ soeDEFAULT
Definition: SOTemplate.h:37
std::shared_lock
STL class.
std::exception::what
T what(T... args)
Json::Value
Represents a JSON value.
Definition: json_value.h:145
ripple::get
T & get(EitherAmount &amt)
Definition: AmountSpec.h:118
ripple::STObject::getHash
uint256 getHash(HashPrefix prefix) const
Definition: STObject.cpp:339