国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

Hyperledger Fabric 使用 CouchDB 和復(fù)雜智能合約開發(fā)

這篇具有很好參考價(jià)值的文章主要介紹了Hyperledger Fabric 使用 CouchDB 和復(fù)雜智能合約開發(fā)。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

前言

在上個(gè)實(shí)驗(yàn)中,我們已經(jīng)實(shí)現(xiàn)了簡單智能合約實(shí)現(xiàn)及客戶端開發(fā),但該實(shí)驗(yàn)中智能合約只有基礎(chǔ)的增刪改查功能,且其中的數(shù)據(jù)管理功能與傳統(tǒng) MySQL 比相差甚遠(yuǎn)。本文將在前面實(shí)驗(yàn)的基礎(chǔ)上,將 Hyperledger Fabric 的默認(rèn)數(shù)據(jù)庫支持 LevelDB 改為 CouchDB 模式,以實(shí)現(xiàn)更復(fù)雜的數(shù)據(jù)檢索功能。此外,對上個(gè)實(shí)驗(yàn)的簡單智能合約進(jìn)一步進(jìn)行功能上和設(shè)計(jì)上的擴(kuò)展,最終實(shí)現(xiàn)了智能合約的分包、分頁查詢、多字段富查詢、查詢交易歷史記錄等功能。

網(wǎng)絡(luò)架構(gòu)

本文網(wǎng)絡(luò)結(jié)構(gòu)直接將 Hyperledger Fabric無排序組織以Raft協(xié)議啟動多個(gè)Orderer服務(wù)、TLS組織運(yùn)行維護(hù)Orderer服務(wù) 中創(chuàng)建的 4-2_RunOrdererByCouncil 復(fù)制為 7_CouchDBAndComplexContract 并修改(建議直接將本案例倉庫 FabricLearn 下的 7_CouchDBAndComplexContract 目錄拷貝到本地運(yùn)行),文中大部分命令在 Hyperledger Fabric定制聯(lián)盟鏈網(wǎng)絡(luò)工程實(shí)踐 中已有介紹因此不會詳細(xì)說明,默認(rèn)情況下,所有操作皆在 7_CouchDBAndComplexContract 根目錄下執(zhí)行。修改成功后網(wǎng)絡(luò)共包含四個(gè)組織—— council 、 soft 、 web 、 hard , 其中 council 組織為網(wǎng)絡(luò)提供 TLS-CA 服務(wù),并且運(yùn)行維護(hù)著三個(gè) orderer 服務(wù);其余每個(gè)組織都運(yùn)行維護(hù)著一個(gè) peer 節(jié)點(diǎn)、一個(gè) couchDB 服務(wù)、一個(gè) admin 用戶和一個(gè) user 用戶,實(shí)驗(yàn)最終網(wǎng)絡(luò)結(jié)構(gòu)如下:

項(xiàng) 運(yùn)行端口 說明
council.ifantasy.net 7050 council 組織的 CA 服務(wù), 為聯(lián)盟鏈網(wǎng)絡(luò)提供 TLS-CA 服務(wù)
orderer1.council.ifantasy.net 7051 council 組織的 orderer1 服務(wù)
orderer1.council.ifantasy.net 7052 council 組織的 orderer1 服務(wù)的 admin 服務(wù)
orderer2.council.ifantasy.net 7054 council 組織的 orderer2 服務(wù)
orderer2.council.ifantasy.net 7055 council 組織的 orderer2 服務(wù)的 admin 服務(wù)
orderer3.council.ifantasy.net 7057 council 組織的 orderer3 服務(wù)
orderer3.council.ifantasy.net 7058 council 組織的 orderer3 服務(wù)的 admin 服務(wù)
soft.ifantasy.net 7250 soft 組織的 CA 服務(wù), 包含成員: peer1 、 admin1 、user1
peer1.soft.ifantasy.net 7251 soft 組織的 peer1 成員節(jié)點(diǎn)
couchdb.soft.ifantasy.net 7255 soft 組織的 couchdb 成員節(jié)點(diǎn)
web.ifantasy.net 7350 web 組織的 CA 服務(wù), 包含成員: peer1 、 admin1 、user1
peer1.web.ifantasy.net 7351 web 組織的 peer1 成員節(jié)點(diǎn)
couchdb.web.ifantasy.net 7355 web 組織的 couchdb 成員節(jié)點(diǎn)
hard.ifantasy.net 7450 hard 組織的 CA 服務(wù), 包含成員: peer1 、 admin1 、user1
peer1.hard.ifantasy.net 7451 hard 組織的 peer1 成員節(jié)點(diǎn)
couchdb.hard.ifantasy.net 7455 hard 組織的 couchdb 成員節(jié)點(diǎn)

添加CouchDB支持并啟動網(wǎng)絡(luò)

添加CouchDB支持

首先,在 envpeer1softenvpeer1soft 、 envpeer1soft 中添加 CouchDB 版本變量:

export COUCHDB_VERSION=3.2

