forked from hyperledger/fabric
-
Notifications
You must be signed in to change notification settings - Fork 0
/
statebasedimpl.go
126 lines (110 loc) · 3.36 KB
/
statebasedimpl.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
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package statebased
import (
"fmt"
"sort"
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/common/cauthdsl"
cb "github.com/hyperledger/fabric/protos/common"
mb "github.com/hyperledger/fabric/protos/msp"
"github.com/hyperledger/fabric/protos/utils"
"github.com/pkg/errors"
)
// stateEP implements the KeyEndorsementPolicy
type stateEP struct {
orgs map[string]mb.MSPRole_MSPRoleType
}
// NewStateEP constructs a state-based endorsement policy from a given
// serialized EP byte array. If the byte array is empty, a new EP is created.
func NewStateEP(policy []byte) (KeyEndorsementPolicy, error) {
s := &stateEP{orgs: make(map[string]mb.MSPRole_MSPRoleType)}
if policy != nil {
spe := &cb.SignaturePolicyEnvelope{}
if err := proto.Unmarshal(policy, spe); err != nil {
return nil, fmt.Errorf("Error unmarshaling to SignaturePolicy: %s", err)
}
err := s.setMSPIDsFromSP(spe)
if err != nil {
return nil, err
}
}
return s, nil
}
// Policy returns the endorsement policy as bytes
func (s *stateEP) Policy() ([]byte, error) {
spe := s.policyFromMSPIDs()
spBytes, err := proto.Marshal(spe)
if err != nil {
return nil, err
}
return spBytes, nil
}
// AddOrgs adds the specified channel orgs to the existing key-level EP
func (s *stateEP) AddOrgs(role RoleType, neworgs ...string) error {
var mspRole mb.MSPRole_MSPRoleType
switch role {
case RoleTypeMember:
mspRole = mb.MSPRole_MEMBER
case RoleTypePeer:
mspRole = mb.MSPRole_PEER
default:
return &RoleTypeDoesNotExistError{RoleType: role}
}
// add new orgs
for _, addorg := range neworgs {
s.orgs[addorg] = mspRole
}
return nil
}
// DelOrgs delete the specified channel orgs from the existing key-level EP
func (s *stateEP) DelOrgs(delorgs ...string) {
for _, delorg := range delorgs {
delete(s.orgs, delorg)
}
}
// ListOrgs returns an array of channel orgs that are required to endorse chnages
func (s *stateEP) ListOrgs() []string {
orgNames := make([]string, 0, len(s.orgs))
for mspid := range s.orgs {
orgNames = append(orgNames, mspid)
}
return orgNames
}
func (s *stateEP) setMSPIDsFromSP(sp *cb.SignaturePolicyEnvelope) error {
// iterate over the identities in this envelope
for _, identity := range sp.Identities {
// this imlementation only supports the ROLE type
if identity.PrincipalClassification == mb.MSPPrincipal_ROLE {
msprole := &mb.MSPRole{}
err := proto.Unmarshal(identity.Principal, msprole)
if err != nil {
return errors.Wrapf(err, "error unmarshaling msp principal")
}
s.orgs[msprole.GetMspIdentifier()] = msprole.GetRole()
}
}
return nil
}
func (s *stateEP) policyFromMSPIDs() *cb.SignaturePolicyEnvelope {
mspids := s.ListOrgs()
sort.Strings(mspids)
principals := make([]*mb.MSPPrincipal, len(mspids))
sigspolicy := make([]*cb.SignaturePolicy, len(mspids))
for i, id := range mspids {
principals[i] = &mb.MSPPrincipal{
PrincipalClassification: mb.MSPPrincipal_ROLE,
Principal: utils.MarshalOrPanic(&mb.MSPRole{Role: s.orgs[id], MspIdentifier: id}),
}
sigspolicy[i] = cauthdsl.SignedBy(int32(i))
}
// create the policy: it requires exactly 1 signature from all of the principals
p := &cb.SignaturePolicyEnvelope{
Version: 0,
Rule: cauthdsl.NOutOf(int32(len(mspids)), sigspolicy),
Identities: principals,
}
return p
}