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

Implement LazyLoadVersion #148

Merged
merged 7 commits into from
Jul 1, 2019
Merged

Implement LazyLoadVersion #148

merged 7 commits into from
Jul 1, 2019

Conversation

alexanderbez
Copy link
Contributor

Implement lazy loading of a given version.

ref: cosmos/cosmos-sdk#4326

@alexanderbez alexanderbez marked this pull request as ready for review June 27, 2019 19:47
@alexanderbez
Copy link
Contributor Author

Let me know if this looks correct @liamsi or if there are any cases I need to be aware of. I've successfully tested this in Gaia.

Copy link
Contributor

@melekes melekes left a comment

Choose a reason for hiding this comment

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

🌟

mutable_tree.go Outdated Show resolved Hide resolved
Copy link
Contributor

@liamsi liamsi left a comment

Choose a reason for hiding this comment

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

The changes look good to me 👍 My only concern is that this adds yet another public method to the API and as a user it might not be clear when to use LazyLoadVersion over LoadVersion. A test that showcases the different behaviour, or a comment in the godoc when to use which method might help here. I'm also wondering if LazyLoadVersion shouldn't be the default (and only) method.

Co-Authored-By: Anton Kaliaev <anton.kalyaev@gmail.com>
@alexanderbez
Copy link
Contributor Author

@liamsi that's a good point. And as you've brought up, I can't think of a reason why one would use LoadVersion() over LazyLoadVersion(). It's not immediately clear to me why you'd need to load all the roots -- I was hoping you'd have more context or a clue here.

If we are in agreement, how about we replace LoadVersion with LazyLoadVersion?

@liamsi
Copy link
Contributor

liamsi commented Jun 28, 2019

Sorry, I don't have any more context on this. Maybe @jaekwon (or @ethanfrey) have?

If we are in agreement, how about we replace LoadVersion with LazyLoadVersion?

As far as I understand it does not make sense to load all the roots. I'm OK with replacing LoadVersion with LazyLoadVersion.

@zmanian
Copy link
Member

zmanian commented Jun 28, 2019

Okay I am not 100% sure we should replace LoadVersion()

LoadVersion is not DOSable. LazyLoadVersion is. Ie. Once you load a tree with LoadVersion() the tree cannot be DOSed by creating a query pattern that requires loading lots of different tree versions to bring the node to a halt.

LoadVersion() can be used safely with a pruning node and queries against snapshots.

LazyLoadVersion() opts a node operator into new risks if the tendermint rpc is world accessible.

@alexanderbez
Copy link
Contributor Author

alexanderbez commented Jun 28, 2019

Valid concerns @zmanian. From doing another pass through of the IAVL implementation and it's relation/usage in the SDK's multistore (I've done this now a few times), I don't quite see where a DOS attack vector could occur? I could very well be wrong here. Here's what I can tell:

  • Height queries always call ndb.getRoot() regardless
  • Root node lookups ndb.getNode() can be cached (regardless of which method we call)
  • The only difference between LoadVersion and LazyLoadVersion is the former reads all the roots AND sets them in tree.versions[version].
  • I don't see how tree.versions would correlate to any DOSing or the prevention thereof. It's mainly only used when it comes to deleting.

Copy link
Member

@zmanian zmanian left a comment

Choose a reason for hiding this comment

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

I'm in favor of replacing LoadVersion entirely at the movement.

@alexanderbez alexanderbez requested a review from zmanian July 1, 2019 18:38
@alexanderbez
Copy link
Contributor Author

alexanderbez commented Jul 1, 2019

Ok so actually taking a stab at replacing LoadVersion with LazyLoadVersion, I see why the need for LoadVersion exists:

The original LoadVersion() loads all the roots and as a result, when you load previous committed/saved versions and then try to overwrite a value and save, you'll get an error (as you should). This obviously does not hold with LazyLoadVersion. I'm sure there are other cases similar to this.

That being the case, I'm going to leave LoadVersion as-is and keep LazyLoadVersion and update the godoc to state it should only be used in cases where only reads are necessary, not writes. In fact, this was the original motivation/use-case.

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.

4 participants