Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sharing the state between peers. #446

Closed
wants to merge 24 commits into from

Conversation

OStevan
Copy link
Contributor

@OStevan OStevan commented Jul 14, 2020

Issue and how it solves the problem?
#420 , this PR proposes a solution in which the Supervisor has a state which would be updated with trusted LightBlocks after each successful pass of fork detection. Subsequent verification requests first read the highest trusted LightBlock in the supervisor state and use that LightBlock as the starting point for verification.

Concerns related to the solution?

  • Core verification on the primary and witnesses is always using InMemoryVersion of LightStore. We could either simplify the instance and remove associated LightStores or try to always use the one associated with the instance
  • Should we actually always use the one associated with an Instance so that for example we can examine the store in case of failure?

Other related discussions?
The solution from #479 deletes the light blocks higher that the previously trusted one in the shared state. The approach here just discards the light store used by the primary.

  • Referenced an issue explaining the need for the change
  • Updated all relevant documentation in docs
  • Updated all code comments where relevant
  • Wrote tests
  • Updated CHANGES.md

@codecov-commenter

This comment has been minimized.

@@ -89,6 +92,7 @@ impl Default for LightNodeConfig {
// TODO(ismail): need at least 2 peers for a proper init
// otherwise the light node will complain on `start` with `no witness left`
light_clients: vec![LightClientConfig::default()],
shared_state_config: "./lightstore".parse().unwrap(),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure I have the right context but doesn't this mean you can remove the separate stores in each light client?
See above:

/// LightClientConfig contains all options of a light client instance.
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct LightClientConfig {
    /// Address of the Tendermint fullnode to connect to and
    /// fetch LightBlock data from.
    pub address: tendermint::net::Address,
    /// PeerID of the same Tendermint fullnode.
    pub peer_id: PeerId,
    /// The data base folder for this instance's store.
    pub db_path: PathBuf,
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is something I wanted to discuss. In practice we can use in-memory state for each peer instance enabling us to remove the separate stores for each light client. I'm however unsure if we might still want to keep these stores to be able to inspect what each light client verified by itself(do we even want such a feature?). @liamsi

Copy link
Member

@liamsi liamsi Jul 17, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm however unsure if we might still want to keep these stores to be able to inspect what each light client verified by itself(do we even want such a feature?).

Not sure tbh, but there might be some cases where this is required for the fork-detector!? @milosevic @ebuchman

@OStevan OStevan force-pushed the ostevan/state-example branch 2 times, most recently from 1d7c6a2 to e3a45f7 Compare July 19, 2020 11:42
let factory: &dyn LightStoreFactory = lock
.state()
.components
.get_downcast_ref::<ProdLightStoreFactory>()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't believe we need the flexibility afforded by the LightStoreFactory trait/component, a plain method which converts a LightStoreConfig to a impl LightStore would likely do the job as well.

This line is also a bit weird because we are always casting to a concrete type, which defeats the purpose of the trait.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Changed it to a function.

@romac
Copy link
Member

romac commented Jul 22, 2020

Looks good to me 👍 Thanks for opening this draft PR for discussion!

I just have one comment on the need for a LightStoreFactory.

That said, I think the general idea of sharing the state between all peers should be carefully considered and reviewed by @josef-widder and @milosevic.

@OStevan OStevan marked this pull request as ready for review July 28, 2020 12:09
@OStevan
Copy link
Contributor Author

OStevan commented Jul 28, 2020

ping @milosevic @josef-widder

@josef-widder
Copy link
Member

In #479, we stated the invariant [LCD-INV-TRUSTED-AGREED.1]. It says that the primary and the secondary always agree on the lightblock for height lightStore.LatestTrusted().Height. This allows us to not store any blocks downloaded from secondaries after fork detection returned: More precisely, fork detection is started from this latest trusted block at all secondaries, and if there is no fork, all downloaded blocks can be dropped. If there is a fork, the downloaded blocks are used to generate "proof of fork".

So I am not sure we need to share the state between peers, but perhaps I didn't get the question...

(@milosevic is on vacations this week)

Copy link
Contributor

@xla xla left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The proposed solution has the character of a band-aid rather than addressing the issue. Seeing the Handle holding onto actual state violates the original design constraints. It would be more effective if we look closer at the problem and maybe even adjust our understanding as @josef-widder pointed out to remove the need for the state all together.

@brapse
Copy link
Contributor

brapse commented Aug 5, 2020

This is a great first step but should integrate the work in #479 and be preceded by an ADR outlining the approach. Might make sense to do this as a separate PR. Will leave the branch for reference.

@brapse brapse closed this Aug 5, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants