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

Posted preminem

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了搭建基于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就升级完毕了。

 

以上是关于搭建基于hyperledger fabric的联盟社区 --升级chaincode的主要内容,如果未能解决你的问题,请参考以下文章

基于hyperledger fabric 联盟链 + vue cli的项目搭建完整教程

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

搭建基于hyperledger fabric的联盟社区 --生成公私钥证书及配置文件

搭建基于hyperledger fabric的联盟社区 --搭建node.js服务器

Hyperledger Fabric 环境搭建及Fabric 测试网络使用(区块链联盟链)

《HyperLedger Fabric 2.3 联盟链搭建》 课程学习笔记