搭建基于hyperledger fabric的联盟社区(七) --升级chaincode

上个版本的chaincode有很多功能不完备,所以要部署新版本的chaincode。Fabric支持在保留现有状态的前提对chaincode进行升级。

一.新版chaincode

新版本的chaincode增加的功能如下:

1.增加了数据追溯功能,在社区用户发起transaction时,chaincode将自动在用户证书中提取用户信息,将其存储在帖子的字段里。

2.加入了敏感词监管功能,敏感词字典和敏感词过滤功能在外部提供,chaincode通过http api(post 请求)调用服务。

3.加入了模糊查询功能。

chaincode代码:

package main

import (
    "bytes"
    "encoding/json"
    "fmt"
    "strconv"
    "strings"
    "net/http"
    "io/ioutil"
    "crypto/x509"
    "encoding/pem"

    "github.com/hyperledger/fabric/core/chaincode/shim"
    sc "github.com/hyperledger/fabric/protos/peer"
)

type SmartContract struct {
}

type Post struct {
    Id   string `json:"id"`
    OriginalWebsite  string `json:"originalwebsite"`
    OriginalID string `json:"originalid"`
    Title  string `json:"title"`
    Content  string `json:"content"`
    AuthorId  string `json:"authorid"`
    PublishTime  string `json:"publishtime"`
    UpdateTime  string `json:"updatetime"`
    Category  string `json:"category"`
    SourceId  string `json:"sourceid"`
    Labels  string `json:"labels"`
    Follower_num  int `json:"follower_num"`
    Browse_num  int `json:"browse_num"`
    Star_num  int `json:"star_num"`
    UserName  string `json:"username"`
}

type PostLength struct {
    Length int `json:"length"`
}

func (s *SmartContract) Init(APIstub shim.ChaincodeStubInterface) sc.Response {
    return shim.Success(nil)
}

func (s *SmartContract) Invoke(APIstub shim.ChaincodeStubInterface) sc.Response {

    function, args := APIstub.GetFunctionAndParameters()

    if function == "queryPost" {
        return s.queryPost(APIstub, args)
    } else if function == "initLedger" {
        return s.initLedger(APIstub)
    }  else if function == "addPost" {
        return s.addPost(APIstub, args)
    } else if function == "updatePost" {
        return s.updatePost(APIstub, args)
    } else if function == "richQueryPosts" {
        return s.richQueryPosts(APIstub, args)
    } else if function == "getPostNum" {
        return s.getPostNum(APIstub, args)
    }
    return shim.Error("Invalid Smart Contract function name.")
}

func (s *SmartContract) queryPost(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

    if len(args) != 1 {
        return shim.Error("Incorrect number of arguments. Expecting 1")
    }
    postAsBytes, _ := APIstub.GetState(args[0])
    return shim.Success(postAsBytes)
}

func (s *SmartContract) initLedger(APIstub shim.ChaincodeStubInterface) sc.Response {
    creatorByte,_:= APIstub.GetCreator()
   certStart := bytes.IndexAny(creatorByte, "-----BEGIN")
   if certStart == -1 {
      fmt.Errorf("No certificate found")
   }
   certText := creatorByte[certStart:]
   bl, _ := pem.Decode(certText)
   if bl == nil {
      fmt.Errorf("Could not decode the PEM structure")
   }

   cert, err := x509.ParseCertificate(bl.Bytes)
   if err != nil {
      fmt.Errorf("ParseCertificate failed")
   }
   uname:=cert.Subject.CommonName

    posts := []Post{
        Post{Id: "1", OriginalWebsite: "b", OriginalID: "c", Title: "如何学习人工智能呢?",Content:"好好学习",AuthorId:"f",PublishTime:"g",UpdateTime:"h",Category:"i",SourceId:"j",Labels:"k",Follower_num:100,Browse_num:200,Star_num:300,UserName:uname},
        Post{Id: "2", OriginalWebsite: "bb", OriginalID: "bb", Title: "目前大数据有什么用呢?",Content:"没用",AuthorId:"ff",PublishTime:"gg",UpdateTime:"hh",Category:"ii",SourceId:"jj",Labels:"kk",Follower_num:400,Browse_num:500,Star_num:600,UserName:uname},
    }
    length := PostLength{Length:len(posts)}
    lengthAsBytes,_ := json.Marshal(length)
    APIstub.PutState("POSTLENGTH",lengthAsBytes)

    i := 0
    for i < len(posts) {
        fmt.Println("i is ", i)
        postAsBytes, _ := json.Marshal(posts[i])
        APIstub.PutState("POST"+strconv.Itoa(i), postAsBytes)
        fmt.Println("Added", posts[i])
        i = i + 1
    }

    return shim.Success(nil)
}

