github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/ledger/kvledger/coll_elg_notifier.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package kvledger 8 9 import ( 10 "github.com/hechain20/hechain/core/ledger" 11 "github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset" 12 "github.com/hyperledger/fabric-protos-go/peer" 13 ) 14 15 // collElgNotifier listens for the chaincode events and determines whether the peer has become eligible for one or more existing 16 // private data collections and notifies the registered listener 17 type collElgNotifier struct { 18 deployedChaincodeInfoProvider ledger.DeployedChaincodeInfoProvider 19 membershipInfoProvider ledger.MembershipInfoProvider 20 listeners map[string]collElgListener 21 } 22 23 // Name returns the name of the listener 24 func (n *collElgNotifier) Name() string { 25 return "collection eligibility listener" 26 } 27 28 func (n *collElgNotifier) Initialize(ledgerID string, qe ledger.SimpleQueryExecutor) error { 29 // Noop 30 return nil 31 } 32 33 // InterestedInNamespaces implements function in interface ledger.StateListener 34 func (n *collElgNotifier) InterestedInNamespaces() []string { 35 return n.deployedChaincodeInfoProvider.Namespaces() 36 } 37 38 // HandleStateUpdates implements function in interface ledger.StateListener 39 // This function gets invoked when one or more chaincodes are deployed or upgraded by a block. 40 // This function, for each upgraded chaincode, performs the following 41 // 1) Retrieves the existing collection configurations and new collection configurations 42 // 2) Computes the collections for which the peer is not eligible as per the existing collection configuration 43 // but is eligible as per the new collection configuration 44 // Finally, it causes an invocation to function 'ProcessCollsEligibilityEnabled' on ledger store with a map {ns:colls} 45 // that contains the details of <ns, coll> combination for which the eligibility of the peer is switched on. 46 func (n *collElgNotifier) HandleStateUpdates(trigger *ledger.StateUpdateTrigger) error { 47 nsCollMap := map[string][]string{} 48 qe := trigger.CommittedStateQueryExecutor 49 postCommitQE := trigger.PostCommitQueryExecutor 50 51 stateUpdates := extractPublicUpdates(trigger.StateUpdates) 52 ccLifecycleInfo, err := n.deployedChaincodeInfoProvider.UpdatedChaincodes(stateUpdates) 53 if err != nil { 54 return err 55 } 56 var existingCCInfo, postCommitCCInfo *ledger.DeployedChaincodeInfo 57 for _, ccInfo := range ccLifecycleInfo { 58 ledgerid := trigger.LedgerID 59 ccName := ccInfo.Name 60 if existingCCInfo, err = n.deployedChaincodeInfoProvider.ChaincodeInfo(ledgerid, ccName, qe); err != nil { 61 return err 62 } 63 if existingCCInfo == nil { // not an upgrade transaction 64 continue 65 } 66 if postCommitCCInfo, err = n.deployedChaincodeInfoProvider.ChaincodeInfo(ledgerid, ccName, postCommitQE); err != nil { 67 return err 68 } 69 elgEnabledCollNames, err := n.elgEnabledCollNames( 70 ledgerid, 71 existingCCInfo.ExplicitCollectionConfigPkg, 72 postCommitCCInfo.ExplicitCollectionConfigPkg, 73 ) 74 if err != nil { 75 return err 76 } 77 logger.Debugf("[%s] collections of chaincode [%s] for which peer was not eligible before and now the eligiblity is enabled - [%s]", 78 ledgerid, ccName, elgEnabledCollNames, 79 ) 80 if len(elgEnabledCollNames) > 0 { 81 nsCollMap[ccName] = elgEnabledCollNames 82 } 83 } 84 if len(nsCollMap) > 0 { 85 return n.invokeLedgerSpecificNotifier(trigger.LedgerID, trigger.CommittingBlockNum, nsCollMap) 86 } 87 return nil 88 } 89 90 func (n *collElgNotifier) registerListener(ledgerID string, listener collElgListener) { 91 n.listeners[ledgerID] = listener 92 } 93 94 func (n *collElgNotifier) invokeLedgerSpecificNotifier(ledgerID string, commtingBlk uint64, nsCollMap map[string][]string) error { 95 listener := n.listeners[ledgerID] 96 return listener.ProcessCollsEligibilityEnabled(commtingBlk, nsCollMap) 97 } 98 99 // elgEnabledCollNames returns the names of the collections for which the peer is not eligible as per 'existingPkg' and is eligible as per 'postCommitPkg' 100 func (n *collElgNotifier) elgEnabledCollNames(ledgerID string, 101 existingPkg, postCommitPkg *peer.CollectionConfigPackage) ([]string, error) { 102 collectionNames := []string{} 103 exisingConfs := retrieveCollConfs(existingPkg) 104 postCommitConfs := retrieveCollConfs(postCommitPkg) 105 existingConfMap := map[string]*peer.StaticCollectionConfig{} 106 for _, existingConf := range exisingConfs { 107 existingConfMap[existingConf.Name] = existingConf 108 } 109 110 for _, postCommitConf := range postCommitConfs { 111 collName := postCommitConf.Name 112 existingConf, ok := existingConfMap[collName] 113 if !ok { // brand new collection 114 continue 115 } 116 membershipEnabled, err := n.elgEnabled(ledgerID, existingConf.MemberOrgsPolicy, postCommitConf.MemberOrgsPolicy) 117 if err != nil { 118 return nil, err 119 } 120 if !membershipEnabled { 121 continue 122 } 123 // not an existing member and added now 124 collectionNames = append(collectionNames, collName) 125 } 126 return collectionNames, nil 127 } 128 129 // elgEnabled returns true if the peer is not eligible for a collection as per 'existingPolicy' and is eligible as per 'postCommitPolicy' 130 func (n *collElgNotifier) elgEnabled(ledgerID string, existingPolicy, postCommitPolicy *peer.CollectionPolicyConfig) (bool, error) { 131 existingMember, err := n.membershipInfoProvider.AmMemberOf(ledgerID, existingPolicy) 132 if err != nil || existingMember { 133 return false, err 134 } 135 return n.membershipInfoProvider.AmMemberOf(ledgerID, postCommitPolicy) 136 } 137 138 func extractPublicUpdates(stateUpdates ledger.StateUpdates) map[string][]*kvrwset.KVWrite { 139 m := map[string][]*kvrwset.KVWrite{} 140 for ns, updates := range stateUpdates { 141 m[ns] = updates.PublicUpdates 142 } 143 return m 144 } 145 146 // StateCommitDone implements function in interface ledger.StateListener 147 func (n *collElgNotifier) StateCommitDone(ledgerID string) { 148 // Noop 149 } 150 151 type collElgListener interface { 152 ProcessCollsEligibilityEnabled(commitingBlk uint64, nsCollMap map[string][]string) error 153 } 154 155 func retrieveCollConfs(collConfPkg *peer.CollectionConfigPackage) []*peer.StaticCollectionConfig { 156 if collConfPkg == nil { 157 return nil 158 } 159 var staticCollConfs []*peer.StaticCollectionConfig 160 protoConfArray := collConfPkg.Config 161 for _, protoConf := range protoConfArray { 162 staticCollConfs = append(staticCollConfs, protoConf.GetStaticCollectionConfig()) 163 } 164 return staticCollConfs 165 }