github.com/kaituanwang/hyperledger@v2.0.1+incompatible/orderer/consensus/etcdraft/util_test.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package etcdraft 8 9 import ( 10 "encoding/base64" 11 "io/ioutil" 12 "path/filepath" 13 "testing" 14 15 "github.com/golang/protobuf/proto" 16 "github.com/hyperledger/fabric-protos-go/common" 17 etcdraftproto "github.com/hyperledger/fabric-protos-go/orderer/etcdraft" 18 "github.com/hyperledger/fabric/bccsp/sw" 19 "github.com/hyperledger/fabric/common/crypto/tlsgen" 20 "github.com/hyperledger/fabric/orderer/common/cluster" 21 "github.com/hyperledger/fabric/protoutil" 22 "github.com/stretchr/testify/assert" 23 ) 24 25 func TestIsConsenterOfChannel(t *testing.T) { 26 certInsideConfigBlock, err := base64.StdEncoding.DecodeString("LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNmekNDQWlhZ0F3SUJBZ0l" + 27 "SQUo4bjFLYTVzS1ZaTXRMTHJ1dldERDB3Q2dZSUtvWkl6ajBFQXdJd2JERUwKTUFrR0ExVUVCaE1DVlZNeEV6QVJCZ05WQkFnVENrTmhiR" + 28 "2xtYjNKdWFXRXhGakFVQmdOVkJBY1REVk5oYmlCRwpjbUZ1WTJselkyOHhGREFTQmdOVkJBb1RDMlY0WVcxd2JHVXVZMjl0TVJvd0dBWUR" + 29 "WUVFERXhGMGJITmpZUzVsCmVHRnRjR3hsTG1OdmJUQWVGdzB4T0RFeE1EWXdPVFE1TURCYUZ3MHlPREV4TURNd09UUTVNREJhTUZreEN6QU" + 30 "oKQmdOVkJBWVRBbFZUTVJNd0VRWURWUVFJRXdwRFlXeHBabTl5Ym1saE1SWXdGQVlEVlFRSEV3MVRZVzRnUm5KaApibU5wYzJOdk1SMHdH" + 31 "d1lEVlFRREV4UnZjbVJsY21WeU1TNWxlR0Z0Y0d4bExtTnZiVEJaTUJNR0J5cUdTTTQ5CkFnRUdDQ3FHU000OUF3RUhBMElBQkRUVlFZc0" + 32 "ZKZWxUcFZDMDFsek5DSkx6OENRMFFGVDBvN1BmSnBwSkl2SXgKUCtRVjQvRGRCSnRqQ0cvcGsvMGFxZXRpSjhZRUFMYmMrOUhmWnExN2tJ" + 33 "Q2pnYnN3Z2Jnd0RnWURWUjBQQVFILwpCQVFEQWdXZ01CMEdBMVVkSlFRV01CUUdDQ3NHQVFVRkJ3TUJCZ2dyQmdFRkJRY0RBakFNQmdOV" + 34 "khSTUJBZjhFCkFqQUFNQ3NHQTFVZEl3UWtNQ0tBSUVBOHFrSVJRTVBuWkxBR2g0TXZla2gzZFpHTmNxcEhZZWlXdzE3Rmw0ZlMKTUV3R0" + 35 "ExVWRFUVJGTUVPQ0ZHOXlaR1Z5WlhJeExtVjRZVzF3YkdVdVkyOXRnZ2h2Y21SbGNtVnlNWUlKYkc5agpZV3hvYjNOMGh3Ui9BQUFCaHh" + 36 "BQUFBQUFBQUFBQUFBQUFBQUFBQUFCTUFvR0NDcUdTTTQ5QkFNQ0EwY0FNRVFDCklFckJZRFVzV0JwOHB0ZVFSaTZyNjNVelhJQi81Sn" + 37 "YxK0RlTkRIUHc3aDljQWlCakYrM3V5TzBvMEdRclB4MEUKUWptYlI5T3BVREN2LzlEUkNXWU9GZitkVlE9PQotLS0tLUVORCBDRVJUSU" + 38 "ZJQ0FURS0tLS0tCg==") 39 assert.NoError(t, err) 40 41 validBlock := func() *common.Block { 42 b, err := ioutil.ReadFile(filepath.Join("testdata", "etcdraftgenesis.block")) 43 assert.NoError(t, err) 44 block := &common.Block{} 45 err = proto.Unmarshal(b, block) 46 assert.NoError(t, err) 47 return block 48 } 49 for _, testCase := range []struct { 50 name string 51 expectedError string 52 configBlock *common.Block 53 certificate []byte 54 }{ 55 { 56 name: "nil block", 57 expectedError: "nil block", 58 }, 59 { 60 name: "no block data", 61 expectedError: "block data is nil", 62 configBlock: &common.Block{}, 63 }, 64 { 65 name: "invalid envelope inside block", 66 expectedError: "failed to unmarshal payload from envelope:" + 67 " error unmarshaling Payload: proto: common.Payload: illegal tag 0 (wire type 1)", 68 configBlock: &common.Block{ 69 Data: &common.BlockData{ 70 Data: [][]byte{protoutil.MarshalOrPanic(&common.Envelope{ 71 Payload: []byte{1, 2, 3}, 72 })}, 73 }, 74 }, 75 }, 76 { 77 name: "valid config block with cert mismatch", 78 configBlock: validBlock(), 79 certificate: certInsideConfigBlock[2:], 80 expectedError: cluster.ErrNotInChannel.Error(), 81 }, 82 { 83 name: "valid config block with matching cert", 84 configBlock: validBlock(), 85 certificate: certInsideConfigBlock, 86 }, 87 } { 88 t.Run(testCase.name, func(t *testing.T) { 89 cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) 90 assert.NoError(t, err) 91 92 consenterCertificate := &ConsenterCertificate{ 93 ConsenterCertificate: testCase.certificate, 94 CryptoProvider: cryptoProvider, 95 } 96 err = consenterCertificate.IsConsenterOfChannel(testCase.configBlock) 97 if testCase.expectedError != "" { 98 assert.EqualError(t, err, testCase.expectedError) 99 } else { 100 assert.NoError(t, err) 101 } 102 }) 103 } 104 } 105 106 func TestCheckConfigMetadata(t *testing.T) { 107 tlsCA, err := tlsgen.NewCA() 108 if err != nil { 109 panic(err) 110 } 111 serverPair, err := tlsCA.NewServerCertKeyPair("localhost") 112 serverCert := serverPair.Cert 113 if err != nil { 114 panic(err) 115 } 116 clientPair, err := tlsCA.NewClientCertKeyPair() 117 clientCert := clientPair.Cert 118 if err != nil { 119 panic(err) 120 } 121 validOptions := &etcdraftproto.Options{ 122 TickInterval: "500ms", 123 ElectionTick: 10, 124 HeartbeatTick: 1, 125 MaxInflightBlocks: 5, 126 SnapshotIntervalSize: 20 * 1024 * 1024, // 20 MB 127 } 128 singleConsenter := &etcdraftproto.Consenter{ 129 Host: "host1", 130 Port: 10001, 131 ClientTlsCert: clientCert, 132 ServerTlsCert: serverCert, 133 } 134 135 // valid metadata should give nil error 136 goodMetadata := &etcdraftproto.ConfigMetadata{ 137 Options: validOptions, 138 Consenters: []*etcdraftproto.Consenter{ 139 singleConsenter, 140 }, 141 } 142 assert.Nil(t, CheckConfigMetadata(goodMetadata)) 143 144 // test variety of bad metadata 145 for _, testCase := range []struct { 146 description string 147 metadata *etcdraftproto.ConfigMetadata 148 errRegex string 149 }{ 150 { 151 description: "nil metadata", 152 metadata: nil, 153 errRegex: "nil Raft config metadata", 154 }, 155 { 156 description: "HeartbeatTick is 0", 157 metadata: &etcdraftproto.ConfigMetadata{ 158 Options: &etcdraftproto.Options{ 159 HeartbeatTick: 0, 160 }, 161 }, 162 errRegex: "none of HeartbeatTick .* can be zero", 163 }, 164 { 165 description: "ElectionTick is 0", 166 metadata: &etcdraftproto.ConfigMetadata{ 167 Options: &etcdraftproto.Options{ 168 HeartbeatTick: validOptions.HeartbeatTick, 169 ElectionTick: 0, 170 }, 171 }, 172 errRegex: "none of .* ElectionTick .* can be zero", 173 }, 174 { 175 description: "MaxInflightBlocks is 0", 176 metadata: &etcdraftproto.ConfigMetadata{ 177 Options: &etcdraftproto.Options{ 178 HeartbeatTick: validOptions.HeartbeatTick, 179 ElectionTick: validOptions.ElectionTick, 180 MaxInflightBlocks: 0, 181 }, 182 }, 183 errRegex: "none of .* MaxInflightBlocks .* can be zero", 184 }, 185 { 186 description: "ElectionTick is less than HeartbeatTick", 187 metadata: &etcdraftproto.ConfigMetadata{ 188 Options: &etcdraftproto.Options{ 189 HeartbeatTick: 10, 190 ElectionTick: 1, 191 MaxInflightBlocks: validOptions.MaxInflightBlocks, 192 }, 193 }, 194 errRegex: "ElectionTick .* must be greater than HeartbeatTick", 195 }, 196 { 197 description: "TickInterval is not parsable", 198 metadata: &etcdraftproto.ConfigMetadata{ 199 Options: &etcdraftproto.Options{ 200 HeartbeatTick: validOptions.HeartbeatTick, 201 ElectionTick: validOptions.ElectionTick, 202 MaxInflightBlocks: validOptions.MaxInflightBlocks, 203 TickInterval: "abcd", 204 }, 205 }, 206 errRegex: "failed to parse TickInterval .* to time duration", 207 }, 208 { 209 description: "TickInterval is 0", 210 metadata: &etcdraftproto.ConfigMetadata{ 211 Options: &etcdraftproto.Options{ 212 HeartbeatTick: validOptions.HeartbeatTick, 213 ElectionTick: validOptions.ElectionTick, 214 MaxInflightBlocks: validOptions.MaxInflightBlocks, 215 TickInterval: "0s", 216 }, 217 }, 218 errRegex: "TickInterval cannot be zero", 219 }, 220 { 221 description: "consenter set is empty", 222 metadata: &etcdraftproto.ConfigMetadata{ 223 Options: validOptions, 224 Consenters: []*etcdraftproto.Consenter{}, 225 }, 226 errRegex: "empty consenter set", 227 }, 228 { 229 description: "metadata has nil consenter", 230 metadata: &etcdraftproto.ConfigMetadata{ 231 Options: validOptions, 232 Consenters: []*etcdraftproto.Consenter{ 233 nil, 234 }, 235 }, 236 errRegex: "metadata has nil consenter", 237 }, 238 { 239 description: "consenter has invalid server cert", 240 metadata: &etcdraftproto.ConfigMetadata{ 241 Options: validOptions, 242 Consenters: []*etcdraftproto.Consenter{ 243 { 244 ServerTlsCert: []byte("invalid"), 245 ClientTlsCert: clientCert, 246 }, 247 }, 248 }, 249 errRegex: "server TLS certificate is not PEM encoded", 250 }, 251 { 252 description: "consenter has invalid client cert", 253 metadata: &etcdraftproto.ConfigMetadata{ 254 Options: validOptions, 255 Consenters: []*etcdraftproto.Consenter{ 256 { 257 ServerTlsCert: serverCert, 258 ClientTlsCert: []byte("invalid"), 259 }, 260 }, 261 }, 262 errRegex: "client TLS certificate is not PEM encoded", 263 }, 264 { 265 description: "metadata has duplicate consenters", 266 metadata: &etcdraftproto.ConfigMetadata{ 267 Options: validOptions, 268 Consenters: []*etcdraftproto.Consenter{ 269 singleConsenter, 270 singleConsenter, 271 }, 272 }, 273 errRegex: "duplicate consenter", 274 }, 275 } { 276 err := CheckConfigMetadata(testCase.metadata) 277 assert.NotNil(t, err, testCase.description) 278 assert.Regexp(t, testCase.errRegex, err) 279 } 280 }