This changes leaf fetching to require already having the next leaf. This tells us what the hash should be for the leaf being fetched.
This addresses two unrelated issues:
Leaf fetching is trusted: we were not previously verifying that the leaf returned by a peer is valid in any way. Now, we can verify the fetched leaf against the expected hash (and similarly for the fetched QC). We exploit the chaining property of HotShot leaves to avoid having to run any kind of consensus light client to verify fetched leaves.
Fetching leaves by hash instead of (or in addition to) by height allows us to implement more providers. For example, we can now implement a provider that pulls leaves from undecided consensus storage, by hash, which allows us to fetch a leaf from our own storage even if we missed the corresponding decide event.
This PR:
Changes leaf fetching to require the next leaf, and fetch/authenticate by hash
Proactive scanning now runs backwards, since leaf fetching becomes kind of inherently backwards. This was a change we wanted anyways (closes #620)
To facilitate that, we have added reverse streams for all the resource types, which may come in handy for the explorer
Receiving a leaf (either by fetching or decide event) now triggers us to fetch the parent if it is missing. This is supplements the proactive fetcher and can often help us obtain missing data really quickly (e.g. if we just missed one decide)
NoStorage is gone. The purpose of NoStorage was to stress test fetching, which it did in the beginning, but it has been ages since we found a real bug this way; we now have plenty of other adversarial fetching tests, and NoStorage is becoming more trouble than it's worth to maintain. In particular, effective fetching now depends on having somewhat reliable storage (a reasonable assumption!) because we assume if you fetch a leaf, you can look it up shortly thereafter and thus fetch its parent. Thus, the NoStorage tests were failing or very slow because of many failed requests, with this change.
Key places to review:
New leaf fetching logic: active_fetch in src/data_source/fetching/leaf.rs
Triggering fetch of the parent leaf: trigger_fetch_for_parent in src/data_source/fetching/leaf.rs
This changes leaf fetching to require already having the next leaf. This tells us what the hash should be for the leaf being fetched.
This addresses two unrelated issues:
This PR:
NoStorage
is gone. The purpose ofNoStorage
was to stress test fetching, which it did in the beginning, but it has been ages since we found a real bug this way; we now have plenty of other adversarial fetching tests, andNoStorage
is becoming more trouble than it's worth to maintain. In particular, effective fetching now depends on having somewhat reliable storage (a reasonable assumption!) because we assume if you fetch a leaf, you can look it up shortly thereafter and thus fetch its parent. Thus, theNoStorage
tests were failing or very slow because of many failed requests, with this change.Key places to review:
active_fetch
insrc/data_source/fetching/leaf.rs
trigger_fetch_for_parent
insrc/data_source/fetching/leaf.rs
src/data_source/fetching.rs