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

Add historical summaries to state and processing #11842

Merged
merged 24 commits into from
Jan 11, 2023

Conversation

terencechain
Copy link
Member

@terencechain terencechain commented Jan 3, 2023

This PR implements ethereum/consensus-specs#2649, which adds historical summaries to the beacon state and updates them for epoch processing. This is part of the Capella update

⚠️ Note: We need to update the new state for beacon-api. But we can do this in subsequent PR

@terencechain terencechain self-assigned this Jan 3, 2023
@terencechain terencechain added the Ready For Review A pull request ready for code review label Jan 9, 2023
@terencechain terencechain marked this pull request as ready for review January 9, 2023 16:13
@terencechain terencechain requested a review from a team as a code owner January 9, 2023 16:13
@terencechain terencechain requested review from potuz and nisdas January 9, 2023 16:13
func ProcessHistoricalRootsUpdate(state state.BeaconState) (state.BeaconState, error) {
// ProcessHistoricalDataUpdate processes the updates to historical data during epoch processing.
// For Capella state, per spec, historical summaries is updated instead of historical roots.
func ProcessHistoricalDataUpdate(state state.BeaconState) (state.BeaconState, error) {
Copy link
Member Author

Choose a reason for hiding this comment

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

I decided to embed two different processing logic for historical data so that callers don't have to worry about what fork uses what.
Another approach is to implement two different functions ProcessHistoricalRootsUpdate and ProcessHistoricalSummariesUpdate with some duplicated conditions and let the callers decide which to call

Copy link
Contributor

@kasey kasey Jan 11, 2023

Choose a reason for hiding this comment

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

+1 to encapsulating that here, the way you're doing it


// HistoricalSummaries of the beacon state.
func (b *BeaconState) HistoricalSummaries() []*ethpb.HistoricalSummary {
if b.historicalSummaries == nil {
Copy link
Member Author

@terencechain terencechain Jan 9, 2023

Choose a reason for hiding this comment

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

I skipped the versioning checks here and HistoricalRoots() because the list would just be emptied and error out upon return. I don't think it's a big deal, and I didn't feel like changing the return argument to include an error. Happy to change it otherwise

Copy link
Contributor

Choose a reason for hiding this comment

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

Don't most of the other getters return an error when a property is accessed on a version of the state which does not have that property?

Copy link
Contributor

@rkapka rkapka left a comment

Choose a reason for hiding this comment

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

Very nice and clean!

beacon-chain/core/epoch/epoch_processing.go Outdated Show resolved Hide resolved
beacon-chain/core/epoch/epoch_processing_test.go Outdated Show resolved Hide resolved
require.NoError(t, err)
return st
},
verifier: func(st state.BeaconState) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Verify historical summaries were not updates?

require.NoError(t, err)
return st
},
verifier: func(st state.BeaconState) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Verify historical roots were not updated?

@@ -85,6 +86,7 @@ type WriteOnlyBeaconState interface {
SetSlashings(val []uint64) error
UpdateSlashingsAtIndex(idx, val uint64) error
AppendHistoricalRoots(root [32]byte) error
AppendHistoricalSummariesUpdate(*ethpb.HistoricalSummary) error
Copy link
Contributor

Choose a reason for hiding this comment

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

This Update part sounds weird. How about AppendHistoricalSummaries?

func (b *BeaconState) AppendHistoricalRoots(root [32]byte) error {
b.lock.Lock()
defer b.lock.Unlock()

if b.version > version.Bellatrix {
return fmt.Errorf("AppendHistoricalRoots is not supported for version %d", b.version)
Copy link
Contributor

Choose a reason for hiding this comment

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

Please use the errNotSupported function

@@ -124,6 +131,29 @@ func (b *BeaconState) AppendHistoricalRoots(root [32]byte) error {
return nil
}

// AppendHistoricalSummariesUpdate AppendHistoricalSummary for the beacon state. Appends the new value
Copy link
Contributor

Choose a reason for hiding this comment

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

Something is not correct

defer b.lock.Unlock()

if b.version < version.Capella {
return fmt.Errorf("AppendHistoricalSummariesUpdate is not supported for version %d", b.version)
Copy link
Contributor

Choose a reason for hiding this comment

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

Please use the errNotSupported function

proto/prysm/v1alpha1/beacon_state.proto Outdated Show resolved Hide resolved
beacon-chain/state/state-native/hasher.go Outdated Show resolved Hide resolved
rkapka
rkapka previously approved these changes Jan 11, 2023
roots, err := st.HistoricalRoots()
if err != nil {
log.WithError(err).Error("could not get historical roots")
return
Copy link
Contributor

Choose a reason for hiding this comment

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

return or continue logging?

Copy link
Member Author

Choose a reason for hiding this comment

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

cont is probably better here

rkapka
rkapka previously approved these changes Jan 11, 2023
}
size, count = sizeAndCountOfByteList(roots)
log.Infof("historical_roots : size = %s, count = %d", humanize.Bytes(size), count)

Copy link
Contributor

Choose a reason for hiding this comment

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

nitpick: not a fan of this whitespace formatting. I've been leaning more towards using WithField to make structured logs easier.

Copy link
Member Author

Choose a reason for hiding this comment

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

It's a little unrelated to this PR

require.NoError(t, err)
require.Equal(t, 0, len(summaries))
_, err = st.HistoricalSummaries()
require.ErrorContains(t, "HistoricalSummaries is not supported for phase0", err)
Copy link
Contributor

Choose a reason for hiding this comment

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

can we use require.ErrorIs instead of string matching the error text?

Copy link
Member Author

Choose a reason for hiding this comment

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

Error is not exported. I can export the error though. Was trying to minimize the changes since the diff is getting big

@prylabs-bulldozer prylabs-bulldozer bot merged commit 7fa3ebf into develop Jan 11, 2023
@delete-merged-branch delete-merged-branch bot deleted the historical-summaries branch January 11, 2023 22:20
@@ -67,15 +68,19 @@ func (b *BeaconState) forkVal() *ethpb.Fork {
}

// HistoricalRoots based on epochs stored in the beacon state.
func (b *BeaconState) HistoricalRoots() [][]byte {
func (b *BeaconState) HistoricalRoots() ([][]byte, error) {
if b.version > version.Bellatrix {
Copy link
Member

Choose a reason for hiding this comment

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

This is not accurate, the historical roots field still exists in the state. Just that it is now 'frozen'

@@ -530,6 +533,7 @@ func (b *BeaconState) Copy() state.BeaconState {
nextSyncCommittee: b.nextSyncCommitteeVal(),
latestExecutionPayloadHeader: b.latestExecutionPayloadHeaderVal(),
latestExecutionPayloadHeaderCapella: b.latestExecutionPayloadHeaderCapellaVal(),
historicalSummaries: b.historicalSummariesVal(),
Copy link
Member

Choose a reason for hiding this comment

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

if we are sharing fields for historical summaries with other state instances, then this is incorrect. This performs a whole copy of the field, when we should just be sharing the reference like how it is done for historical roots:

historicalRoots: b.historicalRoots,

}

return fieldRoots, nil
}

func historicalSummaryRoot(summaries []*ethpb.HistoricalSummary) ([32]byte, error) {
Copy link
Member

Choose a reason for hiding this comment

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

This should be in the stateutil package, since there is where we keep all the state hashing functions at

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Ready For Review A pull request ready for code review
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants