From 5ad94634cc10ab21ba458fd052a2ef2de2ae43cf Mon Sep 17 00:00:00 2001 From: David Enyeart Date: Wed, 10 May 2017 08:19:26 -0400 Subject: [PATCH] [FAB-3525] Fix config block retrieval Upon startup peer was scanning all blocks for each channel's config block. This was extremely inefficient for large chains. This change navigates directly to the config block based on the last block's metadata which has a pointer to the last config block. Change-Id: Ia570f4d64df135e99a24a4206006bb969c7e4476 Signed-off-by: David Enyeart --- core/peer/peer.go | 60 ++++++++++++++++++------------------------ core/peer/peer_test.go | 5 +++- 2 files changed, 29 insertions(+), 36 deletions(-) diff --git a/core/peer/peer.go b/core/peer/peer.go index b8d1e8f8445..0d6fe207d9b 100644 --- a/core/peer/peer.go +++ b/core/peer/peer.go @@ -19,7 +19,6 @@ package peer import ( "errors" "fmt" - "math" "net" "sync" @@ -145,41 +144,32 @@ func InitChain(cid string) { } func getCurrConfigBlockFromLedger(ledger ledger.PeerLedger) (*common.Block, error) { - // Config blocks contain only 1 transaction, so we look for 1-tx - // blocks and check the transaction type - var envelope *common.Envelope - var tx *common.Payload - var block *common.Block - var err error - var currBlockNumber uint64 = math.MaxUint64 - for currBlockNumber >= 0 { - if block, err = ledger.GetBlockByNumber(currBlockNumber); err != nil { - return nil, err - } - if block.Data != nil && len(block.Data.Data) == 1 { - if envelope, err = utils.ExtractEnvelope(block, 0); err != nil { - peerLogger.Warning("Failed to get Envelope from Block %d.", block.Header.Number) - currBlockNumber = block.Header.Number - 1 - continue - } - if tx, err = utils.ExtractPayload(envelope); err != nil { - peerLogger.Warning("Failed to get Payload from Block %d.", block.Header.Number) - currBlockNumber = block.Header.Number - 1 - continue - } - chdr, err := utils.UnmarshalChannelHeader(tx.Header.ChannelHeader) - if err != nil { - peerLogger.Warning("Failed to get ChannelHeader from Block %d, error %s.", block.Header.Number, err) - currBlockNumber = block.Header.Number - 1 - continue - } - if chdr.Type == int32(common.HeaderType_CONFIG) { - return block, nil - } - } - currBlockNumber = block.Header.Number - 1 + peerLogger.Debugf("Getting config block") + + // get last block. Last block number is Height-1 + blockchainInfo, err := ledger.GetBlockchainInfo() + if err != nil { + return nil, err } - return nil, fmt.Errorf("Failed to find config block.") + lastBlock, err := ledger.GetBlockByNumber(blockchainInfo.Height - 1) + if err != nil { + return nil, err + } + + // get most recent config block location from last block metadata + configBlockIndex, err := utils.GetLastConfigIndexFromBlock(lastBlock) + if err != nil { + return nil, err + } + + // get most recent config block + configBlock, err := ledger.GetBlockByNumber(configBlockIndex) + if err != nil { + return nil, err + } + + peerLogger.Debugf("Got config block[%d]", configBlockIndex) + return configBlock, nil } // createChain creates a new chain object and insert it into the chains diff --git a/core/peer/peer_test.go b/core/peer/peer_test.go index 8472abad0e6..65e3d33d458 100644 --- a/core/peer/peer_test.go +++ b/core/peer/peer_test.go @@ -173,8 +173,11 @@ func TestCreateChainFromBlock(t *testing.T) { t.Fatalf("failed to get correct ledger") } - // Config block from ledger + // Get config block from ledger block, err = getCurrConfigBlockFromLedger(ledger) + assert.NoError(t, err, "Failed to get config block from ledger") + assert.NotNil(t, block, "Config block should not be nil") + assert.Equal(t, uint64(0), block.Header.Number, "config block should have been block 0") // Bad ledger ledger = GetLedger("BogusChain")