github.com/koko1123/flow-go-1@v0.29.6/consensus/hotstuff/signature/block_signer_decoder_test.go (about) 1 package signature 2 3 import ( 4 "errors" 5 "testing" 6 7 "github.com/stretchr/testify/mock" 8 "github.com/stretchr/testify/require" 9 "github.com/stretchr/testify/suite" 10 11 hotstuff "github.com/koko1123/flow-go-1/consensus/hotstuff/mocks" 12 "github.com/koko1123/flow-go-1/model/flow" 13 "github.com/koko1123/flow-go-1/model/flow/order" 14 "github.com/koko1123/flow-go-1/module/signature" 15 "github.com/koko1123/flow-go-1/state" 16 "github.com/koko1123/flow-go-1/storage" 17 "github.com/koko1123/flow-go-1/utils/unittest" 18 ) 19 20 func TestBlockSignerDecoder(t *testing.T) { 21 suite.Run(t, new(blockSignerDecoderSuite)) 22 } 23 24 type blockSignerDecoderSuite struct { 25 suite.Suite 26 allConsensus flow.IdentityList 27 committee *hotstuff.Committee 28 29 decoder *BlockSignerDecoder 30 block flow.Block 31 } 32 33 func (s *blockSignerDecoderSuite) SetupTest() { 34 // the default header fixture creates signerIDs for a committee of 10 nodes, so we prepare a committee same as that 35 s.allConsensus = unittest.IdentityListFixture(40, unittest.WithRole(flow.RoleConsensus)).Sort(order.Canonical) 36 37 // prepare valid test block: 38 voterIndices, err := signature.EncodeSignersToIndices(s.allConsensus.NodeIDs(), s.allConsensus.NodeIDs()) 39 require.NoError(s.T(), err) 40 s.block = unittest.BlockFixture() 41 s.block.Header.ParentVoterIndices = voterIndices 42 43 // mock consensus committee 44 s.committee = new(hotstuff.Committee) 45 s.committee.On("Identities", s.block.Header.ParentID).Return(s.allConsensus, nil) 46 47 s.decoder = NewBlockSignerDecoder(s.committee) 48 } 49 50 // Test_SuccessfulDecode tests happy path decoding 51 func (s *blockSignerDecoderSuite) Test_SuccessfulDecode() { 52 ids, err := s.decoder.DecodeSignerIDs(s.block.Header) 53 require.NoError(s.T(), err) 54 require.Equal(s.T(), s.allConsensus.NodeIDs(), ids) 55 } 56 57 // Test_RootBlock tests decoder accepts root block with empty signer indices 58 func (s *blockSignerDecoderSuite) Test_RootBlock() { 59 s.block.Header.ParentVoterIndices = nil 60 s.block.Header.ParentVoterSigData = nil 61 s.block.Header.View = 0 62 63 ids, err := s.decoder.DecodeSignerIDs(s.block.Header) 64 require.NoError(s.T(), err) 65 require.Empty(s.T(), ids) 66 } 67 68 // Test_UnknownBlock tests handling of an unknwon block. 69 // At the moment, hotstuff.Committee returns an storage.ErrNotFound for an unknown block, 70 // which we expect the `BlockSignerDecoder` to wrap into a `state.UnknownBlockError` 71 func (s *blockSignerDecoderSuite) Test_UnknownBlock() { 72 *s.committee = hotstuff.Committee{} 73 s.committee.On("Identities", mock.Anything).Return(nil, storage.ErrNotFound) 74 75 ids, err := s.decoder.DecodeSignerIDs(s.block.Header) 76 require.Empty(s.T(), ids) 77 require.True(s.T(), state.IsUnknownBlockError(err)) 78 } 79 80 // Test_UnexpectedCommitteeException verifies that `BlockSignerDecoder` 81 // does _not_ erroneously interpret an unexpecgted exception from the committee as 82 // a sign of an unknown block, i.e. the decouder should _not_ return an `state.UnknownBlockError` 83 func (s *blockSignerDecoderSuite) Test_UnexpectedCommitteeException() { 84 exception := errors.New("unexpected exception") 85 *s.committee = hotstuff.Committee{} 86 s.committee.On("Identities", mock.Anything).Return(nil, exception) 87 88 ids, err := s.decoder.DecodeSignerIDs(s.block.Header) 89 require.Empty(s.T(), ids) 90 require.False(s.T(), state.IsUnknownBlockError(err)) 91 require.True(s.T(), errors.Is(err, exception)) 92 } 93 94 // Test_InvalidIndices verifies that `BlockSignerDecoder` returns 95 // signature.InvalidSignerIndicesError is the signer indices in the provided header 96 // are not a valid encoding. 97 func (s *blockSignerDecoderSuite) Test_InvalidIndices() { 98 s.block.Header.ParentVoterIndices = unittest.RandomBytes(1) 99 ids, err := s.decoder.DecodeSignerIDs(s.block.Header) 100 require.Empty(s.T(), ids) 101 require.True(s.T(), signature.IsInvalidSignerIndicesError(err)) 102 }