然后,向 compose/docker-base.yaml 文件添加基礎(chǔ) CouchDB 鏡像:

couchdb-base:
    image: couchdb:${COUCHDB_VERSION}
    environment:
      - COUCHDB_USER=admin
      - COUCHDB_PASSWORD=adminpw
    networks:
      - ${DOCKER_NETWORKS}

之后,向 compose/docker-compose.yaml 中的每個(gè)組織添加 CouchDB 容器:

couchdb.soft.ifantasy.net:
    container_name: couchdb.soft.ifantasy.net
    extends:
      file: docker-base.yaml
      service: couchdb-base
    ports:
      - 7255:5984

couchdb.web.ifantasy.net:
    container_name: couchdb.web.ifantasy.net
    extends:
      file: docker-base.yaml
      service: couchdb-base
    ports:
      - 7355:5984

couchdb.hard.ifantasy.net:
    container_name: couchdb.hard.ifantasy.net
    extends:
      file: docker-base.yaml
      service: couchdb-base
    ports:
      - 7455:5984

最后,修改 compose/docker-compose.yaml 中每個(gè) peer 容器的儲存方式(以 peer1.soft.ifantasy.net 為例):

  peer1.soft.ifantasy.net:
    container_name: peer1.soft.ifantasy.net
    extends:
      file: docker-base.yaml
      service: peer-base
    environment:
      - CORE_PEER_ID=peer1.soft.ifantasy.net
      - CORE_PEER_LISTENADDRESS=0.0.0.0:7251
      - CORE_PEER_ADDRESS=peer1.soft.ifantasy.net:7251
      - CORE_PEER_LOCALMSPID=softMSP
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.soft.ifantasy.net:7251
      - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
      - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb.soft.ifantasy.net:5984   # 必須為容器內(nèi)端口
      - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=admin
      - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=adminpw
    volumes:
      - ${LOCAL_CA_PATH}/soft.ifantasy.net/registers/peer1:${DOCKER_CA_PATH}/peer
    ports:
      - 7251:7251
    depends_on:
      - couchdb.soft.ifantasy.net

注意,參數(shù) CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS 后的服務(wù)端口必須為 couchdb 容器的內(nèi)部端口,原因不得而知, 完整代碼見 FabricLearn 下的 7_CouchDBAndComplexContract/compose 目錄。

啟動實(shí)驗(yàn)網(wǎng)絡(luò)

在上述修改完成后,在 7_CouchDBAndComplexContract 目錄下按順序執(zhí)行以下命令啟動基礎(chǔ)實(shí)驗(yàn)網(wǎng)絡(luò):

  1. 設(shè)置DNS(如果未設(shè)置): ./setDNS.sh
  2. 設(shè)置環(huán)境變量: source envpeer1soft
  3. 啟動CA網(wǎng)絡(luò): ./0_Restart.sh
  4. 注冊用戶: ./1_RegisterUser.sh
  5. 獲取用戶證書: ./2_EnrollUser.sh
  6. 配置通道: ./3_Configtxgen.sh

網(wǎng)絡(luò)啟動成功后可見包含 couchdb 容器:

合約開發(fā)

本節(jié)所用智能合約由前一篇文章 Hyperledger Fabric 智能合約開發(fā)及 fabric-sdk-go/fabric-gateway 使用示例 改進(jìn)(拆分)而來,在上篇文章的基礎(chǔ)上對合約進(jìn)行分包分文件處理,使項(xiàng)目具有更好的目錄結(jié)構(gòu)。在實(shí)驗(yàn)根目錄 7_CouchDBAndComplexContract 下創(chuàng)建目錄 project_contract 作為智能合約根目錄,在 project_contract 下執(zhí)行以下命令初始化 GO 模塊:

go mod init github.com/wefantasy/FabricLearn/7_CouchDBAndComplexContract/project_contract

tools 層

