1 Star 0 Fork 0

13683679291/fabric

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
update.go 6.11 KB
一键复制 编辑 原始数据 按行查看 历史
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package configtx
import (
"strings"
cb "github.com/hyperledger/fabric-protos-go/common"
"github.com/hyperledger/fabric/common/policies"
"github.com/hyperledger/fabric/protoutil"
"github.com/pkg/errors"
)
func (vi *ValidatorImpl) verifyReadSet(readSet map[string]comparable) error {
for key, value := range readSet {
existing, ok := vi.configMap[key]
if !ok {
return errors.Errorf("existing config does not contain element for %s but was in the read set", key)
}
if existing.version() != value.version() {
return errors.Errorf("proposed update requires that key %s be at version %d, but it is currently at version %d", key, value.version(), existing.version())
}
}
return nil
}
func computeDeltaSet(readSet, writeSet map[string]comparable) map[string]comparable {
result := make(map[string]comparable)
for key, value := range writeSet {
readVal, ok := readSet[key]
if ok && readVal.version() == value.version() {
continue
}
// If the key in the readset is a different version, we include it
// Error checking on the sanity of the update is done against the config
result[key] = value
}
return result
}
func validateModPolicy(modPolicy string) error {
if modPolicy == "" {
return errors.Errorf("mod_policy not set")
}
trimmed := modPolicy
if modPolicy[0] == '/' {
trimmed = modPolicy[1:]
}
for i, pathElement := range strings.Split(trimmed, pathSeparator) {
err := validateConfigID(pathElement)
if err != nil {
return errors.Wrapf(err, "path element at %d is invalid", i)
}
}
return nil
}
func (vi *ValidatorImpl) verifyDeltaSet(deltaSet map[string]comparable, signedData []*protoutil.SignedData) error {
if len(deltaSet) == 0 {
return errors.Errorf("delta set was empty -- update would have no effect")
}
for key, value := range deltaSet {
logger.Debugf("Processing change to key: %s", key)
if err := validateModPolicy(value.modPolicy()); err != nil {
return errors.Wrapf(err, "invalid mod_policy for element %s", key)
}
existing, ok := vi.configMap[key]
if !ok {
if value.version() != 0 {
return errors.Errorf("attempted to set key %s to version %d, but key does not exist", key, value.version())
}
continue
}
if value.version() != existing.version()+1 {
return errors.Errorf("attempt to set key %s to version %d, but key is at version %d", key, value.version(), existing.version())
}
policy, ok := vi.policyForItem(existing)
if !ok {
return errors.Errorf("unexpected missing policy %s for item %s", existing.modPolicy(), key)
}
// Ensure the policy is satisfied
if err := policy.EvaluateSignedData(signedData); err != nil {
return errors.Wrapf(err, "policy for %s not satisfied", key)
}
}
return nil
}
func verifyFullProposedConfig(writeSet, fullProposedConfig map[string]comparable) error {
for key := range writeSet {
if _, ok := fullProposedConfig[key]; !ok {
return errors.Errorf("writeset contained key %s which did not appear in proposed config", key)
}
}
return nil
}
// authorizeUpdate validates that all modified config has the corresponding modification policies satisfied by the signature set
// it returns a map of the modified config
func (vi *ValidatorImpl) authorizeUpdate(configUpdateEnv *cb.ConfigUpdateEnvelope) (map[string]comparable, error) {
if configUpdateEnv == nil {
return nil, errors.Errorf("cannot process nil ConfigUpdateEnvelope")
}
configUpdate, err := UnmarshalConfigUpdate(configUpdateEnv.ConfigUpdate)
if err != nil {
return nil, err
}
if configUpdate.ChannelId != vi.channelID {
return nil, errors.Errorf("ConfigUpdate for channel '%s' but envelope for channel '%s'", configUpdate.ChannelId, vi.channelID)
}
readSet, err := mapConfig(configUpdate.ReadSet, vi.namespace)
if err != nil {
return nil, errors.Wrapf(err, "error mapping ReadSet")
}
err = vi.verifyReadSet(readSet)
if err != nil {
return nil, errors.Wrapf(err, "error validating ReadSet")
}
writeSet, err := mapConfig(configUpdate.WriteSet, vi.namespace)
if err != nil {
return nil, errors.Wrapf(err, "error mapping WriteSet")
}
deltaSet := computeDeltaSet(readSet, writeSet)
signedData, err := protoutil.ConfigUpdateEnvelopeAsSignedData(configUpdateEnv)
if err != nil {
return nil, err
}
if err = vi.verifyDeltaSet(deltaSet, signedData); err != nil {
return nil, errors.Wrapf(err, "error validating DeltaSet")
}
fullProposedConfig := vi.computeUpdateResult(deltaSet)
if err := verifyFullProposedConfig(writeSet, fullProposedConfig); err != nil {
return nil, errors.Wrapf(err, "full config did not verify")
}
return fullProposedConfig, nil
}
func (vi *ValidatorImpl) policyForItem(item comparable) (policies.Policy, bool) {
manager := vi.pm
modPolicy := item.modPolicy()
logger.Debugf("Getting policy for item %s with mod_policy %s", item.key, modPolicy)
// If the mod_policy path is relative, get the right manager for the context
// If the item has a zero length path, it is the root group, use the base policy manager
// if the mod_policy path is absolute (starts with /) also use the base policy manager
if len(modPolicy) > 0 && modPolicy[0] != policies.PathSeparator[0] && len(item.path) != 0 {
var ok bool
manager, ok = manager.Manager(item.path[1:])
if !ok {
logger.Debugf("Could not find manager at path: %v", item.path[1:])
return nil, ok
}
// In the case of the group type, its key is part of its path for the purposes of finding the policy manager
if item.ConfigGroup != nil {
manager, ok = manager.Manager([]string{item.key})
}
if !ok {
logger.Debugf("Could not find group at subpath: %v", item.key)
return nil, ok
}
}
return manager.GetPolicy(item.modPolicy())
}
// computeUpdateResult takes a configMap generated by an update and produces a new configMap overlaying it onto the old config
func (vi *ValidatorImpl) computeUpdateResult(updatedConfig map[string]comparable) map[string]comparable {
newConfigMap := make(map[string]comparable)
for key, value := range vi.configMap {
newConfigMap[key] = value
}
for key, value := range updatedConfig {
newConfigMap[key] = value
}
return newConfigMap
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/mmcro/fabric.git
git@gitee.com:mmcro/fabric.git
mmcro
fabric
fabric
v2.1.1

搜索帮助