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&)
152  {
153  return std::nullopt;
154  }
155 }
156 
157 template <class Stream>
158 Stream&
160  Stream& s,
161  std::string const& action,
162  PublicKey const& pk,
163  std::uint32_t seq)
164 {
165  s << "Manifest: " << action
166  << ";Pk: " << toBase58(TokenType::NodePublic, pk) << ";Seq: " << seq
167  << ";";
168  return s;
169 }
170 
171 template <class Stream>
172 Stream&
174  Stream& s,
175  std::string const& action,
176  PublicKey const& pk,
177  std::uint32_t seq,
178  std::uint32_t oldSeq)
179 {
180  s << "Manifest: " << action
181  << ";Pk: " << toBase58(TokenType::NodePublic, pk) << ";Seq: " << seq
182  << ";OldSeq: " << oldSeq << ";";
183  return s;
184 }
185 
186 bool
188 {
189  STObject st(sfGeneric);
191  st.set(sit);
192 
193  // Signing key and signature are not required for
194  // master key revocations
196  return false;
197 
198  return ripple::verify(
200 }
201 
202 uint256
204 {
205  STObject st(sfGeneric);
207  st.set(sit);
208  return st.getHash(HashPrefix::manifest);
209 }
210 
211 bool
213 {
214  /*
215  The maximum possible sequence number means that the master key
216  has been revoked.
217  */
219 }
220 
223 {
224  STObject st(sfGeneric);
226  st.set(sit);
227  if (!get(st, sfSignature))
228  return std::nullopt;
229  return st.getFieldVL(sfSignature);
230 }
231 
232 Blob
234 {
235  STObject st(sfGeneric);
237  st.set(sit);
238  return st.getFieldVL(sfMasterSignature);
239 }
240 
243 {
244  try
245  {
246  std::string tokenStr;
247 
248  tokenStr.reserve(std::accumulate(
249  blob.cbegin(),
250  blob.cend(),
251  std::size_t(0),
252  [](std::size_t init, std::string const& s) {
253  return init + s.size();
254  }));
255 
256  for (auto const& line : blob)
257  tokenStr += boost::algorithm::trim_copy(line);
258 
259  tokenStr = base64_decode(tokenStr);
260 
261  Json::Reader r;
262  Json::Value token;
263 
264  if (r.parse(tokenStr, token))
265  {
266  auto const m = token.get("manifest", Json::Value{});
267  auto const k = token.get("validation_secret_key", Json::Value{});
268 
269  if (m.isString() && k.isString())
270  {
271  auto const key = strUnHex(k.asString());
272 
273  if (key && key->size() == 32)
274  return ValidatorToken{m.asString(), makeSlice(*key)};
275  }
276  }
277 
278  return std::nullopt;
279  }
280  catch (std::exception const&)
281  {
282  return std::nullopt;
283  }
284 }
285 
286 PublicKey
288 {
289  std::shared_lock lock{mutex_};
290  auto const iter = map_.find(pk);
291 
292  if (iter != map_.end() && !iter->second.revoked())
293  return iter->second.signingKey;
294 
295  return pk;
296 }
297 
298 PublicKey
300 {
301  std::shared_lock lock{mutex_};
302 
303  if (auto const iter = signingToMasterKeys_.find(pk);
304  iter != signingToMasterKeys_.end())
305  return iter->second;
306 
307  return pk;
308 }
309 
312 {
313  std::shared_lock lock{mutex_};
314  auto const iter = map_.find(pk);
315 
316  if (iter != map_.end() && !iter->second.revoked())
317  return iter->second.sequence;
318 
319  return std::nullopt;
320 }
321 
324 {
325  std::shared_lock lock{mutex_};
326  auto const iter = map_.find(pk);
327 
328  if (iter != map_.end() && !iter->second.revoked())
329  return iter->second.domain;
330 
331  return std::nullopt;
332 }
333 
336 {
337  std::shared_lock lock{mutex_};
338  auto const iter = map_.find(pk);
339 
340  if (iter != map_.end() && !iter->second.revoked())
341  return iter->second.serialized;
342 
343  return std::nullopt;
344 }
345 
346 bool
348 {
349  std::shared_lock lock{mutex_};
350  auto const iter = map_.find(pk);
351 
352  if (iter != map_.end())
353  return iter->second.revoked();
354 
355  return false;
356 }
357 
360 {
361  // Check the manifest against the conditions that do not require a
362  // `unique_lock` (write lock) on the `mutex_`. Since the signature can be
363  // relatively expensive, the `checkSignature` parameter determines if the
364  // signature should be checked. Since `prewriteCheck` is run twice (see
365  // comment below), `checkSignature` only needs to be set to true on the
366  // first run.
367  auto prewriteCheck =
368  [this, &m](auto const& iter, bool checkSignature, auto const& lock)
370  assert(lock.owns_lock());
371  (void)lock; // not used. parameter is present to ensure the mutex is
372  // locked when the lambda is called.
373  if (iter != map_.end() && m.sequence <= iter->second.sequence)
374  {
375  // We received a manifest whose sequence number is not strictly
376  // greater than the one we already know about. This can happen in
377  // several cases including when we receive manifests from a peer who
378  // doesn't have the latest data.
379  if (auto stream = j_.debug())
380  logMftAct(
381  stream,
382  "Stale",
383  m.masterKey,
384  m.sequence,
385  iter->second.sequence);
387  }
388 
389  if (checkSignature && !m.verify())
390  {
391  if (auto stream = j_.warn())
392  logMftAct(stream, "Invalid", m.masterKey, m.sequence);
394  }
395 
396  // If the master key associated with a manifest is or might be
397  // compromised and is, therefore, no longer trustworthy.
398  //
399  // A manifest revocation essentially marks a manifest as compromised. By
400  // setting the sequence number to the highest value possible, the
401  // manifest is effectively neutered and cannot be superseded by a forged
402  // one.
403  bool const revoked = m.revoked();
404 
405  if (auto stream = j_.warn(); stream && revoked)
406  logMftAct(stream, "Revoked", m.masterKey, m.sequence);
407 
408  // Sanity check: the master key of this manifest should not be used as
409  // the ephemeral key of another manifest:
410  if (auto const x = signingToMasterKeys_.find(m.masterKey);
411  x != signingToMasterKeys_.end())
412  {
413  JLOG(j_.warn()) << to_string(m)
414  << ": Master key already used as ephemeral key for "
415  << toBase58(TokenType::NodePublic, x->second);
416 
418  }
419 
420  if (!revoked)
421  {
422  // Sanity check: the ephemeral key of this manifest should not be
423  // used as the master or ephemeral key of another manifest:
424  if (auto const x = signingToMasterKeys_.find(m.signingKey);
425  x != signingToMasterKeys_.end())
426  {
427  JLOG(j_.warn())
428  << to_string(m)
429  << ": Ephemeral key already used as ephemeral key for "
430  << toBase58(TokenType::NodePublic, x->second);
431 
433  }
434 
435  if (auto const x = map_.find(m.signingKey); x != map_.end())
436  {
437  JLOG(j_.warn())
438  << to_string(m) << ": Ephemeral key used as master key for "
439  << to_string(x->second);
440 
442  }
443  }
444 
445  return std::nullopt;
446  };
447 
448  {
450  if (auto d =
451  prewriteCheck(map_.find(m.masterKey), /*checkSig*/ true, sl))
452  return *d;
453  }
454 
456  auto const iter = map_.find(m.masterKey);
457  // Since we released the previously held read lock, it's possible that the
458  // collections have been written to. This means we need to run
459  // `prewriteCheck` again. This re-does work, but `prewriteCheck` is
460  // relatively inexpensive to run, and doing it this way allows us to run
461  // `prewriteCheck` under a `shared_lock` above.
462  // Note, the signature has already been checked above, so it
463  // doesn't need to happen again (signature checks are somewhat expensive).
464  // Note: It's a mistake to use an upgradable lock. This is a recipe for
465  // deadlock.
466  if (auto d = prewriteCheck(iter, /*checkSig*/ false, sl))
467  return *d;
468 
469  bool const revoked = m.revoked();
470  // This is the first manifest we are seeing for a master key. This should
471  // only ever happen once per validator run.
472  if (iter == map_.end())
473  {
474  if (auto stream = j_.info())
475  logMftAct(stream, "AcceptedNew", m.masterKey, m.sequence);
476 
477  if (!revoked)
479 
480  auto masterKey = m.masterKey;
481  map_.emplace(std::move(masterKey), std::move(m));
483  }
484 
485  // An ephemeral key was revoked and superseded by a new key. This is
486  // expected, but should happen infrequently.
487  if (auto stream = j_.info())
488  logMftAct(
489  stream,
490  "AcceptedUpdate",
491  m.masterKey,
492  m.sequence,
493  iter->second.sequence);
494 
495  signingToMasterKeys_.erase(iter->second.signingKey);
496 
497  if (!revoked)
499 
500  iter->second = std::move(m);
501 
502  // Something has changed. Keep track of it.
503  seq_++;
504 
506 }
507 
508 void
510 {
511  auto db = dbCon.checkoutDb();
512  ripple::getManifests(*db, dbTable, *this, j_);
513 }
514 
515 bool
517  DatabaseCon& dbCon,
518  std::string const& dbTable,
519  std::string const& configManifest,
520  std::vector<std::string> const& configRevocation)
521 {
522  load(dbCon, dbTable);
523 
524  if (!configManifest.empty())
525  {
526  auto mo = deserializeManifest(base64_decode(configManifest));
527  if (!mo)
528  {
529  JLOG(j_.error()) << "Malformed validator_token in config";
530  return false;
531  }
532 
533  if (mo->revoked())
534  {
535  JLOG(j_.warn()) << "Configured manifest revokes public key";
536  }
537 
538  if (applyManifest(std::move(*mo)) == ManifestDisposition::invalid)
539  {
540  JLOG(j_.error()) << "Manifest in config was rejected";
541  return false;
542  }
543  }
544 
545  if (!configRevocation.empty())
546  {
547  std::string revocationStr;
548  revocationStr.reserve(std::accumulate(
549  configRevocation.cbegin(),
550  configRevocation.cend(),
551  std::size_t(0),
552  [](std::size_t init, std::string const& s) {
553  return init + s.size();
554  }));
555 
556  for (auto const& line : configRevocation)
557  revocationStr += boost::algorithm::trim_copy(line);
558 
559  auto mo = deserializeManifest(base64_decode(revocationStr));
560 
561  if (!mo || !mo->revoked() ||
562  applyManifest(std::move(*mo)) == ManifestDisposition::invalid)
563  {
564  JLOG(j_.error()) << "Invalid validator key revocation in config";
565  return false;
566  }
567  }
568 
569  return true;
570 }
571 
572 void
574  DatabaseCon& dbCon,
575  std::string const& dbTable,
576  std::function<bool(PublicKey const&)> const& isTrusted)
577 {
578  std::shared_lock lock{mutex_};
579  auto db = dbCon.checkoutDb();
580 
581  saveManifests(*db, dbTable, isTrusted, map_, j_);
582 }
583 } // namespace ripple
ripple::ManifestCache::mutex_
std::shared_mutex mutex_
Definition: Manifest.h:229
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:185
ripple::ManifestCache::getMasterKey
PublicKey getMasterKey(PublicKey const &pk) const
Returns ephemeral signing key's master public key.
Definition: app/misc/impl/Manifest.cpp:299
std::exception
STL class.
ripple::sfGeneric
const SField sfGeneric(access, 0)
Definition: SField.h:327
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:187
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:176
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:232
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:212
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:573
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
Integers of any length that is a multiple of 32-bits.
Definition: base_uint.h:81
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:235
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:222
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:347
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:228
ripple::loadValidatorToken
std::optional< ValidatorToken > loadValidatorToken(std::vector< std::string > const &blob)
Definition: app/misc/impl/Manifest.cpp:242
ripple::ManifestCache::seq_
std::atomic< std::uint32_t > seq_
Definition: Manifest.h:237
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:287
std::uint32_t
ripple::Manifest::getMasterSignature
Blob getMasterSignature() const
Returns manifest master key signature.
Definition: app/misc/impl/Manifest.cpp:233
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:311
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:335
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:323
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:159
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:203
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)
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:516
ripple::sfDomain
const SF_VL sfDomain
ripple::ManifestCache::applyManifest
ManifestDisposition applyManifest(Manifest m)
Add manifest to cache.
Definition: app/misc/impl/Manifest.cpp:359
ripple::strUnHex
std::optional< Blob > strUnHex(std::size_t strSize, Iterator begin, Iterator end)
Definition: StringUtilities.h:50
shared_mutex
ripple::deserializeManifest
std::optional< Manifest > deserializeManifest(Slice s)
Constructs Manifest from serialized string.
Definition: app/misc/impl/Manifest.cpp:53
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.
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