tools 層主要用于編寫智能合約通用工具,創(chuàng)建 tools/contract.go 工具類,主要包含以下函數(shù):

  • ConstructResultByIterator : 根據(jù) fabric 查詢結(jié)果 shim.StateQueryIteratorInterface 生成對應(yīng)切片。
    // 根據(jù)查詢結(jié)果生成切片
    func ConstructResultByIterator[T interface{}](resultsIterator shim.StateQueryIteratorInterface) ([]*T, error) {
        var txs []*T
        for resultsIterator.HasNext() {
            queryResult, err := resultsIterator.Next()
            if err != nil {
                return nil, err
            }
            var tx T
            err = json.Unmarshal(queryResult.Value, &tx)
            if err != nil {
                return nil, err
            }
            txs = append(txs, &tx)
        }
        fmt.Println("select result length: ", len(txs))
        return txs, nil
    }
    
  • SelectByQueryString : 根據(jù) couchdb 查詢字符串完成查詢操作,并返回對應(yīng)切片。
    // 根據(jù)查詢字符串查詢
    func SelectByQueryString[T interface{}](ctx contractapi.TransactionContextInterface, queryString string) ([]*T, error) {
        resultsIterator, err := ctx.GetStub().GetQueryResult(queryString)
        if err != nil {
            return nil, err
        }
        defer resultsIterator.Close()
    
        return ConstructResultByIterator[T](resultsIterator)
    }
    
  • SelectByQueryStringWithPagination : 根據(jù) couchdb 查詢字符串分頁查詢,并返回對應(yīng)切片。
    // 根據(jù)擦查詢字符串分頁查詢
    func SelectByQueryStringWithPagination[T interface{}](ctx contractapi.TransactionContextInterface, queryString string, pageSize int32, bookmark string) (*model.PaginatedQueryResult[T], error) {
        resultsIterator, responseMetadata, err := ctx.GetStub().GetQueryResultWithPagination(queryString, pageSize, bookmark)
        if err != nil {
            return nil, err
        }
        defer resultsIterator.Close()
        var txs []T
        for resultsIterator.HasNext() {
            queryResult, err := resultsIterator.Next()
            if err != nil {
                return nil, err
            }
            var tx T
            err = json.Unmarshal(queryResult.Value, &tx)
            if err != nil {
                return nil, err
            }
            txs = append(txs, tx)
        }
        return &model.PaginatedQueryResult[T]{
            Records:             txs,
            FetchedRecordsCount: responseMetadata.FetchedRecordsCount,
            Bookmark:            responseMetadata.Bookmark,
        }, nil
    }
    
  • SelectHistoryByIndex : 獲得交易創(chuàng)建之后的所有變化(區(qū)塊鏈賬本)。
    // 獲得交易創(chuàng)建之后的所有變化.
    func SelectHistoryByIndex[T interface{}](ctx contractapi.TransactionContextInterface, index string) ([]model.HistoryQueryResult[T], error) {
        resultsIterator, err := ctx.GetStub().GetHistoryForKey(index)
        if err != nil {
            return nil, err
        }
        defer resultsIterator.Close()
    
        var records []model.HistoryQueryResult[T]
        for resultsIterator.HasNext() {
            response, err := resultsIterator.Next()
            if err != nil {
                return nil, err
            }
    
            var tx T
            if len(response.Value) > 0 {
                err = json.Unmarshal(response.Value, &tx)
                if err != nil {
                    return nil, err
                }
            }
            record := model.HistoryQueryResult[T]{
                TxId:      response.TxId,
                Record:    tx,
                IsDelete:  response.IsDelete,
            }
            records = append(records, record)
        }
        return records, nil
    }
    

model 層

model層主要用于申明合約所用數(shù)據(jù)結(jié)構(gòu),其中 model/project.go 內(nèi)容如下:

package model

type Project struct {
Table        string `json:"table" form:"table"` //  數(shù)據(jù)庫標(biāo)記
ID           string `json:"ID"`                 // 項(xiàng)目唯一ID
Name         string `json:"Name"`               // 項(xiàng)目名稱
Username     string `json:"username"`           // 項(xiàng)目主要負(fù)責(zé)人
Organization string `json:"Organization"`       // 項(xiàng)目所屬組織
Category     string `json:"Category"`           // 項(xiàng)目所屬類別
Url          string `json:"Url"`                // 項(xiàng)目介紹地址
Describes    string `json:"Describes"`          // 項(xiàng)目描述
}

func (o *Project) Index() string {
o.Table = "project"
return o.ID
}

func (o *Project) IndexKey() string {
return "table~ID~name"
}

func (o *Project) IndexAttr() []string {
return []string{o.Table, o.ID, o.Name}
}

其中 Index 函數(shù)用于標(biāo)識模型的唯一主鍵; IndexKey 函數(shù)用于標(biāo)識自建索引的字段,其中命名方式必須與字段申明的結(jié)構(gòu)體標(biāo)記 json 一致(大小寫);IndexAttr 用于構(gòu)造具體的索引。model/user.go 申明了用戶的字段信息:

package model

// User  用戶表
type User struct {
Table    string `json:"table" form:"table"`       //  數(shù)據(jù)庫標(biāo)記
Username string `json:"username" form:"username"` //用戶賬戶
Name     string `json:"name" form:"name"`         //真實(shí)姓名
Email    string `json:"email" form:"email"`       //  郵箱
Phone    string `json:"phone" form:"phone"`       //  手機(jī)
}

func (o *User) Index() string {
o.Table = "user"
return o.Username
}

func (o *User) IndexKey() string {
return "table~username~name"
}

func (o *User) IndexAttr() []string {
return []string{o.Table, o.Username, o.Name}
}

model/base.go 申明了基于 CouchDB 的富查詢結(jié)果模型:

package model

import "time"

// 歷史查詢結(jié)果
type HistoryQueryResult[T interface{}] struct {
Record    T         `json:"record"`
TxId      string    `json:"txId"`
Timestamp time.Time `json:"timestamp"`
IsDelete  bool      `json:"isDelete"`
}

