Hyperledger Fabric开发实战

Hyperledger Fabric开发实战-08 供应链金融实

2018-12-09  本文已影响0人  史圣杰

本文是在阅读《区块链开发实战-Hyperledger Fabric关键技术与案例分析》一书的同时,在实践中记录的一些经验与分享。

供应链金融本质上是一种金融服务,围绕核心企业,管理上下游中小企业的资金流和物流,并把单个企业的不可控风险转变为供应链企业整体的可控风险,通过获取各类信息,将风险控制在最低的金融服务。
在整个供应链运行中,各个企业都使用赊销作为交易的主流方式,导致处于供应链中上游的供应商,很难通过"传统"的信贷方式获得银行的资金支持,而资金短缺又会直接导致后续环节的停滞,甚至出现"断链"。供应链金融的出现可以使供应商企业通过其应收账款,贸易数据等信息进行融资。
在供应链运行过程中,各类信息分散保存在各个环节中,供应商的货物信息存储在供应商的仓储信息中,发货信息掌握在物流公司手中,自己信息分布在银行系统中,信息流由核心企业掌握,整个供应链信息不透明,各个参与发都有自己的相关系统,导致整个过程非常繁琐,针对这个问题,区块链的出现给解决这些问题到来了曙光。

系统设计

在应收账款融资场景中,通常设计核心企业,供应商,金融机构这三个参与方。供应商发起供货交易时,向超级账本发送供货交易,核心企业和金融机构签名并确认后,才能记账成功。

组织

我们按照如下规则为三个组织命名:

机构名称 组织标识符 组织ID 组织域名
核心企业 CoreOrg CoreMSP core.jianshu.com
供应商 SupplierOrg SupplierMSP supplier.jianshu.com
金融机构 BankOrg BankMSP bank.jianshu.com

生成证书

配置crypto-config.yaml,使用cryptogen可以生成相关证书

OrdererOrgs:
    - Name: Orderer
      Domain: jianshu.com
      Specs:
            - Hostname: orderer
PeerOrgs:
    - Name: Core
      Domain: core.jianshu.com
      Template:
            Count: 2
      Users:
            Count: 2
    - Name: Supplier
      Domain: supplier.jianshu.com
      Template:
          Count: 2
      Users:
          Count: 2
    - Name: Bank
      Domain: bank.jianshu.com
      Template:
          Count: 2
      Users:
          Count: 2

启动系统

规划好系统之后,整个启动过程与之前的一样,不过这次我们将orderer和三个peer分别部署在4台服务器上,服务器可以在UCloud上按小时付费临时使用。
具体可以参见Hyperledger Fabric开发实战-02简单网络的整个流程。

Chaincode

Chaincode中主要是调用方法,有三个:
putvalue方法,会设置资产的价格
getlastvalue方法用于获取资产的价格
gethistory方法用于获取资产的历史

package main

import (
   "github.com/hyperledger/fabric/core/chaincode/shim"
        pb "github.com/hyperledger/fabric/protos/peer"
        "fmt"
        "encoding/json"
        "time"
)

var asset_name = "asset_name_a"
type scfinancechaincode struct {
    
}

func (t *scfinancechaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
    fmt.Printf(" init success")
    return shim.Success([]byte("init success"))
}

func (t *scfinancechaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response{

    _,args := stub.GetFunctionAndParameters()
    var opttype = args[0]
    var assetname = args[1]
    var optcontent = args[2]

    fmt.Printf("param is %s %s %s \n",opttype,assetname,optcontent)
    if opttype == "putvalue"{
        stub.PutState(assetname,[]byte(optcontent))
        return shim.Success([]byte("success put" + optcontent))
    }else if opttype == "getlastvalue"{
        var kv []byte
        var err error
        kv,err = stub.GetState(assetname)
        if(err != nil){
            return shim.Error("find error!")
        }
        return shim.Success(kv)
    }else if opttype == "gethistory"{
        keysIter,err := stub.GetHistoryForKey(assetname)
        if err != nil {
            return shim.Error(fmt.Sprintf("GetHistoryForKey failed,Error state: %s",err))
        }
        defer keysIter.Close()
        var keys []string
        for keysIter.HasNext(){
            response,iterErr := keysIter.Next()
            if iterErr != nil {
                return shim.Error(fmt.Sprintf("GetHistoryForKey operation failed,Error state: %s",err))
            }

            txid := response.TxId 
            txvalue := response.Value
            txstate := response.IsDelete
            txtimestamp := response.Timestamp
            tm := time.Unix(txtimestamp.Seconds,0)
            datestr := tm.Format("2006-01-02 03:04:05 PM")

            fmt.Printf(" Tx info - txid: %s value: %s if delete: %t datetime: %s\n",txid,string(txvalue),txstate,datestr)
            keys = append(keys,txid)
        }

        jsonKeys,err := json.Marshal(keys)
        if err != nil {
            return shim.Error(fmt.Sprintf("query operation failed,error is %s",err))
        }
        return shim.Success(jsonKeys)
    }else{
        return  shim.Success([]byte("success invoke and No operation"))
    }
}

func main() {
        err := shim.Start(new(scfinancechaincode))
        if err != nil {
                fmt.Printf("Error starting Simple chaincode: %s", err)
        }
}

客户端开发

下面是发送交易的代码,channel首先通过sendTransactionProposal发送提案,获取响应之后,如果所有请求都成功,通过sendTransaction发送交易。

var sendTransaction = function(chaincodeId,func,chaincode_args,channelname){
    let tx_id = null;
    return getOrgUser4Local().then((user) =>{
        tx_id = client.newTransactionID();
        var request = {
            chaincodeId:"supplychain-chaincode",
            fcn:func,
            args:chaincode_args,
            chainId:"cmbcchannel666",
            txId:tx_id
        };
        return channel.sendTransactionProposal(request);
    },(err) => {
        console.log("error",e);
    }).then((chaincodeInvokeResult) => {
        var proposalResponse = chaincodeInvokeResult[0];
        var proposal = chaincodeInvokeResult[1];
        var header = chaincodeInvokeResult[2];
        var all_good = true;
        for(var i in proposalResponse){
            let one_good = false;
            if(proposalResponse && proposalResponse[i].response &&
            proposalResponse[i].response.status === 200){
                one_good = true;
                console.log("transaction is good");
            }else{
                console.error("transaction is bad");
            }
            all_good = all_good & one_good;
        }
        if(all_good){
                /*console.info(util.format(
        
                'successfullly: status - %s,message - "%s",metadata - "%s",endorsemenet signature:"%s"',
                proposalResponse[0].response.status,proposalResponse[0].response.message,
                proposalResponse[0].response.payload,proposalResponse[0].response.endorsement.signature
            ));*/
        
        
            var request = {
                proposalResponses:proposalResponse,
                proposal:proposal,
                header:header
            }
        
            var transactionID = tx_id.getTransactionID();
            return channel.sendTransaction(request);
    
        }
    },(err) => {
        console.log("error",err);
    }).then((sendtransresult) => {
        return sendtransresult;
    },(err) =>{
        console.log("error",err);
    });
    
}
上一篇下一篇

猜你喜欢

热点阅读