89 lines
3.1 KiB
Go
89 lines
3.1 KiB
Go
/*
|
|
Copyright IBM Corp. All Rights Reserved.
|
|
|
|
SPDX-License-Identifier: Apache-2.0
|
|
*/
|
|
|
|
package scc
|
|
|
|
import (
|
|
"github.com/hyperledger/fabric-chaincode-go/shim"
|
|
pb "github.com/hyperledger/fabric-protos-go/peer"
|
|
"github.com/hyperledger/fabric/common/flogging"
|
|
"github.com/hyperledger/fabric/core/container/ccintf"
|
|
)
|
|
|
|
// SysCCVersion is a constant used for the version field of system chaincodes.
|
|
// Historically, the version of a system chaincode was implicitly tied to the exact
|
|
// build version of a peer, which does not work for collecting endorsements across
|
|
// sccs across peers. Until there is a need for separate SCC versions, we use
|
|
// this constant here.
|
|
const SysCCVersion = "syscc"
|
|
|
|
// ChaincodeID returns the chaincode ID of a system chaincode of a given name.
|
|
func ChaincodeID(ccName string) string {
|
|
return ccName + "." + SysCCVersion
|
|
}
|
|
|
|
// XXX should we change this name to actually match the package name? Leaving now for historical consistency
|
|
var sysccLogger = flogging.MustGetLogger("sccapi")
|
|
|
|
// BuiltinSCCs are special system chaincodes, differentiated from other (plugin)
|
|
// system chaincodes. These chaincodes do not need to be initialized in '_lifecycle'
|
|
// and may be invoked without a channel context. It is expected that '_lifecycle'
|
|
// will eventually be the only builtin SCCs.
|
|
// Note, this field should only be used on _endorsement_ side, never in validation
|
|
// as it might change.
|
|
type BuiltinSCCs map[string]struct{}
|
|
|
|
func (bccs BuiltinSCCs) IsSysCC(name string) bool {
|
|
_, ok := bccs[name]
|
|
return ok
|
|
}
|
|
|
|
// A ChaincodeStreamHandler is responsible for handling the ChaincodeStream
|
|
// communication between a per and chaincode.
|
|
type ChaincodeStreamHandler interface {
|
|
HandleChaincodeStream(ccintf.ChaincodeStream) error
|
|
LaunchInProc(packageID string) <-chan struct{}
|
|
}
|
|
|
|
type SelfDescribingSysCC interface {
|
|
// Unique name of the system chaincode
|
|
Name() string
|
|
|
|
// Chaincode returns the underlying chaincode
|
|
Chaincode() shim.Chaincode
|
|
}
|
|
|
|
// DeploySysCC is the hook for system chaincodes where system chaincodes are registered with the fabric.
|
|
// This call directly registers the chaincode with the chaincode handler and bypasses the other usercc constructs.
|
|
func DeploySysCC(sysCC SelfDescribingSysCC, chaincodeStreamHandler ChaincodeStreamHandler) {
|
|
sysccLogger.Infof("deploying system chaincode '%s'", sysCC.Name())
|
|
|
|
ccid := ChaincodeID(sysCC.Name())
|
|
done := chaincodeStreamHandler.LaunchInProc(ccid)
|
|
|
|
peerRcvCCSend := make(chan *pb.ChaincodeMessage)
|
|
ccRcvPeerSend := make(chan *pb.ChaincodeMessage)
|
|
|
|
go func() {
|
|
stream := newInProcStream(peerRcvCCSend, ccRcvPeerSend)
|
|
defer stream.CloseSend()
|
|
|
|
sysccLogger.Debugf("starting chaincode-support stream for %s", ccid)
|
|
err := chaincodeStreamHandler.HandleChaincodeStream(stream)
|
|
sysccLogger.Criticalf("shim stream ended with err: %v", err)
|
|
}()
|
|
|
|
go func(sysCC SelfDescribingSysCC) {
|
|
stream := newInProcStream(ccRcvPeerSend, peerRcvCCSend)
|
|
defer stream.CloseSend()
|
|
|
|
sysccLogger.Debugf("chaincode started for %s", ccid)
|
|
err := shim.StartInProc(ccid, stream, sysCC.Chaincode())
|
|
sysccLogger.Criticalf("system chaincode ended with err: %v", err)
|
|
}(sysCC)
|
|
<-done
|
|
}
|