// 分頁查詢結(jié)果
type PaginatedQueryResult[T interface{}] struct {
Records             []T    `json:"records"`
FetchedRecordsCount int32  `json:"fetchedRecordsCount"`
Bookmark            string `json:"bookmark"`
}

contract 層

contract 層用于實(shí)現(xiàn)智能合約的核心邏輯(本示例為 model 的增刪改查),由于結(jié)合了 CouchDB ,所以相比上個(gè)實(shí)驗(yàn)需要更復(fù)雜的實(shí)現(xiàn)。以 contract/project.go 為例進(jìn)行介紹,由于代碼太長在此就不再粘貼(完整代碼參考 project.go),其中主要功能及實(shí)現(xiàn)方式如下:

  • 插入數(shù)據(jù)( Insert ):先使用 ctx.GetStub().PutState(tx.Index(), txb) 方法插入數(shù)據(jù),然后調(diào)用ctx.GetStub().CreateCompositeKey(tx.IndexKey(), tx.IndexAttr()) 方法為該數(shù)據(jù)創(chuàng)建 CouchDB 索引,最后調(diào)用 ctx.GetStub().PutState(indexKey, value) 將索引存入鏈上。
  • 更新數(shù)據(jù)( Update ):先使用 indexKey, err := ctx.GetStub().CreateCompositeKey(otx.IndexKey(), otx.IndexAttr()) 得到舊數(shù)據(jù)的索引,再調(diào)用 ctx.GetStub().DelState(indexKey) 刪除舊數(shù)據(jù)的索引,然后調(diào)用 ctx.GetStub().PutState(tx.Index(), txb) 更新數(shù)據(jù),最后分別調(diào)用 ctx.GetStub().CreateCompositeKey(tx.IndexKey(), tx.IndexAttr())ctx.GetStub().PutState(indexKey, value) 創(chuàng)建新數(shù)據(jù)索引并存入鏈上。
  • 刪除數(shù)據(jù)( Delete ):先使用 ctx.GetStub().DelState(anstx.Index()) 刪除舊數(shù)據(jù),再調(diào)用 indexKey, err := ctx.GetStub().CreateCompositeKey(tx.IndexKey(), tx.IndexAttr()) 得到舊數(shù)據(jù)索引,最后通過 ctx.GetStub().DelState(indexKey) 刪除舊數(shù)據(jù)索引。
  • 讀取指定index的記錄( SelectByIndex ):使用形如 {"selector":{"ID":"%s", "table":"project"}} 的 CouchDB 查詢語法根據(jù)索引查詢數(shù)據(jù)。
  • 讀取所有數(shù)據(jù)( SelectAll ):使用形如 {"selector":{"table":"project"}} 的 CouchDB 查詢語法查詢所有相關(guān)數(shù)據(jù)。
  • 按某索引查詢所有數(shù)據(jù)( SelectBySome ):使用形如 {"selector":{"%s":"%s", "table":"project"}} 的 CouchDB 查詢語法根據(jù)索引查詢數(shù)據(jù)。
  • 富分頁查詢所有數(shù)據(jù)( SelectAllWithPagination ):使用形如 {"selector":{"table":"project"}} 的 CouchDB 查詢語法調(diào)用上述分頁查詢數(shù)據(jù)工具 tools.SelectByQueryStringWithPagination 來查詢數(shù)據(jù)。
  • 按關(guān)鍵字富分頁查詢所有數(shù)據(jù) SelectBySomeWithPagination ):使用形如 {"selector":{"%s":"%s","table":"project"}} 的 CouchDB 查詢語法調(diào)用上述分頁查詢數(shù)據(jù)工具 tools.SelectByQueryStringWithPagination 來查詢數(shù)據(jù)。
  • 按某索引查詢數(shù)據(jù)歷史( SelectHistoryByIndex ):調(diào)用上述歷史數(shù)據(jù)查詢工具 tools.SelectHistoryByIndex 來查詢數(shù)據(jù)。

contract/user.gomodel/user.go 的核心操作邏輯,此示例只包含簡單的功能,完整源碼參考 user.go。

main 主函數(shù)

主函數(shù)完整代碼如下所示:

package main

import (
        "github.com/hyperledger/fabric-contract-api-go/contractapi"
        "github.com/wefantasy/FabricLearn/7_CouchDBAndComplexContract/project_contract/contract"
)

func main() {
        chaincode, err := contractapi.NewChaincode(&contract.UserContract{}, &contract.ProjectContract{})
        if err != nil {
                panic(err)
        }

        if err := chaincode.Start(); err != nil {
                panic(err)
        }
}

多智能合約只需在 main 的 contractapi.NewChaincode 函數(shù)中按順序申明即可。在智能合約編寫完畢后使用 go mod vendor 來打包依賴,上述工作完成后 project_contract 目錄結(jié)構(gòu)及解釋如下所示:

