Skip to content

Commit 5a76aba

Browse files
committed
Add references map to QueryInstalledChaincode result
FAB-15705 #done Change-Id: I6deef5505ef121604cc92fbe1a86c9b1a76e7e0d Signed-off-by: Alessandro Sorniotti <ale.linux@sopit.net> Signed-off-by: Will Lahti <wtlahti@us.ibm.com>
1 parent d01aaf5 commit 5a76aba

File tree

9 files changed

+448
-109
lines changed

9 files changed

+448
-109
lines changed

core/chaincode/lifecycle/cache.go

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,36 @@ type LocalChaincode struct {
9090
References map[string]map[string]*CachedChaincodeDefinition
9191
}
9292

93+
// ToInstalledChaincode converts a LocalChaincode to an InstalledChaincode,
94+
// which is returned by lifecycle queries.
95+
func (l *LocalChaincode) ToInstalledChaincode() *chaincode.InstalledChaincode {
96+
references := l.createMetadataMapFromReferences()
97+
return &chaincode.InstalledChaincode{
98+
PackageID: l.Info.PackageID,
99+
Label: l.Info.Label,
100+
References: references,
101+
}
102+
}
103+
104+
// createMetadataMapFromReferences returns a map of channel name to a slice
105+
// of chaincode metadata for the chaincode definitions that reference a
106+
// specific local chaincode. This function should only be called by code that
107+
// holds the lock on the cache.
108+
func (l *LocalChaincode) createMetadataMapFromReferences() map[string][]*chaincode.Metadata {
109+
references := map[string][]*chaincode.Metadata{}
110+
for channel, chaincodeMap := range l.References {
111+
metadata := []*chaincode.Metadata{}
112+
for cc, cachedDefinition := range chaincodeMap {
113+
metadata = append(metadata, &chaincode.Metadata{
114+
Name: cc,
115+
Version: cachedDefinition.Definition.EndorsementInfo.Version,
116+
})
117+
}
118+
references[channel] = metadata
119+
}
120+
return references
121+
}
122+
93123
func NewCache(resources *Resources, myOrgMSPID string, metadataManager MetadataHandler) *Cache {
94124
return &Cache{
95125
definedChaincodes: map[string]*ChannelCache{},
@@ -327,27 +357,32 @@ func (c *Cache) ListInstalledChaincodes() []*chaincode.InstalledChaincode {
327357
// even if it isn't yet installed
328358
continue
329359
}
330-
references := map[string][]*chaincode.Metadata{}
331-
for channel, chaincodeMap := range lc.References {
332-
metadata := []*chaincode.Metadata{}
333-
for cc, cachedDefinition := range chaincodeMap {
334-
metadata = append(metadata, &chaincode.Metadata{
335-
Name: cc,
336-
Version: cachedDefinition.Definition.EndorsementInfo.Version,
337-
})
338-
}
339-
references[channel] = metadata
340-
}
341-
installedChaincodes = append(installedChaincodes, &chaincode.InstalledChaincode{
342-
PackageID: lc.Info.PackageID,
343-
Label: lc.Info.Label,
344-
References: references,
345-
})
360+
installedChaincodes = append(installedChaincodes, lc.ToInstalledChaincode())
346361
}
347362

348363
return installedChaincodes
349364
}
350365

