Fabric-小例子

    科技2024-05-14  74

    汽车信息记录

    汽车信息的链码结构 1、引入依赖包

    package main import ( "bytes" "encoding/json" "fmt" "strconv" "github.com/hyperledger/fabric/core/chaincode/shim" sc "github.com/hyperledger/fabric/protos/peer" )

    2、声明一个结构体

    type SimpleChaincode struct { }

    3、声明Init() 和 Invoke() 函数

    // 在链码初始化过程中调用 Init 来数据,此处不做任何操作 func (s *SmartContract) Init(APIstub shim.ChaincodeStubInterface) sc.Response { return shim.Success(nil) } // query 和 invoke 时被自动调用 func (s *SmartContract) Invoke(APIstub shim.ChaincodeStubInterface) sc.Response { // 解析用户调用链码传递的函数名及参数 function, args := APIstub.GetFunctionAndParameters() // 调用不同的函数 if function == "queryCar" { return s.queryCar(APIstub, args) } else if function == "initLedger" { return s.initLedger(APIstub) } else if function == "createCar" { return s.createCar(APIstub, args) } else if function == "queryAllCars" { return s.queryAllCars(APIstub) } else if function == "changeCarOwner" { return s.changeCarOwner(APIstub, args) } return shim.Error("Invalid Smart Contract function name.") }

    4、对Invoke() 函数中的各个函数就是进行声明

    // 初始化账本数据 func (s *SmartContract) initLedger(APIstub shim.ChaincodeStubInterface) sc.Response { cars := []Car{ Car{Make: "Toyota", Model: "Prius", Colour: "blue", Owner: "Tomoko"}, Car{Make: "Ford", Model: "Mustang", Colour: "red", Owner: "Brad"}, Car{Make: "Hyundai", Model: "Tucson", Colour: "green", Owner: "Jin Soo"}, Car{Make: "Volkswagen", Model: "Passat", Colour: "yellow", Owner: "Max"}, Car{Make: "Tesla", Model: "S", Colour: "black", Owner: "Adriana"}, Car{Make: "Peugeot", Model: "205", Colour: "purple", Owner: "Michel"}, Car{Make: "Chery", Model: "S22L", Colour: "white", Owner: "Aarav"}, Car{Make: "Fiat", Model: "Punto", Colour: "violet", Owner: "Pari"}, Car{Make: "Tata", Model: "Nano", Colour: "indigo", Owner: "Valeria"}, Car{Make: "Holden", Model: "Barina", Colour: "brown", Owner: "Shotaro"}, } i := 0 for i < len(cars) { fmt.Println("i is ", i) carAsBytes, _ := json.Marshal(cars[i]) // key 为编号 CARi,value 为 Car 结构体的 json 串 APIstub.PutState("CAR"+strconv.Itoa(i), carAsBytes) fmt.Println("Added", cars[i]) i = i + 1 } return shim.Success(nil) } // 根据编号查询汽车 func (s *SmartContract) queryCar(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { if len(args) != 1 { return shim.Error("Incorrect number of arguments. Expecting 1") } carAsBytes, _ := APIstub.GetState(args[0]) return shim.Success(carAsBytes) } // 创建一辆新的汽车数据 func (s *SmartContract) createCar(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { if len(args) != 5 { return shim.Error("Incorrect number of arguments. Expecting 5") } var car = Car{Make: args[1], Model: args[2], Colour: args[3], Owner: args[4]} carAsBytes, _ := json.Marshal(car) APIstub.PutState(args[0], carAsBytes) return shim.Success(nil) } // 查询全部的汽车 func (s *SmartContract) queryAllCars(APIstub shim.ChaincodeStubInterface) sc.Response { // 查询 startKey(包括)到 endKey(不包括)间的值 startKey := "CAR0" endKey := "CAR999" resultsIterator, err := APIstub.GetStateByRange(startKey, endKey) if err != nil { return shim.Error(err.Error()) } defer resultsIterator.Close() // 延迟关闭迭代器 // 将查询结果以 json 字符串的形式写入 buffer 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\":") // Record is a JSON object, so we write as-is buffer.WriteString(string(queryResponse.Value)) buffer.WriteString("}") bArrayMemberAlreadyWritten = true } buffer.WriteString("]") fmt.Printf("- queryAllCars:\n%s\n", buffer.String()) return shim.Success(buffer.Bytes()) } // 根据汽车编号改变车的拥有者 func (s *SmartContract) changeCarOwner(APIstub shim.ChaincodeStubInterface, args []string) sc.Response { if len(args) != 2 { return shim.Error("Incorrect number of arguments. Expecting 2") } carAsBytes, _ := APIstub.GetState(args[0]) car := Car{} json.Unmarshal(carAsBytes, &car) car.Owner = args[1] // 更改汽车拥有者 carAsBytes, _ = json.Marshal(car) APIstub.PutState(args[0], carAsBytes) // 更新账本 return shim.Success(nil) }

    5、主函数

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

    PS:shim.Start() 中 的SmartContract 是上面声明的结构体

    将该链码放于./fabric/fabric-samples/chaincode/car/go/ 接下来我们启动本地测试网络

    $ docker-compose -f docker-compose-simple.yaml up -d

    docker-compose-simple.yaml文件一般是位于/fabric/fabric-samples/chaincode-docker-devmode

    进入链码容器,对链码进行编译

    $ docker exec -it chaincode bash root@61638bc49a3b:/opt/gopath/src/chaincode# cd car root@61638bc49a3b:/opt/gopath/src/chaincode/car# cd go root@61638bc49a3b:/opt/gopath/src/chaincode/car/go# go build

    执行成功后当前目录会生成一个可执行文件go,此时需要启动这个可执行文件.

    CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=test:0 ./go

    执行成功后显示:

    这边为什么用7052端口,是因为peer:7052是用于链码专用监听地址及端口号,而7051是peer节点监听的是网络端口号.

    2020-10-07 05:35:29.120 UTC [shim] SetupChaincodeLogging -> INFO 001 Chaincode log level not provided; defaulting to: INFO 2020-10-07 05:35:29.120 UTC [shim] SetupChaincodeLogging -> INFO 002 Chaincode (build level: ) starting up ...

    打开终端二 进入cli容器中

    $ docker exec -it cli bash

    查看当前节点加入的通道

    root@ef915a1edb32:/opt/gopath/src/chaincodedev# peer channel list

    显示结果

    Channels peers has joined: myc

    每一个人的通道不一定一样的,所有最好检查一下。

    安装和实例化链码

    root@ef915a1edb32:/opt/gopath/src/chaincodedev# peer chaincode install -p chaincodedev/chaincode/fabcar/go -n test -v 0 root@ef915a1edb32:/opt/gopath/src/chaincodedev# peer chaincode instantiate -n test -v 0 -c '{"Args":[]}' -C myc

    初始化数据,调用initLedger函数:

    root@ef915a1edb32:/opt/gopath/src/chaincodedev# peer chaincode invoke -n test -c '{"Args":["initLedger"]}' -C myc

    查询所有汽车的信息:

    root@ef915a1edb32:/opt/gopath/src/chaincodedev# peer chaincode query -n test -c '{"Args":["queryAllCars"]}' -C myc [{"Key":"CAR0", "Record":{"make":"Toyota","model":"Prius","colour":"blue","owner":"Tomoko"}}, {"Key":"CAR1", "Record":{"make":"Ford","model":"Mustang","colour":"red","owner":"Brad"}}, {"Key":"CAR2", "Record":{"make":"Hyundai","model":"Tucson","colour":"green","owner":"Jin Soo"}}, {"Key":"CAR3", "Record":{"make":"Volkswagen","model":"Passat","colour":"yellow","owner":"Max"}}, {"Key":"CAR4", "Record":{"make":"Tesla","model":"S","colour":"black","owner":"Adriana"}}, {"Key":"CAR5", "Record":{"make":"Peugeot","model":"205","colour":"purple","owner":"Michel"}}, {"Key":"CAR6", "Record":{"make":"Chery","model":"S22L","colour":"white","owner":"Aarav"}}, {"Key":"CAR7", "Record":{"make":"Fiat","model":"Punto","colour":"violet","owner":"Pari"}}, {"Key":"CAR8", "Record":{"make":"Tata","model":"Nano","colour":"indigo","owner":"Valeria"}}, {"Key":"CAR9", "Record":{"make":"Holden","model":"Barina","colour":"brown","owner":"Shotaro"}}]

    创建编号为CAR10的汽车信息

    root@ef915a1edb32:/opt/gopath/src/chaincodedev# peer chaincode invoke -n test -c '{"Args":["createCar","CAR10","Toyota","Prius","blue","233"]}' -C myc

    查询编号为CAR10的汽车信息

    root@ef915a1edb32:/opt/gopath/src/chaincodedev# peer chaincode query -n test -c '{"Args":["queryCar","CAR10"]}' -C myc {"make":"Toyota","model":"Prius","colour":"blue","owner":"233"}

    关闭网络:$ docker-compose -f docker-compose-simple.yaml down

    Processed: 0.010, SQL: 9