Skip to content

Commit

Permalink
Merge pull request #4063 from onflow/yurii/decode-signer-ids-by-block…
Browse files Browse the repository at this point in the history
…-id-fallback

[Committee] Fallback mechanism for `DecodeSignerIDs`
  • Loading branch information
peterargue authored Mar 21, 2023
2 parents 757143d + 3586c81 commit 47858e0
Show file tree
Hide file tree
Showing 3 changed files with 15 additions and 6 deletions.
1 change: 0 additions & 1 deletion consensus/hotstuff/committee.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,6 @@ type BlockSignerDecoder interface {
// consensus committee has reached agreement on validity of parent block. Consequently, the
// returned IdentifierList contains the consensus participants that signed the parent block.
// Expected Error returns during normal operations:
// - model.ErrViewForUnknownEpoch if the given block's parent is within an unknown epoch
// - signature.InvalidSignerIndicesError if signer indices included in the header do
// not encode a valid subset of the consensus committee
DecodeSignerIDs(header *flow.Header) (flow.IdentifierList, error)
Expand Down
13 changes: 10 additions & 3 deletions consensus/hotstuff/signature/block_signer_decoder.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ var _ hotstuff.BlockSignerDecoder = (*BlockSignerDecoder)(nil)
// consensus committee has reached agreement on validity of parent block. Consequently, the
// returned IdentifierList contains the consensus participants that signed the parent block.
// Expected Error returns during normal operations:
// - model.ErrViewForUnknownEpoch if the given block is within an unknown epoch
// - signature.InvalidSignerIndicesError if signer indices included in the header do
// not encode a valid subset of the consensus committee
func (b *BlockSignerDecoder) DecodeSignerIDs(header *flow.Header) (flow.IdentifierList, error) {
Expand All @@ -36,12 +35,20 @@ func (b *BlockSignerDecoder) DecodeSignerIDs(header *flow.Header) (flow.Identifi
return []flow.Identifier{}, nil
}

// we will use IdentitiesByEpoch since it's a faster call and avoids DB lookup
members, err := b.IdentitiesByEpoch(header.ParentView)
if err != nil {
if errors.Is(err, model.ErrViewForUnknownEpoch) {
return nil, fmt.Errorf("could not retrieve identities for block %x with QC view %d: %w", header.ID(), header.ParentView, err)
// possibly, we request epoch which is far behind in the past, in this case we won't have it in cache.
// try asking by parent ID
members, err = b.IdentitiesByBlock(header.ParentID)
if err != nil {
return nil, fmt.Errorf("could not retrieve identities for block %x with QC view %d for parent %x: %w",
header.ID(), header.ParentView, header.ParentID, err)
}
} else {
return nil, fmt.Errorf("unexpected error retrieving identities for block %v: %w", header.ID(), err)
}
return nil, fmt.Errorf("unexpected error retrieving identities for block %v: %w", header.ID(), err)
}
signerIDs, err := signature.DecodeSignerIndicesToIdentifiers(members.NodeIDs(), header.ParentVoterIndices)
if err != nil {
Expand Down
7 changes: 5 additions & 2 deletions consensus/hotstuff/signature/block_signer_decoder_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package signature

import (
"errors"
"fmt"
"testing"

"github.com/stretchr/testify/mock"
Expand All @@ -13,6 +14,7 @@ import (
"github.com/onflow/flow-go/model/flow"
"github.com/onflow/flow-go/model/flow/order"
"github.com/onflow/flow-go/module/signature"
"github.com/onflow/flow-go/state"
"github.com/onflow/flow-go/utils/unittest"
)

Expand Down Expand Up @@ -82,11 +84,12 @@ func (s *blockSignerDecoderSuite) Test_UnexpectedCommitteeException() {
// It should propagate the sentinel error model.ErrViewForUnknownEpoch from Committee.
func (s *blockSignerDecoderSuite) Test_UnknownEpoch() {
*s.committee = *hotstuff.NewDynamicCommittee(s.T())
s.committee.On("IdentitiesByEpoch", mock.Anything).Return(nil, model.ErrViewForUnknownEpoch)
s.committee.On("IdentitiesByEpoch", s.block.Header.ParentView).Return(nil, model.ErrViewForUnknownEpoch)
s.committee.On("IdentitiesByBlock", s.block.Header.ParentID).Return(nil, fmt.Errorf(""))

ids, err := s.decoder.DecodeSignerIDs(s.block.Header)
require.Empty(s.T(), ids)
require.ErrorIs(s.T(), err, model.ErrViewForUnknownEpoch)
require.Error(s.T(), err)
}

// Test_InvalidIndices verifies that `BlockSignerDecoder` returns
Expand Down

0 comments on commit 47858e0

Please sign in to comment.