Skip to content

Commit b7fd939

Browse files
committed
[FAB-187] VSCC uses policies specified upon deploy
This change-set provides support for endorsement policies. At chaincode deploy time, the deployer can specify the endorsement policy it requires from command line. The cc deploy tx is sent to lccc which stores the policy. Later, the validator can extract the policy and send it to VSCC. Change-Id: Ic1bc0e492a9070a355cfba83dfa56d121902c543 Signed-off-by: Alessandro Sorniotti <[email protected]>
1 parent 6255f8d commit b7fd939

File tree

15 files changed

+380
-102
lines changed

15 files changed

+380
-102
lines changed

core/chaincode/ccproviderimpl.go

+12-5
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,8 @@ package chaincode
1919
import (
2020
"context"
2121

22+
"fmt"
23+
2224
"github.com/hyperledger/fabric/core/common/ccprovider"
2325
"github.com/hyperledger/fabric/core/ledger"
2426
pb "github.com/hyperledger/fabric/protos/peer"
@@ -72,18 +74,23 @@ func (c *ccProviderImpl) GetCCContext(cid, name, version, txid string, syscc boo
7274

7375
// GetCCValidationInfoFromLCCC returns the VSCC and the policy listed in LCCC for the supplied chaincode
7476
func (c *ccProviderImpl) GetCCValidationInfoFromLCCC(ctxt context.Context, txid string, prop *pb.Proposal, chainID string, chaincodeID string) (string, []byte, error) {
77+
// LCCC does not have any notion about its own
78+
// endorsing policy - we should never call this
79+
// function with lccc as the chaincodeID
80+
if chaincodeID == "lccc" {
81+
panic("GetCCValidationInfoFromLCCC invoke for LCCC")
82+
}
83+
7584
data, err := GetChaincodeDataFromLCCC(ctxt, txid, prop, chainID, chaincodeID)
7685
if err != nil {
7786
return "", nil, err
7887
}
7988

80-
vscc := "vscc"
81-
// Check whenever VSCC defined for chaincode data
82-
if data != nil && data.Vscc != "" {
83-
vscc = data.Vscc
89+
if data == nil || data.Vscc == "" || data.Policy == nil {
90+
return "", nil, fmt.Errorf("Incorrect validation info in LCCC")
8491
}
8592

86-
return vscc, data.Policy, nil
93+
return data.Vscc, data.Policy, nil
8794
}
8895

8996
// ExecuteChaincode executes the chaincode specified in the context with the specified arguments

core/chaincode/exectransaction_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,7 @@ func endTxSimulationCDS(chainID string, txid string, txsim ledger.TxSimulator, p
141141
return err
142142
}
143143
// get a proposal - we need it to get a transaction
144-
prop, err := putils.CreateDeployProposalFromCDS(txid, chainID, cds, ss)
144+
prop, err := putils.CreateDeployProposalFromCDS(txid, chainID, cds, ss, nil, nil, nil)
145145
if err != nil {
146146
return err
147147
}

core/committer/txvalidator/validator.go

+24-65
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,17 @@ import (
2020
"fmt"
2121

2222
"github.com/golang/protobuf/proto"
23-
"github.com/hyperledger/fabric/common/cauthdsl"
2423
coreUtil "github.com/hyperledger/fabric/common/util"
2524
"github.com/hyperledger/fabric/core/chaincode/shim"
2625
"github.com/hyperledger/fabric/core/common/ccprovider"
2726
"github.com/hyperledger/fabric/core/common/validation"
2827
"github.com/hyperledger/fabric/core/ledger"
2928
ledgerUtil "github.com/hyperledger/fabric/core/ledger/util"
3029
"github.com/hyperledger/fabric/msp"
30+
3131
"github.com/hyperledger/fabric/protos/common"
3232
"github.com/hyperledger/fabric/protos/utils"
3333
"github.com/op/go-logging"
34-
"github.com/syndtr/goleveldb/leveldb/errors"
3534
)
3635

3736
// Support provides all of the needed to evaluate the VSCC
@@ -177,41 +176,6 @@ func (v *txValidator) Validate(block *common.Block) error {
177176
return nil
178177
}
179178

180-
// getSemiHardcodedPolicy returns a policy that requests
181-
// one valid signature from the first MSP in this
182-
// chain's MSP manager
183-
// FIXME: this needs to be removed as soon as we extract the policy from LCCC
184-
func getSemiHardcodedPolicy(chainID string, mspMgr msp.MSPManager) ([]byte, error) {
185-
// 1) determine the MSP identifier for the first MSP in this chain
186-
var msp msp.MSP
187-
msps, err := mspMgr.GetMSPs()
188-
if err != nil {
189-
return nil, fmt.Errorf("Could not retrieve the MSPs for the chain manager, err %s", err)
190-
}
191-
if len(msps) == 0 {
192-
return nil, errors.New("At least one MSP was expected")
193-
}
194-
for _, m := range msps {
195-
msp = m
196-
break
197-
}
198-
mspid, err := msp.GetIdentifier()
199-
if err != nil {
200-
return nil, fmt.Errorf("Failure getting the msp identifier, err %s", err)
201-
}
202-
203-
// 2) get the policy
204-
p := cauthdsl.SignedByMspMember(mspid)
205-
206-
// 3) marshal it and return it
207-
b, err := proto.Marshal(p)
208-
if err != nil {
209-
return nil, fmt.Errorf("Could not marshal policy, err %s", err)
210-
}
211-
212-
return b, err
213-
}
214-
215179
func (v *vsccValidatorImpl) VSCCValidateTx(payload *common.Payload, envBytes []byte) error {
216180
// Chain ID
217181
chainID := payload.Header.ChainHeader.ChainID
@@ -230,21 +194,6 @@ func (v *vsccValidatorImpl) VSCCValidateTx(payload *common.Payload, envBytes []b
230194
return err
231195
}
232196

233-
// TODO: temporary workaround until the policy is specified
234-
// by the deployer and can be retrieved via LCCC: we create
235-
// a policy that requests 1 valid signature from this chain's
236-
// MSP
237-
policy, err := getSemiHardcodedPolicy(chainID, v.support.MSPManager())
238-
if err != nil {
239-
return err
240-
}
241-
242-
// build arguments for VSCC invocation
243-
// args[0] - function name (not used now)
244-
// args[1] - serialized Envelope
245-
// args[2] - serialized policy
246-
args := [][]byte{[]byte(""), envBytes, policy}
247-
248197
ctxt, err := v.ccprovider.GetContext(v.support.Ledger())
249198
if err != nil {
250199
logger.Errorf("Cannot obtain context for txid=%s, err %s", txid, err)
@@ -258,22 +207,32 @@ func (v *vsccValidatorImpl) VSCCValidateTx(payload *common.Payload, envBytes []b
258207
return err
259208
}
260209

261-
// TODO: Temporary solution until FAB-1422 get resolved
262-
// Explanation: we actually deploying chaincode transaction,
263-
// hence no lccc yet to query for the data, therefore currently
264-
// introducing a workaround to skip obtaining LCCC data.
265-
vscc := "vscc"
266-
if hdrExt.ChaincodeID.Name != "lccc" {
267-
// Extracting vscc from lccc
268-
// TODO: extract policy as well when available; it's the second argument returned by GetCCValidationInfoFromLCCC
269-
vscc, _, err = v.ccprovider.GetCCValidationInfoFromLCCC(ctxt, txid, nil, chainID, hdrExt.ChaincodeID.Name)
270-
if err != nil {
271-
logger.Errorf("Unable to get chaincode data from LCCC for txid %s, due to %s", txid, err)
272-
return err
273-
}
210+
// LCCC should not undergo standard VSCC type of
211+
// validation. It should instead go through system
212+
// policy validation to determine whether the issuer
213+
// is entitled to deploy a chaincode on our chain
214+
// VSCCValidateTx should
215+
if hdrExt.ChaincodeID.Name == "lccc" {
216+
// TODO: until FAB-1934 is in, we need to stop here
217+
logger.Infof("Invocation of LCCC detected, no further VSCC validation necessary")
218+
return nil
219+
}
220+
221+
// obtain name of the VSCC and the policy from LCCC
222+
vscc, policy, err := v.ccprovider.GetCCValidationInfoFromLCCC(ctxt, txid, nil, chainID, hdrExt.ChaincodeID.Name)
223+
if err != nil {
224+
logger.Errorf("Unable to get chaincode data from LCCC for txid %s, due to %s", txid, err)
225+
return err
274226
}
275227

228+
// build arguments for VSCC invocation
229+
// args[0] - function name (not used now)
230+
// args[1] - serialized Envelope
231+
// args[2] - serialized policy
232+
args := [][]byte{[]byte(""), envBytes, policy}
233+
276234
vscctxid := coreUtil.GenerateUUID()
235+
277236
// Get chaincode version
278237
version := coreUtil.GetSysCCVersion()
279238
cccid := v.ccprovider.GetCCContext(chainID, vscc, version, vscctxid, true, nil)
+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
/*
2+
Copyright IBM Corp. 2017 All Rights Reserved.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package sysccprovider
18+
19+
// SystemChaincodeProvider provides an abstraction layer that is
20+
// used for different packages to interact with code in the
21+
// system chaincode package without importing it; more methods
22+
// should be added below if necessary
23+
type SystemChaincodeProvider interface {
24+
// IsSysCC returns true if the supplied chaincode is a system chaincode
25+
IsSysCC(name string) bool
26+
}
27+
28+
var sccFactory SystemChaincodeProviderFactory
29+
30+
// SystemChaincodeProviderFactory defines a factory interface so
31+
// that the actual implementation can be injected
32+
type SystemChaincodeProviderFactory interface {
33+
NewSystemChaincodeProvider() SystemChaincodeProvider
34+
}
35+
36+
// RegisterSystemChaincodeProviderFactory is to be called once to set
37+
// the factory that will be used to obtain instances of ChaincodeProvider
38+
func RegisterSystemChaincodeProviderFactory(sccfact SystemChaincodeProviderFactory) {
39+
sccFactory = sccfact
40+
}
41+
42+
// GetSystemChaincodeProvider returns instances of SystemChaincodeProvider;
43+
// the actual implementation is controlled by the factory that
44+
// is registered via RegisterSystemChaincodeProviderFactory
45+
func GetSystemChaincodeProvider() SystemChaincodeProvider {
46+
if sccFactory == nil {
47+
panic("The factory must be set first via RegisterSystemChaincodeProviderFactory")
48+
}
49+
return sccFactory.NewSystemChaincodeProvider()
50+
}

core/endorser/endorser.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ func (e *Endorser) callChaincode(ctxt context.Context, chainID string, version s
128128
//
129129
//NOTE that if there's an error all simulation, including the chaincode
130130
//table changes in lccc will be thrown away
131-
if cid.Name == "lccc" && len(cis.ChaincodeSpec.Input.Args) == 3 && (string(cis.ChaincodeSpec.Input.Args[0]) == "deploy" || string(cis.ChaincodeSpec.Input.Args[0]) == "upgrade") {
131+
if cid.Name == "lccc" && len(cis.ChaincodeSpec.Input.Args) >= 3 && (string(cis.ChaincodeSpec.Input.Args[0]) == "deploy" || string(cis.ChaincodeSpec.Input.Args[0]) == "upgrade") {
132132
var ccVersion string
133133
switch string(cis.ChaincodeSpec.Input.Args[0]) {
134134
case "deploy":

core/peer/peer.go

+12
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434
"github.com/hyperledger/fabric/core/ledger"
3535
"github.com/hyperledger/fabric/core/ledger/ledgermgmt"
3636
"github.com/hyperledger/fabric/gossip/service"
37+
"github.com/hyperledger/fabric/msp"
3738
mspmgmt "github.com/hyperledger/fabric/msp/mgmt"
3839
"github.com/hyperledger/fabric/peer/sharedconfig"
3940
"github.com/hyperledger/fabric/protos/common"
@@ -255,6 +256,17 @@ func GetLedger(cid string) ledger.PeerLedger {
255256
return nil
256257
}
257258

259+
// GetMSPMgr returns the MSP manager of the chain with chain ID.
260+
// Note that this call returns nil if chain cid has not been created.
261+
func GetMSPMgr(cid string) msp.MSPManager {
262+
chains.RLock()
263+
defer chains.RUnlock()
264+
if c, ok := chains.list[cid]; ok {
265+
return c.cs.MSPManager()
266+
}
267+
return nil
268+
}
269+
258270
// GetCommitter returns the committer of the chain with chain ID. Note that this
259271
// call returns nil if chain cid has not been created.
260272
func GetCommitter(cid string) committer.Committer {

0 commit comments

Comments
 (0)