project_contract
├── contract            // 智能合約核心邏輯
│   ├── project.go
│   └── user.go
├── go.mod
├── go.sum
├── main.go             // 智能合約入口函數(shù)
├── model               // 申明數(shù)據(jù)模型
│   ├── base.go         // 申明分頁等數(shù)據(jù)結(jié)構(gòu)
│   ├── project.go
│   └── user.go
├── tools               // 工具目錄
│   └── contract.go     // 智能合約通用工具,查詢歷史/分頁查詢等
└── vendor              // 依賴目錄

合約部署和測試

如無特殊說明,以下命令默認(rèn)運(yùn)行于實(shí)驗(yàn)根目錄 7_CouchDBAndComplexContract 下:

  1. 合約打包
    source envpeer1soft
    peer lifecycle chaincode package basic.tar.gz --path project_contract --label basic_1
    
  2. 三組織安裝
     source envpeer1soft
     peer lifecycle chaincode install basic.tar.gz
     peer lifecycle chaincode queryinstalled
     source envpeer1web
     peer lifecycle chaincode install basic.tar.gz
     peer lifecycle chaincode queryinstalled
     source envpeer1hard
     peer lifecycle chaincode install basic.tar.gz
     peer lifecycle chaincode queryinstalled
    
  3. 三組織批準(zhǔn)
    export CHAINCODE_ID=basic_1:22e38a78d2ddfe9c3cbeff91140ee209c901adcc24cd2b11f863a53abcdc825a
    source envpeer1soft
    peer lifecycle chaincode approveformyorg -o orderer1.council.ifantasy.net:7051 --tls --cafile $ORDERER_CA  --channelID testchannel --name basic --version 1.0 --sequence 1 --waitForEvent --package-id $CHAINCODE_ID
    peer lifecycle chaincode queryapproved -C testchannel -n basic --sequence 1
    source envpeer1web
    peer lifecycle chaincode approveformyorg -o orderer3.council.ifantasy.net:7057 --tls --cafile $ORDERER_CA  --channelID testchannel --name basic --version 1.0 --sequence 1 --waitForEvent --package-id $CHAINCODE_ID
    peer lifecycle chaincode queryapproved -C testchannel -n basic --sequence 1
    source envpeer1hard
    peer lifecycle chaincode approveformyorg -o orderer2.council.ifantasy.net:7054 --tls --cafile $ORDERER_CA  --channelID testchannel --name basic --version 1.0 --sequence 1 --waitForEvent --package-id $CHAINCODE_ID
    peer lifecycle chaincode queryapproved -C testchannel -n basic --sequence 1
    
    注意:由于我們有兩個(gè)智能合約,且每個(gè)智能合約都包含 InitLedger 函數(shù)來初始化數(shù)據(jù),所以在這里以及后續(xù)鏈碼操作中需要?jiǎng)h除 --init-required 參數(shù)(因?yàn)楹霞s不需要初始化)。
  4. 提交鏈碼
    source envpeer1soft
    peer lifecycle chaincode commit -o orderer2.council.ifantasy.net:7054 --tls --cafile $ORDERER_CA --channelID testchannel --name basic --version 1.0 --sequence 1 --peerAddresses peer1.soft.ifantasy.net:7251 --tlsRootCertFiles $CORE_PEER_TLS_ROOTCERT_FILE --peerAddresses peer1.web.ifantasy.net:7351 --tlsRootCertFiles $CORE_PEER_TLS_ROOTCERT_FILE
    
  5. 初始化鏈碼數(shù)據(jù)并測試
    source envpeer1soft
    peer chaincode invoke -o orderer1.council.ifantasy.net:7051 --tls --cafile $ORDERER_CA --channelID testchannel --name basic --peerAddresses peer1.soft.ifantasy.net:7251 --tlsRootCertFiles $CORE_PEER_TLS_ROOTCERT_FILE --peerAddresses peer1.web.ifantasy.net:7351 --tlsRootCertFiles $CORE_PEER_TLS_ROOTCERT_FILE -c '{"Args":["UserContract:InitLedger"]}'
    peer chaincode invoke -o orderer1.council.ifantasy.net:7051 --tls --cafile $ORDERER_CA --channelID testchannel --name basic --peerAddresses peer1.soft.ifantasy.net:7251 --tlsRootCertFiles $CORE_PEER_TLS_ROOTCERT_FILE --peerAddresses peer1.web.ifantasy.net:7351 --tlsRootCertFiles $CORE_PEER_TLS_ROOTCERT_FILE -c '{"Args":["ProjectContract:InitLedger"]}'
    
    peer chaincode invoke -o orderer1.council.ifantasy.net:7051 --tls --cafile $ORDERER_CA --channelID testchannel --name basic --peerAddresses peer1.soft.ifantasy.net:7251 --tlsRootCertFiles $CORE_PEER_TLS_ROOTCERT_FILE --peerAddresses peer1.web.ifantasy.net:7351 --tlsRootCertFiles $CORE_PEER_TLS_ROOTCERT_FILE -c '{"Args":["UserContract:GetAllUsers"]}'
    peer chaincode invoke -o orderer1.council.ifantasy.net:7051 --tls --cafile $ORDERER_CA --channelID testchannel --name basic --peerAddresses peer1.soft.ifantasy.net:7251 --tlsRootCertFiles $CORE_PEER_TLS_ROOTCERT_FILE --peerAddresses peer1.web.ifantasy.net:7351 --tlsRootCertFiles $CORE_PEER_TLS_ROOTCERT_FILE -c '{"Args":["ProjectContract:SelectAll"]}'
    peer chaincode invoke -o orderer1.council.ifantasy.net:7051 --tls --cafile $ORDERER_CA --channelID testchannel --name basic --peerAddresses peer1.soft.ifantasy.net:7251 --tlsRootCertFiles $CORE_PEER_TLS_ROOTCERT_FILE --peerAddresses peer1.web.ifantasy.net:7351 --tlsRootCertFiles $CORE_PEER_TLS_ROOTCERT_FILE -c '{"Args":["ProjectContract:SelectBySome", "name", "工作室聯(lián)盟鏈管理系統(tǒng)"]}'
    

