-
Notifications
You must be signed in to change notification settings - Fork 180
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
[Dynamic Protocol State] Protocol state storage #4559
[Dynamic Protocol State] Protocol state storage #4559
Conversation
…d fixed usages. Updated signer indices
…nding on context. Updated usages. Fixed tests
…/6232-static-identity-model
…ing on DB lookups.
Co-authored-by: Jordan Schalm <jordan@dapperlabs.com>
…-protocol-state-storage-layer
// Common situation during the epoch setup phase for epoch N+1 | ||
// * we are currently in Epoch N | ||
// * previous epoch N-1 is known (specifically EpochSetup and EpochCommit events) | ||
// * network is currently in the setup phase for the next epoch, i.e. EpochSetup event (starting setup phase) has already been observed | ||
t.Run("setup-phase", func(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the staking phase we test both scenarios:
- previous epoch unknown: first epoch after spork
- previous epoch unknown: common case for later epochs in spork
However, for the setup phase we don't test the scenario where no prior epoch is known. I think we should extend the test here.
same for testing the epoch commit phase
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added respective TODO to issue #4649
storage/badger/protocol_state.go
Outdated
// ByBlockID returns the protocol state by block ID. | ||
func (s *ProtocolState) ByBlockID(blockID flow.Identifier) (*flow.RichProtocolStateEntry, error) { | ||
tx := s.db.NewTransaction(false) | ||
defer tx.Discard() | ||
return s.byBlockID(blockID)(tx) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
performance concern
I am would suggest to also include a cache for the secondary index here as well. The Headers
implementation provides a nice example, where we have a secondary index by height that is also backed by a cache
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added as TODO to issue #4649
) | ||
|
||
// ProtocolState implements persistent storage for storing entities of protocol state. | ||
// Protocol state uses an embedded cache without storing capabilities(store happens on first retrieval) to avoid unnecessary |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am wondering how much of a challenge it would be to actually cache the RichProtocolStateEntry
on store. At the moment, we insert a ProtocolStateEntry
(non-rich) -- presumably this is the reason for not storing the RichProtocolStateEntry
. However, to me this seems to be an artifact that could indicate room for improvement in the software design:
- I think for about 95% of the blocks that we store, we need the
RichProtocolStateEntry
state later. This is because we finalize 95% of all proposed blocks, i.e. the blocks have children; I would guess we that we query theRichProtocolStateEntry
when processing a block's child. - To me it would be most natural if the process evolving the identity table produced the
RichProtocolStateEntry
. TheRichProtocolStateEntry
would ideally provide methods to generate/return its condensed version.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added respective TODO to issue #4649
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tried to address as many comments as I could and added most of the remaining TODOs to #4649
// Common situation during the epoch setup phase for epoch N+1 | ||
// * we are currently in Epoch N | ||
// * previous epoch N-1 is known (specifically EpochSetup and EpochCommit events) | ||
// * network is currently in the setup phase for the next epoch, i.e. EpochSetup event (starting setup phase) has already been observed | ||
t.Run("setup-phase", func(t *testing.T) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added respective TODO to issue #4649
) | ||
|
||
// ProtocolState implements persistent storage for storing entities of protocol state. | ||
// Protocol state uses an embedded cache without storing capabilities(store happens on first retrieval) to avoid unnecessary |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added respective TODO to issue #4649
Co-authored-by: Alexander Hentschel <alex.hentschel@axiomzen.co>
Failing test:
|
…nflow/flow-go into yurii/5529-dynamic-protocol-state-storage-layer
Context
This PR implements a storage system for protocol state along with auxiliary data structures, storage access layer and caching strategy. Some of important concepts:
flow.ProtocolStateEntry
is stored in DB and is designed in a way to minimize storage overhead.flow.RichProtocolStateEntry
decorates basicflow.ProtocolStateEntry
with additional data that has to be queried from storage layer (such asEpochSetup
events).storage.ProtocolState
operates withflow.ProtocolStateEntry
for storing andflow.RichProtocolStateEntry
for queryingbadger.ProtocolState
uses a cache with no-op storing capability, in this case cache is populated only on queries. Cache itself operates withflow.RichProtocolStateEntry
to avoid querying extra data.