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 }