func (s *SmartContract) addPost(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

    if len(args) != 13 {
        return shim.Error("Incorrect number of arguments. Expecting 13")
    }

    filteredtitle := sensitiveSupervision(args[2])
    filteredcontent := sensitiveSupervision(args[3])

    creatorByte,_:= APIstub.GetCreator()
   certStart := bytes.IndexAny(creatorByte, "-----BEGIN")
   if certStart == -1 {
      fmt.Errorf("No certificate found")
   }
   certText := creatorByte[certStart:]
   bl, _ := pem.Decode(certText)
   if bl == nil {
      fmt.Errorf("Could not decode the PEM structure")
   }

   cert, err := x509.ParseCertificate(bl.Bytes)
   if err != nil {
      fmt.Errorf("ParseCertificate failed")
   }
   uname:=cert.Subject.CommonName

    args10,error := strconv.Atoi(args[10])
    args11,error := strconv.Atoi(args[11])
    args12,error := strconv.Atoi(args[12])

    if error != nil{
     fmt.Println("String conversion integer failed!")
    }
    lengthAsBytes, _ := APIstub.GetState("POSTLENGTH")
    length := PostLength{}
    json.Unmarshal(lengthAsBytes,&length)
    newlength := length.Length+1
    var post = Post{Id: strconv.Itoa(newlength), OriginalWebsite: args[0], OriginalID: args[1], Title: filteredtitle,Content:filteredcontent,AuthorId:args[4],PublishTime:args[5],UpdateTime:args[6],Category:args[7],SourceId:args[8],Labels:args[9],Follower_num:args10,Browse_num:args11,Star_num:args12,UserName:uname}
    postAsBytes, _ := json.Marshal(post)
    APIstub.PutState("POST"+strconv.Itoa(newlength), postAsBytes)
    length.Length = newlength
    lengthAsBytes,_ = json.Marshal(length)
    APIstub.PutState("POSTLENGTH",lengthAsBytes)
    return shim.Success(lengthAsBytes)
}

func (s *SmartContract) updatePost(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

    if len(args) != 14 {
        return shim.Error("Incorrect number of arguments. Expecting 14")
    }

    filteredtitle := sensitiveSupervision(args[3])
    filteredcontent := sensitiveSupervision(args[4])

    creatorByte,_:= APIstub.GetCreator()
   certStart := bytes.IndexAny(creatorByte, "-----BEGIN")
   if certStart == -1 {
      fmt.Errorf("No certificate found")
   }
   certText := creatorByte[certStart:]
   bl, _ := pem.Decode(certText)
   if bl == nil {
      fmt.Errorf("Could not decode the PEM structure")
   }

   cert, err := x509.ParseCertificate(bl.Bytes)
   if err != nil {
      fmt.Errorf("ParseCertificate failed")
   }
   uname:=cert.Subject.CommonName

    args11,error := strconv.Atoi(args[11])
    args12,error := strconv.Atoi(args[12])
    args13,error := strconv.Atoi(args[13])
    if error != nil{
     fmt.Println("String conversion integer failed!")
    }
    var post = Post{Id: args[0], OriginalWebsite: args[1], OriginalID: args[2], Title: filteredtitle,Content:filteredcontent,AuthorId:args[5],PublishTime:args[6],UpdateTime:args[7],Category:args[8],SourceId:args[9],Labels:args[10],Follower_num:args11,Browse_num:args12,Star_num:args13,UserName:uname}
    postAsBytes, _ := json.Marshal(post)
    APIstub.PutState("POST"+args[0], postAsBytes)
    return shim.Success(nil)
}

