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