Skip to content

Commit

Permalink
Improve manifest relaying:
Browse files Browse the repository at this point in the history
The manifest relay code would only ever relay manifests from validators
on a server's UNL which means that the manifests of validators that are
not broadly trusted can fail to propagate across the network, which can
make it difficult to detect and track such validators.

This commit, if merged, propagates all manifests on a best-effort basis
resulting in broader availability of manifests on the network and avoid
the need to introduce on-ledger manifest storage or to establish one or
more manifest repositories.
  • Loading branch information
nbougalis authored and manojsdoshi committed Jan 15, 2021
1 parent 41a896b commit e3ed384
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 45 deletions.
2 changes: 2 additions & 0 deletions src/ripple/app/misc/NetworkOPs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1922,6 +1922,8 @@ NetworkOPsImp::pubManifest(Manifest const& mo)
if (auto sig = mo.getSignature())
jvObj[jss::signature] = strHex(*sig);
jvObj[jss::master_signature] = strHex(mo.getMasterSignature());
if (!mo.domain.empty())
jvObj[jss::domain] = mo.domain;

for (auto i = mStreamMaps[sManifests].begin();
i != mStreamMaps[sManifests].end();)
Expand Down
74 changes: 29 additions & 45 deletions src/ripple/overlay/impl/OverlayImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -662,73 +662,57 @@ OverlayImpl::onManifests(
auto const n = m->list_size();
auto const& journal = from->pjournal();

JLOG(journal.debug()) << "TMManifest, " << n
<< (n == 1 ? " item" : " items");
protocol::TMManifests relay;

for (std::size_t i = 0; i < n; ++i)
{
auto& s = m->list().Get(i).stobject();

if (auto mo = deserializeManifest(s))
{
uint256 const hash = mo->hash();
if (!hashRouter.addSuppressionPeer(hash, from->id()))
{
JLOG(journal.info()) << "Duplicate manifest #" << i + 1;
continue;
}

if (!app_.validators().listed(mo->masterKey))
{
JLOG(journal.info()) << "Untrusted manifest #" << i + 1;
app_.getOPs().pubManifest(*mo);
continue;
}

auto const serialized = mo->serialized;

auto const result =
app_.validatorManifests().applyManifest(std::move(*mo));

if (result == ManifestDisposition::accepted)
{
app_.getOPs().pubManifest(*deserializeManifest(serialized));
}
relay.add_list()->set_stobject(s);

if (result == ManifestDisposition::accepted)
{
auto db = app_.getWalletDB().checkoutDb();

soci::transaction tr(*db);
static const char* const sql =
"INSERT INTO ValidatorManifests (RawData) VALUES "
"(:rawData);";
soci::blob rawData(*db);
convert(serialized, rawData);
*db << sql, soci::use(rawData);
tr.commit();

protocol::TMManifests o;
o.add_list()->set_stobject(s);

auto const toSkip = hashRouter.shouldRelay(hash);
if (toSkip)
foreach(send_if_not(
std::make_shared<Message>(o, protocol::mtMANIFESTS),
peer_in_set(*toSkip)));
}
else
{
JLOG(journal.info())
<< "Bad manifest #" << i + 1 << ": " << to_string(result);
// N.B.: this is important; the applyManifest call above moves
// the loaded Manifest out of the optional so we need to
// reload it here.
mo = deserializeManifest(serialized);
assert(mo);

app_.getOPs().pubManifest(*mo);

if (app_.validators().listed(mo->masterKey))
{
auto db = app_.getWalletDB().checkoutDb();

soci::transaction tr(*db);
static const char* const sql =
"INSERT INTO ValidatorManifests (RawData) VALUES "
"(:rawData);";
soci::blob rawData(*db);
convert(serialized, rawData);
*db << sql, soci::use(rawData);
tr.commit();
}
}
}
else
{
JLOG(journal.warn()) << "Malformed manifest #" << i + 1;
JLOG(journal.debug())
<< "Malformed manifest #" << i + 1 << ": " << strHex(s);
continue;
}
}

if (!relay.list().empty())
for_each([m2 = std::make_shared<Message>(relay, protocol::mtMANIFESTS)](
std::shared_ptr<PeerImp>&& p) { p->send(m2); });
}

void
Expand Down
11 changes: 11 additions & 0 deletions src/ripple/overlay/impl/PeerImp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,17 @@ PeerImp::onMessageEnd(
void
PeerImp::onMessage(std::shared_ptr<protocol::TMManifests> const& m)
{
auto const s = m->list_size();

if (s == 0)
{
fee_ = Resource::feeUnwantedData;
return;
}

if (s > 100)
fee_ = Resource::feeMediumBurdenPeer;

// VFALCO What's the right job type?
auto that = shared_from_this();
app_.getJobQueue().addJob(
Expand Down

0 comments on commit e3ed384

Please sign in to comment.