func (s *SmartContract) richQueryPosts(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

    if len(args) != 3 {
        return shim.Error("Incorrect number of arguments. Expecting 3")
    }

    var queryString string

    if args[1] == "0" {
        queryString = fmt.Sprintf("{\"selector\":{\"%s\":\"%s\"}}", args[0],args[2])
    } else if args[1] == "1" {
      queryString = fmt.Sprintf("{\"selector\":{\"%s\":{\"$gt\":%s}}}", args[0],args[2])
    } else if args[1] == "2" {
      queryString = fmt.Sprintf("{\"selector\":{\"%s\":{\"$gte\":%s}}}", args[0],args[2])
    } else if args[1] == "3" {
      queryString = fmt.Sprintf("{\"selector\":{\"%s\":{\"$lt\":%s}}}", args[0],args[2])
    } else if args[1] == "4" {
      queryString = fmt.Sprintf("{\"selector\":{\"%s\":{\"$lte\":%s}}}", args[0],args[2])
    } else if args[1] == "5" {
      between := strings.Split(args[2], ",")
      queryString = fmt.Sprintf("{\"selector\":{\"$and\":[{\"%s\":{\"$gte\":%s}},{\"%s\":{\"$lte\":%s}}]}}", args[0],between[0],args[0],between[1])
    } else if args[1] == "6" {
      queryString = fmt.Sprintf("{\"selector\":{\"%s\":{\"$regex\":\"(?i)%s\"}}}", args[0],args[2])
    }  else {
        return shim.Error("Incorrect number of arguments. Expecting 0~6")
    }

    resultsIterator, err := APIstub.GetQueryResult(queryString)
    if err != nil {
        return shim.Error(err.Error())
    }
    defer resultsIterator.Close()

    var buffer bytes.Buffer
    buffer.WriteString("[")

    bArrayMemberAlreadyWritten := false
    for resultsIterator.HasNext() {
        queryResponse, err := resultsIterator.Next()
        if err != nil {
            return shim.Error(err.Error())
        }

        if bArrayMemberAlreadyWritten == true {
            buffer.WriteString(",")
        }
        buffer.WriteString("{\"Key\":")
        buffer.WriteString("\"")
        buffer.WriteString(queryResponse.Key)
        buffer.WriteString("\"")

        buffer.WriteString(", \"Record\":")

        buffer.WriteString(string(queryResponse.Value))
        buffer.WriteString("}")
        bArrayMemberAlreadyWritten = true
    }
    buffer.WriteString("]")

    fmt.Printf("- richQueryPosts:\n%s\n", buffer.String())

    return shim.Success(buffer.Bytes())
}

