上个版本的chaincode有很多功能不完备,所以要部署新版本的chaincode。Fabric支持在保留现有状态的前提对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)
}
}
|
docker cp community2.0 cli:/opt/gopath/src/github.com/hyperledger/fabric/examples/chaincode/go
docker exec -it cli bash
peer chaincode install -n mycc -v 2.0 -p github.com/hyperledger/fabric/examples/chaincode/go/community2.0
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就升级完毕了。