Hyperledger Fabric開發(fā)實(shí)戰(zhàn)-08 供應(yīng)鏈金融實(shí)戰(zhàn)

本文是在閱讀《區(qū)塊鏈開發(fā)實(shí)戰(zhàn)-Hyperledger Fabric關(guān)鍵技術(shù)與案例分析》一書的同時(shí),在實(shí)踐中記錄的一些經(jīng)驗(yàn)與分享。

供應(yīng)鏈金融本質(zhì)上是一種金融服務(wù),圍繞核心企業(yè),管理上下游中小企業(yè)的資金流和物流,并把單個(gè)企業(yè)的不可控風(fēng)險(xiǎn)轉(zhuǎn)變?yōu)楣?yīng)鏈企業(yè)整體的可控風(fēng)險(xiǎn),通過獲取各類信息,將風(fēng)險(xiǎn)控制在最低的金融服務(wù)。
在整個(gè)供應(yīng)鏈運(yùn)行中,各個(gè)企業(yè)都使用賒銷作為交易的主流方式,導(dǎo)致處于供應(yīng)鏈中上游的供應(yīng)商,很難通過"傳統(tǒng)"的信貸方式獲得銀行的資金支持,而資金短缺又會(huì)直接導(dǎo)致后續(xù)環(huán)節(jié)的停滯,甚至出現(xiàn)"斷鏈"。供應(yīng)鏈金融的出現(xiàn)可以使供應(yīng)商企業(yè)通過其應(yīng)收賬款,貿(mào)易數(shù)據(jù)等信息進(jìn)行融資。
在供應(yīng)鏈運(yùn)行過程中,各類信息分散保存在各個(gè)環(huán)節(jié)中,供應(yīng)商的貨物信息存儲(chǔ)在供應(yīng)商的倉儲(chǔ)信息中,發(fā)貨信息掌握在物流公司手中,自己信息分布在銀行系統(tǒng)中,信息流由核心企業(yè)掌握,整個(gè)供應(yīng)鏈信息不透明,各個(gè)參與發(fā)都有自己的相關(guān)系統(tǒng),導(dǎo)致整個(gè)過程非常繁瑣,針對(duì)這個(gè)問題,區(qū)塊鏈的出現(xiàn)給解決這些問題到來了曙光。

系統(tǒng)設(shè)計(jì)

在應(yīng)收賬款融資場(chǎng)景中,通常設(shè)計(jì)核心企業(yè),供應(yīng)商,金融機(jī)構(gòu)這三個(gè)參與方。供應(yīng)商發(fā)起供貨交易時(shí),向超級(jí)賬本發(fā)送供貨交易,核心企業(yè)和金融機(jī)構(gòu)簽名并確認(rèn)后,才能記賬成功。

組織

我們按照如下規(guī)則為三個(gè)組織命名:

機(jī)構(gòu)名稱 組織標(biāo)識(shí)符 組織ID 組織域名
核心企業(yè) CoreOrg CoreMSP core.jianshu.com
供應(yīng)商 SupplierOrg SupplierMSP supplier.jianshu.com
金融機(jī)構(gòu) BankOrg BankMSP bank.jianshu.com

生成證書

配置crypto-config.yaml,使用cryptogen可以生成相關(guān)證書

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

啟動(dòng)系統(tǒng)

規(guī)劃好系統(tǒng)之后,整個(gè)啟動(dòng)過程與之前的一樣,不過這次我們將orderer和三個(gè)peer分別部署在4臺(tái)服務(wù)器上,服務(wù)器可以在UCloud上按小時(shí)付費(fèi)臨時(shí)使用。
具體可以參見Hyperledger Fabric開發(fā)實(shí)戰(zhàn)-02簡(jiǎn)單網(wǎng)絡(luò)的整個(gè)流程。

Chaincode

Chaincode中主要是調(diào)用方法,有三個(gè):
putvalue方法,會(huì)設(shè)置資產(chǎn)的價(jià)格
getlastvalue方法用于獲取資產(chǎn)的價(jià)格
gethistory方法用于獲取資產(chǎn)的歷史

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)
        }
}

客戶端開發(fā)

下面是發(fā)送交易的代碼,channel首先通過sendTransactionProposal發(fā)送提案,獲取響應(yīng)之后,如果所有請(qǐng)求都成功,通過sendTransaction發(fā)送交易。

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);
    });
    
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容