github.com/true-sqn/fabric@v2.1.1+incompatible/orderer/consensus/etcdraft/blockpuller_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package etcdraft_test
     8  
     9  import (
    10  	"io/ioutil"
    11  	"testing"
    12  
    13  	"github.com/golang/protobuf/proto"
    14  	"github.com/hyperledger/fabric-protos-go/common"
    15  	"github.com/hyperledger/fabric/bccsp/sw"
    16  	"github.com/hyperledger/fabric/common/crypto/tlsgen"
    17  	"github.com/hyperledger/fabric/internal/pkg/comm"
    18  	"github.com/hyperledger/fabric/orderer/common/cluster"
    19  	"github.com/hyperledger/fabric/orderer/common/cluster/mocks"
    20  	"github.com/hyperledger/fabric/orderer/common/localconfig"
    21  	"github.com/hyperledger/fabric/orderer/consensus"
    22  	"github.com/hyperledger/fabric/orderer/consensus/etcdraft"
    23  	"github.com/hyperledger/fabric/orderer/mocks/common/multichannel"
    24  	"github.com/hyperledger/fabric/protoutil"
    25  	"github.com/stretchr/testify/assert"
    26  )
    27  
    28  func TestEndpointconfigFromFromSupport(t *testing.T) {
    29  	blockBytes, err := ioutil.ReadFile("testdata/mychannel.block")
    30  	assert.NoError(t, err)
    31  
    32  	goodConfigBlock := &common.Block{}
    33  	assert.NoError(t, proto.Unmarshal(blockBytes, goodConfigBlock))
    34  
    35  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
    36  	assert.NoError(t, err)
    37  
    38  	for _, testCase := range []struct {
    39  		name            string
    40  		height          uint64
    41  		blockAtHeight   *common.Block
    42  		lastConfigBlock *common.Block
    43  		expectedError   string
    44  	}{
    45  		{
    46  			name:          "Block returns nil",
    47  			expectedError: "unable to retrieve block [99]",
    48  			height:        100,
    49  		},
    50  		{
    51  			name:          "Last config block number cannot be retrieved from last block",
    52  			blockAtHeight: &common.Block{},
    53  			expectedError: "failed to retrieve metadata: no metadata in block",
    54  			height:        100,
    55  		},
    56  		{
    57  			name: "Last config block cannot be retrieved",
    58  			blockAtHeight: &common.Block{
    59  				Metadata: &common.BlockMetadata{
    60  					Metadata: [][]byte{{}, protoutil.MarshalOrPanic(&common.Metadata{
    61  						Value: protoutil.MarshalOrPanic(&common.LastConfig{Index: 42}),
    62  					})},
    63  				},
    64  			},
    65  			expectedError: "unable to retrieve last config block [42]",
    66  			height:        100,
    67  		},
    68  		{
    69  			name: "Last config block is retrieved but it is invalid",
    70  			blockAtHeight: &common.Block{
    71  				Metadata: &common.BlockMetadata{
    72  					Metadata: [][]byte{{}, protoutil.MarshalOrPanic(&common.Metadata{
    73  						Value: protoutil.MarshalOrPanic(&common.LastConfig{Index: 42}),
    74  					})},
    75  				},
    76  			},
    77  			lastConfigBlock: &common.Block{},
    78  			expectedError:   "block data is nil",
    79  			height:          100,
    80  		},
    81  		{
    82  			name: "Last config block is retrieved and is valid",
    83  			blockAtHeight: &common.Block{
    84  				Metadata: &common.BlockMetadata{
    85  					Metadata: [][]byte{{}, protoutil.MarshalOrPanic(&common.Metadata{
    86  						Value: protoutil.MarshalOrPanic(&common.LastConfig{Index: 42}),
    87  					})},
    88  				},
    89  			},
    90  			lastConfigBlock: goodConfigBlock,
    91  			height:          100,
    92  		},
    93  	} {
    94  		t.Run(testCase.name, func(t *testing.T) {
    95  			cs := &multichannel.ConsenterSupport{
    96  				BlockByIndex: make(map[uint64]*common.Block),
    97  			}
    98  			cs.HeightVal = testCase.height
    99  			cs.BlockByIndex[cs.HeightVal-1] = testCase.blockAtHeight
   100  			cs.BlockByIndex[42] = testCase.lastConfigBlock
   101  
   102  			certs, err := etcdraft.EndpointconfigFromSupport(cs, cryptoProvider)
   103  			if testCase.expectedError == "" {
   104  				assert.NotNil(t, certs)
   105  				assert.NoError(t, err)
   106  				return
   107  			}
   108  			assert.EqualError(t, err, testCase.expectedError)
   109  			assert.Nil(t, certs)
   110  		})
   111  	}
   112  }
   113  
   114  func TestNewBlockPuller(t *testing.T) {
   115  	ca, err := tlsgen.NewCA()
   116  	assert.NoError(t, err)
   117  
   118  	blockBytes, err := ioutil.ReadFile("testdata/mychannel.block")
   119  	assert.NoError(t, err)
   120  
   121  	goodConfigBlock := &common.Block{}
   122  	assert.NoError(t, proto.Unmarshal(blockBytes, goodConfigBlock))
   123  
   124  	lastBlock := &common.Block{
   125  		Metadata: &common.BlockMetadata{
   126  			Metadata: [][]byte{{}, protoutil.MarshalOrPanic(&common.Metadata{
   127  				Value: protoutil.MarshalOrPanic(&common.LastConfig{Index: 42}),
   128  			})},
   129  		},
   130  	}
   131  
   132  	cs := &multichannel.ConsenterSupport{
   133  		HeightVal: 100,
   134  		BlockByIndex: map[uint64]*common.Block{
   135  			42: goodConfigBlock,
   136  			99: lastBlock,
   137  		},
   138  	}
   139  
   140  	dialer := &cluster.PredicateDialer{
   141  		Config: comm.ClientConfig{
   142  			SecOpts: comm.SecureOptions{
   143  				Certificate: ca.CertBytes(),
   144  			},
   145  		},
   146  	}
   147  
   148  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
   149  	assert.NoError(t, err)
   150  
   151  	bp, err := etcdraft.NewBlockPuller(cs, dialer, localconfig.Cluster{}, cryptoProvider)
   152  	assert.NoError(t, err)
   153  	assert.NotNil(t, bp)
   154  
   155  	// From here on, we test failures.
   156  	for _, testCase := range []struct {
   157  		name          string
   158  		expectedError string
   159  		cs            consensus.ConsenterSupport
   160  		dialer        *cluster.PredicateDialer
   161  		certificate   []byte
   162  	}{
   163  		{
   164  			name: "Unable to retrieve block",
   165  			cs: &multichannel.ConsenterSupport{
   166  				HeightVal: 100,
   167  			},
   168  			certificate:   ca.CertBytes(),
   169  			expectedError: "unable to retrieve block [99]",
   170  			dialer:        dialer,
   171  		},
   172  		{
   173  			name:          "Certificate is invalid",
   174  			cs:            cs,
   175  			certificate:   []byte{1, 2, 3},
   176  			expectedError: "client certificate isn't in PEM format: \x01\x02\x03",
   177  			dialer:        dialer,
   178  		},
   179  	} {
   180  		t.Run(testCase.name, func(t *testing.T) {
   181  			testCase.dialer.Config.SecOpts.Certificate = testCase.certificate
   182  			bp, err := etcdraft.NewBlockPuller(testCase.cs, testCase.dialer, localconfig.Cluster{}, cryptoProvider)
   183  			assert.Nil(t, bp)
   184  			assert.EqualError(t, err, testCase.expectedError)
   185  		})
   186  	}
   187  }
   188  
   189  func TestLedgerBlockPuller(t *testing.T) {
   190  	currHeight := func() uint64 {
   191  		return 1
   192  	}
   193  
   194  	genesisBlock := &common.Block{Header: &common.BlockHeader{Number: 0}}
   195  	notGenesisBlock := &common.Block{Header: &common.BlockHeader{Number: 1}}
   196  
   197  	blockRetriever := &mocks.BlockRetriever{}
   198  	blockRetriever.On("Block", uint64(0)).Return(genesisBlock)
   199  
   200  	puller := &mocks.ChainPuller{}
   201  	puller.On("PullBlock", uint64(1)).Return(notGenesisBlock)
   202  
   203  	lbp := &etcdraft.LedgerBlockPuller{
   204  		Height:         currHeight,
   205  		BlockRetriever: blockRetriever,
   206  		BlockPuller:    puller,
   207  	}
   208  
   209  	assert.Equal(t, genesisBlock, lbp.PullBlock(0))
   210  	assert.Equal(t, notGenesisBlock, lbp.PullBlock(1))
   211  }