func  (s *SmartContract) getPostNum(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

    if len(args) != 3 {
        return shim.Error("Incorrect number of arguments. Expecting 3")
    }
   var queryString string

    if args[1] == "0" {
        queryString = fmt.Sprintf("{\"selector\":{\"%s\":\"%s\"}}", args[0],args[2])
    } else if args[1] == "1" {
      queryString = fmt.Sprintf("{\"selector\":{\"%s\":{\"$gt\":%s}}}", args[0],args[2])
    } else if args[1] == "2" {
      queryString = fmt.Sprintf("{\"selector\":{\"%s\":{\"$gte\":%s}}}", args[0],args[2])
    } else if args[1] == "3" {
      queryString = fmt.Sprintf("{\"selector\":{\"%s\":{\"$lt\":%s}}}", args[0],args[2])
    } else if args[1] == "4" {
      queryString = fmt.Sprintf("{\"selector\":{\"%s\":{\"$lte\":%s}}}", args[0],args[2])
    } else if args[1] == "5" {
      between := strings.Split(args[2], ",")
      queryString = fmt.Sprintf("{\"selector\":{\"$and\":[{\"%s\":{\"$gte\":%s}},{\"%s\":{\"$lte\":%s}}]}}", args[0],between[0],args[0],between[1])
    } else if args[1] == "6" {
      queryString = fmt.Sprintf("{\"selector\":{\"%s\":{\"$regex\":\"(?i)%s\"}}}", args[0],args[2])
    } else {
        return shim.Error("Incorrect number of arguments. Expecting 0~6")
    }

    resultsIterator, err := APIstub.GetQueryResult(queryString)
    if err != nil {
        return shim.Error(err.Error())
    }
    defer resultsIterator.Close()

    i := 0

    for resultsIterator.HasNext() {
      resultsIterator.Next()

      i = i + 1

    }

    fmt.Printf("- getPostNum:\n%s\n", strconv.Itoa(i))

    return shim.Success([]byte(strconv.Itoa(i)))
}

func sensitiveSupervision(arg string) string {
  quertString := fmt.Sprintf("{\"content\":\"%s\"}",arg)
    resp, err := http.Post("http://敏感监管url",
        "application/x-www-form-urlencoded",
        strings.NewReader(quertString))
    if err != nil {
        fmt.Println(err)
    }

    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {

    }

    return string(body)

}

func main() {
    err := shim.Start(new(SmartContract))
    if err != nil {
        fmt.Printf("Error creating new Smart Contract: %s", err)
    }
}

 

二.升级链码步骤

2.1 从宿主机将chaincode拷贝进容器

docker cp community2.0 cli:/opt/gopath/src/github.com/hyperledger/fabric/examples/chaincode/go

2.2 安装新版本chaincode,打包到peer节点

docker exec -it cli bash
peer chaincode install -n mycc -v 2.0 -p github.com/hyperledger/fabric/examples/chaincode/go/community2.0

2.3 升级chaincode

peer chaincode upgrade -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc -v 2.0 -c ‘{"Args":["init"]}‘ -P "OR      (‘Org1MSP.member‘,‘Org2MSP.member‘)"

这样chaincode就升级完毕了。

时间: 2024-07-31 07:09:41

搭建基于hyperledger fabric的联盟社区(七) --升级chaincode的相关文章

搭建基于hyperledger fabric的联盟社区(八) --Fabric证书解析

一.证书目录解析 通过cryptogen生成所有证书文件后,以peerOrgannizations的第一个组织树org1为例,每个目录和对应文件的功能如下: ca: 存放组织的根证书和对应的私钥文件,默认采用EC算法,证书为自签名.组织内的实体将基于该证书作为证书根. tlsca:存放组织tls连接用的根证书和私钥文件.(TLS是传输层安全协议,其实就是SSL,现在叫TLS了) msp:存放代表该组织的身份信息. admincerts:组织管理员的身份验证证书,被根证书签名. cacerts:组

学习Hyperledger Fabric 实战联盟链

第1章 区块链技术基础本章介绍了区块链技术的相关基础技术要点,纯技术理论角度阐释区块链底层相关概念及所用技术 第2章 Hyperledger Fabric入门本章简单介绍了Hyperledger组织相关的区块链框架及工具,以及Fabric相关的项目介绍,并搭建了第一个Fabric区块链网络,让大家能够快速体验区块链的魅力 第3章 Hyperledger Fabric系统架构本章概括了Fabric的体系架构,包括服务组件,网络拓扑以及Fabric的典型交易流程,让大家对Fabric先有一个整体的概

Hyperledger Fabric 1.0.1至Hyperledger Fabric 1.0.5所升级的内容及修复的问题

