From 58ecff98adbb615be4061337aafeb3c1bcef9c4f Mon Sep 17 00:00:00 2001 From: Yoav Tock Date: Thu, 17 Aug 2023 08:31:59 +0300 Subject: [PATCH] BFT Block Puller: integration with delivery client Integrate the BFT block deliverer with the deliver client. If the consensus-type is BFT, the BFTDeliverer is created. Signed-off-by: Yoav Tock Change-Id: I94c4c5ef3060df4119fc079b2b27630e92015d98 --- core/deliverservice/config.go | 2 +- core/deliverservice/deliveryclient.go | 49 ++- core/deliverservice/deliveryclient_test.go | 387 ++++++++++++++++----- 3 files changed, 346 insertions(+), 92 deletions(-) diff --git a/core/deliverservice/config.go b/core/deliverservice/config.go index e344749ea39..ea908f521f9 100644 --- a/core/deliverservice/config.go +++ b/core/deliverservice/config.go @@ -31,7 +31,7 @@ type DeliverServiceConfig struct { PeerTLSEnabled bool // BlockGossipEnabled enables block forwarding via gossip BlockGossipEnabled bool - // ReConnectBackoffThreshold sets the delivery service maximal delay between consencutive retries. + // ReConnectBackoffThreshold sets the delivery service maximal delay between consecutive retries. ReConnectBackoffThreshold time.Duration // ReconnectTotalTimeThreshold sets the total time the delivery service may spend in reconnection attempts // until its retry logic gives up and returns an error. diff --git a/core/deliverservice/deliveryclient.go b/core/deliverservice/deliveryclient.go index e48f59c590f..9dabaa3f900 100644 --- a/core/deliverservice/deliveryclient.go +++ b/core/deliverservice/deliveryclient.go @@ -157,6 +157,7 @@ func (d *deliverServiceImpl) StartDeliverForChannel(chainID string, ledgerInfo b } func (d *deliverServiceImpl) createBlockDelivererCFT(chainID string, ledgerInfo blocksprovider.LedgerInfo) (*blocksprovider.Deliverer, error) { + logger.Infof("Creating a CFT (crash fault tolerant) BlockDeliverer for channel `%s`", chainID) dc := &blocksprovider.Deliverer{ ChannelID: chainID, BlockHandler: &GossipBlockHandler{ @@ -199,10 +200,50 @@ func (d *deliverServiceImpl) createBlockDelivererCFT(chainID string, ledgerInfo return dc, nil } -func (d *deliverServiceImpl) createBlockDelivererBFT(chainID string, ledgerInfo blocksprovider.LedgerInfo) (*blocksprovider.Deliverer, error) { - // TODO create a BFT BlockDeliverer - logger.Warning("Consensus type `BFT` BlockDeliverer not supported yet, creating a CFT one") - return d.createBlockDelivererCFT(chainID, ledgerInfo) +func (d *deliverServiceImpl) createBlockDelivererBFT(chainID string, ledgerInfo blocksprovider.LedgerInfo) (*blocksprovider.BFTDeliverer, error) { + logger.Infof("Creating a BFT (byzantine fault tolerant) BlockDeliverer for channel `%s`", chainID) + dcBFT := &blocksprovider.BFTDeliverer{ + ChannelID: chainID, + BlockHandler: &GossipBlockHandler{ + gossip: d.conf.Gossip, + blockGossipDisabled: true, // Block gossip is deprecated since in v2.2 and is no longer supported in v3.x + logger: flogging.MustGetLogger("peer.blocksprovider").With("channel", chainID), + }, + Ledger: ledgerInfo, + BlockVerifier: d.conf.CryptoSvc, + Dialer: blocksprovider.DialerAdapter{ + ClientConfig: comm.ClientConfig{ + DialTimeout: d.conf.DeliverServiceConfig.ConnectionTimeout, + KaOpts: d.conf.DeliverServiceConfig.KeepaliveOptions, + SecOpts: d.conf.DeliverServiceConfig.SecOpts, + }, + }, + Orderers: d.conf.OrdererSource, + DoneC: make(chan struct{}), + Signer: d.conf.Signer, + DeliverStreamer: blocksprovider.DeliverAdapter{}, + CensorshipDetectorFactory: &blocksprovider.BFTCensorshipMonitorFactory{}, + Logger: flogging.MustGetLogger("peer.blocksprovider").With("channel", chainID), + InitialRetryInterval: 100 * time.Millisecond, // TODO expose in config + MaxRetryInterval: d.conf.DeliverServiceConfig.ReConnectBackoffThreshold, + BlockCensorshipTimeout: 30 * time.Second, // TODO expose in config + MaxRetryDuration: 12 * time.Hour, // In v3 block gossip is no longer supported. We set it long to avoid needlessly calling the handler. + MaxRetryDurationExceededHandler: func() (stopRetries bool) { + return false // In v3 block gossip is no longer supported, the peer never stops retrying. + }, + } + + if d.conf.DeliverServiceConfig.SecOpts.RequireClientCert { + cert, err := d.conf.DeliverServiceConfig.SecOpts.ClientCertificate() + if err != nil { + return nil, fmt.Errorf("failed to access client TLS configuration: %w", err) + } + dcBFT.TLSCertHash = util.ComputeSHA256(cert.Certificate[0]) + } + + dcBFT.Initialize() + + return dcBFT, nil } // StopDeliverForChannel stops blocks delivery for channel by stopping channel block provider diff --git a/core/deliverservice/deliveryclient_test.go b/core/deliverservice/deliveryclient_test.go index f73a8a4e032..31085b0b52b 100644 --- a/core/deliverservice/deliveryclient_test.go +++ b/core/deliverservice/deliveryclient_test.go @@ -8,12 +8,14 @@ package deliverservice import ( "fmt" + "io/ioutil" "os" "path" "testing" "time" cb "github.com/hyperledger/fabric-protos-go/common" + "github.com/hyperledger/fabric/bccsp" "github.com/hyperledger/fabric/bccsp/sw" "github.com/hyperledger/fabric/common/crypto/tlsgen" "github.com/hyperledger/fabric/common/flogging" @@ -35,46 +37,8 @@ func TestStartDeliverForChannel(t *testing.T) { fakeLedgerInfo := &fake.LedgerInfo{} fakeLedgerInfo.LedgerHeightReturns(0, fmt.Errorf("fake-ledger-error")) - secOpts := comm.SecureOptions{ - UseTLS: true, - RequireClientCert: true, - // The below certificates were taken from the peer TLS - // dir as output by cryptogen. - // They are server.crt and server.key respectively. - Certificate: []byte(`-----BEGIN CERTIFICATE----- -MIIChTCCAiygAwIBAgIQOrr7/tDzKhhCba04E6QVWzAKBggqhkjOPQQDAjB2MQsw -CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy -YW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEfMB0GA1UEAxMWdGxz -Y2Eub3JnMS5leGFtcGxlLmNvbTAeFw0xOTA4MjcyMDA2MDBaFw0yOTA4MjQyMDA2 -MDBaMFsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQH -Ew1TYW4gRnJhbmNpc2NvMR8wHQYDVQQDExZwZWVyMC5vcmcxLmV4YW1wbGUuY29t -MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExglppLxiAYSasrdFsrZJDxRULGBb -wHlArrap9SmAzGIeeIuqe9t3F23Q5Jry9lAnIh8h3UlkvZZpClXcjRiCeqOBtjCB -szAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC -MAwGA1UdEwEB/wQCMAAwKwYDVR0jBCQwIoAgL35aqafj6SNnWdI4aMLh+oaFJvsA -aoHgYMkcPvvkiWcwRwYDVR0RBEAwPoIWcGVlcjAub3JnMS5leGFtcGxlLmNvbYIF -cGVlcjCCFnBlZXIwLm9yZzEuZXhhbXBsZS5jb22CBXBlZXIwMAoGCCqGSM49BAMC -A0cAMEQCIAiAGoYeKPMd3bqtixZji8q2zGzLmIzq83xdTJoZqm50AiAKleso2EVi -2TwsekWGpMaCOI6JV1+ZONyti6vBChhUYg== ------END CERTIFICATE-----`), - Key: []byte(`-----BEGIN PRIVATE KEY----- -MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgxiyAFyD0Eg1NxjbS -U2EKDLoTQr3WPK8z7WyeOSzr+GGhRANCAATGCWmkvGIBhJqyt0WytkkPFFQsYFvA -eUCutqn1KYDMYh54i6p723cXbdDkmvL2UCciHyHdSWS9lmkKVdyNGIJ6 ------END PRIVATE KEY-----`, - ), - } - - confAppRaft := genesisconfig.Load(genesisconfig.SampleAppChannelEtcdRaftProfile, configtest.GetDevConfigDir()) - certDir := t.TempDir() - tlsCA, err := tlsgen.NewCA() - require.NoError(t, err) - generateCertificates(t, confAppRaft, tlsCA, certDir) - bootstrapper, err := encoder.NewBootstrapper(confAppRaft) - require.NoError(t, err) - channelConfigProto := &cb.Config{ChannelGroup: bootstrapper.GenesisChannelGroup()} - cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) - require.NoError(t, err) + secOpts := testSecureOptions() + channelConfigProto, cryptoProvider := testSetup(t, "CFT") t.Run("Green Path With Mutual TLS", func(t *testing.T) { ds := NewDeliverService(&Config{ @@ -86,7 +50,7 @@ eUCutqn1KYDMYh54i6p723cXbdDkmvL2UCciHyHdSWS9lmkKVdyNGIJ6 }).(*deliverServiceImpl) finalized := make(chan struct{}) - err = ds.StartDeliverForChannel("channel-id", fakeLedgerInfo, func() { + err := ds.StartDeliverForChannel("channel-id", fakeLedgerInfo, func() { close(finalized) }) require.NoError(t, err) @@ -192,76 +156,244 @@ eUCutqn1KYDMYh54i6p723cXbdDkmvL2UCciHyHdSWS9lmkKVdyNGIJ6 }) } -func TestStopDeliverForChannel(t *testing.T) { - t.Run("Green path", func(t *testing.T) { - ds := NewDeliverService(&Config{}).(*deliverServiceImpl) - doneA := make(chan struct{}) - ds.blockDeliverer = &blocksprovider.Deliverer{ - DoneC: doneA, - Logger: flogging.MustGetLogger("deliveryclient.test"), +func TestStartDeliverForChannel_BFT(t *testing.T) { + flogging.ActivateSpec("debug") + + fakeLedgerInfo := &fake.LedgerInfo{} + fakeLedgerInfo.LedgerHeightReturns(0, fmt.Errorf("fake-ledger-error")) + + secOpts := testSecureOptions() + channelConfigProto, cryptoProvider := testSetup(t, "BFT") + + t.Run("Green Path With Mutual TLS", func(t *testing.T) { + ds := NewDeliverService(&Config{ + DeliverServiceConfig: &DeliverServiceConfig{ + SecOpts: secOpts, + }, + ChannelConfig: channelConfigProto, + CryptoProvider: cryptoProvider, + }).(*deliverServiceImpl) + + finalized := make(chan struct{}) + err := ds.StartDeliverForChannel("channel-id", fakeLedgerInfo, func() { + close(finalized) + }) + require.NoError(t, err) + + select { + case <-finalized: + case <-time.After(time.Second): + require.FailNow(t, "finalizer should have executed") } - ds.channelID = "channel-id" - err := ds.StopDeliverForChannel() + require.NotNil(t, ds.blockDeliverer) + bpd := ds.blockDeliverer.(*blocksprovider.BFTDeliverer) + + require.Equal(t, "76f7a03f8dfdb0ef7c4b28b3901fe163c730e906c70e4cdf887054ad5f608bed", fmt.Sprintf("%x", bpd.TLSCertHash)) + }) + + t.Run("Green Path without mutual TLS", func(t *testing.T) { + ds := NewDeliverService(&Config{ + DeliverServiceConfig: &DeliverServiceConfig{}, + ChannelConfig: channelConfigProto, + CryptoProvider: cryptoProvider, + }).(*deliverServiceImpl) + + finalized := make(chan struct{}) + err := ds.StartDeliverForChannel("channel-id", fakeLedgerInfo, func() { + close(finalized) + }) require.NoError(t, err) select { - case <-doneA: - default: - require.Fail(t, "should have stopped the blocksprovider") + case <-finalized: + case <-time.After(time.Second): + require.FailNow(t, "finalizer should have executed") } + + require.NotNil(t, ds.blockDeliverer) + bpd := ds.blockDeliverer.(*blocksprovider.BFTDeliverer) + require.Nil(t, bpd.TLSCertHash) }) - t.Run("Already stopping", func(t *testing.T) { - ds := NewDeliverService(&Config{}).(*deliverServiceImpl) - ds.blockDeliverer = &blocksprovider.Deliverer{ - DoneC: make(chan struct{}), - Logger: flogging.MustGetLogger("deliveryclient.test"), + t.Run("Can restart for channel: Start->Stop->Start", func(t *testing.T) { + ds := NewDeliverService(&Config{ + DeliverServiceConfig: &DeliverServiceConfig{}, + ChannelConfig: channelConfigProto, + CryptoProvider: cryptoProvider, + }).(*deliverServiceImpl) + + finalized := make(chan struct{}) + err := ds.StartDeliverForChannel("channel-id", fakeLedgerInfo, func() { + close(finalized) + }) + require.NoError(t, err) + + select { + case <-finalized: + case <-time.After(time.Second): + require.FailNow(t, "finalizer should have executed") + } + + require.NotNil(t, ds.blockDeliverer) + bpd := ds.blockDeliverer.(*blocksprovider.BFTDeliverer) + require.Nil(t, bpd.TLSCertHash) + + err = ds.StopDeliverForChannel() + require.NoError(t, err) + require.Nil(t, ds.blockDeliverer) + + finalized2 := make(chan struct{}) + err = ds.StartDeliverForChannel("channel-id", fakeLedgerInfo, func() { + close(finalized2) + }) + require.NoError(t, err) + select { + case <-finalized2: + case <-time.After(time.Second): + require.FailNow(t, "finalizer should have executed") } - ds.channelID = "channel-id" + }) + + t.Run("Exists", func(t *testing.T) { + ds := NewDeliverService(&Config{ + DeliverServiceConfig: &DeliverServiceConfig{}, + ChannelConfig: channelConfigProto, + CryptoProvider: cryptoProvider, + }).(*deliverServiceImpl) + + err := ds.StartDeliverForChannel("channel-id", fakeLedgerInfo, func() {}) + require.NoError(t, err) + + err = ds.StartDeliverForChannel("channel-id", fakeLedgerInfo, func() {}) + require.EqualError(t, err, "block deliverer for channel `channel-id` already exists") + }) + + t.Run("Stopping", func(t *testing.T) { + ds := NewDeliverService(&Config{ + DeliverServiceConfig: &DeliverServiceConfig{}, + }).(*deliverServiceImpl) ds.Stop() - err := ds.StopDeliverForChannel() - require.EqualError(t, err, "block deliverer for channel `channel-id` is already stopped") + + err := ds.StartDeliverForChannel("channel-id", fakeLedgerInfo, func() {}) + require.EqualError(t, err, "block deliverer for channel `channel-id` is stopping") }) +} + +func TestStopDeliverForChannel(t *testing.T) { + createBlockDeliverer := func(consensusClass string) (BlockDeliverer, chan struct{}) { + doneCh := make(chan struct{}) + var d BlockDeliverer + switch consensusClass { + case "BFT": + d = &blocksprovider.BFTDeliverer{ + DoneC: doneCh, + Logger: flogging.MustGetLogger("deliveryclient.test"), + } + case "CFT": + d = &blocksprovider.Deliverer{ + DoneC: doneCh, + Logger: flogging.MustGetLogger("deliveryclient.test"), + } + default: + require.Failf(t, "unexpected consensusClass: %s", consensusClass) + } + + return d, doneCh + } + + for _, consensusClass := range []string{"CFT", "BFT"} { + t.Run("Green path: "+consensusClass, func(t *testing.T) { + ds := NewDeliverService(&Config{}).(*deliverServiceImpl) + bd, doneCh := createBlockDeliverer(consensusClass) + ds.blockDeliverer = bd + ds.channelID = "channel-id" + + err := ds.StopDeliverForChannel() + require.NoError(t, err) + + select { + case <-doneCh: + default: + require.Fail(t, "should have stopped the blocksprovider") + } + }) + + t.Run("Already stopping: "+consensusClass, func(t *testing.T) { + ds := NewDeliverService(&Config{}).(*deliverServiceImpl) + bd, _ := createBlockDeliverer(consensusClass) + ds.blockDeliverer = bd + ds.channelID = "channel-id" - t.Run("Already stopped", func(t *testing.T) { + ds.Stop() + err := ds.StopDeliverForChannel() + require.EqualError(t, err, "block deliverer for channel `channel-id` is already stopped") + }) + + t.Run("Already stopped: "+consensusClass, func(t *testing.T) { + ds := NewDeliverService(&Config{}).(*deliverServiceImpl) + bd, _ := createBlockDeliverer(consensusClass) + ds.blockDeliverer = bd + ds.channelID = "channel-id" + + ds.StopDeliverForChannel() + err := ds.StopDeliverForChannel() + require.EqualError(t, err, "block deliverer for channel `channel-id` is , can't stop delivery") + }) + } +} + +func TestStop(t *testing.T) { + t.Run("CFT deliverer", func(t *testing.T) { ds := NewDeliverService(&Config{}).(*deliverServiceImpl) ds.blockDeliverer = &blocksprovider.Deliverer{ DoneC: make(chan struct{}), Logger: flogging.MustGetLogger("deliveryclient.test"), } - ds.channelID = "channel-id" - ds.StopDeliverForChannel() - err := ds.StopDeliverForChannel() - require.EqualError(t, err, "block deliverer for channel `channel-id` is , can't stop delivery") + require.False(t, ds.stopping) + bpd := ds.blockDeliverer.(*blocksprovider.Deliverer) + select { + case <-bpd.DoneC: + require.Fail(t, "block providers should not be closed") + default: + } + + ds.Stop() + require.True(t, ds.stopping) + + select { + case <-bpd.DoneC: + default: + require.Fail(t, "block providers should te closed") + } }) -} -func TestStop(t *testing.T) { - ds := NewDeliverService(&Config{}).(*deliverServiceImpl) - ds.blockDeliverer = &blocksprovider.Deliverer{ - DoneC: make(chan struct{}), - Logger: flogging.MustGetLogger("deliveryclient.test"), - } + t.Run("BFT deliverer", func(t *testing.T) { + ds := NewDeliverService(&Config{}).(*deliverServiceImpl) + ds.blockDeliverer = &blocksprovider.BFTDeliverer{ + DoneC: make(chan struct{}), + Logger: flogging.MustGetLogger("deliveryclient.test"), + } - require.False(t, ds.stopping) - bpd := ds.blockDeliverer.(*blocksprovider.Deliverer) - select { - case <-bpd.DoneC: - require.Fail(t, "block providers should not be closed") - default: - } + require.False(t, ds.stopping) + bpd := ds.blockDeliverer.(*blocksprovider.BFTDeliverer) + select { + case <-bpd.DoneC: + require.Fail(t, "block providers should not be closed") + default: + } - ds.Stop() - require.True(t, ds.stopping) + ds.Stop() + require.True(t, ds.stopping) - select { - case <-bpd.DoneC: - default: - require.Fail(t, "block providers should te closed") - } + select { + case <-bpd.DoneC: + default: + require.Fail(t, "block providers should te closed") + } + }) } // TODO this pattern repeats itself in several places. Make it common in the 'genesisconfig' package to easily create @@ -284,3 +416,84 @@ func generateCertificates(t *testing.T, confAppRaft *genesisconfig.Profile, tlsC c.ClientTlsCert = []byte(clnP) } } + +func generateCertificatesSmartBFT(t *testing.T, confAppSmartBFT *genesisconfig.Profile, tlsCA tlsgen.CA, certDir string) { + for i, c := range confAppSmartBFT.Orderer.ConsenterMapping { + t.Logf("BFT Consenter: %+v", c) + srvC, err := tlsCA.NewServerCertKeyPair(c.Host) + require.NoError(t, err) + srvP := path.Join(certDir, fmt.Sprintf("server%d.crt", i)) + err = ioutil.WriteFile(srvP, srvC.Cert, 0o644) + require.NoError(t, err) + + clnC, err := tlsCA.NewClientCertKeyPair() + require.NoError(t, err) + clnP := path.Join(certDir, fmt.Sprintf("client%d.crt", i)) + err = ioutil.WriteFile(clnP, clnC.Cert, 0o644) + require.NoError(t, err) + + c.Identity = srvP + c.ServerTLSCert = srvP + c.ClientTLSCert = clnP + } +} + +func testSecureOptions() comm.SecureOptions { + secOpts := comm.SecureOptions{ + UseTLS: true, + RequireClientCert: true, + // The below certificates were taken from the peer TLS + // dir as output by cryptogen. + // They are server.crt and server.key respectively. + Certificate: []byte(`-----BEGIN CERTIFICATE----- +MIIChTCCAiygAwIBAgIQOrr7/tDzKhhCba04E6QVWzAKBggqhkjOPQQDAjB2MQsw +CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy +YW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEfMB0GA1UEAxMWdGxz +Y2Eub3JnMS5leGFtcGxlLmNvbTAeFw0xOTA4MjcyMDA2MDBaFw0yOTA4MjQyMDA2 +MDBaMFsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQH +Ew1TYW4gRnJhbmNpc2NvMR8wHQYDVQQDExZwZWVyMC5vcmcxLmV4YW1wbGUuY29t +MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAExglppLxiAYSasrdFsrZJDxRULGBb +wHlArrap9SmAzGIeeIuqe9t3F23Q5Jry9lAnIh8h3UlkvZZpClXcjRiCeqOBtjCB +szAOBgNVHQ8BAf8EBAMCBaAwHQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMC +MAwGA1UdEwEB/wQCMAAwKwYDVR0jBCQwIoAgL35aqafj6SNnWdI4aMLh+oaFJvsA +aoHgYMkcPvvkiWcwRwYDVR0RBEAwPoIWcGVlcjAub3JnMS5leGFtcGxlLmNvbYIF +cGVlcjCCFnBlZXIwLm9yZzEuZXhhbXBsZS5jb22CBXBlZXIwMAoGCCqGSM49BAMC +A0cAMEQCIAiAGoYeKPMd3bqtixZji8q2zGzLmIzq83xdTJoZqm50AiAKleso2EVi +2TwsekWGpMaCOI6JV1+ZONyti6vBChhUYg== +-----END CERTIFICATE-----`), + Key: []byte(`-----BEGIN PRIVATE KEY----- +MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgxiyAFyD0Eg1NxjbS +U2EKDLoTQr3WPK8z7WyeOSzr+GGhRANCAATGCWmkvGIBhJqyt0WytkkPFFQsYFvA +eUCutqn1KYDMYh54i6p723cXbdDkmvL2UCciHyHdSWS9lmkKVdyNGIJ6 +-----END PRIVATE KEY-----`, + ), + } + + return secOpts +} + +func testSetup(t *testing.T, consensusClass string) (*cb.Config, bccsp.BCCSP) { + var configProfile *genesisconfig.Profile + certDir := t.TempDir() + tlsCA, err := tlsgen.NewCA() + require.NoError(t, err) + + switch consensusClass { + case "CFT": + configProfile = genesisconfig.Load(genesisconfig.SampleAppChannelEtcdRaftProfile, configtest.GetDevConfigDir()) + generateCertificates(t, configProfile, tlsCA, certDir) + case "BFT": + configProfile = genesisconfig.Load(genesisconfig.SampleAppChannelSmartBftProfile, configtest.GetDevConfigDir()) + generateCertificatesSmartBFT(t, configProfile, tlsCA, certDir) + default: + t.Errorf("unexpected consensusClass: %s", consensusClass) + } + + bootstrapper, err := encoder.NewBootstrapper(configProfile) + require.NoError(t, err) + channelConfigProto := &cb.Config{ChannelGroup: bootstrapper.GenesisChannelGroup()} + cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore()) + require.NoError(t, err) + + return channelConfigProto, cryptoProvider +}