智能合约 与 chaincode(Smart Contract & chaincode):
一个chaincode可以包含多个智能合约;
智能合约:用来创建交易transaction的,它产生的transaction,会被记在账本里(在智能合约里我们定义了各个organiza组织之间的业务规则,业务规范);
1、智能合约是如何跟账本Ledger交流的 (1)blockchain的开发人员根据客户的业务逻辑编写智能合约 (2)blockchain的开发人员根据客户的需求开发Client端 (3)当客户端发送一个请求的时候,可以通过智能合约调用API去操作Worldstate DB(增删改查get,put,delete) ?? ?get->直接返回数据,不会在区块里存下任何交易; ?? ?put/delete->在修改操作Worldstate的同时还会在blockchain里增加新的区块,增加新的交易记录; (4)当交易完成的时候通过智能合约发送Event,通知交易结果; (5)还可以通过Client端直接操作blockchain
?2、Hyperledger Fabric智能合约的一个例子: 一个智能合约创建完,需要把它打包,打包到chaincode里,chaincode只有部署了之后才能给用户去使用(一个chaincode可以包含多个智能合约); Fabric的Chaincode运行在容器中,可以使用Go,Java,Node.js语言开发,Golang是目前为主比较成熟稳定的; 也有人将智能合约称为Chaincode(其实这样是不准确的); 智能合约的组成: (1)必须在main包下; (2)导入blockchain的API的依赖; (3)定义一个结构体; (4)为结构体绑定Init()和Invoke()方法: ?? ?4.1 初始化链码Init()方法,Initialize the chaincode; ?? ?4.2 绑定Invoke()方法,在chaincode实例化完成之后,真正执行一个交易的时候,就会调用Invoke()方法; (5)主方法-main()函数;
一个完整的例子 // (1)必须在main包下: package main // (2)导入blockchain的API的依赖: import( ? ?"fmt" ? ?"github.com/hyperledger/fabric/core/chaincode/shim" ? ?pb "github.com/hyperledger/fabric/protos/peer" ) //(3)定义一个结构体: type SimpleChaincode struct { } //(4)为结构体绑定Init()和Invoke()方法: // 4.1 初始化链码()Initialize the chaincode func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response{ ?? ?fmt.Println(" << ====[Init] success init it is view in docker ======") ? ? // 定义A,B两个参数 ?? ?A = args[0] ?? ?Aval, err = strconv.Atoi(args[1]) ?? ?B = args[2] ?? ?Bval, err = strconv.Atoi(args[3]) ?? ?fmt.Printf("Aval= d%, Bval= d%\n", Aval, Bval) ?? ?// 调用API,stub.PutState(),将数据存到worldstate DB里(Write the state to the ledger) ?? ?err = stub.PutState(A, []byte(strconv.Atoa(Aval))) ?? ?err = stub.PutState(B, []byte(strconv.Atoa(Bval))) ? ? return shim.Success([]byte("success init")) } // 4.2 绑定Invoke()方法,在chaincode实例化完成之后,真正执行一个交易的时候,就会调用Invoke()方法 func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response{ ? ? fmt.Println(" << ====[Invoke] success init it is view in docker ======") ?? ?function, args := stub.GetFunctionAndParameters() ?? ?if function == "invoke"{ ?? ??? ?// 把数据从A转给B ?? ??? ?return t.invoke(stub, args) ?? ?}else if function == "delete"{ ?? ??? ?// 从Worldstate DB里删掉这个实体 ?? ??? ?return t.delete(stub, args) ?? ?}else if function == "query"{ ?? ??? ?// 查询某个数据 ?? ??? ?return t.query(stub, args) ?? ?} ? ? return shim.Success([]byte("success init")) } //(5)还可以通过Client端直接操作blockchain: func main(){ ? ? err := shim.Start(new(SimpleChaincode)) ? ? if err != nil{ ? ? ? ? fmt.Println("Error starting Simple chaincode : %s",err) ? ? } }
3、Chaincode LifeCycle链码的命周期 打包 ? ?-> 安装 ? ?-> 实例化 ? ? ?-> 运行 Package -> Install -> Instantiate -> Running Upgrade -> Running
Instantiate状态:实例化的时候会做一些数据初始化的工作,就会执行Init()方法;
(1)Package:对chaincode进行打包: ?? ?① 打包的时候会生成CDS(ChaincodeDeploymentSpec) ?? ??? ?the source code-包含了源代码; ?? ??? ?the name-定义了chaincode的名字; ?? ??? ?version-定义了版本; ?? ?② 打包的时候还可以指定初始化时的背书策略Endorsement Policies-指定谁来做实例化; ?? ?③ 打包的时候还可以指定初始化时的签名Signatures-指定谁拥有own这个chaincode; ?? ?④ 打包chaincode 命令: ?? ??? ?$ peer chaincode package -n mycc -p github.com/hyperledger/fabric-samples/chaincode/abstore/go? ?? ??? ? ?-v 1.0 -s -S -i "AND('OrgA.admin')" ccpack.out ?? ??? ??? ?# chaincode名 ?? ??? ??? ?-n mycc ?? ??? ??? ?# chaincode path路径 ?? ??? ??? ?-p github.com/hyperledger/fabric-samples/chaincode/abstore/go ?? ??? ??? ?# 版本 ?? ??? ??? ?-v 1.0 ?? ??? ??? ?# 实例化的policy ?? ??? ??? ?-i "AND('OrgA.admin')" ?? ??? ??? ?# 打包的结果是:ccpack.out ?? ?⑤ 打包好之后进行签名 ?? ??? ?$ peer chaincode signpackage ccpack.out signedccpack.out (2)Install:安装chaincode; ?? ?① chaincode是安装在peer节点上的; ?? ?② 一个peer节点能安装多个chaincode(一个chaincode可以包含多个智能合约); ?? ?③ 这个channel上所有的背书节点,都要安装上这个chaincode; ?? ??? ?$ peer chaincode instantiate -n mycc -v1.0 -c '{"Args": ["a", "100", "b", "200"]}' -P " AND('Org1.member', 'Org2.member')" (3)Running:运行状态; ?? ?① Running状态Client端就可以发送交易请求了,发送了交易请求 -> chaincode就可以产生,创建交易记录 -> 更新账本Ledger -> Clien端收到返回的交易结果(完成一个真正的交易记录); ?? ??? ?# 在mycha的channel上查询a的值,chaincode名字是mycc; ?? ??? ?$ peer chaincode query -C mycha -n mycc -c '{"Args":["query", a]}' ?? ??? ?# 做一个交易,从a转移10块钱给b ?? ??? ?$ peer chaincode invoke -o order-url -C mycha -n mycc -c '{"Args":["invoke","a","b","10"]}' (4)Upgrade:更新链码; ?? ?一个chaincode可以随时被更新; ?? ?在更新之前我们要把新版本的chaincode安装到所有的背书节点上; ?? ?执行更新命令: ?? ?$ peer chaincode upgrade -C mycha -n mycc -v1.0 -c '{"Args": ["a", "200", "b", "600"]}'
4、System Chaincode,系统chaincode-除了我们手写的chaincode,系统也有一些System Chaincode,为我们提供一些功能: ?? ?System Chaincode是运行在peer节点的进程上,我们手写的chaincode会新起一个进程来运行; ?? ?LSCC(LifeCycle System chaincode):处理打包Package,处理安装Install,处理升级Upgrade等,都是通过LSCC处理的; ?? ?CSCC(Configuration system chaincode):在组建一个channel的时候,配置一些参数都是通过CSCC处理的; ?? ?QSCC(Query system chaincode):提供了一些账本Ledger查询的API,通过这些API我们可以取到block,和历史交易记录;
|