Commit 3d3b4a77 authored by manish's avatar manish Committed by Gari Singh
Browse files

Ledger-lscc: Interface for decoupling ledger and lscc



This CR
- Introduces an interface 'DeployedChaincodeInfoProvider'
for decoupling the ledger code from chaincode lifecycle code

- Declares ledger's dependency on this interface explicitly.
The intent is that ledger code will use this dependency for
listening to chaincode lifecycle events and for querying
the information about the deployed chaicodes

- Introduces a convenient function in legder that other modules
can use directly to get information about the chaincodes

FAB-11562 #done

Change-Id: I3eb0e798f00ceb18203128fd9da93822fc2bca2b
Signed-off-by: default avatarmanish <manish.sethi@gmail.com>
parent 080f1aff
......@@ -23,6 +23,21 @@ type TxSimulator struct {
result1 []byte
result2 error
}
GetStateRangeScanIteratorStub func(namespace string, startKey string, endKey string) (commonledger.ResultsIterator, error)
getStateRangeScanIteratorMutex sync.RWMutex
getStateRangeScanIteratorArgsForCall []struct {
namespace string
startKey string
endKey string
}
getStateRangeScanIteratorReturns struct {
result1 commonledger.ResultsIterator
result2 error
}
getStateRangeScanIteratorReturnsOnCall map[int]struct {
result1 commonledger.ResultsIterator
result2 error
}
GetStateMetadataStub func(namespace, key string) (map[string][]byte, error)
getStateMetadataMutex sync.RWMutex
getStateMetadataArgsForCall []struct {
......@@ -51,21 +66,6 @@ type TxSimulator struct {
result1 [][]byte
result2 error
}
GetStateRangeScanIteratorStub func(namespace string, startKey string, endKey string) (commonledger.ResultsIterator, error)
getStateRangeScanIteratorMutex sync.RWMutex
getStateRangeScanIteratorArgsForCall []struct {
namespace string
startKey string
endKey string
}
getStateRangeScanIteratorReturns struct {
result1 commonledger.ResultsIterator
result2 error
}
getStateRangeScanIteratorReturnsOnCall map[int]struct {
result1 commonledger.ResultsIterator
result2 error
}
ExecuteQueryStub func(namespace, query string) (commonledger.ResultsIterator, error)
executeQueryMutex sync.RWMutex
executeQueryArgsForCall []struct {
......@@ -366,6 +366,59 @@ func (fake *TxSimulator) GetStateReturnsOnCall(i int, result1 []byte, result2 er
}{result1, result2}
}
func (fake *TxSimulator) GetStateRangeScanIterator(namespace string, startKey string, endKey string) (commonledger.ResultsIterator, error) {
fake.getStateRangeScanIteratorMutex.Lock()
ret, specificReturn := fake.getStateRangeScanIteratorReturnsOnCall[len(fake.getStateRangeScanIteratorArgsForCall)]
fake.getStateRangeScanIteratorArgsForCall = append(fake.getStateRangeScanIteratorArgsForCall, struct {
namespace string
startKey string
endKey string
}{namespace, startKey, endKey})
fake.recordInvocation("GetStateRangeScanIterator", []interface{}{namespace, startKey, endKey})
fake.getStateRangeScanIteratorMutex.Unlock()
if fake.GetStateRangeScanIteratorStub != nil {
return fake.GetStateRangeScanIteratorStub(namespace, startKey, endKey)
}
if specificReturn {
return ret.result1, ret.result2
}
return fake.getStateRangeScanIteratorReturns.result1, fake.getStateRangeScanIteratorReturns.result2
}
func (fake *TxSimulator) GetStateRangeScanIteratorCallCount() int {
fake.getStateRangeScanIteratorMutex.RLock()
defer fake.getStateRangeScanIteratorMutex.RUnlock()
return len(fake.getStateRangeScanIteratorArgsForCall)
}
func (fake *TxSimulator) GetStateRangeScanIteratorArgsForCall(i int) (string, string, string) {
fake.getStateRangeScanIteratorMutex.RLock()
defer fake.getStateRangeScanIteratorMutex.RUnlock()
return fake.getStateRangeScanIteratorArgsForCall[i].namespace, fake.getStateRangeScanIteratorArgsForCall[i].startKey, fake.getStateRangeScanIteratorArgsForCall[i].endKey
}
func (fake *TxSimulator) GetStateRangeScanIteratorReturns(result1 commonledger.ResultsIterator, result2 error) {
fake.GetStateRangeScanIteratorStub = nil
fake.getStateRangeScanIteratorReturns = struct {
result1 commonledger.ResultsIterator
result2 error
}{result1, result2}
}
func (fake *TxSimulator) GetStateRangeScanIteratorReturnsOnCall(i int, result1 commonledger.ResultsIterator, result2 error) {
fake.GetStateRangeScanIteratorStub = nil
if fake.getStateRangeScanIteratorReturnsOnCall == nil {
fake.getStateRangeScanIteratorReturnsOnCall = make(map[int]struct {
result1 commonledger.ResultsIterator
result2 error
})
}
fake.getStateRangeScanIteratorReturnsOnCall[i] = struct {
result1 commonledger.ResultsIterator
result2 error
}{result1, result2}
}
func (fake *TxSimulator) GetStateMetadata(namespace string, key string) (map[string][]byte, error) {
fake.getStateMetadataMutex.Lock()
ret, specificReturn := fake.getStateMetadataReturnsOnCall[len(fake.getStateMetadataArgsForCall)]
......@@ -475,59 +528,6 @@ func (fake *TxSimulator) GetStateMultipleKeysReturnsOnCall(i int, result1 [][]by
}{result1, result2}
}
func (fake *TxSimulator) GetStateRangeScanIterator(namespace string, startKey string, endKey string) (commonledger.ResultsIterator, error) {
fake.getStateRangeScanIteratorMutex.Lock()
ret, specificReturn := fake.getStateRangeScanIteratorReturnsOnCall[len(fake.getStateRangeScanIteratorArgsForCall)]
fake.getStateRangeScanIteratorArgsForCall = append(fake.getStateRangeScanIteratorArgsForCall, struct {
namespace string
startKey string
endKey string
}{namespace, startKey, endKey})
fake.recordInvocation("GetStateRangeScanIterator", []interface{}{namespace, startKey, endKey})
fake.getStateRangeScanIteratorMutex.Unlock()
if fake.GetStateRangeScanIteratorStub != nil {
return fake.GetStateRangeScanIteratorStub(namespace, startKey, endKey)
}
if specificReturn {
return ret.result1, ret.result2
}
return fake.getStateRangeScanIteratorReturns.result1, fake.getStateRangeScanIteratorReturns.result2
}
func (fake *TxSimulator) GetStateRangeScanIteratorCallCount() int {
fake.getStateRangeScanIteratorMutex.RLock()
defer fake.getStateRangeScanIteratorMutex.RUnlock()
return len(fake.getStateRangeScanIteratorArgsForCall)
}
func (fake *TxSimulator) GetStateRangeScanIteratorArgsForCall(i int) (string, string, string) {
fake.getStateRangeScanIteratorMutex.RLock()
defer fake.getStateRangeScanIteratorMutex.RUnlock()
return fake.getStateRangeScanIteratorArgsForCall[i].namespace, fake.getStateRangeScanIteratorArgsForCall[i].startKey, fake.getStateRangeScanIteratorArgsForCall[i].endKey
}
func (fake *TxSimulator) GetStateRangeScanIteratorReturns(result1 commonledger.ResultsIterator, result2 error) {
fake.GetStateRangeScanIteratorStub = nil
fake.getStateRangeScanIteratorReturns = struct {
result1 commonledger.ResultsIterator
result2 error
}{result1, result2}
}
func (fake *TxSimulator) GetStateRangeScanIteratorReturnsOnCall(i int, result1 commonledger.ResultsIterator, result2 error) {
fake.GetStateRangeScanIteratorStub = nil
if fake.getStateRangeScanIteratorReturnsOnCall == nil {
fake.getStateRangeScanIteratorReturnsOnCall = make(map[int]struct {
result1 commonledger.ResultsIterator
result2 error
})
}
fake.getStateRangeScanIteratorReturnsOnCall[i] = struct {
result1 commonledger.ResultsIterator
result2 error
}{result1, result2}
}
func (fake *TxSimulator) ExecuteQuery(namespace string, query string) (commonledger.ResultsIterator, error) {
fake.executeQueryMutex.Lock()
ret, specificReturn := fake.executeQueryReturnsOnCall[len(fake.executeQueryArgsForCall)]
......@@ -1472,12 +1472,12 @@ func (fake *TxSimulator) Invocations() map[string][][]interface{} {
defer fake.invocationsMutex.RUnlock()
fake.getStateMutex.RLock()
defer fake.getStateMutex.RUnlock()
fake.getStateRangeScanIteratorMutex.RLock()
defer fake.getStateRangeScanIteratorMutex.RUnlock()
fake.getStateMetadataMutex.RLock()
defer fake.getStateMetadataMutex.RUnlock()
fake.getStateMultipleKeysMutex.RLock()
defer fake.getStateMultipleKeysMutex.RUnlock()
fake.getStateRangeScanIteratorMutex.RLock()
defer fake.getStateRangeScanIteratorMutex.RUnlock()
fake.executeQueryMutex.RLock()
defer fake.executeQueryMutex.RUnlock()
fake.getPrivateDataMutex.RLock()
......
......@@ -43,7 +43,7 @@ func (ctp *customTxProcessor) GenerateSimulationResults(txEnvelop *common.Envelo
func TestCustomProcessor(t *testing.T) {
env := newTestEnv(t)
defer env.cleanup()
provider, _ := NewProvider()
provider := testutilNewProvider(t)
defer provider.Close()
// create a custom tx processor and register it to handle '100 and 101' type of transaction
......
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package kvledger
import (
"github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/protos/common"
)
type deployedCCInfoRetriever struct {
ledger ledger.PeerLedger
infoProvider ledger.DeployedChaincodeInfoProvider
}
func (r *deployedCCInfoRetriever) ChaincodeInfo(chaincodeName string) (*ledger.DeployedChaincodeInfo, error) {
qe, err := r.ledger.NewQueryExecutor()
if err != nil {
return nil, err
}
defer qe.Done()
return r.infoProvider.ChaincodeInfo(chaincodeName, qe)
}
func (r *deployedCCInfoRetriever) CollectionInfo(chaincodeName, collectionName string) (*common.StaticCollectionConfig, error) {
qe, err := r.ledger.NewQueryExecutor()
if err != nil {
return nil, err
}
defer qe.Done()
return r.infoProvider.CollectionInfo(chaincodeName, collectionName, qe)
}
......@@ -55,7 +55,9 @@ func init() {
// Note, if subledgers are supported in the future,
// the various ledgers could be created/managed at this level
cleanup()
ledgermgmt.Initialize(nil, platforms.NewRegistry(&golang.Platform{}))
ledgermgmt.Initialize(&ledgermgmt.Initializer{
PlatformRegistry: platforms.NewRegistry(&golang.Platform{}),
})
var err error
gb, _ := configtxtest.MakeGenesisBlock(ledgerID)
......
......@@ -50,7 +50,8 @@ func newKVLedger(
historyDB historydb.HistoryDB,
configHistoryMgr confighistory.Mgr,
stateListeners []ledger.StateListener,
bookkeeperProvider bookkeeping.Provider) (*kvLedger, error) {
bookkeeperProvider bookkeeping.Provider,
ccInfoProvider ledger.DeployedChaincodeInfoProvider) (*kvLedger, error) {
logger.Debugf("Creating KVLedger ledgerID=%s: ", ledgerID)
stateListeners = append(stateListeners, configHistoryMgr)
......
......@@ -10,11 +10,10 @@ import (
"bytes"
"fmt"
"github.com/hyperledger/fabric/core/ledger/confighistory"
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/common/ledger/util/leveldbhelper"
"github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/core/ledger/confighistory"
"github.com/hyperledger/fabric/core/ledger/kvledger/bookkeeping"
"github.com/hyperledger/fabric/core/ledger/kvledger/history/historydb"
"github.com/hyperledger/fabric/core/ledger/kvledger/history/historydb/historyleveldb"
......@@ -48,39 +47,36 @@ type Provider struct {
configHistoryMgr confighistory.Mgr
stateListeners []ledger.StateListener
bookkeepingProvider bookkeeping.Provider
initializer *ledger.Initializer
}
// NewProvider instantiates a new Provider.
// This is not thread-safe and assumed to be synchronized be the caller
func NewProvider() (ledger.PeerLedgerProvider, error) {
logger.Info("Initializing ledger provider")
// Initialize the ID store (inventory of chainIds/ledgerIds)
idStore := openIDStore(ledgerconfig.GetLedgerProviderPath())
ledgerStoreProvider := ledgerstorage.NewProvider()
// Initialize the versioned database (state database)
vdbProvider, err := privacyenabledstate.NewCommonStorageDBProvider()
if err != nil {
return nil, err
}
// Initialize the history database (index for history of values by key)
historydbProvider := historyleveldb.NewHistoryDBProvider()
bookkeepingProvider := bookkeeping.NewProvider()
// Initialize config history mgr
configHistoryMgr := confighistory.NewMgr()
logger.Info("ledger provider Initialized")
provider := &Provider{idStore, ledgerStoreProvider, vdbProvider, historydbProvider, configHistoryMgr, nil, bookkeepingProvider}
provider.recoverUnderConstructionLedger()
provider := &Provider{idStore, ledgerStoreProvider,
vdbProvider, historydbProvider, nil, nil, bookkeepingProvider, nil}
return provider, nil
}
// Initialize implements the corresponding method from interface ledger.PeerLedgerProvider
func (provider *Provider) Initialize(stateListeners []ledger.StateListener) {
provider.stateListeners = stateListeners
func (provider *Provider) Initialize(initializer *ledger.Initializer) {
provider.initializer = initializer
provider.configHistoryMgr = confighistory.NewMgr()
provider.stateListeners = initializer.StateListeners
provider.recoverUnderConstructionLedger()
}
// Create implements the corresponding method from interface ledger.PeerLedgerProvider
......@@ -155,7 +151,8 @@ func (provider *Provider) openInternal(ledgerID string) (ledger.PeerLedger, erro
// Create a kvLedger for this chain/ledger, which encasulates the underlying data stores
// (id store, blockstore, state database, history database)
l, err := newKVLedger(ledgerID, blockStore, vDB, historyDB, provider.configHistoryMgr, provider.stateListeners, provider.bookkeepingProvider)
l, err := newKVLedger(ledgerID, blockStore, vDB, historyDB, provider.configHistoryMgr,
provider.stateListeners, provider.bookkeepingProvider, provider.initializer.DeployedChaincodeInfoProvider)
if err != nil {
return nil, err
}
......
......@@ -27,8 +27,9 @@ import (
"github.com/hyperledger/fabric/common/ledger/blkstorage/fsblkstorage"
"github.com/hyperledger/fabric/common/ledger/testutil"
"github.com/hyperledger/fabric/common/util"
ledgerproto "github.com/hyperledger/fabric/core/ledger"
lgr "github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/core/ledger/ledgerconfig"
"github.com/hyperledger/fabric/core/ledger/mock"
"github.com/hyperledger/fabric/protos/common"
"github.com/hyperledger/fabric/protos/ledger/queryresult"
putils "github.com/hyperledger/fabric/protos/utils"
......@@ -39,7 +40,7 @@ func TestLedgerProvider(t *testing.T) {
env := newTestEnv(t)
defer env.cleanup()
numLedgers := 10
provider, _ := NewProvider()
provider := testutilNewProvider(t)
existingLedgerIDs, err := provider.List()
testutil.AssertNoError(t, err, "")
testutil.AssertEquals(t, len(existingLedgerIDs), 0)
......@@ -55,7 +56,7 @@ func TestLedgerProvider(t *testing.T) {
provider.Close()
provider, _ = NewProvider()
provider = testutilNewProvider(t)
defer provider.Close()
ledgerIds, _ := provider.List()
testutil.AssertEquals(t, len(ledgerIds), numLedgers)
......@@ -97,12 +98,12 @@ func TestLedgerProvider(t *testing.T) {
func TestRecovery(t *testing.T) {
env := newTestEnv(t)
defer env.cleanup()
provider, _ := NewProvider()
provider := testutilNewProvider(t)
// now create the genesis block
genesisBlock, _ := configtxtest.MakeGenesisBlock(constructTestLedgerID(1))
ledger, err := provider.(*Provider).openInternal(constructTestLedgerID(1))
ledger.CommitWithPvtData(&ledgerproto.BlockAndPvtData{Block: genesisBlock})
ledger.CommitWithPvtData(&lgr.BlockAndPvtData{Block: genesisBlock})
ledger.Close()
// Case 1: assume a crash happens, force underconstruction flag to be set to simulate
......@@ -111,8 +112,7 @@ func TestRecovery(t *testing.T) {
provider.Close()
// construct a new provider to invoke recovery
provider, err = NewProvider()
testutil.AssertNoError(t, err, "Provider failed to recover an underConstructionLedger")
provider = testutilNewProvider(t)
// verify the underecoveryflag and open the ledger
flag, err := provider.(*Provider).idStore.getUnderConstructionFlag()
testutil.AssertNoError(t, err, "Failed to read the underconstruction flag")
......@@ -127,7 +127,7 @@ func TestRecovery(t *testing.T) {
provider.Close()
// construct a new provider to invoke recovery
provider, err = NewProvider()
provider = testutilNewProvider(t)
testutil.AssertNoError(t, err, "Provider failed to recover an underConstructionLedger")
flag, err = provider.(*Provider).idStore.getUnderConstructionFlag()
testutil.AssertNoError(t, err, "Failed to read the underconstruction flag")
......@@ -139,8 +139,8 @@ func TestMultipleLedgerBasicRW(t *testing.T) {
env := newTestEnv(t)
defer env.cleanup()
numLedgers := 10
provider, _ := NewProvider()
ledgers := make([]ledgerproto.PeerLedger, numLedgers)
provider := testutilNewProvider(t)
ledgers := make([]lgr.PeerLedger, numLedgers)
for i := 0; i < numLedgers; i++ {
bg, gb := testutil.NewBlockGenerator(t, constructTestLedgerID(i), false)
l, err := provider.Create(gb)
......@@ -155,16 +155,16 @@ func TestMultipleLedgerBasicRW(t *testing.T) {
testutil.AssertNoError(t, err, "")
pubSimBytes, _ := res.GetPubSimulationBytes()
b := bg.NextBlock([][]byte{pubSimBytes})
err = l.CommitWithPvtData(&ledgerproto.BlockAndPvtData{Block: b})
err = l.CommitWithPvtData(&lgr.BlockAndPvtData{Block: b})
l.Close()
testutil.AssertNoError(t, err, "")
}
provider.Close()
provider, _ = NewProvider()
provider = testutilNewProvider(t)
defer provider.Close()
ledgers = make([]ledgerproto.PeerLedger, numLedgers)
ledgers = make([]lgr.PeerLedger, numLedgers)
for i := 0; i < numLedgers; i++ {
l, err := provider.Open(constructTestLedgerID(i))
testutil.AssertNoError(t, err, "")
......@@ -189,7 +189,7 @@ func TestLedgerBackup(t *testing.T) {
// create and populate a ledger in the original environment
env := createTestEnv(t, originalPath)
provider, _ := NewProvider()
provider := testutilNewProvider(t)
bg, gb := testutil.NewBlockGenerator(t, ledgerid, false)
gbHash := gb.Header.Hash()
ledger, _ := provider.Create(gb)
......@@ -203,7 +203,7 @@ func TestLedgerBackup(t *testing.T) {
simRes, _ := simulator.GetTxSimulationResults()
pubSimBytes, _ := simRes.GetPubSimulationBytes()
block1 := bg.NextBlock([][]byte{pubSimBytes})
ledger.CommitWithPvtData(&ledgerproto.BlockAndPvtData{Block: block1})
ledger.CommitWithPvtData(&lgr.BlockAndPvtData{Block: block1})
txid = util.GenerateUUID()
simulator, _ = ledger.NewTxSimulator(txid)
......@@ -214,7 +214,7 @@ func TestLedgerBackup(t *testing.T) {
simRes, _ = simulator.GetTxSimulationResults()
pubSimBytes, _ = simRes.GetPubSimulationBytes()
block2 := bg.NextBlock([][]byte{pubSimBytes})
ledger.CommitWithPvtData(&ledgerproto.BlockAndPvtData{Block: block2})
ledger.CommitWithPvtData(&lgr.BlockAndPvtData{Block: block2})
ledger.Close()
provider.Close()
......@@ -231,7 +231,7 @@ func TestLedgerBackup(t *testing.T) {
defer env.cleanup()
// Instantiate the ledger from restore environment and this should behave exactly as it would have in the original environment
provider, _ = NewProvider()
provider = testutilNewProvider(t)
defer provider.Close()
_, err := provider.Create(gb)
......@@ -300,3 +300,12 @@ func TestLedgerBackup(t *testing.T) {
func constructTestLedgerID(i int) string {
return fmt.Sprintf("ledger_%06d", i)
}
func testutilNewProvider(t *testing.T) lgr.PeerLedgerProvider {
provider, err := NewProvider()
testutil.AssertNoError(t, err, "")
provider.Initialize(&lgr.Initializer{
DeployedChaincodeInfoProvider: &mock.DeployedChaincodeInfoProvider{},
})
return provider
}
......@@ -41,7 +41,7 @@ func TestMain(m *testing.M) {
func TestKVLedgerBlockStorage(t *testing.T) {
env := newTestEnv(t)
defer env.cleanup()
provider, _ := NewProvider()
provider := testutilNewProvider(t)
defer provider.Close()
bg, gb := testutil.NewBlockGenerator(t, "testLedger", false)
......@@ -124,7 +124,7 @@ func TestKVLedgerBlockStorageWithPvtdata(t *testing.T) {
t.Skip()
env := newTestEnv(t)
defer env.cleanup()
provider, _ := NewProvider()
provider := testutilNewProvider(t)
defer provider.Close()
bg, gb := testutil.NewBlockGenerator(t, "testLedger", false)
......@@ -185,7 +185,7 @@ func TestKVLedgerBlockStorageWithPvtdata(t *testing.T) {
func TestKVLedgerDBRecovery(t *testing.T) {
env := newTestEnv(t)
defer env.cleanup()
provider, _ := NewProvider()
provider := testutilNewProvider(t)
defer provider.Close()
testLedgerid := "testLedger"
bg, gb := testutil.NewBlockGenerator(t, testLedgerid, false)
......@@ -257,7 +257,7 @@ func TestKVLedgerDBRecovery(t *testing.T) {
// Here the peer comes online and calls NewKVLedger to get a handler for the ledger
// StateDB and HistoryDB should be recovered before returning from NewKVLedger call
provider, _ = NewProvider()
provider = testutilNewProvider(t)
ledger, _ = provider.Open(testLedgerid)
checkBCSummaryForTest(t, ledger,
&bcSummary{
......@@ -305,7 +305,7 @@ func TestKVLedgerDBRecovery(t *testing.T) {
// we assume here that the peer comes online and calls NewKVLedger to get a handler for the ledger
// history DB should be recovered before returning from NewKVLedger call
provider, _ = NewProvider()
provider = testutilNewProvider(t)
ledger, _ = provider.Open(testLedgerid)
checkBCSummaryForTest(t, ledger,
......@@ -354,7 +354,7 @@ func TestKVLedgerDBRecovery(t *testing.T) {
// we assume here that the peer comes online and calls NewKVLedger to get a handler for the ledger
// state DB should be recovered before returning from NewKVLedger call
provider, _ = NewProvider()
provider = testutilNewProvider(t)
ledger, _ = provider.Open(testLedgerid)
checkBCSummaryForTest(t, ledger,
&bcSummary{
......@@ -379,7 +379,7 @@ func TestLedgerWithCouchDbEnabledWithBinaryAndJSONData(t *testing.T) {
env := newTestEnv(t)
defer env.cleanup()
provider, _ := NewProvider()
provider := testutilNewProvider(t)
defer provider.Close()
bg, gb := testutil.NewBlockGenerator(t, "testLedger", false)
gbHash := gb.Header.Hash()
......
......@@ -18,7 +18,6 @@ package main
import (
"fmt"
"os"
configtxtest "github.com/hyperledger/fabric/common/configtx/test"
......@@ -56,7 +55,9 @@ func init() {
testutil.SetupCoreYAMLConfig()
cleanup()
ledgermgmt.Initialize(nil, platforms.NewRegistry(&golang.Platform{}))
ledgermgmt.Initialize(&ledgermgmt.Initializer{
PlatformRegistry: platforms.NewRegistry(&golang.Platform{}),
})
var err error
gb, _ := configtxtest.MakeGenesisBlock(ledgerID)
peerLedger, err = ledgermgmt.CreateLedger(gb)
......
......@@ -9,10 +9,10 @@ package kvledger
import (
"testing"
"github.com/hyperledger/fabric/protos/ledger/rwset/kvrwset"
"github.com/hyperledger/fabric/common/ledger/testutil"
"github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/core/ledger/mock"
"github.com/hyperledger/fabric/protos/ledger/rwset/kvrwset"
"github.com/stretchr/testify/assert"
)
......@@ -26,7 +26,10 @@ func TestStateListener(t *testing.T) {
channelid := "testLedger"
namespace := "testchaincode"
mockListener := &mockStateListener{namespace: namespace}
provider.Initialize([]ledger.StateListener{mockListener})
provider.Initialize(&ledger.Initializer{
DeployedChaincodeInfoProvider: &mock.DeployedChaincodeInfoProvider{},
StateListeners: []ledger.StateListener{mockListener},
})
bg, gb := testutil.NewBlockGenerator(t, channelid, false)
lgr, err := provider.Create(gb)
......
......@@ -11,12 +11,19 @@ import (
commonledger "github.com/hyperledger/fabric/common/ledger"
"github.com/hyperledger/fabric/protos/common"
"github.com/hyperledger/fabric/protos/ledger/rwset"
"github.com/hyperledger/fabric/protos/ledger/rwset/kvrwset"
"github.com/hyperledger/fabric/protos/peer"
)
// Initializer encapsulates dependencies for PeerLedgerProvider
type Initializer struct {
StateListeners []StateListener
DeployedChaincodeInfoProvider DeployedChaincodeInfoProvider
}
// PeerLedgerProvider provides handle to ledger instances
type PeerLedgerProvider interface {
Initialize(statelisteners []StateListener)
Initialize(initializer *Initializer)
// Create creates a new ledger with the given genesis block.
// This function guarantees that the creation of ledger and committing the genesis block would an atomic action
// The chain id retrieved from the genesis block is treated as a ledger id
......@@ -373,3 +380,38 @@ type PvtdataHashMismatch struct {
ChaincodeName, CollectionName string
ExpectedHash []byte
}
// DeployedChaincodeInfoProvider is a dependency that is used by ledger to build collection config history
// LSCC module is expected to provide an implementation fo this dependencys
type DeployedChaincodeInfoProvider interface {
Namespaces() []string
UpdatedChaincodes(stateUpdates map[string][]*kvrwset.KVWrite) ([]*ChaincodeLifecycleInfo, error)
ChaincodeInfo(chaincodeName string, qe SimpleQueryExecutor) (*DeployedChaincodeInfo, error)
CollectionInfo(chaincodeName, collectionName string, qe SimpleQueryExecutor) (*common.StaticCollectionConfig, error)
}