Skip to content

Commit db236d6

Browse files
committed
[FAB-3493] Fix LAST_CONFIG on new channels
The fix submitted in [1] works in that it delivers what we were looking for (a pointer to the last config block) but is based on an incorrect assumption: that the sequence number of the genesis block of a non-system channel should be zero. I assumed that should be the case, what with it being the genesis block and all, but this breaks the abstraction that the config update framework introduces. This changeset introduces the right fix. Thanks to Jason Yellick for pointing this out. [1] https://gerrit.hyperledger.org/r/#/c/8825/ Change-Id: I61ef2825c4cfe55495a4d81cff759fd6c340c191 Signed-off-by: Kostas Christidis <[email protected]>
1 parent 587387f commit db236d6

File tree

4 files changed

+28
-3
lines changed

4 files changed

+28
-3
lines changed

orderer/common/broadcast/broadcast.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,7 @@ func (bh *handlerImpl) Handle(srv ab.AtomicBroadcast_BroadcastServer) error {
162162
}
163163

164164
if logger.IsEnabledFor(logging.DEBUG) {
165-
logger.Debugf("Broadcast has successfully enqueued message of type %d for chain %s", chdr.Type, chdr.ChannelId)
165+
logger.Debugf("Broadcast has successfully enqueued message of type %s for chain %s", cb.HeaderType_name[chdr.Type], chdr.ChannelId)
166166
}
167167

168168
err = srv.Send(&ab.BroadcastResponse{Status: cb.Status_SUCCESS})

orderer/multichain/chainsupport.go

+3
Original file line numberDiff line numberDiff line change
@@ -231,6 +231,7 @@ func (cs *chainSupport) addLastConfigSignature(block *cb.Block) {
231231
}
232232

233233
lastConfigValue := utils.MarshalOrPanic(&cb.LastConfig{Index: cs.lastConfig})
234+
logger.Debugf("[channel: %s] About to write block, setting its LAST_CONFIG to %d", cs.ChainID(), cs.lastConfig)
234235

235236
lastConfigSignature.Signature = utils.SignOrPanic(cs.signer, util.ConcatenateBytes(lastConfigValue, lastConfigSignature.SignatureHeader, block.Header.Bytes()))
236237

@@ -257,6 +258,8 @@ func (cs *chainSupport) WriteBlock(block *cb.Block, committers []filter.Committe
257258
if err != nil {
258259
logger.Panicf("[channel: %s] Could not append block: %s", cs.ChainID(), err)
259260
}
261+
logger.Debugf("[channel: %s] Wrote block %d", cs.ChainID(), block.GetHeader().Number)
262+
260263
return block
261264
}
262265

orderer/multichain/manager.go

