forked from hyperledger/fabric
/
deployedcc_infoprovider.go
157 lines (139 loc) · 5.67 KB
/
deployedcc_infoprovider.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package lscc
import (
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric-protos-go/ledger/queryresult"
"github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
"github.com/hyperledger/fabric-protos-go/peer"
"github.com/hyperledger/fabric/core/common/ccprovider"
"github.com/hyperledger/fabric/core/common/privdata"
"github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil"
"github.com/pkg/errors"
)
const (
lsccNamespace = "lscc"
)
// DeployedCCInfoProvider implements interface ledger.DeployedChaincodeInfoProvider
type DeployedCCInfoProvider struct {
}
// Namespaces implements function in interface ledger.DeployedChaincodeInfoProvider
func (p *DeployedCCInfoProvider) Namespaces() []string {
return []string{lsccNamespace}
}
// UpdatedChaincodes implements function in interface ledger.DeployedChaincodeInfoProvider
func (p *DeployedCCInfoProvider) UpdatedChaincodes(stateUpdates map[string][]*kvrwset.KVWrite) ([]*ledger.ChaincodeLifecycleInfo, error) {
lsccUpdates := stateUpdates[lsccNamespace]
lifecycleInfo := []*ledger.ChaincodeLifecycleInfo{}
updatedCCNames := map[string]bool{}
for _, kvWrite := range lsccUpdates {
if rwsetutil.IsKVWriteDelete(kvWrite) {
// lscc namespace is not expected to have deletes
continue
}
// There are LSCC entries for the chaincode and for the chaincode collections.
// We can detect collections based on the presence of a CollectionSeparator,
// which never exists in chaincode names.
if privdata.IsCollectionConfigKey(kvWrite.Key) {
ccname := privdata.GetCCNameFromCollectionConfigKey(kvWrite.Key)
updatedCCNames[ccname] = true
continue
}
updatedCCNames[kvWrite.Key] = true
}
for updatedCCNames := range updatedCCNames {
lifecycleInfo = append(lifecycleInfo, &ledger.ChaincodeLifecycleInfo{Name: updatedCCNames})
}
return lifecycleInfo, nil
}
func (p *DeployedCCInfoProvider) ImplicitCollections(channelName, chaincodeName string, qe ledger.SimpleQueryExecutor) ([]*peer.StaticCollectionConfig, error) {
return nil, nil
}
// GenerateImplicitCollectionForOrg is not implemented for legacy chaincodes
func (p *DeployedCCInfoProvider) GenerateImplicitCollectionForOrg(mspid string) *peer.StaticCollectionConfig {
return nil
}
// ChaincodeInfo implements function in interface ledger.DeployedChaincodeInfoProvider
func (p *DeployedCCInfoProvider) ChaincodeInfo(channelName, chaincodeName string, qe ledger.SimpleQueryExecutor) (*ledger.DeployedChaincodeInfo, error) {
chaincodeDataBytes, err := qe.GetState(lsccNamespace, chaincodeName)
if err != nil || chaincodeDataBytes == nil {
return nil, err
}
chaincodeData := &ccprovider.ChaincodeData{}
if err := proto.Unmarshal(chaincodeDataBytes, chaincodeData); err != nil {
return nil, errors.Wrap(err, "error unmarshalling chaincode state data")
}
collConfigPkg, err := fetchCollConfigPkg(chaincodeName, qe)
if err != nil {
return nil, err
}
return &ledger.DeployedChaincodeInfo{
Name: chaincodeName,
Hash: chaincodeData.Id,
Version: chaincodeData.Version,
ExplicitCollectionConfigPkg: collConfigPkg,
IsLegacy: true,
}, nil
}
// AllChaincodesInfo returns the mapping of chaincode name to DeployedChaincodeInfo for legacy chaincodes
func (p *DeployedCCInfoProvider) AllChaincodesInfo(channelName string, qe ledger.SimpleQueryExecutor) (map[string]*ledger.DeployedChaincodeInfo, error) {
iter, err := qe.GetStateRangeScanIterator(lsccNamespace, "", "")
if err != nil {
return nil, err
}
defer iter.Close()
result := make(map[string]*ledger.DeployedChaincodeInfo)
for {
entry, err := iter.Next()
if err != nil {
return nil, err
}
if entry == nil {
break
}
kv := entry.(*queryresult.KV)
if !privdata.IsCollectionConfigKey(kv.Key) {
deployedccInfo, err := p.ChaincodeInfo(channelName, kv.Key, qe)
if err != nil {
return nil, err
}
result[kv.Key] = deployedccInfo
}
}
return result, nil
}
// AllCollectionsConfigPkg implements function in interface ledger.DeployedChaincodeInfoProvider
// this implementation returns just the explicit collection config package as the implicit collections
// are not used with legacy lifecycle
func (p *DeployedCCInfoProvider) AllCollectionsConfigPkg(channelName, chaincodeName string, qe ledger.SimpleQueryExecutor) (*peer.CollectionConfigPackage, error) {
return fetchCollConfigPkg(chaincodeName, qe)
}
// CollectionInfo implements function in interface ledger.DeployedChaincodeInfoProvider
func (p *DeployedCCInfoProvider) CollectionInfo(channelName, chaincodeName, collectionName string, qe ledger.SimpleQueryExecutor) (*peer.StaticCollectionConfig, error) {
collConfigPkg, err := fetchCollConfigPkg(chaincodeName, qe)
if err != nil || collConfigPkg == nil {
return nil, err
}
for _, conf := range collConfigPkg.Config {
staticCollConfig := conf.GetStaticCollectionConfig()
if staticCollConfig != nil && staticCollConfig.Name == collectionName {
return staticCollConfig, nil
}
}
return nil, nil
}
func fetchCollConfigPkg(chaincodeName string, qe ledger.SimpleQueryExecutor) (*peer.CollectionConfigPackage, error) {
collKey := privdata.BuildCollectionKVSKey(chaincodeName)
collectionConfigPkgBytes, err := qe.GetState(lsccNamespace, collKey)
if err != nil || collectionConfigPkgBytes == nil {
return nil, err
}
collectionConfigPkg := &peer.CollectionConfigPackage{}
if err := proto.Unmarshal(collectionConfigPkgBytes, collectionConfigPkg); err != nil {
return nil, errors.Wrap(err, "error unmarshalling chaincode collection config pkg")
}
return collectionConfigPkg, nil
}