Skip to content

Commit c8a9e48

Browse files
author
Jason Yellick
committed
FAB-16599 Wire externalbuilder MD provider
This CR takes the new externalbuilder MD provider and wires it through to the assorted places where the ledger needs to be provided with the chaincode metadata (such as couchdb indices). Signed-off-by: Jason Yellick <jyellick@us.ibm.com> Change-Id: I68ee5711ac22467a06a7f57e645ee2e074d67284
1 parent 0e1b6a6 commit c8a9e48

File tree

11 files changed

+123
-30
lines changed

11 files changed

+123
-30
lines changed

core/chaincode/lifecycle/cache.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
"github.com/hyperledger/fabric/common/chaincode"
1717
"github.com/hyperledger/fabric/common/util"
1818
"github.com/hyperledger/fabric/core/chaincode/persistence"
19+
"github.com/hyperledger/fabric/core/container/externalbuilders"
1920
"github.com/hyperledger/fabric/core/ledger"
2021
"github.com/hyperledger/fabric/protoutil"
2122

@@ -121,14 +122,14 @@ func (l *LocalChaincode) createMetadataMapFromReferences() map[string][]*chainco
121122
return references
122123
}
123124

124-
func NewCache(resources *Resources, myOrgMSPID string, metadataManager MetadataHandler, custodian *ChaincodeCustodian) *Cache {
125+
func NewCache(resources *Resources, myOrgMSPID string, metadataManager MetadataHandler, custodian *ChaincodeCustodian, ebMetadata *externalbuilders.MetadataProvider) *Cache {
125126
return &Cache{
126127
chaincodeCustodian: custodian,
127128
definedChaincodes: map[string]*ChannelCache{},
128129
localChaincodes: map[string]*LocalChaincode{},
129130
Resources: resources,
130131
MyOrgMSPID: myOrgMSPID,
131-
eventBroker: NewEventBroker(resources.ChaincodeStore, resources.PackageParser),
132+
eventBroker: NewEventBroker(resources.ChaincodeStore, resources.PackageParser, ebMetadata),
132133
MetadataHandler: metadataManager,
133134
}
134135
}

core/chaincode/lifecycle/cache_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"github.com/hyperledger/fabric/core/chaincode/lifecycle/mock"
2121
"github.com/hyperledger/fabric/core/chaincode/persistence"
2222
"github.com/hyperledger/fabric/core/container"
23+
"github.com/hyperledger/fabric/core/container/externalbuilders"
2324
"github.com/hyperledger/fabric/core/ledger"
2425
ledgermock "github.com/hyperledger/fabric/core/ledger/mock"
2526
"github.com/hyperledger/fabric/protoutil"
@@ -75,7 +76,7 @@ var _ = Describe("Cache", func() {
7576
chaincodeCustodian = lifecycle.NewChaincodeCustodian()
7677

7778
var err error
78-
c = lifecycle.NewCache(resources, "my-mspid", fakeMetadataHandler, chaincodeCustodian)
79+
c = lifecycle.NewCache(resources, "my-mspid", fakeMetadataHandler, chaincodeCustodian, &externalbuilders.MetadataProvider{})
7980
Expect(err).NotTo(HaveOccurred())
8081

8182
channelCache = &lifecycle.ChannelCache{

core/chaincode/lifecycle/event_broker.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,23 +8,26 @@ package lifecycle
88
import (
99
"sync"
1010

11+
"github.com/hyperledger/fabric/core/container/externalbuilders"
1112
"github.com/hyperledger/fabric/core/ledger"
1213
"github.com/pkg/errors"
1314
)
1415

1516
// EventBroker receives events from lifecycle cache and in turn invokes the registered listeners
1617
type EventBroker struct {
1718
chaincodeStore ChaincodeStore
19+
ebMetadata *externalbuilders.MetadataProvider
1820
pkgParser PackageParser
1921
defineCallbackStatus *sync.Map
2022

2123
mutex sync.Mutex
2224
listeners map[string][]ledger.ChaincodeLifecycleEventListener
2325
}
2426

25-
func NewEventBroker(chaincodeStore ChaincodeStore, pkgParser PackageParser) *EventBroker {
27+
func NewEventBroker(chaincodeStore ChaincodeStore, pkgParser PackageParser, ebMetadata *externalbuilders.MetadataProvider) *EventBroker {
2628
return &EventBroker{
2729
chaincodeStore: chaincodeStore,
30+
ebMetadata: ebMetadata,
2831
pkgParser: pkgParser,
2932
listeners: make(map[string][]ledger.ChaincodeLifecycleEventListener),
3033
defineCallbackStatus: &sync.Map{},
@@ -154,6 +157,15 @@ func (b *EventBroker) invokeDoneOnListeners(channelID string, succeeded bool) {
154157
}
155158

156159
func (b *EventBroker) loadDBArtifacts(packageID string) ([]byte, error) {
160+
md, err := b.ebMetadata.PackageMetadata(packageID)
161+
if err != nil {
162+
return nil, err
163+
}
164+
165+
if md != nil {
166+
return md, nil
167+
}
168+
157169
pkgBytes, err := b.chaincodeStore.Load(packageID)
158170
if err != nil {
159171
return nil, err

core/chaincode/lifecycle/event_broker_test.go

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ import (
1111
"github.com/hyperledger/fabric/core/chaincode/lifecycle"
1212
"github.com/hyperledger/fabric/core/chaincode/lifecycle/mock"
1313
"github.com/hyperledger/fabric/core/chaincode/persistence"
14+
"github.com/hyperledger/fabric/core/container/externalbuilders"
15+
"github.com/hyperledger/fabric/core/ledger"
1416
ledgermock "github.com/hyperledger/fabric/core/ledger/mock"
1517
. "github.com/onsi/ginkgo"
1618
. "github.com/onsi/gomega"
@@ -25,13 +27,17 @@ var _ = Describe("EventBroker", func() {
2527
eventBroker *lifecycle.EventBroker
2628
cachedChaincodeDef *lifecycle.CachedChaincodeDefinition
2729
localChaincode *lifecycle.LocalChaincode
30+
ebMetadata *externalbuilders.MetadataProvider
2831
)
2932

3033
BeforeEach(func() {
3134
fakeListener = &ledgermock.ChaincodeLifecycleEventListener{}
3235
chaincodeStore = &mock.ChaincodeStore{}
3336
pkgParser = &mock.PackageParser{}
34-
eventBroker = lifecycle.NewEventBroker(chaincodeStore, pkgParser)
37+
ebMetadata = &externalbuilders.MetadataProvider{
38+
DurablePath: "testdata",
39+
}
40+
eventBroker = lifecycle.NewEventBroker(chaincodeStore, pkgParser, ebMetadata)
3541
cachedChaincodeDef = &lifecycle.CachedChaincodeDefinition{}
3642
localChaincode = &lifecycle.LocalChaincode{
3743
Info: &lifecycle.ChaincodeInstallInfo{
@@ -141,6 +147,14 @@ var _ = Describe("EventBroker", func() {
141147
It("invokes listener", func() {
142148
eventBroker.ProcessInstallEvent(localChaincode)
143149
Expect(fakeListener.HandleChaincodeDeployCallCount()).To(Equal(1))
150+
def, md := fakeListener.HandleChaincodeDeployArgsForCall(0)
151+
Expect(def).To(Equal(&ledger.ChaincodeDefinition{
152+
Name: "chaincode-1",
153+
Hash: []byte("PackageID"),
154+
Version: "version-1",
155+
}))
156+
Expect(md).To(Equal([]byte("db-artifacts")))
157+
144158
Expect(fakeListener.ChaincodeDeployDoneCallCount()).To(Equal(1))
145159
})
146160

@@ -153,6 +167,24 @@ var _ = Describe("EventBroker", func() {
153167
Expect(fakeListener.ChaincodeDeployDoneCallCount()).To(Equal(1))
154168
})
155169

170+
When("the metadata is defined by the external builders", func() {
171+
BeforeEach(func() {
172+
localChaincode.Info.PackageID = "external-built-cc"
173+
})
174+
175+
It("does not invoke listener", func() {
176+
eventBroker.ProcessInstallEvent(localChaincode)
177+
Expect(fakeListener.HandleChaincodeDeployCallCount()).To(Equal(1))
178+
def, md := fakeListener.HandleChaincodeDeployArgsForCall(0)
179+
Expect(def).To(Equal(&ledger.ChaincodeDefinition{
180+
Name: "chaincode-1",
181+
Hash: []byte("external-built-cc"),
182+
Version: "version-1",
183+
}))
184+
Expect(len(md)).To(Equal(2560)) // A tar, and not our mock value
185+
})
186+
})
187+
156188
Context("when chaincode store returns error", func() {
157189
BeforeEach(func() {
158190
chaincodeStore.LoadReturns(nil, errors.New("loading-error"))
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

core/ledger/kvledger/tests/env.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
"github.com/hyperledger/fabric/common/ledger/util"
2020
"github.com/hyperledger/fabric/common/metrics/disabled"
2121
"github.com/hyperledger/fabric/core/common/privdata"
22+
"github.com/hyperledger/fabric/core/container/externalbuilders"
2223
"github.com/hyperledger/fabric/core/ledger"
2324
"github.com/hyperledger/fabric/core/ledger/kvledger"
2425
"github.com/hyperledger/fabric/core/ledger/ledgermgmt"
@@ -48,7 +49,12 @@ type env struct {
4849
func newEnv(t *testing.T) *env {
4950
cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
5051
assert.NoError(t, err)
51-
return newEnvWithInitializer(t, &ledgermgmt.Initializer{Hasher: cryptoProvider})
52+
return newEnvWithInitializer(t, &ledgermgmt.Initializer{
53+
Hasher: cryptoProvider,
54+
EbMetadataProvider: &externalbuilders.MetadataProvider{
55+
DurablePath: "testdata",
56+
},
57+
})
5258
}
5359

5460
func newEnvWithInitializer(t *testing.T, initializer *ledgermgmt.Initializer) *env {

core/ledger/ledgermgmt/ledger_mgmt.go

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,14 @@ var ErrLedgerMgmtNotInitialized = errors.New("ledger mgmt should be initialized
3131

3232
// LedgerMgr manages ledgers for all channels
3333
type LedgerMgr struct {
34-
lock sync.Mutex
35-
openedLedgers map[string]ledger.PeerLedger
36-
ledgerProvider ledger.PeerLedgerProvider
34+
lock sync.Mutex
35+
openedLedgers map[string]ledger.PeerLedger
36+
ledgerProvider ledger.PeerLedgerProvider
37+
ebMetadataProvider MetadataProvider
38+
}
39+
40+
type MetadataProvider interface {
41+
PackageMetadata(ccid string) ([]byte, error)
3742
}
3843

3944
// Initializer encapsulates all the external dependencies for the ledger module
@@ -47,6 +52,7 @@ type Initializer struct {
4752
HealthCheckRegistry ledger.HealthCheckRegistry
4853
Config *ledger.Config
4954
Hasher ledger.Hasher
55+
EbMetadataProvider MetadataProvider
5056
}
5157

5258
// NewLedgerMgr creates a new LedgerMgr
@@ -73,8 +79,9 @@ func NewLedgerMgr(initializer *Initializer) *LedgerMgr {
7379
panic(fmt.Sprintf("Error in instantiating ledger provider: %s", err))
7480
}
7581
ledgerMgr := &LedgerMgr{
76-
openedLedgers: make(map[string]ledger.PeerLedger),
77-
ledgerProvider: provider,
82+
openedLedgers: make(map[string]ledger.PeerLedger),
83+
ledgerProvider: provider,
84+
ebMetadataProvider: initializer.EbMetadataProvider,
7885
}
7986
// TODO remove the following package level init
8087
cceventmgmt.Initialize(&chaincodeInfoProviderImpl{
@@ -219,5 +226,13 @@ func (p *chaincodeInfoProviderImpl) GetDeployedChaincodeInfo(chainid string,
219226

220227
// RetrieveChaincodeArtifacts implements function in the interface cceventmgmt.ChaincodeInfoProvider
221228
func (p *chaincodeInfoProviderImpl) RetrieveChaincodeArtifacts(chaincodeDefinition *cceventmgmt.ChaincodeDefinition) (installed bool, dbArtifactsTar []byte, err error) {
222-
return ccprovider.ExtractStatedbArtifactsForChaincode(chaincodeDefinition.Name + ":" + chaincodeDefinition.Version)
229+
ccid := chaincodeDefinition.Name + ":" + chaincodeDefinition.Version
230+
md, err := p.ledgerMgr.ebMetadataProvider.PackageMetadata(ccid)
231+
if err != nil {
232+
return false, nil, err
233+
}
234+
if md != nil {
235+
return true, md, nil
236+
}
237+
return ccprovider.ExtractStatedbArtifactsForChaincode(ccid)
223238
}

core/scc/lscc/lscc.go

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
"github.com/hyperledger/fabric/core/common/privdata"
2929
"github.com/hyperledger/fabric/core/common/sysccprovider"
3030
"github.com/hyperledger/fabric/core/container"
31+
"github.com/hyperledger/fabric/core/container/externalbuilders"
3132
"github.com/hyperledger/fabric/core/ledger"
3233
"github.com/hyperledger/fabric/core/ledger/cceventmgmt"
3334
"github.com/hyperledger/fabric/core/peer"
@@ -161,6 +162,8 @@ type SCC struct {
161162

162163
ChaincodeBuilder ChaincodeBuilder
163164

165+
EbMetadataProvider *externalbuilders.MetadataProvider
166+
164167
// BCCSP instance
165168
BCCSP bccsp.BCCSP
166169
}
@@ -694,13 +697,20 @@ func (lscc *SCC) executeInstall(stub shim.ChaincodeStubInterface, ccbytes []byte
694697
return errors.WithMessage(err, "could not build chaincode")
695698
}
696699

697-
// Get any statedb artifacts from the chaincode package, e.g. couchdb index definitions
698-
statedbArtifactsTar, err := ccprovider.ExtractStatedbArtifactsFromCCPackage(ccpack)
700+
md, err := lscc.EbMetadataProvider.PackageMetadata(ccid)
699701
if err != nil {
700-
return err
702+
return errors.WithMessage(err, "external builder release metadata found, but could not be packaged")
703+
}
704+
705+
if md == nil {
706+
// Get any statedb artifacts from the chaincode package, e.g. couchdb index definitions
707+
md, err = ccprovider.ExtractStatedbArtifactsFromCCPackage(ccpack)
708+
if err != nil {
709+
return err
710+
}
701711
}
702712

703-
if err = isValidStatedbArtifactsTar(statedbArtifactsTar); err != nil {
713+
if err = isValidStatedbArtifactsTar(md); err != nil {
704714
return InvalidStatedbArtifactsErr(err.Error())
705715
}
706716

@@ -713,7 +723,7 @@ func (lscc *SCC) executeInstall(stub shim.ChaincodeStubInterface, ccbytes []byte
713723
// any channel's statedb where the chaincode is already instantiated
714724
// Note - this step is done prior to PutChaincodeToLocalStorage() since this step is idempotent and harmless until endorsements start,
715725
// that is, if there are errors deploying the indexes the chaincode install can safely be re-attempted later.
716-
err = cceventmgmt.GetMgr().HandleChaincodeInstall(chaincodeDefinition, statedbArtifactsTar)
726+
err = cceventmgmt.GetMgr().HandleChaincodeInstall(chaincodeDefinition, md)
717727
defer func() {
718728
cceventmgmt.GetMgr().ChaincodeInstallDone(err == nil)
719729
}()

core/scc/lscc/lscc_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import (
3535
"github.com/hyperledger/fabric/core/chaincode/lifecycle"
3636
"github.com/hyperledger/fabric/core/common/ccprovider"
3737
"github.com/hyperledger/fabric/core/container"
38+
"github.com/hyperledger/fabric/core/container/externalbuilders"
3839
"github.com/hyperledger/fabric/core/ledger/ledgermgmt"
3940
"github.com/hyperledger/fabric/core/ledger/ledgermgmt/ledgermgmttest"
4041
"github.com/hyperledger/fabric/core/policy"
@@ -164,6 +165,9 @@ func TestInstall(t *testing.T) {
164165
BCCSP: cryptoProvider,
165166
BuildRegistry: &container.BuildRegistry{},
166167
ChaincodeBuilder: chaincodeBuilder,
168+
EbMetadataProvider: &externalbuilders.MetadataProvider{
169+
DurablePath: "testdata",
170+
},
167171
}
168172
stub := shimtest.NewMockStub("lscc", scc)
169173
res := stub.MockInit("1", nil)
@@ -196,6 +200,10 @@ func TestInstall(t *testing.T) {
196200
testInstall(t, "example02-different", "0", path, false, "could not build chaincode: fake-build-error", "Alice", scc, stub, nil)
197201
chaincodeBuilder.BuildReturns(nil)
198202

203+
// This is a bad test, but it does at least exercise the external builder md path
204+
// The integration tests will ultimately ensure that it actually works.
205+
testInstall(t, "external-built", "cc", path, false, "", "Alice", scc, stub, nil)
206+
199207
testInstall(t, "example02-2", "1.0", path, false, "", "Alice", scc, stub, nil)
200208
testInstall(t, "example02.go", "0", path, false, InvalidChaincodeNameErr("example02.go").Error(), "Alice", scc, stub, nil)
201209
testInstall(t, "", "0", path, false, InvalidChaincodeNameErr("").Error(), "Alice", scc, stub, nil)
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

0 commit comments

Comments
 (0)