366+
// GetInstalledChaincode returns all of the information about a specific
367+
// installed chaincode.
368+
func (c *Cache) GetInstalledChaincode(packageID ccpersistence.PackageID) (*chaincode.InstalledChaincode, error) {
369+
c.mutex.RLock()
370+
defer c.mutex.RUnlock()
371+
372+
for _, lc := range c.localChaincodes {
373+
if lc.Info == nil {
374+
// the update function adds an entry to localChaincodes
375+
// even if it isn't yet installed
376+
continue
377+
}
378+
if lc.Info.PackageID == packageID {
379+
return lc.ToInstalledChaincode(), nil
380+
}
381+
}
382+
383+
return nil, errors.Errorf("could not find chaincode with package id '%s'", packageID)
384+
}
385+
351386
// update should only be called with the write lock already held
352387
func (c *Cache) update(initializing bool, channelID string, dirtyChaincodes map[string]struct{}, qe ledger.SimpleQueryExecutor) error {
353388
channelCache, ok := c.definedChaincodes[channelID]

core/chaincode/lifecycle/cache_test.go

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,7 +122,7 @@ var _ = Describe("Cache", func() {
122122
},
123123
},
124124
string(util.ComputeSHA256(protoutil.MarshalOrPanic(&lb.StateData{
125-
Type: &lb.StateData_String_{String_: "another-packageID"},
125+
Type: &lb.StateData_String_{String_: "notinstalled-packageID"},
126126
}))): {
127127
References: map[string]map[string]*lifecycle.CachedChaincodeDefinition{
128128
"channel-id": {
@@ -209,7 +209,7 @@ var _ = Describe("Cache", func() {
209209
})
210210
})
211211

212-
Describe("InstalledChaincodes", func() {
212+
Describe("ListInstalledChaincodes", func() {
213213
It("returns the installed chaincodes", func() {
214214
installedChaincodes := c.ListInstalledChaincodes()
215215
Expect(installedChaincodes).To(Equal([]*chaincode.InstalledChaincode{
@@ -229,6 +229,33 @@ var _ = Describe("Cache", func() {
229229
})
230230
})
231231

232+
Describe("GetInstalledChaincode", func() {
233+
It("returns the requested installed chaincode", func() {
234+
installedChaincode, err := c.GetInstalledChaincode(ccpersistence.PackageID("packageID"))
235+
Expect(installedChaincode).To(Equal(&chaincode.InstalledChaincode{
236+
Label: "chaincode-label",
237+
PackageID: "packageID",
238+
References: map[string][]*chaincode.Metadata{
239+
"channel-id": {
240+
&chaincode.Metadata{
241+
Name: "chaincode-name",
242+
Version: "chaincode-version",
243+
},
244+
},
245+
},
246+
}))
247+
Expect(err).NotTo(HaveOccurred())
248+
})
249+
250+
Context("when the chaincode is not installed", func() {
251+
It("returns an error", func() {
252+
installedChaincode, err := c.GetInstalledChaincode(ccpersistence.PackageID("notinstalled-packageID"))
253+
Expect(installedChaincode).To(BeNil())
254+
Expect(err).To(MatchError("could not find chaincode with package id 'notinstalled-packageID'"))
255+
})
256+
})
257+
})
258+
232259
Describe("InitializeLocalChaincodes", func() {
233260
It("loads the already installed chaincodes into the cache", func() {
234261
Expect(channelCache.Chaincodes["chaincode-name"].InstallInfo).To(BeNil())

core/chaincode/lifecycle/lifecycle.go

Lines changed: 3 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,7 @@ type InstallListener interface {
192192
//go:generate counterfeiter -o mock/installed_chaincodes_lister.go --fake-name InstalledChaincodesLister . InstalledChaincodesLister
193193
type InstalledChaincodesLister interface {
194194
ListInstalledChaincodes() []*chaincode.InstalledChaincode
195+
GetInstalledChaincode(packageID p.PackageID) (*chaincode.InstalledChaincode, error)
195196
}
196197

197198
// Resources stores the common functions needed by all components of the lifecycle
@@ -529,29 +530,9 @@ func (ef *ExternalFunctions) QueryNamespaceDefinitions(publicState RangeableStat
529530
return result, nil
530531
}
531532

532-
// QueryInstalledChaincode returns the hash of an installed chaincode of a given name and version.
533+
// QueryInstalledChaincode returns metadata for the chaincode with the supplied package ID.
533534
func (ef *ExternalFunctions) QueryInstalledChaincode(packageID p.PackageID) (*chaincode.InstalledChaincode, error) {
534-
ccPackageBytes, err := ef.Resources.ChaincodeStore.Load(packageID)
535-
if err != nil {
536-
if _, ok := err.(persistence.CodePackageNotFoundErr); ok {
537-
return nil, err
538-
}
539-
return nil, errors.WithMessagef(err, "could not load chaincode with package id '%s'", packageID)
540-
}
541-
542-
parsedCCPackage, err := ef.Resources.PackageParser.Parse(ccPackageBytes)
543-
if err != nil {
544-
return nil, errors.WithMessagef(err, "could not parse chaincode with package id '%s'", packageID)
545-
}
546-
547-
if parsedCCPackage.Metadata == nil {
548-
return nil, errors.Errorf("empty metadata for chaincode with package id '%s'", packageID)
549-
}
550-
551-
return &chaincode.InstalledChaincode{
552-
PackageID: packageID,
553-
Label: parsedCCPackage.Metadata.Label,
554-
}, nil
535+
return ef.InstalledChaincodesLister.GetInstalledChaincode(packageID)
555536
}
556537

557538
// QueryInstalledChaincodes returns a list of installed chaincodes

core/chaincode/lifecycle/lifecycle_test.go

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,74 @@ var _ = Describe("ExternalFunctions", func() {
332332
})
333333
})
334334

335+
Describe("QueryInstalledChaincode", func() {
336+
BeforeEach(func() {
337+
fakeLister.GetInstalledChaincodeReturns(&chaincode.InstalledChaincode{
338+
Label: "installed-cc2",
339+
PackageID: "installed-package-id2",
340+
References: map[string][]*chaincode.Metadata{
341+
"test-channel": {
342+
&chaincode.Metadata{
343+
Name: "test-chaincode",
344+
Version: "test-version",
345+
},
346+
&chaincode.Metadata{
347+
Name: "hello-chaincode",
348+
Version: "hello-version",
349+
},
350+
},
351+
"another-channel": {
352+
&chaincode.Metadata{
353+
Name: "another-chaincode",
354+
Version: "another-version",
355+
},
356+
},
357+
},
358+
}, nil)
359+
})
360+
361+
It("returns installed chaincode information", func() {
362+
result, err := ef.QueryInstalledChaincode(p.PackageID("installed-package-id2"))
363+
Expect(err).NotTo(HaveOccurred())
364+
Expect(result).To(Equal(
365+
&chaincode.InstalledChaincode{
366+
Label: "installed-cc2",
367+
PackageID: "installed-package-id2",
368+
References: map[string][]*chaincode.Metadata{
369+
"test-channel": {
370+
&chaincode.Metadata{
371+
Name: "test-chaincode",
372+
Version: "test-version",
373+
},
374+
&chaincode.Metadata{
375+
Name: "hello-chaincode",
376+
Version: "hello-version",
377+
},
378+
},
379+
"another-channel": {
380+
&chaincode.Metadata{
381+
Name: "another-chaincode",
382+
Version: "another-version",
383+
},
384+
},
385+
},
386+
},
387+
))
388+
})
389+
390+
Context("when the chaincode isn't installed", func() {
391+
BeforeEach(func() {
392+
fakeLister.GetInstalledChaincodeReturns(nil, errors.New("another-fake-error"))
393+
})
394+
395+
It("returns an error", func() {
396+
result, err := ef.QueryInstalledChaincode(p.PackageID("not-there"))
397+
Expect(err.Error()).To(Equal("another-fake-error"))
398+
Expect(result).To(BeNil())
399+
})
400+
})
401+
})
402+
335403
Describe("QueryInstalledChaincodes", func() {
336404
var chaincodes []*chaincode.InstalledChaincode
337405

core/chaincode/lifecycle/mock/installed_chaincodes_lister.go

Lines changed: 79 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

core/chaincode/lifecycle/scc.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ type SCCFunctions interface {
7777
// InstallChaincode persists a chaincode definition to disk
7878
InstallChaincode([]byte) (*chaincode.InstalledChaincode, error)
7979

80-
// QueryInstalledChaincode returns the hash for a given name and version of an installed chaincode
80+
// QueryInstalledChaincode returns metadata for the chaincode with the supplied package ID.
8181
QueryInstalledChaincode(packageID persistenceintf.PackageID) (*chaincode.InstalledChaincode, error)
8282

8383
// GetInstalledChaincodePackage returns the chaincode package
@@ -280,9 +280,26 @@ func (i *Invocation) QueryInstalledChaincode(input *lb.QueryInstalledChaincodeAr
280280
if err != nil {
281281
return nil, err
282282
}
283+
284+
references := map[string]*lb.QueryInstalledChaincodeResult_References{}
285+
for channel, chaincodeMetadata := range chaincode.References {
286+
chaincodes := make([]*lb.QueryInstalledChaincodeResult_Chaincode, len(chaincodeMetadata))
287+
for i, metadata := range chaincodeMetadata {
288+
chaincodes[i] = &lb.QueryInstalledChaincodeResult_Chaincode{
289+
Name: metadata.Name,
290+
Version: metadata.Version,
291+
}
292+
}
293+
294+
references[channel] = &lb.QueryInstalledChaincodeResult_References{
295+
Chaincodes: chaincodes,
296+
}
297+
}
298+
283299
return &lb.QueryInstalledChaincodeResult{
284-
Label: chaincode.Label,
285-
PackageId: chaincode.PackageID.String(),
300+
Label: chaincode.Label,
301+
PackageId: chaincode.PackageID.String(),
302+
References: references,
286303
}, nil
287304
}
288305

0 commit comments

Comments
 (0)