注意,在多合約的情況下調(diào)用鏈碼,需要在所調(diào)用的合約函數(shù)前指定所屬合約,如 ProjectContract:SelectBySome ,其它合約示例調(diào)用方式大致一樣,在此不再贅述。此外由于 CouchDB 自帶了數(shù)據(jù)庫管理界面,則可以通過本例中任意一個(gè) CouchDB 的服務(wù)地址來訪問鏈上數(shù)據(jù),如 http://192.168.27.72:7355/_utils/#login (虛擬機(jī)IP為 192.168.27.72 ,soft 組織的 CouchDB 端口 7355),輸入docker中配置的賬戶admin密碼adminpw即可進(jìn)入系統(tǒng):


至此,本實(shí)驗(yàn)基本完成。

可能存在的問題

  1. peer lifecycle chaincode install 時(shí)遇到錯(cuò)誤:
Error creating tx-manage chaincode: Error compiling schema for DataContract [SelectBySomeWithPagination]. Return schema invalid. Object has no key 'PaginatedQueryResult[github.com'
panic: Error creating tx-manage chaincode: Error compiling schema for DataContract [SelectBySomeWithPagination]. Return schema invalid. Object has no key 'PaginatedQueryResult[github.com'

goroutine 1 [running]:
log.Panicf({0xa24b02?, 0x1?}, {0xc00014ff50?, 0x407679?, 0x404c71?})
        /usr/local/go/src/log/log.go:392 +0x67
main.main()
        /chaincode/input/src/main.go:201 +0x8e

原因及解決方法: 所用 docker fabric 2.4 鏡像的 Golang 版本太低不支持泛型,需要?jiǎng)h除并重新安裝 docker fabric 2.4 (盡管 tag 一樣,但鏡像內(nèi)容會更新)。

  1. 智能合約調(diào)用時(shí)遇到錯(cuò)誤:
[notice] 2022-11-13T12:13:49.502557Z nonode@nohost <0.286.0> -------- rexi_server : started servers
[notice] 2022-11-13T12:13:49.504490Z nonode@nohost <0.290.0> -------- rexi_buffer : started servers
[warning] 2022-11-13T12:13:49.530610Z nonode@nohost <0.298.0> -------- creating missing database: _nodes
[info] 2022-11-13T12:13:49.530670Z nonode@nohost <0.299.0> -------- open_result error {not_found,no_db_file} for _nodes
[error] 2022-11-13T12:13:49.537681Z nonode@nohost <0.304.0> -------- CRASH REPORT Process  (<0.304.0>) with 2 neighbors crashed with reason: no match of right hand value {error,enospc} at couch_bt_engine:init/2(line:154) <= 
……

原因及解決方法: 可能是 docker volume 把硬盤占滿了,使用 docker volume rm $(docker volume ls -qf dangling=true) 清除所有再重試
使用

  1. 遇到錯(cuò)誤:
# github.com/hyperledger/fabric-sdk-go/internal/github.com/hyperledger/fabric/discovery/client
/root/go/pkg/mod/github.com/hyperledger/fabric-sdk-go@v1.0.0/internal/github.com/hyperledger/fabric/discovery/client/api.go:47:38: undefined: discovery.ChaincodeCall
/root/go/pkg/mod/github.com/hyperledger/fabric-sdk-go@v1.0.0/internal/github.com/hyperledger/fabric/discovery/client/client.go:83:63: undefined: discovery.ChaincodeInterest
/root/go/pkg/mod/github.com/hyperledger/fabric-sdk-go@v1.0.0/internal/github.com/hyperledger/fabric/discovery/client/client.go:120:65: undefined: discovery.ChaincodeCall
/root/go/pkg/mod/github.com/hyperledger/fabric-sdk-go@v1.0.0/internal/github.com/hyperledger/fabric/discovery/client/client.go:124:23: undefined: discovery.ChaincodeInterest
/root/go/pkg/mod/github.com/hyperledger/fabric-sdk-go@v1.0.0/internal/github.com/hyperledger/fabric/discovery/client/client.go:229:105: undefined: discovery.ChaincodeCall
/root/go/pkg/mod/github.com/hyperledger/fabric-sdk-go@v1.0.0/internal/github.com/hyperledger/fabric/discovery/client/client.go:247:64: undefined: discovery.ChaincodeCall
/root/go/pkg/mod/github.com/hyperledger/fabric-sdk-go@v1.0.0/internal/github.com/hyperledger/fabric/discovery/client/client.go:604:48: undefined: discovery.ChaincodeInterest
/root/go/pkg/mod/github.com/hyperledger/fabric-sdk-go@v1.0.0/internal/github.com/hyperledger/fabric/discovery/client/client.go:620:35: undefined: discovery.ChaincodeCall

