mirror of
https://github.com/XRPLF/rippled.git
synced 2026-10-20 10:38:22 +00:00
Compare commits
1 Commits
mvadari/re
...
vvysokikh1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c5059c5485 |
@@ -343,17 +343,33 @@ ManifestCache::revoked(PublicKey const& pk) const
|
|||||||
ManifestDisposition
|
ManifestDisposition
|
||||||
ManifestCache::applyManifest(Manifest m)
|
ManifestCache::applyManifest(Manifest m)
|
||||||
{
|
{
|
||||||
|
if (!m.verify())
|
||||||
|
{
|
||||||
|
if (auto stream = j_.warn())
|
||||||
|
logMftAct(stream, "Invalid", m.masterKey, m.sequence);
|
||||||
|
return ManifestDisposition::invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool const revoked = m.revoked();
|
||||||
|
if (auto stream = j_.warn(); stream && revoked)
|
||||||
|
logMftAct(stream, "Revoked", m.masterKey, m.sequence);
|
||||||
|
|
||||||
|
if (!revoked && !m.signingKey)
|
||||||
|
{
|
||||||
|
JLOG(j_.warn()) << to_string(m)
|
||||||
|
<< ": is not revoked and the manifest has no "
|
||||||
|
"signing key. Hence, the manifest is "
|
||||||
|
"invalid";
|
||||||
|
return ManifestDisposition::invalid;
|
||||||
|
}
|
||||||
|
|
||||||
// Check the manifest against the conditions that do not require a
|
// Check the manifest against the conditions that do not require a
|
||||||
// `unique_lock` (write lock) on the `mutex_`. Since the signature can be
|
// `unique_lock` (write lock) on the `mutex_`.
|
||||||
// relatively expensive, the `checkSignature` parameter determines if the
|
auto prewriteCheck = [&](auto const& iter, auto const& lock) -> std::optional<ManifestDisposition> {
|
||||||
// signature should be checked. Since `prewriteCheck` is run twice (see
|
XRPL_ASSERT(lock.owns_lock(), "xrpl::ManifestCache::applyManifest : locked");
|
||||||
// comment below), `checkSignature` only needs to be set to true on the
|
|
||||||
// first run.
|
|
||||||
auto prewriteCheck =
|
|
||||||
[this, &m](auto const& iter, bool checkSignature, auto const& lock) -> std::optional<ManifestDisposition> {
|
|
||||||
XRPL_ASSERT(lock.owns_lock(), "xrpl::ManifestCache::applyManifest::prewriteCheck : locked");
|
|
||||||
(void)lock; // not used. parameter is present to ensure the mutex is
|
(void)lock; // not used. parameter is present to ensure the mutex is
|
||||||
// locked when the lambda is called.
|
// locked when the lambda is called.
|
||||||
|
|
||||||
if (iter != map_.end() && m.sequence <= iter->second.sequence)
|
if (iter != map_.end() && m.sequence <= iter->second.sequence)
|
||||||
{
|
{
|
||||||
// We received a manifest whose sequence number is not strictly
|
// We received a manifest whose sequence number is not strictly
|
||||||
@@ -365,13 +381,6 @@ ManifestCache::applyManifest(Manifest m)
|
|||||||
return ManifestDisposition::stale;
|
return ManifestDisposition::stale;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (checkSignature && !m.verify())
|
|
||||||
{
|
|
||||||
if (auto stream = j_.warn())
|
|
||||||
logMftAct(stream, "Invalid", m.masterKey, m.sequence);
|
|
||||||
return ManifestDisposition::invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the master key associated with a manifest is or might be
|
// If the master key associated with a manifest is or might be
|
||||||
// compromised and is, therefore, no longer trustworthy.
|
// compromised and is, therefore, no longer trustworthy.
|
||||||
//
|
//
|
||||||
@@ -379,10 +388,6 @@ ManifestCache::applyManifest(Manifest m)
|
|||||||
// setting the sequence number to the highest value possible, the
|
// setting the sequence number to the highest value possible, the
|
||||||
// manifest is effectively neutered and cannot be superseded by a forged
|
// manifest is effectively neutered and cannot be superseded by a forged
|
||||||
// one.
|
// one.
|
||||||
bool const revoked = m.revoked();
|
|
||||||
|
|
||||||
if (auto stream = j_.warn(); stream && revoked)
|
|
||||||
logMftAct(stream, "Revoked", m.masterKey, m.sequence);
|
|
||||||
|
|
||||||
// Sanity check: the master key of this manifest should not be used as
|
// Sanity check: the master key of this manifest should not be used as
|
||||||
// the ephemeral key of another manifest:
|
// the ephemeral key of another manifest:
|
||||||
@@ -396,15 +401,6 @@ ManifestCache::applyManifest(Manifest m)
|
|||||||
|
|
||||||
if (!revoked)
|
if (!revoked)
|
||||||
{
|
{
|
||||||
if (!m.signingKey)
|
|
||||||
{
|
|
||||||
JLOG(j_.warn()) << to_string(m)
|
|
||||||
<< ": is not revoked and the manifest has no "
|
|
||||||
"signing key. Hence, the manifest is "
|
|
||||||
"invalid";
|
|
||||||
return ManifestDisposition::invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sanity check: the ephemeral key of this manifest should not be
|
// Sanity check: the ephemeral key of this manifest should not be
|
||||||
// used as the master or ephemeral key of another manifest:
|
// used as the master or ephemeral key of another manifest:
|
||||||
if (auto const x = signingToMasterKeys_.find(*m.signingKey); x != signingToMasterKeys_.end())
|
if (auto const x = signingToMasterKeys_.find(*m.signingKey); x != signingToMasterKeys_.end())
|
||||||
@@ -428,25 +424,23 @@ ManifestCache::applyManifest(Manifest m)
|
|||||||
|
|
||||||
{
|
{
|
||||||
std::shared_lock sl{mutex_};
|
std::shared_lock sl{mutex_};
|
||||||
if (auto d = prewriteCheck(map_.find(m.masterKey), /*checkSig*/ true, sl))
|
if (auto d = prewriteCheck(map_.find(m.masterKey), sl))
|
||||||
return *d;
|
return *d;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unique_lock sl{mutex_};
|
std::unique_lock ul{mutex_};
|
||||||
auto const iter = map_.find(m.masterKey);
|
auto const iter = map_.find(m.masterKey);
|
||||||
|
|
||||||
// Since we released the previously held read lock, it's possible that the
|
// Since we released the previously held read lock, it's possible that the
|
||||||
// collections have been written to. This means we need to run
|
// collections have been written to. This means we need to run
|
||||||
// `prewriteCheck` again. This re-does work, but `prewriteCheck` is
|
// `prewriteCheck` again. This re-does work, but `prewriteCheck` is
|
||||||
// relatively inexpensive to run, and doing it this way allows us to run
|
// relatively inexpensive to run, and doing it this way allows us to run
|
||||||
// `prewriteCheck` under a `shared_lock` above.
|
// `prewriteCheck` under a `shared_lock` above.
|
||||||
// Note, the signature has already been checked above, so it
|
|
||||||
// doesn't need to happen again (signature checks are somewhat expensive).
|
|
||||||
// Note: It's a mistake to use an upgradable lock. This is a recipe for
|
// Note: It's a mistake to use an upgradable lock. This is a recipe for
|
||||||
// deadlock.
|
// deadlock.
|
||||||
if (auto d = prewriteCheck(iter, /*checkSig*/ false, sl))
|
if (auto d = prewriteCheck(iter, ul))
|
||||||
return *d;
|
return *d;
|
||||||
|
|
||||||
bool const revoked = m.revoked();
|
|
||||||
// This is the first manifest we are seeing for a master key. This should
|
// This is the first manifest we are seeing for a master key. This should
|
||||||
// only ever happen once per validator run.
|
// only ever happen once per validator run.
|
||||||
if (iter == map_.end())
|
if (iter == map_.end())
|
||||||
|
|||||||
Reference in New Issue
Block a user