Fabric 1.1源代码分析之 系统链码初始化过程(哥哥篇)
# Fabric 1.1源代码分析之 Fabric 1.1源代码分析 系统链码初始化过程
* 链码这一块的代码非常的绕。基本上就是一个大循环。限于水平或者其它原因,差露可能难免,各位看官包涵则个...
* 链码这一块的代码非常的绕。基本上就是一个大循环。限于水平或者其它原因,差露可能难免,各位看官包涵则个...
## 1、系统链码
* 系统链码跟智能合约链码涉及到的文件差不多,流程也差不多。只是智能合约是grpc,系统链码是chan实现调用.
LSCC Lifecycle system chaincode,处理生命周期请求。我理解的生命周期请求应该指的是一个chaincode的安装,实例化,升级,
卸载等对其生命周期起关键作用的一系列操作请求。
CSCC Configuration system chaincode,处理在peer程序端的channel配置。
QSCC Query system chaincode,提供账本查询接口,如获取块和交易信息。
ESCC Endorsement system chaincode,通过对交易申请的应答信息进行签名,来提供背书功能。
VSCC Validation system chaincode,处理交易校验,包括检查背书策略和版本在并发时的控制。
## 2、系统链码注册
* 在/core/chaincode/shim/interfaces_stable.go中实现了下面的接口
```go
type
Chaincode
interface {
// Init is called during Instantiate transaction after the chaincode container
// has been established for the first time, allowing the chaincode to
// initialize its internal data
Init(stub ChaincodeStubInterface) pb.Response
// Invoke is called to update or query the ledger in a proposal transaction.
// Updated state variables are not committed to the ledger until the
// transaction is committed.
Invoke(stub ChaincodeStubInterface) pb.Response
}
```
* 在core/scc/sysccapi.go中定义了SystemChaincode结构体,其中定义了 Chaincode接口变量
```go
type
SystemChaincode
struct {
//Unique name of the system chaincode
Name
string
//Path to the system chaincode; currently not used
Path
string
//InitArgs initialization arguments to startup the system chaincode
InitArgs [][]
byte
// Chaincode is the actual chaincode object
Chaincode shim.Chaincode
// InvokableExternal keeps track of whether
// this system chaincode can be invoked
// through a proposal sent to this peer
InvokableExternal
bool
// InvokableCC2CC keeps track of whether
// this system chaincode can be invoked
// by way of a chaincode-to-chaincode
// invocation
InvokableCC2CC
bool
// Enabled a convenient switch to enable/disable system chaincode without
// having to remove entry from importsysccs.go
Enabled
bool
}
```
* 在 core/scc/importsysccs.go文件中对系统链码进行了初始化,并且每个Chainoce指定了具体实现
在
```go
//see systemchaincode_test.go for an example using "sample_syscc"
var systemChaincodes = []*SystemChaincode{
{
Enabled:
true,
Name:
"cscc",
Path:
"github.com/hyperledger/fabric/core/scc/cscc",
InitArgs: [][]
byte{[]byte(
"")},
Chaincode: &cscc.PeerConfiger{},
InvokableExternal:
true,
// cscc is invoked to join a channel
},
{
Enabled:
true,
Name:
"lscc",
Path:
"github.com/hyperledger/fabric/core/scc/lscc",
InitArgs: [][]
byte{[]byte(
"")},
Chaincode: lscc.NewLifeCycleSysCC(),
InvokableExternal:
true,
// lscc is invoked to deploy new chaincodes
InvokableCC2CC:
true,
// lscc can be invoked by other chaincodes
},
{
Enabled:
true,
Name:
"escc",
Path:
"github.com/hyperledger/fabric/core/scc/escc",
InitArgs: [][]
byte{[]byte(
"")},
Chaincode: &escc.EndorserOneValidSignature{},
},
{
Enabled:
true,
Name:
"vscc",
Path:
"github.com/hyperledger/fabric/core/scc/vscc",
InitArgs: [][]
byte{[]byte(
"")},
Chaincode: &vscc.ValidatorOneValidSignature{},
},
{
Enabled:
true,
Name:
"qscc",
Path:
"github.com/hyperledger/fabric/core/chaincode/qscc",
InitArgs: [][]
byte{[]byte(
"")},
Chaincode: &qscc.LedgerQuerier{},
InvokableExternal:
true,
// qscc can be invoked to retrieve blocks
InvokableCC2CC:
true,
// qscc can be invoked to retrieve blocks also by a cc
},
}
```
* 注册流程图
![](
systemcoderegist.png)
## 3、系统链码初始化
* 系统注册完成后会对链码初始化.跟一般chaincode稍有不同的是chaincode在合约里通过grpc与peer节点交互。
而系统链码则是在协程里通过chan 实现交互.下面代码创建两个 peerRcvCCSend := make(chan *pb.ChaincodeMessage)
ccRcvPeerSend := make(chan *pb.ChaincodeMessage) ,是客户端和服务端共同的参数
```go
func (ipc *inprocContainer) launchInProc(ctxt context.Context, id
string, args []
string, env []
string, ccSupport ccintf.CCSupport)
error {
peerRcvCCSend :=
make(
chan *pb.ChaincodeMessage)
ccRcvPeerSend :=
make(
chan *pb.ChaincodeMessage)
var err error
ccchan :=
make(
chan
struct{},
1)
ccsupportchan :=
make(
chan
struct{},
1)
//启动客户端处理
go
func() {
defer
close(ccchan)
inprocLogger.Debugf(
"chaincode started for %s", id)
if args ==
nil {
args = ipc.args
}
if env ==
nil {
env = ipc.env
}
err := _shimStartInProc(env, args, ipc.chaincode, ccRcvPeerSend, peerRcvCCSend)
if err !=
nil {
err = fmt.Errorf(
"chaincode-support ended with err: %s", err)
_inprocLoggerErrorf(
"%s", err)
}
inprocLogger.Debugf(
"chaincode ended with for %s with err: %s", id, err)
}()
//启动服务端处理
go
func() {
defer
close(ccsupportchan)
inprocStream := newInProcStream(peerRcvCCSend, ccRcvPeerSend)
inprocLogger.Debugf(
"chaincode-support started for %s", id)
err := ccSupport.HandleChaincodeStream(ctxt, inprocStream)
if err !=
nil {
err = fmt.Errorf(
"chaincode ended with err: %s", err)
_inprocLoggerErrorf(
"%s", err)
}
inprocLogger.Debugf(
"chaincode-support ended with for %s with err: %s", id, err)
}()
select {
case <-ccchan:
close(peerRcvCCSend)
inprocLogger.Debugf(
"chaincode %s quit", id)
case <-ccsupportchan:
close(ccRcvPeerSend)
inprocLogger.Debugf(
"chaincode support %s quit", id)
case <-ipc.stopChan:
close(ccRcvPeerSend)
close(peerRcvCCSend)
inprocLogger.Debugf(
"chaincode %s stopped", id)
}
return err
}
```
* 初始化流程图
![](
systemcodeinit.png)
## 4、系统链码的执行
...