github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/core/committer/txvalidator/v14/plugin_validator.go (about) 1 /* 2 Copyright hechain. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package txvalidator 8 9 import ( 10 "fmt" 11 "sync" 12 13 "github.com/hechain20/hechain/common/cauthdsl" 14 ledger2 "github.com/hechain20/hechain/common/ledger" 15 vp "github.com/hechain20/hechain/core/committer/txvalidator/plugin" 16 validation "github.com/hechain20/hechain/core/handlers/validation/api" 17 vc "github.com/hechain20/hechain/core/handlers/validation/api/capabilities" 18 vi "github.com/hechain20/hechain/core/handlers/validation/api/identities" 19 vs "github.com/hechain20/hechain/core/handlers/validation/api/state" 20 "github.com/hechain20/hechain/core/ledger" 21 "github.com/hechain20/hechain/msp" 22 "github.com/hechain20/hechain/protoutil" 23 "github.com/hyperledger/fabric-protos-go/common" 24 "github.com/pkg/errors" 25 ) 26 27 //go:generate mockery -dir . -name Mapper -case underscore -output mocks/ 28 29 // Mapper local interface use to generate mock for foreign interface. 30 type Mapper interface { 31 vp.Mapper 32 } 33 34 //go:generate mockery -dir . -name PluginFactory -case underscore -output mocks/ 35 36 // PluginFactory local interface used to generate mock for foreign interface. 37 type PluginFactory interface { 38 validation.PluginFactory 39 } 40 41 //go:generate mockery -dir . -name Plugin -case underscore -output mocks/ 42 43 // Plugin local interface used to generate mock for foreign interface. 44 type Plugin interface { 45 validation.Plugin 46 } 47 48 //go:generate mockery -dir . -name QueryExecutorCreator -case underscore -output mocks/ 49 50 // QueryExecutorCreator creates new query executors 51 type QueryExecutorCreator interface { 52 NewQueryExecutor() (ledger.QueryExecutor, error) 53 } 54 55 // Context defines information about a transaction 56 // that is being validated 57 type Context struct { 58 Seq int 59 Envelope []byte 60 TxID string 61 Channel string 62 VSCCName string 63 Policy []byte 64 Namespace string 65 Block *common.Block 66 } 67 68 // String returns a string representation of this Context 69 func (c Context) String() string { 70 return fmt.Sprintf("Tx %s, seq %d out of %d in block %d for channel %s with validation plugin %s", c.TxID, c.Seq, len(c.Block.Data.Data), c.Block.Header.Number, c.Channel, c.VSCCName) 71 } 72 73 // PluginValidator values transactions with validation plugins 74 type PluginValidator struct { 75 sync.Mutex 76 pluginChannelMapping map[vp.Name]*pluginsByChannel 77 vp.Mapper 78 QueryExecutorCreator 79 msp.IdentityDeserializer 80 capabilities vc.Capabilities 81 } 82 83 //go:generate mockery -dir . -name Capabilities -case underscore -output mocks/ 84 85 // Capabilities local interface used to generate mock for foreign interface. 86 type Capabilities interface { 87 vc.Capabilities 88 } 89 90 //go:generate mockery -dir . -name IdentityDeserializer -case underscore -output mocks/ 91 92 // IdentityDeserializer local interface used to generate mock for foreign interface. 93 type IdentityDeserializer interface { 94 msp.IdentityDeserializer 95 } 96 97 // NewPluginValidator creates a new PluginValidator 98 func NewPluginValidator(pm vp.Mapper, qec QueryExecutorCreator, deserializer msp.IdentityDeserializer, capabilities vc.Capabilities) *PluginValidator { 99 return &PluginValidator{ 100 capabilities: capabilities, 101 pluginChannelMapping: make(map[vp.Name]*pluginsByChannel), 102 Mapper: pm, 103 QueryExecutorCreator: qec, 104 IdentityDeserializer: deserializer, 105 } 106 } 107 108 func (pv *PluginValidator) ValidateWithPlugin(ctx *Context) error { 109 plugin, err := pv.getOrCreatePlugin(ctx) 110 if err != nil { 111 return &validation.ExecutionFailureError{ 112 Reason: fmt.Sprintf("plugin with name %s couldn't be used: %v", ctx.VSCCName, err), 113 } 114 } 115 err = plugin.Validate(ctx.Block, ctx.Namespace, ctx.Seq, 0, vp.SerializedPolicy(ctx.Policy)) 116 validityStatus := "valid" 117 if err != nil { 118 validityStatus = fmt.Sprintf("invalid: %v", err) 119 } 120 logger.Debug("Transaction", ctx.TxID, "appears to be", validityStatus) 121 return err 122 } 123 124 func (pv *PluginValidator) getOrCreatePlugin(ctx *Context) (validation.Plugin, error) { 125 pluginFactory := pv.FactoryByName(vp.Name(ctx.VSCCName)) 126 if pluginFactory == nil { 127 return nil, errors.Errorf("plugin with name %s wasn't found", ctx.VSCCName) 128 } 129 130 pluginsByChannel := pv.getOrCreatePluginChannelMapping(vp.Name(ctx.VSCCName), pluginFactory) 131 return pluginsByChannel.createPluginIfAbsent(ctx.Channel) 132 } 133 134 func (pv *PluginValidator) getOrCreatePluginChannelMapping(plugin vp.Name, pf validation.PluginFactory) *pluginsByChannel { 135 pv.Lock() 136 defer pv.Unlock() 137 endorserChannelMapping, exists := pv.pluginChannelMapping[vp.Name(plugin)] 138 if !exists { 139 endorserChannelMapping = &pluginsByChannel{ 140 pluginFactory: pf, 141 channels2Plugins: make(map[string]validation.Plugin), 142 pv: pv, 143 } 144 pv.pluginChannelMapping[vp.Name(plugin)] = endorserChannelMapping 145 } 146 return endorserChannelMapping 147 } 148 149 type pluginsByChannel struct { 150 sync.RWMutex 151 pluginFactory validation.PluginFactory 152 channels2Plugins map[string]validation.Plugin 153 pv *PluginValidator 154 } 155 156 func (pbc *pluginsByChannel) createPluginIfAbsent(channel string) (validation.Plugin, error) { 157 pbc.RLock() 158 plugin, exists := pbc.channels2Plugins[channel] 159 pbc.RUnlock() 160 if exists { 161 return plugin, nil 162 } 163 164 pbc.Lock() 165 defer pbc.Unlock() 166 plugin, exists = pbc.channels2Plugins[channel] 167 if exists { 168 return plugin, nil 169 } 170 171 pluginInstance := pbc.pluginFactory.New() 172 plugin, err := pbc.initPlugin(pluginInstance, channel) 173 if err != nil { 174 return nil, err 175 } 176 pbc.channels2Plugins[channel] = plugin 177 return plugin, nil 178 } 179 180 func (pbc *pluginsByChannel) initPlugin(plugin validation.Plugin, channel string) (validation.Plugin, error) { 181 pe := &PolicyEvaluator{IdentityDeserializer: pbc.pv.IdentityDeserializer} 182 sf := &StateFetcherImpl{QueryExecutorCreator: pbc.pv} 183 if err := plugin.Init(pe, sf, pbc.pv.capabilities, &legacyCollectionInfoProvider{}); err != nil { 184 return nil, errors.Wrap(err, "failed initializing plugin") 185 } 186 return plugin, nil 187 } 188 189 // legacyCollectionInfoProvider implements a provider for collection 190 // information for the legacy lifecycle. It will never be called but 191 // it is necessary to have this dependency passed at init time to the 192 // default plugin 193 type legacyCollectionInfoProvider struct{} 194 195 func (*legacyCollectionInfoProvider) CollectionValidationInfo(chaincodeName, collectionName string, state vs.State) ([]byte, error, error) { 196 panic("programming error") 197 } 198 199 type PolicyEvaluator struct { 200 msp.IdentityDeserializer 201 } 202 203 // Evaluate takes a set of SignedData and evaluates whether this set of signatures satisfies the policy 204 func (id *PolicyEvaluator) Evaluate(policyBytes []byte, signatureSet []*protoutil.SignedData) error { 205 pp := cauthdsl.NewPolicyProvider(id.IdentityDeserializer) 206 policy, _, err := pp.NewPolicy(policyBytes) 207 if err != nil { 208 return err 209 } 210 return policy.EvaluateSignedData(signatureSet) 211 } 212 213 // DeserializeIdentity unmarshals the given identity to msp.Identity 214 func (id *PolicyEvaluator) DeserializeIdentity(serializedIdentity []byte) (vi.Identity, error) { 215 mspIdentity, err := id.IdentityDeserializer.DeserializeIdentity(serializedIdentity) 216 if err != nil { 217 return nil, err 218 } 219 return &identity{Identity: mspIdentity}, nil 220 } 221 222 type identity struct { 223 msp.Identity 224 } 225 226 func (i *identity) GetIdentityIdentifier() *vi.IdentityIdentifier { 227 identifier := i.Identity.GetIdentifier() 228 return &vi.IdentityIdentifier{ 229 Id: identifier.Id, 230 Mspid: identifier.Mspid, 231 } 232 } 233 234 type StateFetcherImpl struct { 235 QueryExecutorCreator 236 } 237 238 func (sf *StateFetcherImpl) FetchState() (vs.State, error) { 239 qe, err := sf.NewQueryExecutor() 240 if err != nil { 241 return nil, err 242 } 243 return &StateImpl{qe}, nil 244 } 245 246 type StateImpl struct { 247 ledger.QueryExecutor 248 } 249 250 func (s *StateImpl) GetStateRangeScanIterator(namespace string, startKey string, endKey string) (vs.ResultsIterator, error) { 251 it, err := s.QueryExecutor.GetStateRangeScanIterator(namespace, startKey, endKey) 252 if err != nil { 253 return nil, err 254 } 255 return &ResultsIteratorImpl{ResultsIterator: it}, nil 256 } 257 258 type ResultsIteratorImpl struct { 259 ledger2.ResultsIterator 260 } 261 262 func (it *ResultsIteratorImpl) Next() (vs.QueryResult, error) { 263 return it.ResultsIterator.Next() 264 }