-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? # to your account
Sync from newest to oldest #620
Comments
I'm thinking of an idea that might be better. Instead of having major and minor scans that run repeatedly, we just have 2 scans total, that both run perpetually, and we dovetail them in chunks. I will call these scans "heads" and "tails". The heads scan always follows the chain head. It's job is to fetch recent blocks that we may have missed on decide, such as if we briefly lost network connection and missed a decide. The tails scan starts at the tail of the chain and follows behind the heads scan. Its job is to fetch old data that we're missing, such as after a long restart. Both of these scans follow the same exact pattern, except for where they start and what they do when the reach the current block height:
The big advantage of this scheme is a bounded amount of work done each time a scan runs. We don't have occasional long pauses where a major scan runs, CPU usage spikes, and we stop fetching more recent missing blocks (because minor scans have to wait for the major scan to finish). Another big advantage is on startup, we don't have to wait for a major scan to read from the database all the way from 0, before we start fetching more recent blocks which are more likely to be missing. |
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: 1. 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. 2. 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. Knock-on changes: * 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.
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: 1. 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. 2. 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. Knock-on changes: * 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.
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: 1. 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. 2. 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. Knock-on changes: * 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.
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: 1. 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. 2. 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. Knock-on changes: * 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.
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: 1. 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. 2. 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. Knock-on changes: * 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.
It would be better to run proactive scans, especially major scans, backwards, because the newest data is both the most likely to be missing (in the case where a node has just been offline for a short time, like an update) and the most likely to be queried.
Adding a reverse block stream might help simplify some of the transaction streaming stuff for the explorer as well.
The text was updated successfully, but these errors were encountered: