github.com/osdi23p228/fabric@v0.0.0-20221218062954-77808885f5db/common/channelconfig/bundle_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  	"testing"
    11  
    12  	cb "github.com/hyperledger/fabric-protos-go/common"
    13  	ab "github.com/hyperledger/fabric-protos-go/orderer"
    14  	cc "github.com/osdi23p228/fabric/common/capabilities"
    15  	"github.com/stretchr/testify/assert"
    16  )
    17  
    18  func TestValidateNew(t *testing.T) {
    19  	t.Run("DisappearingOrdererConfig", func(t *testing.T) {
    20  		cb := &Bundle{
    21  			channelConfig: &ChannelConfig{
    22  				ordererConfig: &OrdererConfig{},
    23  			},
    24  		}
    25  
    26  		nb := &Bundle{
    27  			channelConfig: &ChannelConfig{},
    28  		}
    29  
    30  		err := cb.ValidateNew(nb)
    31  		assert.Error(t, err)
    32  		assert.Regexp(t, "current config has orderer section, but new config does not", err.Error())
    33  	})
    34  
    35  	t.Run("DisappearingApplicationConfig", func(t *testing.T) {
    36  		cb := &Bundle{
    37  			channelConfig: &ChannelConfig{
    38  				appConfig: &ApplicationConfig{},
    39  			},
    40  		}
    41  
    42  		nb := &Bundle{
    43  			channelConfig: &ChannelConfig{},
    44  		}
    45  
    46  		err := cb.ValidateNew(nb)
    47  		assert.Error(t, err)
    48  		assert.Regexp(t, "current config has application section, but new config does not", err.Error())
    49  	})
    50  
    51  	t.Run("DisappearingConsortiumsConfig", func(t *testing.T) {
    52  		cb := &Bundle{
    53  			channelConfig: &ChannelConfig{
    54  				consortiumsConfig: &ConsortiumsConfig{},
    55  			},
    56  		}
    57  
    58  		nb := &Bundle{
    59  			channelConfig: &ChannelConfig{},
    60  		}
    61  
    62  		err := cb.ValidateNew(nb)
    63  		assert.Error(t, err)
    64  		assert.Regexp(t, "current config has consortiums section, but new config does not", err.Error())
    65  	})
    66  
    67  	t.Run("Prevent adding ConsortiumsConfig to standard channel", func(t *testing.T) {
    68  		cb := &Bundle{
    69  			channelConfig: &ChannelConfig{},
    70  		}
    71  
    72  		nb := &Bundle{
    73  			channelConfig: &ChannelConfig{
    74  				consortiumsConfig: &ConsortiumsConfig{},
    75  			},
    76  		}
    77  
    78  		err := cb.ValidateNew(nb)
    79  		assert.EqualError(t, err, "current config has no consortiums section, but new config does")
    80  	})
    81  
    82  	t.Run("ConsensusTypeChange", func(t *testing.T) {
    83  		currb := &Bundle{
    84  			channelConfig: &ChannelConfig{
    85  				ordererConfig: &OrdererConfig{
    86  					protos: &OrdererProtos{
    87  						ConsensusType: &ab.ConsensusType{
    88  							Type: "type1",
    89  						},
    90  						Capabilities: &cb.Capabilities{},
    91  					},
    92  				},
    93  				protos: &ChannelProtos{
    94  					Capabilities: &cb.Capabilities{},
    95  				},
    96  			},
    97  		}
    98  
    99  		newb := &Bundle{
   100  			channelConfig: &ChannelConfig{
   101  				ordererConfig: &OrdererConfig{
   102  					protos: &OrdererProtos{
   103  						ConsensusType: &ab.ConsensusType{
   104  							Type: "type2",
   105  						},
   106  						Capabilities: &cb.Capabilities{},
   107  					},
   108  				},
   109  				protos: &ChannelProtos{
   110  					Capabilities: &cb.Capabilities{},
   111  				},
   112  			},
   113  		}
   114  
   115  		err := currb.ValidateNew(newb)
   116  		assert.Error(t, err)
   117  		assert.Contains(t, err.Error(), "attempted to change consensus type from")
   118  	})
   119  
   120  	t.Run("OrdererOrgMSPIDChange", func(t *testing.T) {
   121  		currb := &Bundle{
   122  			channelConfig: &ChannelConfig{
   123  				ordererConfig: &OrdererConfig{
   124  					protos: &OrdererProtos{
   125  						ConsensusType: &ab.ConsensusType{
   126  							Type: "type1",
   127  						},
   128  						Capabilities: &cb.Capabilities{},
   129  					},
   130  					orgs: map[string]OrdererOrg{
   131  						"org1": &OrdererOrgConfig{OrganizationConfig: &OrganizationConfig{mspID: "org1msp"}},
   132  						"org2": &OrdererOrgConfig{OrganizationConfig: &OrganizationConfig{mspID: "org2msp"}},
   133  						"org3": &OrdererOrgConfig{OrganizationConfig: &OrganizationConfig{mspID: "org3msp"}},
   134  					},
   135  				},
   136  				protos: &ChannelProtos{
   137  					Capabilities: &cb.Capabilities{},
   138  				},
   139  			},
   140  		}
   141  
   142  		newb := &Bundle{
   143  			channelConfig: &ChannelConfig{
   144  				ordererConfig: &OrdererConfig{
   145  					protos: &OrdererProtos{
   146  						ConsensusType: &ab.ConsensusType{
   147  							Type: "type1",
   148  						},
   149  						Capabilities: &cb.Capabilities{},
   150  					},
   151  					orgs: map[string]OrdererOrg{
   152  						"org1": &OrdererOrgConfig{OrganizationConfig: &OrganizationConfig{mspID: "org1msp"}},
   153  						"org3": &OrdererOrgConfig{OrganizationConfig: &OrganizationConfig{mspID: "org2msp"}},
   154  					},
   155  				},
   156  				protos: &ChannelProtos{
   157  					Capabilities: &cb.Capabilities{},
   158  				},
   159  			},
   160  		}
   161  
   162  		err := currb.ValidateNew(newb)
   163  		assert.Error(t, err)
   164  		assert.Regexp(t, "orderer org org3 attempted to change MSP ID from", err.Error())
   165  	})
   166  
   167  	t.Run("ApplicationOrgMSPIDChange", func(t *testing.T) {
   168  		currb := &Bundle{
   169  			channelConfig: &ChannelConfig{
   170  				appConfig: &ApplicationConfig{
   171  					applicationOrgs: map[string]ApplicationOrg{
   172  						"org1": &ApplicationOrgConfig{OrganizationConfig: &OrganizationConfig{mspID: "org1msp"}},
   173  						"org2": &ApplicationOrgConfig{OrganizationConfig: &OrganizationConfig{mspID: "org2msp"}},
   174  						"org3": &ApplicationOrgConfig{OrganizationConfig: &OrganizationConfig{mspID: "org3msp"}},
   175  					},
   176  				},
   177  				protos: &ChannelProtos{
   178  					Capabilities: &cb.Capabilities{},
   179  				},
   180  			},
   181  		}
   182  
   183  		nb := &Bundle{
   184  			channelConfig: &ChannelConfig{
   185  				appConfig: &ApplicationConfig{
   186  					applicationOrgs: map[string]ApplicationOrg{
   187  						"org1": &ApplicationOrgConfig{OrganizationConfig: &OrganizationConfig{mspID: "org1msp"}},
   188  						"org3": &ApplicationOrgConfig{OrganizationConfig: &OrganizationConfig{mspID: "org2msp"}},
   189  					},
   190  				},
   191  				protos: &ChannelProtos{
   192  					Capabilities: &cb.Capabilities{},
   193  				},
   194  			},
   195  		}
   196  
   197  		err := currb.ValidateNew(nb)
   198  		assert.Error(t, err)
   199  		assert.Regexp(t, "application org org3 attempted to change MSP ID from", err.Error())
   200  	})
   201  
   202  	t.Run("ConsortiumOrgMSPIDChange", func(t *testing.T) {
   203  		currb := &Bundle{
   204  			channelConfig: &ChannelConfig{
   205  				consortiumsConfig: &ConsortiumsConfig{
   206  					consortiums: map[string]Consortium{
   207  						"consortium1": &ConsortiumConfig{
   208  							orgs: map[string]Org{
   209  								"org1": &OrganizationConfig{mspID: "org1msp"},
   210  								"org2": &OrganizationConfig{mspID: "org2msp"},
   211  								"org3": &OrganizationConfig{mspID: "org3msp"},
   212  							},
   213  						},
   214  						"consortium2": &ConsortiumConfig{},
   215  						"consortium3": &ConsortiumConfig{},
   216  					},
   217  				},
   218  				protos: &ChannelProtos{
   219  					Capabilities: &cb.Capabilities{},
   220  				},
   221  			},
   222  		}
   223  
   224  		nb := &Bundle{
   225  			channelConfig: &ChannelConfig{
   226  				consortiumsConfig: &ConsortiumsConfig{
   227  					consortiums: map[string]Consortium{
   228  						"consortium1": &ConsortiumConfig{
   229  							orgs: map[string]Org{
   230  								"org1": &OrganizationConfig{mspID: "org1msp"},
   231  								"org3": &OrganizationConfig{mspID: "org2msp"},
   232  							},
   233  						},
   234  					},
   235  				},
   236  				protos: &ChannelProtos{
   237  					Capabilities: &cb.Capabilities{},
   238  				},
   239  			},
   240  		}
   241  
   242  		err := currb.ValidateNew(nb)
   243  		assert.Error(t, err)
   244  		assert.Regexp(t, "consortium consortium1 org org3 attempted to change MSP ID from", err.Error())
   245  	})
   246  }
   247  
   248  func TestValidateNewWithConsensusMigration(t *testing.T) {
   249  	t.Run("ConsensusTypeMigration Green Path", func(t *testing.T) {
   250  		for _, sysChan := range []bool{false, true} {
   251  			b0 := generateMigrationBundle(sysChan, "kafka", ab.ConsensusType_STATE_NORMAL)
   252  			b1 := generateMigrationBundle(sysChan, "kafka", ab.ConsensusType_STATE_NORMAL)
   253  			err := b0.ValidateNew(b1)
   254  			assert.NoError(t, err)
   255  
   256  			b2 := generateMigrationBundle(sysChan, "kafka", ab.ConsensusType_STATE_MAINTENANCE)
   257  			err = b1.ValidateNew(b2)
   258  			assert.NoError(t, err)
   259  
   260  			b3 := generateMigrationBundle(sysChan, "etcdraft", ab.ConsensusType_STATE_MAINTENANCE)
   261  			err = b2.ValidateNew(b3)
   262  			assert.NoError(t, err)
   263  
   264  			b4 := generateMigrationBundle(sysChan, "etcdraft", ab.ConsensusType_STATE_NORMAL)
   265  			err = b3.ValidateNew(b4)
   266  			assert.NoError(t, err)
   267  
   268  			b5 := generateMigrationBundle(sysChan, "etcdraft", ab.ConsensusType_STATE_NORMAL)
   269  			err = b4.ValidateNew(b5)
   270  			assert.NoError(t, err)
   271  		}
   272  	})
   273  
   274  	t.Run("ConsensusTypeMigration Abort Path", func(t *testing.T) {
   275  		for _, sysChan := range []bool{false, true} {
   276  			b1 := generateMigrationBundle(sysChan, "kafka", ab.ConsensusType_STATE_NORMAL)
   277  			b2 := generateMigrationBundle(sysChan, "kafka", ab.ConsensusType_STATE_MAINTENANCE)
   278  			err := b1.ValidateNew(b2)
   279  			assert.NoError(t, err)
   280  
   281  			b3 := generateMigrationBundle(sysChan, "kafka", ab.ConsensusType_STATE_NORMAL)
   282  			err = b2.ValidateNew(b3)
   283  			assert.NoError(t, err)
   284  		}
   285  	})
   286  }
   287  
   288  func generateMigrationBundle(sysChan bool, cType string, cState ab.ConsensusType_State) *Bundle {
   289  	b := &Bundle{
   290  		channelConfig: &ChannelConfig{
   291  			ordererConfig: &OrdererConfig{
   292  				protos: &OrdererProtos{
   293  					ConsensusType: &ab.ConsensusType{
   294  						Type:  cType,
   295  						State: cState,
   296  					},
   297  					Capabilities: &cb.Capabilities{
   298  						Capabilities: map[string]*cb.Capability{
   299  							cc.OrdererV1_4_2: {},
   300  						},
   301  					},
   302  				},
   303  			},
   304  			protos: &ChannelProtos{
   305  				Capabilities: &cb.Capabilities{
   306  					Capabilities: map[string]*cb.Capability{
   307  						cc.ChannelV1_4_2: {},
   308  					},
   309  				},
   310  			},
   311  		},
   312  	}
   313  
   314  	if sysChan {
   315  		b.channelConfig.consortiumsConfig = &ConsortiumsConfig{}
   316  	}
   317  
   318  	return b
   319  }
   320  
   321  func TestPrevalidation(t *testing.T) {
   322  	t.Run("NilConfig", func(t *testing.T) {
   323  		err := preValidate(nil)
   324  
   325  		assert.Error(t, err)
   326  		assert.Regexp(t, "channelconfig Config cannot be nil", err.Error())
   327  	})
   328  
   329  	t.Run("NilChannelGroup", func(t *testing.T) {
   330  		err := preValidate(&cb.Config{})
   331  
   332  		assert.Error(t, err)
   333  		assert.Regexp(t, "config must contain a channel group", err.Error())
   334  	})
   335  
   336  	t.Run("BadChannelCapabilities", func(t *testing.T) {
   337  		err := preValidate(&cb.Config{
   338  			ChannelGroup: &cb.ConfigGroup{
   339  				Groups: map[string]*cb.ConfigGroup{
   340  					OrdererGroupKey: {},
   341  				},
   342  				Values: map[string]*cb.ConfigValue{
   343  					CapabilitiesKey: {},
   344  				},
   345  			},
   346  		})
   347  
   348  		assert.Error(t, err)
   349  		assert.Regexp(t, "cannot enable channel capabilities without orderer support first", err.Error())
   350  	})
   351  
   352  	t.Run("BadApplicationCapabilities", func(t *testing.T) {
   353  		err := preValidate(&cb.Config{
   354  			ChannelGroup: &cb.ConfigGroup{
   355  				Groups: map[string]*cb.ConfigGroup{
   356  					ApplicationGroupKey: {
   357  						Values: map[string]*cb.ConfigValue{
   358  							CapabilitiesKey: {},
   359  						},
   360  					},
   361  					OrdererGroupKey: {},
   362  				},
   363  			},
   364  		})
   365  
   366  		assert.Error(t, err)
   367  		assert.Regexp(t, "cannot enable application capabilities without orderer support first", err.Error())
   368  	})
   369  
   370  	t.Run("ValidCapabilities", func(t *testing.T) {
   371  		err := preValidate(&cb.Config{
   372  			ChannelGroup: &cb.ConfigGroup{
   373  				Groups: map[string]*cb.ConfigGroup{
   374  					ApplicationGroupKey: {
   375  						Values: map[string]*cb.ConfigValue{
   376  							CapabilitiesKey: {},
   377  						},
   378  					},
   379  					OrdererGroupKey: {
   380  						Values: map[string]*cb.ConfigValue{
   381  							CapabilitiesKey: {},
   382  						},
   383  					},
   384  				},
   385  				Values: map[string]*cb.ConfigValue{
   386  					CapabilitiesKey: {},
   387  				},
   388  			},
   389  		})
   390  
   391  		assert.NoError(t, err)
   392  	})
   393  }