+5
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,11 @@ func (ml *multiLedger) newChain(configtx *cb.Envelope) {
187187

188188
logger.Infof("Created and starting new chain %s", chainID)
189189

190+
cs.lastConfigSeq = cs.Sequence()
191+
// The sequence number on the genesis block of the system channel will be 0.
192+
// The sequence number on the genesis block of every non-system channel will be 1.
193+
logger.Debugf("[channel: %s] Last config set to %d", chainID, cs.lastConfigSeq)
194+
190195
newChains[string(chainID)] = cs
191196
cs.start()
192197

orderer/multichain/manager_test.go

+19-2
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"testing"
2222
"time"
2323

24+
"github.com/golang/protobuf/proto"
2425
"github.com/hyperledger/fabric/common/configtx"
2526
genesisconfig "github.com/hyperledger/fabric/common/configtx/tool/localconfig"
2627
"github.com/hyperledger/fabric/common/configtx/tool/provisional"
@@ -235,15 +236,17 @@ func TestSignatureFilter(t *testing.T) {
235236

236237
// This test brings up the entire system, with the mock consenter, including the broadcasters etc. and creates a new chain
237238
func TestNewChain(t *testing.T) {
239+
expectedLastConfigBlockNumber := uint64(0)
240+
expectedLastConfigSeq := uint64(1)
241+
newChainID := "TestNewChain"
242+
238243
lf, rl := NewRAMLedgerAndFactory(10)
239244

240245
consenters := make(map[string]Consenter)
241246
consenters[conf.Orderer.OrdererType] = &mockConsenter{}
242247

243248
manager := NewManagerImpl(lf, consenters, mockCrypto())
244249

245-
newChainID := "TestNewChain"
246-
247250
envConfigUpdate, err := configtx.MakeChainCreationTransaction(newChainID, genesisconfig.SampleConsortiumName, mockSigningIdentity)
248251
assert.NoError(t, err, "Constructing chain creation tx")
249252

@@ -252,6 +255,7 @@ func TestNewChain(t *testing.T) {
252255

253256
configEnv, err := cm.ProposeConfigUpdate(envConfigUpdate)
254257
assert.NoError(t, err, "Proposing initial update")
258+
assert.Equal(t, expectedLastConfigSeq, configEnv.GetConfig().Sequence, "Sequence of config envelope for new channel should always be set to %d", expectedLastConfigSeq)
255259

256260
ingressTx, err := utils.CreateSignedEnvelope(cb.HeaderType_CONFIG, newChainID, mockCrypto(), configEnv, msgVersion, epoch)
257261
assert.NoError(t, err, "Creating ingresstx")
@@ -260,6 +264,7 @@ func TestNewChain(t *testing.T) {
260264

261265
chainSupport, ok := manager.GetChain(manager.SystemChannelID())
262266
assert.True(t, ok, "Could not find system channel")
267+
263268
chainSupport.Enqueue(wrapped)
264269

265270
it, _ := rl.Iterator(&ab.SeekPosition{Type: &ab.SeekPosition_Specified{Specified: &ab.SeekSpecified{Number: 1}}})
@@ -300,6 +305,7 @@ func TestNewChain(t *testing.T) {
300305
if status != cb.Status_SUCCESS {
301306
t.Fatalf("Could not retrieve new chain genesis block")
302307
}
308+
testLastConfigBlockNumber(t, block, expectedLastConfigBlockNumber)
303309
if len(block.Data.Data) != 1 {
304310
t.Fatalf("Should have had only one message in the new genesis block")
305311
}
@@ -315,6 +321,7 @@ func TestNewChain(t *testing.T) {
315321
if status != cb.Status_SUCCESS {
316322
t.Fatalf("Could not retrieve block on new chain")
317323
}
324+
testLastConfigBlockNumber(t, block, expectedLastConfigBlockNumber)
318325
for i := 0; i < int(conf.Orderer.BatchSize.MaxMessageCount); i++ {
319326
if !reflect.DeepEqual(utils.ExtractEnvelopeOrPanic(block, i), messages[i]) {
320327
t.Errorf("Block contents wrong at index %d in new chain", i)
@@ -324,3 +331,13 @@ func TestNewChain(t *testing.T) {
324331
t.Fatalf("Block 1 not produced after timeout on new chain")
325332
}
326333
}
334+
335+
func testLastConfigBlockNumber(t *testing.T, block *cb.Block, expectedBlockNumber uint64) {
336+
metadataItem := &cb.Metadata{}
337+
err := proto.Unmarshal(block.Metadata.Metadata[cb.BlockMetadataIndex_LAST_CONFIG], metadataItem)
338+
assert.NoError(t, err, "Block should carry LAST_CONFIG metadata item")
339+
lastConfig := &cb.LastConfig{}
340+
err = proto.Unmarshal(metadataItem.Value, lastConfig)
341+
assert.NoError(t, err, "LAST_CONFIG metadata item should carry last config value")
342+
assert.Equal(t, expectedBlockNumber, lastConfig.Index, "LAST_CONFIG value should point to last config block")
343+
}

0 commit comments

Comments
 (0)