1 Star 0 Fork 0

13683679291/fabric

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
encoder.go 19.25 KB
一键复制 编辑 原始数据 按行查看 历史
/*
Copyright IBM Corp. 2016 All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package encoder
import (
"github.com/hyperledger/fabric/common/cauthdsl"
"github.com/hyperledger/fabric/common/channelconfig"
"github.com/hyperledger/fabric/common/crypto"
"github.com/hyperledger/fabric/common/flogging"
"github.com/hyperledger/fabric/common/genesis"
"github.com/hyperledger/fabric/common/policies"
"github.com/hyperledger/fabric/common/resourcesconfig"
genesisconfig "github.com/hyperledger/fabric/common/tools/configtxgen/localconfig"
"github.com/hyperledger/fabric/common/tools/configtxlator/update"
"github.com/hyperledger/fabric/common/util"
"github.com/hyperledger/fabric/msp"
cb "github.com/hyperledger/fabric/protos/common"
pb "github.com/hyperledger/fabric/protos/peer"
"github.com/hyperledger/fabric/protos/utils"
"github.com/golang/protobuf/proto"
"github.com/pkg/errors"
)
const (
pkgLogID = "common/tools/configtxgen/encoder"
ordererAdminsPolicyName = "/Channel/Orderer/Admins"
msgVersion = int32(0)
epoch = 0
)
var logger = flogging.MustGetLogger(pkgLogID)
func init() {
flogging.SetModuleLevel(pkgLogID, "info")
}
const (
// ConsensusTypeSolo identifies the solo consensus implementation.
ConsensusTypeSolo = "solo"
// ConsensusTypeKafka identifies the Kafka-based consensus implementation.
ConsensusTypeKafka = "kafka"
// BlockValidationPolicyKey TODO
BlockValidationPolicyKey = "BlockValidation"
// OrdererAdminsPolicy is the absolute path to the orderer admins policy
OrdererAdminsPolicy = "/Channel/Orderer/Admins"
)
func addValue(cg *cb.ConfigGroup, value channelconfig.ConfigValue, modPolicy string) {
cg.Values[value.Key()] = &cb.ConfigValue{
Value: utils.MarshalOrPanic(value.Value()),
ModPolicy: modPolicy,
}
}
func addPolicy(cg *cb.ConfigGroup, policy policies.ConfigPolicy, modPolicy string) {
cg.Policies[policy.Key()] = &cb.ConfigPolicy{
Policy: policy.Value(),
ModPolicy: modPolicy,
}
}
// addImplicitMetaPolicyDefaults adds the Readers/Writers/Admins policies, with Any/Any/Majority rules respectively.
func addImplicitMetaPolicyDefaults(cg *cb.ConfigGroup) {
addPolicy(cg, policies.ImplicitMetaMajorityPolicy(channelconfig.AdminsPolicyKey), channelconfig.AdminsPolicyKey)
addPolicy(cg, policies.ImplicitMetaAnyPolicy(channelconfig.ReadersPolicyKey), channelconfig.AdminsPolicyKey)
addPolicy(cg, policies.ImplicitMetaAnyPolicy(channelconfig.WritersPolicyKey), channelconfig.AdminsPolicyKey)
}
// addSignaturePolicyDefaults adds the Readers/Writers/Admins policies as signature policies requiring one signature from the given mspID.
// If devMode is set to true, the Admins policy will accept arbitrary user certs for admin functions, otherwise it requires the cert satisfies
// the admin role principal.
func addSignaturePolicyDefaults(cg *cb.ConfigGroup, mspID string, devMode bool) {
if devMode {
addPolicy(cg, policies.SignaturePolicy(channelconfig.AdminsPolicyKey, cauthdsl.SignedByMspMember(mspID)), channelconfig.AdminsPolicyKey)
} else {
addPolicy(cg, policies.SignaturePolicy(channelconfig.AdminsPolicyKey, cauthdsl.SignedByMspAdmin(mspID)), channelconfig.AdminsPolicyKey)
}
addPolicy(cg, policies.SignaturePolicy(channelconfig.ReadersPolicyKey, cauthdsl.SignedByMspMember(mspID)), channelconfig.AdminsPolicyKey)
addPolicy(cg, policies.SignaturePolicy(channelconfig.WritersPolicyKey, cauthdsl.SignedByMspMember(mspID)), channelconfig.AdminsPolicyKey)
}
// NewChannelGroup defines the root of the channel configuration. It defines basic operating principles like the hashing
// algorithm used for the blocks, as well as the location of the ordering service. It will recursively call into the
// NewOrdererGroup, NewConsortiumsGroup, and NewApplicationGroup depending on whether these sub-elements are set in the
// configuration. All mod_policy values are set to "Admins" for this group, with the exception of the OrdererAddresses
// value which is set to "/Channel/Orderer/Admins".
func NewChannelGroup(conf *genesisconfig.Profile) (*cb.ConfigGroup, error) {
if conf.Orderer == nil {
return nil, errors.New("missing orderer config section")
}
channelGroup := cb.NewConfigGroup()
addImplicitMetaPolicyDefaults(channelGroup)
addValue(channelGroup, channelconfig.HashingAlgorithmValue(), channelconfig.AdminsPolicyKey)
addValue(channelGroup, channelconfig.BlockDataHashingStructureValue(), channelconfig.AdminsPolicyKey)
addValue(channelGroup, channelconfig.OrdererAddressesValue(conf.Orderer.Addresses), ordererAdminsPolicyName)
if conf.Consortium != "" {
addValue(channelGroup, channelconfig.ConsortiumValue(conf.Consortium), channelconfig.AdminsPolicyKey)
}
if len(conf.Capabilities) > 0 {
addValue(channelGroup, channelconfig.CapabilitiesValue(conf.Capabilities), channelconfig.AdminsPolicyKey)
}
var err error
channelGroup.Groups[channelconfig.OrdererGroupKey], err = NewOrdererGroup(conf.Orderer)
if err != nil {
return nil, errors.Wrap(err, "could not create orderer group")
}
if conf.Application != nil {
channelGroup.Groups[channelconfig.ApplicationGroupKey], err = NewApplicationGroup(conf.Application)
if err != nil {
return nil, errors.Wrap(err, "could not create application group")
}
}
if conf.Consortiums != nil {
channelGroup.Groups[channelconfig.ConsortiumsGroupKey], err = NewConsortiumsGroup(conf.Consortiums)
if err != nil {
return nil, errors.Wrap(err, "could not create consortiums group")
}
}
channelGroup.ModPolicy = channelconfig.AdminsPolicyKey
return channelGroup, nil
}
// NewOrdererGroup returns the orderer component of the channel configuration. It defines parameters of the ordering service
// about how large blocks should be, how frequently they should be emitted, etc. as well as the organizations of the ordering network.
// It sets the mod_policy of all elements to "Admins". This group is always present in any channel configuration.
func NewOrdererGroup(conf *genesisconfig.Orderer) (*cb.ConfigGroup, error) {
ordererGroup := cb.NewConfigGroup()
addImplicitMetaPolicyDefaults(ordererGroup)
ordererGroup.Policies[BlockValidationPolicyKey] = &cb.ConfigPolicy{
Policy: policies.ImplicitMetaAnyPolicy(channelconfig.WritersPolicyKey).Value(),
ModPolicy: channelconfig.AdminsPolicyKey,
}
addValue(ordererGroup, channelconfig.ConsensusTypeValue(conf.OrdererType), channelconfig.AdminsPolicyKey)
addValue(ordererGroup, channelconfig.BatchSizeValue(
conf.BatchSize.MaxMessageCount,
conf.BatchSize.AbsoluteMaxBytes,
conf.BatchSize.PreferredMaxBytes,
), channelconfig.AdminsPolicyKey)
addValue(ordererGroup, channelconfig.BatchTimeoutValue(conf.BatchTimeout.String()), channelconfig.AdminsPolicyKey)
addValue(ordererGroup, channelconfig.ChannelRestrictionsValue(conf.MaxChannels), channelconfig.AdminsPolicyKey)
if len(conf.Capabilities) > 0 {
addValue(ordererGroup, channelconfig.CapabilitiesValue(conf.Capabilities), channelconfig.AdminsPolicyKey)
}
switch conf.OrdererType {
case ConsensusTypeSolo:
case ConsensusTypeKafka:
addValue(ordererGroup, channelconfig.KafkaBrokersValue(conf.Kafka.Brokers), channelconfig.AdminsPolicyKey)
default:
return nil, errors.Errorf("unknown orderer type: %s", conf.OrdererType)
}
for _, org := range conf.Organizations {
var err error
ordererGroup.Groups[org.Name], err = NewOrdererOrgGroup(org)
if err != nil {
return nil, errors.Wrap(err, "failed to create orderer org")
}
}
ordererGroup.ModPolicy = channelconfig.AdminsPolicyKey
return ordererGroup, nil
}
// NewOrdererOrgGroup returns an orderer org component of the channel configuration. It defines the crypto material for the
// organization (its MSP). It sets the mod_policy of all elements to "Admins".
func NewOrdererOrgGroup(conf *genesisconfig.Organization) (*cb.ConfigGroup, error) {
mspConfig, err := msp.GetVerifyingMspConfig(conf.MSPDir, conf.ID, conf.MSPType)
if err != nil {
return nil, errors.Wrapf(err, "1 - Error loading MSP configuration for org: %s", conf.Name)
}
ordererOrgGroup := cb.NewConfigGroup()
addSignaturePolicyDefaults(ordererOrgGroup, conf.ID, conf.AdminPrincipal != genesisconfig.AdminRoleAdminPrincipal)
addValue(ordererOrgGroup, channelconfig.MSPValue(mspConfig), channelconfig.AdminsPolicyKey)
ordererOrgGroup.ModPolicy = channelconfig.AdminsPolicyKey
return ordererOrgGroup, nil
}
// NewApplicationGroup returns the application component of the channel configuration. It defines the organizations which are involved
// in application logic like chaincodes, and how these members may interact with the orderer. It sets the mod_policy of all elements to "Admins".
func NewApplicationGroup(conf *genesisconfig.Application) (*cb.ConfigGroup, error) {
applicationGroup := cb.NewConfigGroup()
addImplicitMetaPolicyDefaults(applicationGroup)
if len(conf.Capabilities) > 0 {
addValue(applicationGroup, channelconfig.CapabilitiesValue(conf.Capabilities), channelconfig.AdminsPolicyKey)
}
for _, org := range conf.Organizations {
var err error
applicationGroup.Groups[org.Name], err = NewApplicationOrgGroup(org)
if err != nil {
return nil, errors.Wrap(err, "failed to create application org")
}
}
applicationGroup.ModPolicy = channelconfig.AdminsPolicyKey
return applicationGroup, nil
}
// NewApplicationOrgGroup returns an application org component of the channel configuration. It defines the crypto material for the organization
// (its MSP) as well as its anchor peers for use by the gossip network. It sets the mod_policy of all elements to "Admins".
func NewApplicationOrgGroup(conf *genesisconfig.Organization) (*cb.ConfigGroup, error) {
mspConfig, err := msp.GetVerifyingMspConfig(conf.MSPDir, conf.ID, conf.MSPType)
if err != nil {
return nil, errors.Wrapf(err, "1 - Error loading MSP configuration for org %s: %s", conf.Name)
}
applicationOrgGroup := cb.NewConfigGroup()
addSignaturePolicyDefaults(applicationOrgGroup, conf.ID, conf.AdminPrincipal != genesisconfig.AdminRoleAdminPrincipal)
addValue(applicationOrgGroup, channelconfig.MSPValue(mspConfig), channelconfig.AdminsPolicyKey)
var anchorProtos []*pb.AnchorPeer
for _, anchorPeer := range conf.AnchorPeers {
anchorProtos = append(anchorProtos, &pb.AnchorPeer{
Host: anchorPeer.Host,
Port: int32(anchorPeer.Port),
})
}
addValue(applicationOrgGroup, channelconfig.AnchorPeersValue(anchorProtos), channelconfig.AdminsPolicyKey)
applicationOrgGroup.ModPolicy = channelconfig.AdminsPolicyKey
return applicationOrgGroup, nil
}
// NewConsortiumsGroup returns the consortiums component of the channel configuration. This element is only defined for the ordering system channel.
// It sets the mod_policy for all elements to "/Channel/Orderer/Admins".
func NewConsortiumsGroup(conf map[string]*genesisconfig.Consortium) (*cb.ConfigGroup, error) {
consortiumsGroup := cb.NewConfigGroup()
// This policy is not referenced anywhere, it is only used as part of the implicit meta policy rule at the channel level, so this setting
// effectively degrades control of the ordering system channel to the ordering admins
addPolicy(consortiumsGroup, policies.SignaturePolicy(channelconfig.AdminsPolicyKey, cauthdsl.AcceptAllPolicy), ordererAdminsPolicyName)
for consortiumName, consortium := range conf {
var err error
consortiumsGroup.Groups[consortiumName], err = NewConsortiumGroup(consortium)
if err != nil {
return nil, errors.Wrapf(err, "failed to create consortium %s", consortiumName)
}
}
consortiumsGroup.ModPolicy = ordererAdminsPolicyName
return consortiumsGroup, nil
}
// NewConsortiums returns a consortiums component of the channel configuration. Each consortium defines the organizations which may be involved in channel
// creation, as well as the channel creation policy the orderer checks at channel creation time to authorize the action. It sets the mod_policy of all
// elements to "/Channel/Orderer/Admins".
func NewConsortiumGroup(conf *genesisconfig.Consortium) (*cb.ConfigGroup, error) {
consortiumGroup := cb.NewConfigGroup()
for _, org := range conf.Organizations {
var err error
// Note, NewOrdererOrgGroup is correct here, as the structure is identical
consortiumGroup.Groups[org.Name], err = NewOrdererOrgGroup(org)
if err != nil {
return nil, errors.Wrap(err, "failed to create consortium org")
}
}
addValue(consortiumGroup, channelconfig.ChannelCreationPolicyValue(policies.ImplicitMetaAnyPolicy(channelconfig.AdminsPolicyKey).Value()), ordererAdminsPolicyName)
consortiumGroup.ModPolicy = ordererAdminsPolicyName
return consortiumGroup, nil
}
// NewChannelCreateConfigUpdate generates a ConfigUpdate which can be sent to the orderer to create a new channel. Optionally, the channel group of the
// ordering system channel may be passed in, and the resulting ConfigUpdate will extract the appropriate versions from this file.
func NewChannelCreateConfigUpdate(channelID string, orderingSystemChannelGroup *cb.ConfigGroup, conf *genesisconfig.Profile) (*cb.ConfigUpdate, error) {
if conf.Application == nil {
return nil, errors.New("cannot define a new channel with no Application section")
}
if conf.Consortium == "" {
return nil, errors.New("cannot define a new channel with no Consortium value")
}
// Otherwise, parse only the application section, and encapsulate it inside a channel group
ag, err := NewApplicationGroup(conf.Application)
if err != nil {
return nil, errors.Wrapf(err, "could not turn channel application profile into application group")
}
agc, err := channelconfig.NewApplicationConfig(ag, channelconfig.NewMSPConfigHandler(msp.MSPv1_1))
if err != nil {
return nil, errors.Wrapf(err, "could not parse application to application group")
}
var template, newChannelGroup *cb.ConfigGroup
if orderingSystemChannelGroup != nil {
// In the case that a ordering system channel definition was provided, use it to compute the update
if orderingSystemChannelGroup.Groups == nil {
return nil, errors.New("missing all channel groups")
}
consortiums, ok := orderingSystemChannelGroup.Groups[channelconfig.ConsortiumsGroupKey]
if !ok {
return nil, errors.New("bad consortiums group")
}
consortium, ok := consortiums.Groups[conf.Consortium]
if !ok {
return nil, errors.Errorf("bad consortium: %s", conf.Consortium)
}
template = proto.Clone(orderingSystemChannelGroup).(*cb.ConfigGroup)
template.Groups[channelconfig.ApplicationGroupKey] = proto.Clone(consortium).(*cb.ConfigGroup)
// This is a bit of a hack. If the channel config specifies all consortium members, then it does not look
// like a modification. The below adds a fake org with an illegal name which cannot actually exist, which
// will always appear to be deleted, triggering the correct update computation.
template.Groups[channelconfig.ApplicationGroupKey].Groups["*IllegalKey*!"] = &cb.ConfigGroup{}
delete(template.Groups, channelconfig.ConsortiumsGroupKey)
newChannelGroup = proto.Clone(orderingSystemChannelGroup).(*cb.ConfigGroup)
delete(newChannelGroup.Groups, channelconfig.ConsortiumsGroupKey)
newChannelGroup.Groups[channelconfig.ApplicationGroupKey].Values = ag.Values
newChannelGroup.Groups[channelconfig.ApplicationGroupKey].Policies = ag.Policies
for orgName, org := range template.Groups[channelconfig.ApplicationGroupKey].Groups {
if _, ok := ag.Groups[orgName]; ok {
newChannelGroup.Groups[channelconfig.ApplicationGroupKey].Groups[orgName] = org
}
}
} else {
newChannelGroup = &cb.ConfigGroup{
Groups: map[string]*cb.ConfigGroup{
channelconfig.ApplicationGroupKey: ag,
},
}
// Otherwise assume the orgs have not been modified
template = proto.Clone(newChannelGroup).(*cb.ConfigGroup)
template.Groups[channelconfig.ApplicationGroupKey].Values = nil
template.Groups[channelconfig.ApplicationGroupKey].Policies = nil
}
updt, err := update.Compute(&cb.Config{ChannelGroup: template}, &cb.Config{ChannelGroup: newChannelGroup})
if err != nil {
return nil, errors.Wrapf(err, "could not compute update")
}
// Add the consortium name to create the channel for into the write set as required.
updt.ChannelId = channelID
updt.ReadSet.Values[channelconfig.ConsortiumKey] = &cb.ConfigValue{Version: 0}
updt.WriteSet.Values[channelconfig.ConsortiumKey] = &cb.ConfigValue{
Version: 0,
Value: utils.MarshalOrPanic(&cb.Consortium{
Name: conf.Consortium,
}),
}
// If this channel uses the new lifecycle config, specify the seed data
if agc.Capabilities().ResourcesTree() {
defaultModPolicy := policies.ChannelApplicationAdmins
if conf.Application.Resources != nil {
defaultModPolicy = conf.Application.Resources.DefaultModPolicy
}
updt.IsolatedData = map[string][]byte{
pb.ResourceConfigSeedDataKey: utils.MarshalOrPanic(&cb.Config{
Type: int32(cb.ConfigType_RESOURCE),
ChannelGroup: &cb.ConfigGroup{
Groups: map[string]*cb.ConfigGroup{
resourcesconfig.ChaincodesGroupKey: {
ModPolicy: defaultModPolicy,
},
resourcesconfig.PeerPoliciesGroupKey: {
ModPolicy: defaultModPolicy,
},
resourcesconfig.APIsGroupKey: {
ModPolicy: defaultModPolicy,
},
},
ModPolicy: defaultModPolicy,
},
}),
}
}
return updt, nil
}
// MakeChannelCreationTransaction is a handy utility function for creating transactions for channel creation
func MakeChannelCreationTransaction(channelID string, signer crypto.LocalSigner, orderingSystemChannelConfigGroup *cb.ConfigGroup, conf *genesisconfig.Profile) (*cb.Envelope, error) {
newChannelConfigUpdate, err := NewChannelCreateConfigUpdate(channelID, orderingSystemChannelConfigGroup, conf)
if err != nil {
return nil, errors.Wrap(err, "config update generation failure")
}
newConfigUpdateEnv := &cb.ConfigUpdateEnvelope{
ConfigUpdate: utils.MarshalOrPanic(newChannelConfigUpdate),
}
if signer != nil {
sigHeader, err := signer.NewSignatureHeader()
if err != nil {
return nil, errors.Wrap(err, "creating signature header failed")
}
newConfigUpdateEnv.Signatures = []*cb.ConfigSignature{{
SignatureHeader: utils.MarshalOrPanic(sigHeader),
}}
newConfigUpdateEnv.Signatures[0].Signature, err = signer.Sign(util.ConcatenateBytes(newConfigUpdateEnv.Signatures[0].SignatureHeader, newConfigUpdateEnv.ConfigUpdate))
if err != nil {
return nil, errors.Wrap(err, "signature failure over config update")
}
}
return utils.CreateSignedEnvelope(cb.HeaderType_CONFIG_UPDATE, channelID, signer, newConfigUpdateEnv, msgVersion, epoch)
}
// Bootstrapper is a wrapper around NewChannelConfigGroup which can produce genesis blocks
type Bootstrapper struct {
channelGroup *cb.ConfigGroup
}
// New creates a new Bootstrapper for generating genesis blocks
func New(config *genesisconfig.Profile) *Bootstrapper {
channelGroup, err := NewChannelGroup(config)
if err != nil {
logger.Panicf("Error creating channel group: %s", err)
}
return &Bootstrapper{
channelGroup: channelGroup,
}
}
// GenesisBlock produces a genesis block for the default test chain id
func (bs *Bootstrapper) GenesisBlock() *cb.Block {
block, err := genesis.NewFactoryImpl(bs.channelGroup).Block(genesisconfig.TestChainID)
if err != nil {
logger.Panicf("Error creating genesis block from channel group: %s", err)
}
return block
}
// GenesisBlockForChannel produces a genesis block for a given channel ID
func (bs *Bootstrapper) GenesisBlockForChannel(channelID string) *cb.Block {
block, err := genesis.NewFactoryImpl(bs.channelGroup).Block(channelID)
if err != nil {
logger.Panicf("Error creating genesis block from channel group: %s", err)
}
return block
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/mmcro/fabric.git
git@gitee.com:mmcro/fabric.git
mmcro
fabric
fabric
v1.1.0-alpha

搜索帮助

0d507c66 1850385 C8b1a773 1850385