github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/orderer/common/follower/block_puller_test.go (about)

     1  /*
     2  Copyright hechain. 2017 All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package follower_test
     8  
     9  import (
    10  	"fmt"
    11  	"io/ioutil"
    12  	"os"
    13  	"path"
    14  	"sync/atomic"
    15  	"testing"
    16  
    17  	"github.com/hechain20/hechain/bccsp"
    18  	"github.com/hechain20/hechain/bccsp/sw"
    19  	"github.com/hechain20/hechain/common/crypto/tlsgen"
    20  	"github.com/hechain20/hechain/core/config/configtest"
    21  	"github.com/hechain20/hechain/internal/configtxgen/encoder"
    22  	"github.com/hechain20/hechain/internal/configtxgen/genesisconfig"
    23  	"github.com/hechain20/hechain/internal/pkg/comm"
    24  	"github.com/hechain20/hechain/internal/pkg/identity"
    25  	"github.com/hechain20/hechain/orderer/common/cluster"
    26  	"github.com/hechain20/hechain/orderer/common/follower"
    27  	"github.com/hechain20/hechain/orderer/common/follower/mocks"
    28  	"github.com/hechain20/hechain/orderer/common/localconfig"
    29  	"github.com/hechain20/hechain/protoutil"
    30  	cb "github.com/hyperledger/fabric-protos-go/common"
    31  	"github.com/pkg/errors"
    32  	"github.com/stretchr/testify/require"
    33  )
    34  
    35  //go:generate counterfeiter -o mocks/signer_serializer.go --fake-name SignerSerializer . signerSerializer
    36  
    37  type signerSerializer interface {
    38  	identity.SignerSerializer
    39  }
    40  
    41  var (
    42  	channelID  string
    43  	mockSigner *mocks.SignerSerializer
    44  	tlsCA      tlsgen.CA
    45  	dialer     *cluster.PredicateDialer
    46  	cryptoProv bccsp.BCCSP
    47  )
    48  
    49  func setupBlockPullerTest(t *testing.T) {
    50  	channelID = "my-raft-channel"
    51  	mockSigner = &mocks.SignerSerializer{}
    52  
    53  	var err error
    54  	tlsCA, err = tlsgen.NewCA()
    55  	require.NoError(t, err)
    56  	dialer = &cluster.PredicateDialer{
    57  		Config: comm.ClientConfig{
    58  			SecOpts: comm.SecureOptions{
    59  				Certificate: tlsCA.CertBytes(),
    60  			},
    61  		},
    62  	}
    63  
    64  	cryptoProv, err = sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
    65  	require.NoError(t, err)
    66  }
    67  
    68  func TestNewBlockPullerFactory(t *testing.T) {
    69  	setupBlockPullerTest(t)
    70  
    71  	t.Run("good", func(t *testing.T) {
    72  		bpf, err := follower.NewBlockPullerCreator(channelID, testLogger, mockSigner, dialer, localconfig.Cluster{}, cryptoProv)
    73  		require.NoError(t, err)
    74  		require.NotNil(t, bpf)
    75  	})
    76  
    77  	t.Run("dialer is nil", func(t *testing.T) {
    78  		require.Panics(t, func() {
    79  			follower.NewBlockPullerCreator(channelID, testLogger, mockSigner, nil, localconfig.Cluster{}, cryptoProv)
    80  		})
    81  	})
    82  
    83  	t.Run("dialer has bad cert", func(t *testing.T) {
    84  		badDialer := &cluster.PredicateDialer{
    85  			Config: dialer.Config,
    86  		}
    87  		badDialer.Config.SecOpts.Certificate = []byte("not-a-certificate")
    88  		bpf, err := follower.NewBlockPullerCreator(channelID, testLogger, mockSigner, badDialer, localconfig.Cluster{}, cryptoProv)
    89  		require.EqualError(t, err, "client certificate isn't in PEM format: not-a-certificate")
    90  		require.Nil(t, bpf)
    91  	})
    92  }
    93  
    94  func TestBlockPullerFactory_BlockPuller(t *testing.T) {
    95  	setupBlockPullerTest(t)
    96  
    97  	factory, err := follower.NewBlockPullerCreator(channelID, testLogger, mockSigner, dialer, localconfig.Cluster{}, cryptoProv)
    98  	require.NotNil(t, factory)
    99  	require.NoError(t, err)
   100  
   101  	t.Run("good", func(t *testing.T) {
   102  		joinBlockAppRaft := generateJoinBlock(t, tlsCA, channelID, 10)
   103  		require.NotNil(t, joinBlockAppRaft)
   104  		bp, err := factory.BlockPuller(joinBlockAppRaft, make(chan struct{}))
   105  		require.NoError(t, err)
   106  		require.NotNil(t, bp)
   107  	})
   108  
   109  	t.Run("bad join block", func(t *testing.T) {
   110  		bp, err := factory.BlockPuller(&cb.Block{Header: &cb.BlockHeader{}}, make(chan struct{}))
   111  		require.EqualError(t, err, "error extracting endpoints from config block: block data is nil")
   112  		require.Nil(t, bp)
   113  	})
   114  }
   115  
   116  func TestBlockPullerFactory_VerifyBlockSequence(t *testing.T) {
   117  	// replaces cluster.VerifyBlocks, count blocks
   118  	var numBlocks int32
   119  	altVerifyBlocks := func(blockBuff []*cb.Block, signatureVerifier cluster.BlockVerifier) error { // replaces cluster.VerifyBlocks, count invocations
   120  		if len(blockBuff) == 0 {
   121  			return errors.New("buffer is empty")
   122  		}
   123  
   124  		require.NotNil(t, signatureVerifier)
   125  		atomic.StoreInt32(&numBlocks, int32(len(blockBuff)))
   126  		return nil
   127  	}
   128  
   129  	t.Run("skip genesis block, alone", func(t *testing.T) {
   130  		setupBlockPullerTest(t)
   131  		atomic.StoreInt32(&numBlocks, 0)
   132  		creator, err := follower.NewBlockPullerCreator(channelID, testLogger, mockSigner, dialer, localconfig.Cluster{}, cryptoProv)
   133  		require.NotNil(t, creator)
   134  		require.NoError(t, err)
   135  		creator.ClusterVerifyBlocks = altVerifyBlocks
   136  		blocks := []*cb.Block{
   137  			generateJoinBlock(t, tlsCA, channelID, 0),
   138  		}
   139  
   140  		err = creator.VerifyBlockSequence(blocks, "")
   141  		require.NoError(t, err)
   142  		require.Equal(t, int32(0), atomic.LoadInt32(&numBlocks))
   143  	})
   144  
   145  	t.Run("skip genesis block as part of a slice", func(t *testing.T) {
   146  		setupBlockPullerTest(t)
   147  		atomic.StoreInt32(&numBlocks, 0)
   148  		creator, err := follower.NewBlockPullerCreator(channelID, testLogger, mockSigner, dialer, localconfig.Cluster{}, cryptoProv)
   149  		require.NotNil(t, creator)
   150  		require.NoError(t, err)
   151  		creator.ClusterVerifyBlocks = altVerifyBlocks
   152  		blocks := []*cb.Block{
   153  			generateJoinBlock(t, tlsCA, channelID, 0),
   154  			protoutil.NewBlock(1, []byte{}),
   155  			protoutil.NewBlock(2, []byte{}),
   156  		}
   157  
   158  		err = creator.VerifyBlockSequence(blocks, "")
   159  		require.NoError(t, err)
   160  		require.Equal(t, int32(2), atomic.LoadInt32(&numBlocks))
   161  	})
   162  
   163  	t.Run("verify all blocks in slice", func(t *testing.T) {
   164  		setupBlockPullerTest(t)
   165  		atomic.StoreInt32(&numBlocks, 0)
   166  		creator, err := follower.NewBlockPullerCreator(channelID, testLogger, mockSigner, dialer, localconfig.Cluster{}, cryptoProv)
   167  		require.NotNil(t, creator)
   168  		require.NoError(t, err)
   169  		creator.ClusterVerifyBlocks = altVerifyBlocks
   170  
   171  		blocks := []*cb.Block{protoutil.NewBlock(4, []byte{}), protoutil.NewBlock(5, []byte{}), protoutil.NewBlock(6, []byte{})}
   172  
   173  		err = creator.VerifyBlockSequence(blocks, "")
   174  		require.EqualError(t, err, "nil block signature verifier")
   175  
   176  		creator.UpdateVerifierFromConfigBlock(generateJoinBlock(t, tlsCA, channelID, 0))
   177  		err = creator.VerifyBlockSequence(blocks, "")
   178  		require.NoError(t, err)
   179  		require.Equal(t, int32(3), atomic.LoadInt32(&numBlocks))
   180  	})
   181  }
   182  
   183  func generateJoinBlock(t *testing.T, tlsCA tlsgen.CA, channelID string, number uint64) *cb.Block {
   184  	tmpdir, err := ioutil.TempDir("", "block-puller-test-")
   185  	require.NoError(t, err)
   186  	defer os.RemoveAll(tmpdir)
   187  
   188  	confAppRaft := genesisconfig.Load(genesisconfig.SampleDevModeEtcdRaftProfile, configtest.GetDevConfigDir())
   189  	confAppRaft.Consortiums = nil
   190  	confAppRaft.Consortium = ""
   191  	generateCertificates(t, confAppRaft, tlsCA, tmpdir)
   192  	bootstrapper, err := encoder.NewBootstrapper(confAppRaft)
   193  	require.NoError(t, err, "cannot create bootstrapper")
   194  
   195  	joinBlockAppRaft := bootstrapper.GenesisBlockForChannel(channelID)
   196  	joinBlockAppRaft.Header.Number = number
   197  	return joinBlockAppRaft
   198  }
   199  
   200  func generateCertificates(t *testing.T, confAppRaft *genesisconfig.Profile, tlsCA tlsgen.CA, certDir string) {
   201  	for i, c := range confAppRaft.Orderer.EtcdRaft.Consenters {
   202  		srvC, err := tlsCA.NewServerCertKeyPair(c.Host)
   203  		require.NoError(t, err)
   204  		srvP := path.Join(certDir, fmt.Sprintf("server%d.crt", i))
   205  		err = ioutil.WriteFile(srvP, srvC.Cert, 0o644)
   206  		require.NoError(t, err)
   207  
   208  		clnC, err := tlsCA.NewClientCertKeyPair()
   209  		require.NoError(t, err)
   210  		clnP := path.Join(certDir, fmt.Sprintf("client%d.crt", i))
   211  		err = ioutil.WriteFile(clnP, clnC.Cert, 0o644)
   212  		require.NoError(t, err)
   213  
   214  		c.ServerTlsCert = []byte(srvP)
   215  		c.ClientTlsCert = []byte(clnP)
   216  	}
   217  }