Skip to content

Commit

Permalink
FAB-18276 Ch.Part.API: extractSystemChannel must skip empty ledger (#…
Browse files Browse the repository at this point in the history
…2023)

- orderer/common/server/main.go extractSystemChannel() panics when
it hits an empty ledger.

- In addition this method is not covered with unit tests at all.

- Remove some dead code.

Signed-off-by: Yoav Tock <tock@il.ibm.com>
Change-Id: Ie13156784d2ec600e3f97d34f20f6836b28f7662
  • Loading branch information
tock-ibm authored Oct 19, 2020
1 parent 69bc731 commit c6f07dd
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 47 deletions.
29 changes: 4 additions & 25 deletions orderer/common/server/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -384,31 +384,6 @@ func reuseListener(conf *localconfig.TopLevel) bool {
return false
}

// Extract system channel last config block
func extractSysChanLastConfig(lf blockledger.Factory, bootstrapBlock *cb.Block) *cb.Block {
// Are we bootstrapping?
channelCount := len(lf.ChannelIDs())
if channelCount == 0 {
logger.Info("Bootstrapping because no existing channels")
return nil
}
logger.Infof("Not bootstrapping because of %d existing channels", channelCount)

systemChannelName, err := protoutil.GetChannelIDFromBlock(bootstrapBlock)
if err != nil {
logger.Panicf("Failed extracting system channel name from bootstrap block: %v", err)
}
systemChannelLedger, err := lf.GetOrCreate(systemChannelName)
if err != nil {
logger.Panicf("Failed getting system channel ledger: %v", err)
}
height := systemChannelLedger.Height()
lastConfigBlock := multichannel.ConfigBlockOrPanic(systemChannelLedger)
logger.Infof("System channel: name=%s, height=%d, last config block number=%d",
systemChannelName, height, lastConfigBlock.Header.Number)
return lastConfigBlock
}

// extractSystemChannel loops through all channels, and return the last
// config block for the system channel. Returns nil if no system channel
// was found.
Expand All @@ -418,6 +393,10 @@ func extractSystemChannel(lf blockledger.Factory, bccsp bccsp.BCCSP) *cb.Block {
if err != nil {
logger.Panicf("Failed getting channel %v's ledger: %v", cID, err)
}
if channelLedger.Height() == 0 {
continue // Some channels may have an empty ledger and (possibly) a join-block, skip those
}

channelConfigBlock := multichannel.ConfigBlockOrPanic(channelLedger)

err = onboarding.ValidateBootstrapBlock(channelConfigBlock, bccsp)
Expand Down
55 changes: 33 additions & 22 deletions orderer/common/server/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -394,51 +394,62 @@ func TestInitSystemChannelWithJoinBlock(t *testing.T) {

}

func TestExtractSysChanLastConfig(t *testing.T) {
func TestExtractSystemChannel(t *testing.T) {
cryptoProvider, _ := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())

tmpdir, err := ioutil.TempDir("", "main_test-")
require.NoError(t, err)
defer os.RemoveAll(tmpdir)

rlf, err := fileledger.New(tmpdir, &disabled.Provider{})
require.NoError(t, err)

conf := genesisconfig.Load(genesisconfig.SampleInsecureSoloProfile, configtest.GetDevConfigDir())
genesisBlock := encoder.New(conf).GenesisBlock()

lastConf := extractSysChanLastConfig(rlf, genesisBlock)
require.Nil(t, lastConf)
lastConf := extractSystemChannel(rlf, cryptoProvider)
require.Nil(t, lastConf, "no ledgers")

rl, err := rlf.GetOrCreate("testchannelid")
_, err = rlf.GetOrCreate("emptychannelid")
require.NoError(t, err)

err = rl.Append(genesisBlock)
require.NoError(t, err)
lastConf = extractSystemChannel(rlf, cryptoProvider)
require.Nil(t, lastConf, "skip empty ledger")

lastConf = extractSysChanLastConfig(rlf, genesisBlock)
require.NotNil(t, lastConf)
require.Equal(t, uint64(0), lastConf.Header.Number)
conf := genesisconfig.Load(genesisconfig.SampleInsecureSoloProfile, configtest.GetDevConfigDir())
conf.Consortiums = nil
configBlock := encoder.New(conf).GenesisBlock()
rl, err := rlf.GetOrCreate("appchannelid")
err = rl.Append(configBlock)
require.NoError(t, err)

require.Panics(t, func() {
_ = extractSysChanLastConfig(rlf, nil)
})
lastConf = extractSystemChannel(rlf, cryptoProvider)
require.Nil(t, lastConf, "skip app ledger")

configTx, err := protoutil.CreateSignedEnvelope(common.HeaderType_CONFIG, "testchannelid", nil, &common.ConfigEnvelope{}, 0, 0)
conf = genesisconfig.Load(genesisconfig.SampleInsecureSoloProfile, configtest.GetDevConfigDir())
configBlock = encoder.New(conf).GenesisBlock()
rl, err = rlf.GetOrCreate("testchannelid")
err = rl.Append(configBlock)
require.NoError(t, err)

nextBlock := blockledger.CreateNextBlock(rl, []*common.Envelope{configTx})
nextBlock.Metadata.Metadata[common.BlockMetadataIndex_SIGNATURES] = protoutil.MarshalOrPanic(&common.Metadata{
lastConf = extractSystemChannel(rlf, cryptoProvider)
require.NotNil(t, lastConf, "get system channel genesis block")
require.Equal(t, uint64(0), lastConf.Header.Number)

// Make and append the next config block
prevHash := protoutil.BlockHeaderHash(configBlock.Header)
configBlock.Header.Number = 1
configBlock.Header.PreviousHash = prevHash
configBlock.Metadata.Metadata[common.BlockMetadataIndex_SIGNATURES] = protoutil.MarshalOrPanic(&common.Metadata{
Value: protoutil.MarshalOrPanic(&common.OrdererBlockMetadata{
LastConfig: &common.LastConfig{Index: rl.Height()},
}),
})
nextBlock.Metadata.Metadata[common.BlockMetadataIndex_LAST_CONFIG] = protoutil.MarshalOrPanic(&common.Metadata{
configBlock.Metadata.Metadata[common.BlockMetadataIndex_LAST_CONFIG] = protoutil.MarshalOrPanic(&common.Metadata{
Value: protoutil.MarshalOrPanic(&common.LastConfig{Index: rl.Height()}),
})
err = rl.Append(nextBlock)
err = rl.Append(configBlock)
require.NoError(t, err)

lastConf = extractSysChanLastConfig(rlf, genesisBlock)
require.NotNil(t, lastConf)
lastConf = extractSystemChannel(rlf, cryptoProvider)
require.NotNil(t, lastConf, "get system channel last config block")
require.Equal(t, uint64(1), lastConf.Header.Number)
}

Expand Down

0 comments on commit c6f07dd

Please sign in to comment.