原因及解決方法: github.com/hyperledger/fabric-sdk-go 需要指定 20220117 版本,將 go.mod 文件對應(yīng)依賴替換如下:

github.com/hyperledger/fabric-sdk-go v1.0.1-0.20220117114400-c848d119936b。
  1. 遇到錯(cuò)誤:
Error compiling schema for ****[**]. Return schema invalid. Object has no key 'Wrapper[[]<part of module name>'

原因及解決方法:智能合約返回值不支持泛型,將智能合約返回值換成 interface{} 即可。

  1. 查詢歷史記錄出現(xiàn)遇到錯(cuò)誤:
Error: could not assemble transaction: ProposalResponsePayloads do not match (base64):

原因及解決方法:鏈碼輸出(返回)數(shù)據(jù)中不要使用地址傳遞(推薦值傳遞),因?yàn)榈刂范际莿討B(tài)分配,每次取到的值都不一樣,造成共識失敗。

  1. 遇到錯(cuò)誤:
Failed to evaluate: Multiple errors occurred: - Transaction processing for endorser [localhost:7451]: Chaincode status Code: (500) UNKNOWN. Description: Error handling success response. Value did not match schema:\n1. return: Invalid type. Expected: array, given: string - Transaction processing for endorser [localhost:7251]: Chaincode status Code: (500) UNKNOWN. Description: Error handling success response. Value did not match schema:\n1. return: Invalid type. Expected: array, given: string

原因及解決方法:鏈碼返回值不能為 []byte ,這是一個(gè) fabric 的 bug,對于復(fù)雜返回類型建議直接返回字符串 string文章來源地址http://www.zghlxwxcb.cn/news/detail-414435.html