基础更新 各版本每次迭代都会有一些基础更新内容,如文档修改覆盖.测试用例完善.用户体验改进及删除冗余无效代码等- 下面分类介绍的是一些版本迭代的重要更新内容,因个人实操和理解能力有限,部分更新并未看懂,如果有错误的地方,还望各位大神指正!  1.0.5更新内容 1.更新文档并适配最新configtxgen的修改 2.区块中迭代器关闭后引发的Nil问题 3.Kafka版本回归到0.9.0.1 4.允许对Kafka的信息进行更灵活的配置 5.修复块存储中非必要的启动消息 6.修复single_tx_

HyperLedger Fabric Introduction——区块链超级账本介绍

介绍 HyperLedger Fabric是一个基于模块化架构的分布式账本解决方案平台,它拥有深度加密.便捷扩展.部署灵活及可插拔等特性.它设计之初的目的是支持不同组件的可插拔实现,并适应整个经济生态系统中存在的复杂性和高精度性. HyperLedger Fabric与其它的区块链平台解决方案相比,提供了一种独特的扩展便捷和灵活部署的架构.它更多的适用于联盟链形式,即适合企业级之间的区块链联盟方向,建立在可信任的基础上.如果是企业级区块链部署的话,建议可以采用HyperLedger Fabric

HyperLedger Fabric 学习思路分享

HyperLedger Fabric 学习思路分享 HyperLedger Fabric最初是由Digital Asset和IBM公司贡献的.由Linux基金会主办的一个超级账本项目,它是一个目前非常流行并广为人知的区块链网络框架的实现方案.作为一种基于模块化架构开发应用程序或解决方案的基础,HyperLedger Fabric支持如共识和会员服务等即插即用的组件,它的设计初衷是支持不同组件的可插拔实现,并适应整个经济生态系统的复杂性和高精度性.HyperLedger Fabric利用容器技术运

Hyperledger Fabric on SAP Cloud Platform

今天的文章来自Wen Aviva, 坐Jerry面对面的程序媛. Jerry在之前的公众号文章<在SAP UI中使用纯JavaScript显示产品主数据的3D模型视图>已经介绍过Aviva了,SAP成都C4C开发团队中其他同事评价她为:"美腻与智慧的化身","云时代女王","是大家前沿技术的引路人".因为Jerry和Aviva就在一个组,所以我的看法是,这些评价都实至名归. 比如Jerry了解到的Javascript 3D渲染,增强现

Hyperledger Fabric 账本结构解析

前言 现在很多人都在从事区块链方面的研究,作者也一直在基于Hyperledger Fabric做一些开发工作.为了方便后来人更快的入门,本着"开源"的精神,在本文中向大家讲解一下Hyperledger Fabric账本的结构和原理.作者解析的Fabric的工程版本为v1.0.1,在新版本中可能会有些许偏差. ps:作者默认各位读者已经具备了一定的区块链基本知识,不再做一些基础知识的阐述. Hyperledger Fabric账本的结构 在作者最初了解bitcoin的时候有一个疑问:矿工

基于docker的 Hyperledger Fabric 多机环境搭建(上)

环境:ubuntu 16.04 Docker  17.04.0-ce go 1.7.4 consoul v0.8.0.4 ======================================================================= 一.项目准备 想必能搜到这篇文章的人对Hyperledger Fabric(以下简称Fabric)已经是有了一定的了解了,我就不多介绍了. 先说一下Fabric的构建环境: Hyperledger Fabric  tag v1.0.0

HyperLedger Fabric基于zookeeper和kafka集群配置解析

简述 在搭建HyperLedger Fabric环境的过程中,我们会用到一个configtx.yaml文件(可参考Hyperledger Fabric 1.0 从零开始(八)--Fabric多节点集群生产部署),该配置文件主要用于构建创世区块(在构建创世区块之前需要先创建与之对应的所有节点的验证文件集合),其中在配置Orderer信息中有一个OrdererType参数,该参数可配置为"solo" and "kafka",之前博文所讲的环境配置皆是solo,即单节点共