-
Notifications
You must be signed in to change notification settings - Fork 146
fix(lib/grandpa): Storing Justification Allows Extra Bytes (GSR-13) #2618
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
Changes from all commits
8abfdba
6d93ce5
5d9d0ee
1f49294
28a6f27
209e046
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -120,7 +120,10 @@ func newTestSyncer(t *testing.T) *Service { | |
| cfg.LogLvl = log.Trace | ||
| mockFinalityGadget := NewMockFinalityGadget(ctrl) | ||
| mockFinalityGadget.EXPECT().VerifyBlockJustification(gomock.AssignableToTypeOf(common.Hash{}), | ||
| gomock.AssignableToTypeOf([]byte{})).AnyTimes() | ||
| gomock.AssignableToTypeOf([]byte{})).DoAndReturn(func(hash common.Hash, justification []byte) ([]byte, error) { | ||
| return justification, nil | ||
| }).AnyTimes() | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a way to know exactly how many times this runs?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, since this is in |
||
|
|
||
| cfg.FinalityGadget = mockFinalityGadget | ||
| cfg.Network = newMockNetwork() | ||
| cfg.Telemetry = mockTelemetryClient | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -553,48 +553,49 @@ func (h *MessageHandler) verifyJustification(just *SignedVote, round, setID uint | |
| return nil | ||
| } | ||
|
|
||
| // VerifyBlockJustification verifies the finality justification for a block | ||
| func (s *Service) VerifyBlockJustification(hash common.Hash, justification []byte) error { | ||
| // VerifyBlockJustification verifies the finality justification for a block, returns scale encoded justification with | ||
| // any extra bytes removed. | ||
| func (s *Service) VerifyBlockJustification(hash common.Hash, justification []byte) ([]byte, error) { | ||
| fj := Justification{} | ||
| err := scale.Unmarshal(justification, &fj) | ||
| if err != nil { | ||
| return err | ||
| return nil, err | ||
| } | ||
|
|
||
| setID, err := s.grandpaState.GetSetIDByBlockNumber(uint(fj.Commit.Number)) | ||
| if err != nil { | ||
| return fmt.Errorf("cannot get set ID from block number: %w", err) | ||
| return nil, fmt.Errorf("cannot get set ID from block number: %w", err) | ||
| } | ||
|
|
||
| has, err := s.blockState.HasFinalisedBlock(fj.Round, setID) | ||
| if err != nil { | ||
| return err | ||
| return nil, err | ||
| } | ||
|
|
||
| if has { | ||
| return fmt.Errorf("already have finalised block with setID=%d and round=%d", setID, fj.Round) | ||
| return nil, fmt.Errorf("already have finalised block with setID=%d and round=%d", setID, fj.Round) | ||
| } | ||
|
|
||
| isDescendant, err := isDescendantOfHighestFinalisedBlock(s.blockState, fj.Commit.Hash) | ||
| if err != nil { | ||
| return err | ||
| return nil, err | ||
| } | ||
|
|
||
| if !isDescendant { | ||
| return errVoteBlockMismatch | ||
| return nil, errVoteBlockMismatch | ||
| } | ||
|
|
||
| auths, err := s.grandpaState.GetAuthorities(setID) | ||
| if err != nil { | ||
| return fmt.Errorf("cannot get authorities for set ID: %w", err) | ||
| return nil, fmt.Errorf("cannot get authorities for set ID: %w", err) | ||
| } | ||
|
|
||
| // threshold is two-thirds the number of authorities, | ||
| // uses the current set of authorities to define the threshold | ||
| threshold := (2 * len(auths) / 3) | ||
|
|
||
| if len(fj.Commit.Precommits) < threshold { | ||
| return ErrMinVotesNotMet | ||
| return nil, ErrMinVotesNotMet | ||
| } | ||
|
|
||
| authPubKeys := make([]AuthData, len(fj.Commit.Precommits)) | ||
|
|
@@ -604,7 +605,7 @@ func (s *Service) VerifyBlockJustification(hash common.Hash, justification []byt | |
|
|
||
| equivocatoryVoters, err := getEquivocatoryVoters(authPubKeys) | ||
| if err != nil { | ||
| return fmt.Errorf("could not get valid equivocatory voters: %w", err) | ||
| return nil, fmt.Errorf("could not get valid equivocatory voters: %w", err) | ||
| } | ||
|
|
||
| var count int | ||
|
|
@@ -617,20 +618,20 @@ func (s *Service) VerifyBlockJustification(hash common.Hash, justification []byt | |
| // check if vote was for descendant of committed block | ||
| isDescendant, err := s.blockState.IsDescendantOf(hash, just.Vote.Hash) | ||
| if err != nil { | ||
| return err | ||
| return nil, err | ||
| } | ||
|
|
||
| if !isDescendant { | ||
| return ErrPrecommitBlockMismatch | ||
| return nil, ErrPrecommitBlockMismatch | ||
| } | ||
|
|
||
| pk, err := ed25519.NewPublicKey(just.AuthorityID[:]) | ||
| if err != nil { | ||
| return err | ||
| return nil, err | ||
| } | ||
|
|
||
| if !isInAuthSet(pk, auths) { | ||
| return ErrAuthorityNotInSet | ||
| return nil, ErrAuthorityNotInSet | ||
| } | ||
|
|
||
| // verify signature for each precommit | ||
|
|
@@ -641,16 +642,16 @@ func (s *Service) VerifyBlockJustification(hash common.Hash, justification []byt | |
| SetID: setID, | ||
| }) | ||
| if err != nil { | ||
| return err | ||
| return nil, err | ||
| } | ||
|
|
||
| ok, err := pk.Verify(msg, just.Signature[:]) | ||
| if err != nil { | ||
| return err | ||
| return nil, err | ||
| } | ||
|
|
||
| if !ok { | ||
| return ErrInvalidSignature | ||
| return nil, ErrInvalidSignature | ||
| } | ||
|
|
||
| if _, ok := equivocatoryVoters[just.AuthorityID]; ok { | ||
|
|
@@ -661,30 +662,30 @@ func (s *Service) VerifyBlockJustification(hash common.Hash, justification []byt | |
| } | ||
|
|
||
| if count+len(equivocatoryVoters) < threshold { | ||
| return ErrMinVotesNotMet | ||
| return nil, ErrMinVotesNotMet | ||
| } | ||
|
|
||
| err = verifyBlockHashAgainstBlockNumber(s.blockState, fj.Commit.Hash, uint(fj.Commit.Number)) | ||
| if err != nil { | ||
| return err | ||
| return nil, err | ||
| } | ||
|
|
||
| for _, preCommit := range fj.Commit.Precommits { | ||
| err := verifyBlockHashAgainstBlockNumber(s.blockState, preCommit.Vote.Hash, uint(preCommit.Vote.Number)) | ||
| if err != nil { | ||
| return err | ||
| return nil, err | ||
| } | ||
| } | ||
|
|
||
| err = s.blockState.SetFinalisedHash(hash, fj.Round, setID) | ||
| if err != nil { | ||
| return err | ||
| return nil, err | ||
| } | ||
|
|
||
| logger.Debugf( | ||
| "set finalised block with hash %s, round %d and set id %d", | ||
| hash, fj.Round, setID) | ||
| return nil | ||
| return scale.Marshal(fj) | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A little confused, just for my own understanding where are the extra bytes trimmed here? Is it just by unmarshalling then marshalling?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, the extra bytes are removed when the un-marshaled Justification is marshaled. |
||
| } | ||
|
|
||
| func verifyBlockHashAgainstBlockNumber(bs BlockState, hash common.Hash, number uint) error { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.