到了這里,關(guān)于Hyperledger Fabric 使用 CouchDB 和復(fù)雜智能合約開發(fā)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 11. Fabric2.2 區(qū)塊鏈農(nóng)產(chǎn)品溯源系統(tǒng) - 智能合約開發(fā)-1

    智能合約與業(yè)務(wù)邏輯關(guān)聯(lián)度高,承載大量業(yè)務(wù)邏輯,本小節(jié)教大家搭建智能合約開發(fā)環(huán)境GoLand,并編寫合約打包腳本。 作者在windows電腦安裝ubuntu18.04版本虛擬機(jī)(vmware),Linux環(huán)境也有Goland版本,可用性絲毫不差,所有的區(qū)塊鏈開發(fā)在Linux環(huán)境進(jìn)行。 官方可以下載,要么評估

    2023年04月20日
    瀏覽(18)
  • fabric智能合約

    fabric智能合約

    fabric架構(gòu)分為兩個(gè)部分, 應(yīng)用層 和 區(qū)塊鏈底層 。 對于 應(yīng)用層 來說,fabric提供了基于GRPC協(xié)議的API來于區(qū)塊鏈進(jìn)行通訊,并且在API的基礎(chǔ)上封裝了支持go語言、Java語言、node.js等SDK,方便客戶端的調(diào)用。由于區(qū)塊鏈?zhǔn)欠植际降馁~本,并且交易需要進(jìn)行共識之后才能夠進(jìn)行上鏈

    2023年04月23日
    瀏覽(35)
  • Fabric智能合約——Chaincode(一)簡介

    Fabric智能合約——Chaincode(一)簡介

    Fabric智能合約整體介紹,首先看一下 Fabric交易流程 ?在這張圖中,5、6步是public數(shù)據(jù)的步驟,7、8、9是private數(shù)據(jù)的步驟,除了這一部分外,其他步驟均相同。 ????????Fabric中智能合約稱為鏈碼(Chaincode),使用計(jì)算機(jī)語言描述合約條款、交易的條件、交易的業(yè)務(wù)邏輯等,

    2024年02月07日
    瀏覽(18)
  • Fabric 搭建測試網(wǎng)絡(luò)并部署智能合約

    Fabric 搭建測試網(wǎng)絡(luò)并部署智能合約

    1. 搭建網(wǎng)絡(luò): 詳見博客 2. 對Test Network的創(chuàng)建和關(guān)閉 3. Starting a chaincode on the channel: 智能合約(Smart Contract): 包含管理區(qū)塊鏈賬本上assets的邏輯。 在Fabric上智能合約就是鏈碼的形式存在. 當(dāng)網(wǎng)絡(luò)運(yùn)行后,鏈碼會被部署到網(wǎng)絡(luò)中節(jié)點(diǎn)和通道上. 應(yīng)用(Application): 由區(qū)塊鏈系統(tǒng)的成員執(zhí)行

    2024年02月03日
    瀏覽(21)
  • fabric 2.3 手動搭建網(wǎng)絡(luò)&安裝chaincode智能合約

    fabric 2.3 手動搭建網(wǎng)絡(luò)&安裝chaincode智能合約

    搭建好fabric之后,要在test-network下手動啟動一個(gè)fabric網(wǎng)絡(luò)。將下載過來的order和peer1兩個(gè)文件夾放到~/go/src/github.com/hyperledger/fabric/scripts/fabric-samples/test-network目錄下。 生成證書文件: 生成創(chuàng)世塊: 之后便可以去啟動order和peer,分別進(jìn)入order和peer1文件夾下,打開終端輸入 orde

    2024年01月24日
    瀏覽(20)
  • Hyperledger Fabric測試網(wǎng)絡(luò)的準(zhǔn)備和基本使用

    Hyperledger Fabric測試網(wǎng)絡(luò)的準(zhǔn)備和基本使用

    相關(guān)安裝 npm、node、git、docker、docker-compose。docker保證一直運(yùn)行 2.安裝Java、maven環(huán)境 https://blog.csdn.net/qq_41829594/article/details/122408706 https://www.oracle.com/java/technologies/downloads/ https://maven.apache.org/download.cgi 在/etc/profile配置環(huán)境變量,之后source文件使其生效,檢查是否安裝成功 3.安裝

    2024年02月16日
    瀏覽(65)
  • 如果Fabric的智能合約函數(shù)陷入死循環(huán)會怎么樣

    大家好,我是 powervip !今天和大家一起探討一下:如果Fabric的智能合約函數(shù)陷入死循環(huán)會怎么樣 先看一段合約函數(shù)代碼: func (t *SimpleChaincode) Test(stub shim.ChaincodeStubInterface, args []string) pb.Response { // 選擇商品價(jià)格在1元到100元之間的商品名稱和數(shù)量 s := \\\"{\\\"fields\\\": [\\\"GoodsName\\\",

    2023年04月21日
    瀏覽(18)
  • 樹莓派4B與智能渦輪流量計(jì)通過RS485(modbus RTU協(xié)議)收發(fā)數(shù)據(jù)(二)(Hyperledger Fabric環(huán)境中上傳數(shù)據(jù))

    樹莓派4B與智能渦輪流量計(jì)通過RS485(modbus RTU協(xié)議)收發(fā)數(shù)據(jù)(二)(Hyperledger Fabric環(huán)境中上傳數(shù)據(jù))

    上一篇博客配置好了樹莓派端的串口通信,這次在加入渦輪流量計(jì)之前也先用PC端模擬樹莓派測試一下該儀表是否能正常工作。 流量計(jì)說明書如下: ?并且在設(shè)備上電時(shí)以(9600,8n1格式)自動發(fā)送四個(gè)字節(jié): 返碼格式:站地址(1字節(jié))+波特率(2字節(jié))+格式(1字節(jié)) 8n1格式

    2023年04月21日
    瀏覽(32)
  • 8. Fabric2.2 區(qū)塊鏈農(nóng)產(chǎn)品溯源系統(tǒng) - 智能合約設(shè)計(jì)

    根據(jù)上小節(jié)的需求分析與方案設(shè)計(jì)來進(jìn)行智能合約的設(shè)計(jì)。 智能合約設(shè)計(jì)最核心的是存儲字段的設(shè)計(jì)、也就是索引設(shè)計(jì),F(xiàn)abric 常見的時(shí)間狀態(tài)存儲引擎是LevelDB 或 CouchDB,這兩個(gè)數(shù)據(jù)庫是KV存儲,KV存儲不像SQL類型存儲,一張表創(chuàng)建多個(gè)字段,多個(gè)字段索引可以進(jìn)行各種復(fù)查詢

    2023年04月08日
    瀏覽(28)
  • Linux搭建Hyperledger Fabric區(qū)塊鏈框架 - Hyperledger Fabric模型概念

    Linux搭建Hyperledger Fabric區(qū)塊鏈框架 - Hyperledger Fabric模型概念

    2015年,Linux基金會啟動了Hyperledger項(xiàng)目,目標(biāo)是發(fā)展跨行業(yè)的區(qū)塊鏈技術(shù)。 Hyperledger Fabric是Hyperledger中的一個(gè)區(qū)塊鏈項(xiàng)目,包含一個(gè)賬本,使用智能合約并且是一個(gè)通過所有參與者管理交易的系統(tǒng)。 Hyperledger Fabric 是分布式賬本解決方案的平臺,以模塊化架構(gòu)為基礎(chǔ),支持不同

    2023年04月08日
    瀏覽(19)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包