github.com/ewagmig/fabric@v2.1.1+incompatible/common/channelconfig/util_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package channelconfig
     8  
     9  import (
    10  	"fmt"
    11  	"io/ioutil"
    12  	"testing"
    13  
    14  	"github.com/golang/protobuf/proto"
    15  	cb "github.com/hyperledger/fabric-protos-go/common"
    16  	mspprotos "github.com/hyperledger/fabric-protos-go/msp"
    17  	ab "github.com/hyperledger/fabric-protos-go/orderer"
    18  	"github.com/hyperledger/fabric-protos-go/orderer/etcdraft"
    19  	pb "github.com/hyperledger/fabric-protos-go/peer"
    20  	"github.com/hyperledger/fabric/bccsp/sw"
    21  	"github.com/hyperledger/fabric/common/capabilities"
    22  	"github.com/hyperledger/fabric/protoutil"
    23  	"github.com/stretchr/testify/assert"
    24  	"github.com/stretchr/testify/require"
    25  )
    26  
    27  // The tests in this file are all relatively pointless, as all of this function is exercised
    28  // in the normal startup path and things will break horribly if they are broken.
    29  // There's additionally really nothing to test without simply re-implementing the function
    30  // in the test, which also provides no value.  But, not including these produces an artificially
    31  // low code coverage count, so here they are.
    32  
    33  func basicTest(t *testing.T, sv *StandardConfigValue) {
    34  	assert.NotNil(t, sv)
    35  	assert.NotEmpty(t, sv.Key())
    36  	assert.NotNil(t, sv.Value())
    37  }
    38  
    39  func TestUtilsBasic(t *testing.T) {
    40  	basicTest(t, ConsortiumValue("foo"))
    41  	basicTest(t, HashingAlgorithmValue())
    42  	basicTest(t, BlockDataHashingStructureValue())
    43  	basicTest(t, OrdererAddressesValue([]string{"foo:1", "bar:2"}))
    44  	basicTest(t, ConsensusTypeValue("foo", []byte("bar")))
    45  	basicTest(t, BatchSizeValue(1, 2, 3))
    46  	basicTest(t, BatchTimeoutValue("1s"))
    47  	basicTest(t, ChannelRestrictionsValue(7))
    48  	basicTest(t, KafkaBrokersValue([]string{"foo:1", "bar:2"}))
    49  	basicTest(t, MSPValue(&mspprotos.MSPConfig{}))
    50  	basicTest(t, CapabilitiesValue(map[string]bool{"foo": true, "bar": false}))
    51  	basicTest(t, AnchorPeersValue([]*pb.AnchorPeer{{}, {}}))
    52  	basicTest(t, ChannelCreationPolicyValue(&cb.Policy{}))
    53  	basicTest(t, ACLValues(map[string]string{"foo": "fooval", "bar": "barval"}))
    54  }
    55  
    56  // createCfgBlockWithSupportedCapabilities will create a config block that contains valid capabilities and should be accepted by the peer
    57  func createCfgBlockWithSupportedCapabilities(t *testing.T) *cb.Block {
    58  	// Create a config
    59  	config := &cb.Config{
    60  		Sequence:     0,
    61  		ChannelGroup: protoutil.NewConfigGroup(),
    62  	}
    63  
    64  	// construct the config for top group
    65  	config.ChannelGroup.Version = 0
    66  	config.ChannelGroup.ModPolicy = AdminsPolicyKey
    67  	config.ChannelGroup.Values[BlockDataHashingStructureKey] = &cb.ConfigValue{
    68  		Value: protoutil.MarshalOrPanic(&cb.BlockDataHashingStructure{
    69  			Width: defaultBlockDataHashingStructureWidth,
    70  		}),
    71  		ModPolicy: AdminsPolicyKey,
    72  	}
    73  	topCapabilities := make(map[string]bool)
    74  	topCapabilities[capabilities.ChannelV1_1] = true
    75  	config.ChannelGroup.Values[CapabilitiesKey] = &cb.ConfigValue{
    76  		Value:     protoutil.MarshalOrPanic(CapabilitiesValue(topCapabilities).Value()),
    77  		ModPolicy: AdminsPolicyKey,
    78  	}
    79  	config.ChannelGroup.Values[ConsortiumKey] = &cb.ConfigValue{
    80  		Value: protoutil.MarshalOrPanic(&cb.Consortium{
    81  			Name: "testConsortium",
    82  		}),
    83  		ModPolicy: AdminsPolicyKey,
    84  	}
    85  	config.ChannelGroup.Values[HashingAlgorithmKey] = &cb.ConfigValue{
    86  		Value: protoutil.MarshalOrPanic(&cb.HashingAlgorithm{
    87  			Name: defaultHashingAlgorithm,
    88  		}),
    89  		ModPolicy: AdminsPolicyKey,
    90  	}
    91  	config.ChannelGroup.Values[OrdererAddressesKey] = &cb.ConfigValue{
    92  		Value: protoutil.MarshalOrPanic(&cb.OrdererAddresses{
    93  			Addresses: []string{"orderer.example.com"},
    94  		}),
    95  		ModPolicy: AdminsPolicyKey,
    96  	}
    97  
    98  	// construct the config for Application group
    99  	config.ChannelGroup.Groups[ApplicationGroupKey] = protoutil.NewConfigGroup()
   100  	config.ChannelGroup.Groups[ApplicationGroupKey].Version = 0
   101  	config.ChannelGroup.Groups[ApplicationGroupKey].ModPolicy = AdminsPolicyKey
   102  	config.ChannelGroup.Groups[ApplicationGroupKey].Policies[ReadersPolicyKey] = &cb.ConfigPolicy{}
   103  	config.ChannelGroup.Groups[ApplicationGroupKey].Policies[WritersPolicyKey] = &cb.ConfigPolicy{}
   104  	config.ChannelGroup.Groups[ApplicationGroupKey].Policies[AdminsPolicyKey] = &cb.ConfigPolicy{}
   105  	appCapabilities := make(map[string]bool)
   106  	appCapabilities[capabilities.ApplicationV1_1] = true
   107  	config.ChannelGroup.Groups[ApplicationGroupKey].Values[CapabilitiesKey] = &cb.ConfigValue{
   108  		Value:     protoutil.MarshalOrPanic(CapabilitiesValue(appCapabilities).Value()),
   109  		ModPolicy: AdminsPolicyKey,
   110  	}
   111  
   112  	// construct the config for Orderer group
   113  	config.ChannelGroup.Groups[OrdererGroupKey] = protoutil.NewConfigGroup()
   114  	config.ChannelGroup.Groups[OrdererGroupKey].Version = 0
   115  	config.ChannelGroup.Groups[OrdererGroupKey].ModPolicy = AdminsPolicyKey
   116  	config.ChannelGroup.Groups[OrdererGroupKey].Policies[ReadersPolicyKey] = &cb.ConfigPolicy{}
   117  	config.ChannelGroup.Groups[OrdererGroupKey].Policies[WritersPolicyKey] = &cb.ConfigPolicy{}
   118  	config.ChannelGroup.Groups[OrdererGroupKey].Policies[AdminsPolicyKey] = &cb.ConfigPolicy{}
   119  	config.ChannelGroup.Groups[OrdererGroupKey].Values[BatchSizeKey] = &cb.ConfigValue{
   120  		Value: protoutil.MarshalOrPanic(
   121  			&ab.BatchSize{
   122  				MaxMessageCount:   65535,
   123  				AbsoluteMaxBytes:  1024000000,
   124  				PreferredMaxBytes: 1024000000,
   125  			}),
   126  		ModPolicy: AdminsPolicyKey,
   127  	}
   128  	config.ChannelGroup.Groups[OrdererGroupKey].Values[BatchTimeoutKey] = &cb.ConfigValue{
   129  		Value: protoutil.MarshalOrPanic(
   130  			&ab.BatchTimeout{
   131  				Timeout: "2s",
   132  			}),
   133  		ModPolicy: AdminsPolicyKey,
   134  	}
   135  	ordererCapabilities := make(map[string]bool)
   136  	ordererCapabilities[capabilities.OrdererV1_1] = true
   137  	config.ChannelGroup.Groups[OrdererGroupKey].Values[CapabilitiesKey] = &cb.ConfigValue{
   138  		Value:     protoutil.MarshalOrPanic(CapabilitiesValue(ordererCapabilities).Value()),
   139  		ModPolicy: AdminsPolicyKey,
   140  	}
   141  	config.ChannelGroup.Groups[OrdererGroupKey].Values[ConsensusTypeKey] = &cb.ConfigValue{
   142  		Value: protoutil.MarshalOrPanic(
   143  			&ab.ConsensusType{
   144  				Type: "solo",
   145  			}),
   146  		ModPolicy: AdminsPolicyKey,
   147  	}
   148  
   149  	env := &cb.Envelope{
   150  		Payload: protoutil.MarshalOrPanic(&cb.Payload{
   151  			Header: &cb.Header{
   152  				ChannelHeader: protoutil.MarshalOrPanic(&cb.ChannelHeader{
   153  					ChannelId: "testChain",
   154  					Type:      int32(cb.HeaderType_CONFIG),
   155  				}),
   156  			},
   157  			Data: protoutil.MarshalOrPanic(&cb.ConfigEnvelope{
   158  				Config: config,
   159  			}),
   160  		}),
   161  	}
   162  	configBlock := &cb.Block{
   163  		Data: &cb.BlockData{
   164  			Data: [][]byte{[]byte(protoutil.MarshalOrPanic(env))},
   165  		},
   166  	}
   167  	return configBlock
   168  }
   169  
   170  // createCfgBlockWithUnSupportedCapabilities will create a config block that contains mismatched capabilities and should be rejected by the peer
   171  func createCfgBlockWithUnsupportedCapabilities(t *testing.T) *cb.Block {
   172  	// Create a config
   173  	config := &cb.Config{
   174  		Sequence:     0,
   175  		ChannelGroup: protoutil.NewConfigGroup(),
   176  	}
   177  
   178  	// construct the config for top group
   179  	config.ChannelGroup.Version = 0
   180  	config.ChannelGroup.ModPolicy = AdminsPolicyKey
   181  	config.ChannelGroup.Values[BlockDataHashingStructureKey] = &cb.ConfigValue{
   182  		Value: protoutil.MarshalOrPanic(&cb.BlockDataHashingStructure{
   183  			Width: defaultBlockDataHashingStructureWidth,
   184  		}),
   185  		ModPolicy: AdminsPolicyKey,
   186  	}
   187  	topCapabilities := make(map[string]bool)
   188  	topCapabilities["INCOMPATIBLE_CAPABILITIES"] = true
   189  	config.ChannelGroup.Values[CapabilitiesKey] = &cb.ConfigValue{
   190  		Value:     protoutil.MarshalOrPanic(CapabilitiesValue(topCapabilities).Value()),
   191  		ModPolicy: AdminsPolicyKey,
   192  	}
   193  	config.ChannelGroup.Values[ConsortiumKey] = &cb.ConfigValue{
   194  		Value: protoutil.MarshalOrPanic(&cb.Consortium{
   195  			Name: "testConsortium",
   196  		}),
   197  		ModPolicy: AdminsPolicyKey,
   198  	}
   199  	config.ChannelGroup.Values[HashingAlgorithmKey] = &cb.ConfigValue{
   200  		Value: protoutil.MarshalOrPanic(&cb.HashingAlgorithm{
   201  			Name: defaultHashingAlgorithm,
   202  		}),
   203  		ModPolicy: AdminsPolicyKey,
   204  	}
   205  	config.ChannelGroup.Values[OrdererAddressesKey] = &cb.ConfigValue{
   206  		Value: protoutil.MarshalOrPanic(&cb.OrdererAddresses{
   207  			Addresses: []string{"orderer.example.com"},
   208  		}),
   209  		ModPolicy: AdminsPolicyKey,
   210  	}
   211  
   212  	// construct the config for Application group
   213  	config.ChannelGroup.Groups[ApplicationGroupKey] = protoutil.NewConfigGroup()
   214  	config.ChannelGroup.Groups[ApplicationGroupKey].Version = 0
   215  	config.ChannelGroup.Groups[ApplicationGroupKey].ModPolicy = AdminsPolicyKey
   216  	config.ChannelGroup.Groups[ApplicationGroupKey].Policies[ReadersPolicyKey] = &cb.ConfigPolicy{}
   217  	config.ChannelGroup.Groups[ApplicationGroupKey].Policies[WritersPolicyKey] = &cb.ConfigPolicy{}
   218  	config.ChannelGroup.Groups[ApplicationGroupKey].Policies[AdminsPolicyKey] = &cb.ConfigPolicy{}
   219  	appCapabilities := make(map[string]bool)
   220  	appCapabilities["INCOMPATIBLE_CAPABILITIES"] = true
   221  	config.ChannelGroup.Groups[ApplicationGroupKey].Values[CapabilitiesKey] = &cb.ConfigValue{
   222  		Value:     protoutil.MarshalOrPanic(CapabilitiesValue(appCapabilities).Value()),
   223  		ModPolicy: AdminsPolicyKey,
   224  	}
   225  
   226  	// construct the config for Orderer group
   227  	config.ChannelGroup.Groups[OrdererGroupKey] = protoutil.NewConfigGroup()
   228  	config.ChannelGroup.Groups[OrdererGroupKey].Version = 0
   229  	config.ChannelGroup.Groups[OrdererGroupKey].ModPolicy = AdminsPolicyKey
   230  	config.ChannelGroup.Groups[OrdererGroupKey].Policies[ReadersPolicyKey] = &cb.ConfigPolicy{}
   231  	config.ChannelGroup.Groups[OrdererGroupKey].Policies[WritersPolicyKey] = &cb.ConfigPolicy{}
   232  	config.ChannelGroup.Groups[OrdererGroupKey].Policies[AdminsPolicyKey] = &cb.ConfigPolicy{}
   233  	config.ChannelGroup.Groups[OrdererGroupKey].Values[BatchSizeKey] = &cb.ConfigValue{
   234  		Value: protoutil.MarshalOrPanic(
   235  			&ab.BatchSize{
   236  				MaxMessageCount:   65535,
   237  				AbsoluteMaxBytes:  1024000000,
   238  				PreferredMaxBytes: 1024000000,
   239  			}),
   240  		ModPolicy: AdminsPolicyKey,
   241  	}
   242  	config.ChannelGroup.Groups[OrdererGroupKey].Values[BatchTimeoutKey] = &cb.ConfigValue{
   243  		Value: protoutil.MarshalOrPanic(
   244  			&ab.BatchTimeout{
   245  				Timeout: "2s",
   246  			}),
   247  		ModPolicy: AdminsPolicyKey,
   248  	}
   249  	ordererCapabilities := make(map[string]bool)
   250  	ordererCapabilities["INCOMPATIBLE_CAPABILITIES"] = true
   251  	config.ChannelGroup.Groups[OrdererGroupKey].Values[CapabilitiesKey] = &cb.ConfigValue{
   252  		Value:     protoutil.MarshalOrPanic(CapabilitiesValue(ordererCapabilities).Value()),
   253  		ModPolicy: AdminsPolicyKey,
   254  	}
   255  	config.ChannelGroup.Groups[OrdererGroupKey].Values[ConsensusTypeKey] = &cb.ConfigValue{
   256  		Value: protoutil.MarshalOrPanic(
   257  			&ab.ConsensusType{
   258  				Type: "solo",
   259  			}),
   260  		ModPolicy: AdminsPolicyKey,
   261  	}
   262  
   263  	env := &cb.Envelope{
   264  		Payload: protoutil.MarshalOrPanic(&cb.Payload{
   265  			Header: &cb.Header{
   266  				ChannelHeader: protoutil.MarshalOrPanic(&cb.ChannelHeader{
   267  					ChannelId: "testChain",
   268  					Type:      int32(cb.HeaderType_CONFIG),
   269  				}),
   270  			},
   271  			Data: protoutil.MarshalOrPanic(&cb.ConfigEnvelope{
   272  				Config: config,
   273  			}),
   274  		}),
   275  	}
   276  	configBlock := &cb.Block{
   277  		Data: &cb.BlockData{
   278  			Data: [][]byte{[]byte(protoutil.MarshalOrPanic(env))},
   279  		},
   280  	}
   281  	return configBlock
   282  }
   283  
   284  func TestValidateCapabilities(t *testing.T) {
   285  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
   286  	assert.NoError(t, err)
   287  
   288  	// Test config block with valid capabilities requirement
   289  	cfgBlock := createCfgBlockWithSupportedCapabilities(t)
   290  	err = ValidateCapabilities(cfgBlock, cryptoProvider)
   291  	assert.NoError(t, err)
   292  
   293  	// Test config block with invalid capabilities requirement
   294  	cfgBlock = createCfgBlockWithUnsupportedCapabilities(t)
   295  	err = ValidateCapabilities(cfgBlock, cryptoProvider)
   296  	assert.EqualError(t, err, "Channel capability INCOMPATIBLE_CAPABILITIES is required but not supported")
   297  }
   298  
   299  func TestMarshalEtcdRaftMetadata(t *testing.T) {
   300  	md := &etcdraft.ConfigMetadata{
   301  		Consenters: []*etcdraft.Consenter{
   302  			{
   303  				Host:          "node-1.example.com",
   304  				Port:          7050,
   305  				ClientTlsCert: []byte("testdata/tls-client-1.pem"),
   306  				ServerTlsCert: []byte("testdata/tls-server-1.pem"),
   307  			},
   308  			{
   309  				Host:          "node-2.example.com",
   310  				Port:          7050,
   311  				ClientTlsCert: []byte("testdata/tls-client-2.pem"),
   312  				ServerTlsCert: []byte("testdata/tls-server-2.pem"),
   313  			},
   314  			{
   315  				Host:          "node-3.example.com",
   316  				Port:          7050,
   317  				ClientTlsCert: []byte("testdata/tls-client-3.pem"),
   318  				ServerTlsCert: []byte("testdata/tls-server-3.pem"),
   319  			},
   320  		},
   321  	}
   322  	packed, err := MarshalEtcdRaftMetadata(md)
   323  	require.Nil(t, err, "marshalling should succeed")
   324  	assert.NotNil(t, packed)
   325  
   326  	packed, err = MarshalEtcdRaftMetadata(md)
   327  	require.Nil(t, err, "marshalling should succeed a second time because we did not mutate ourselves")
   328  	assert.NotNil(t, packed)
   329  
   330  	unpacked := &etcdraft.ConfigMetadata{}
   331  	require.Nil(t, proto.Unmarshal(packed, unpacked), "unmarshalling should succeed")
   332  
   333  	var outputCerts, inputCerts [3][]byte
   334  	for i := range unpacked.GetConsenters() {
   335  		outputCerts[i] = []byte(unpacked.GetConsenters()[i].GetClientTlsCert())
   336  		inputCerts[i], _ = ioutil.ReadFile(fmt.Sprintf("testdata/tls-client-%d.pem", i+1))
   337  
   338  	}
   339  
   340  	for i := 0; i < len(inputCerts)-1; i++ {
   341  		require.NotEqual(t, outputCerts[i+1], outputCerts[i], "expected extracted certs to differ from each other")
   342  	}
   343  }