Hyperledger Fabric チェーン コードの変更とテスト (1)

前回のブログでは、スマート タービン流量計を使用してデータを収集し、Hyperledger のチェーン コードにアップロードしました。チェーン コードの一部のデータ構造は以前に変更されましたが、まだ小さな問題がいくつかあります。

https://blog.csdn.net/qq_43824745/article/details/125876812?spm=1001.2014.3001.5501

以前のテスト チェーンコードは次のとおりです。

/*
SPDX-License-Identifier: Apache-2.0
*/
 
package main
 
import (
	"encoding/json"
	"fmt"
 
	"github.com/hyperledger/fabric-contract-api-go/contractapi"
)
 
type SmartContract struct {
	contractapi.Contract
}
 
type Data struct {
	Now	string `json:"now(L/H)"`
	Total   string `json:"total(L)"`
}
 
 
type QueryResult struct {
	Key    string `json:"Key"`
	Record *Data
}
 
 
func (s *SmartContract) InitLedger(ctx contractapi.TransactionContextInterface) error {
	datas := []Data{
		Data{Now:"0", Total: "0"},
	}
 
	for data := range datas {
		dataAsBytes, _ := json.Marshal(data)
		err := ctx.GetStub().PutState("2022-07-20 00:00", dataAsBytes)
 
		if err != nil {
			return fmt.Errorf("Failed to put to world state. %s", err.Error())
		}
	}
 
	return nil
}
 
 
func (s *SmartContract) AddData(ctx contractapi.TransactionContextInterface, dataNumber string, now string, total string) error {
	data := Data{
		Now:	now,
		Total:   total,
	}
 
	dataAsBytes, _ := json.Marshal(data)
 
	return ctx.GetStub().PutState(dataNumber, dataAsBytes)
}
 
 
func (s *SmartContract) QueryData(ctx contractapi.TransactionContextInterface, dataNumber string) (*Data, error) {
	dataAsBytes, err := ctx.GetStub().GetState(dataNumber)
 
	if err != nil {
		return nil, fmt.Errorf("Failed to read from world state. %s", err.Error())
	}
 
	if dataAsBytes == nil {
		return nil, fmt.Errorf("%s does not exist", dataNumber)
	}
 
	data := new(Data)
	_ = json.Unmarshal(dataAsBytes, data)
 
	return data, nil
}
 
 
func (s *SmartContract) QueryAllDatas(ctx contractapi.TransactionContextInterface) ([]QueryResult, error) {
	startKey := ""
	endKey := ""
 
	resultsIterator, err := ctx.GetStub().GetStateByRange(startKey, endKey)
 
	if err != nil {
		return nil, err
	}
	defer resultsIterator.Close()
 
	results := []QueryResult{}
 
	for resultsIterator.HasNext() {
		queryResponse, err := resultsIterator.Next()
 
		if err != nil {
			return nil, err
		}
 
		data := new(Data)
		_ = json.Unmarshal(queryResponse.Value, data)
 
		queryResult := QueryResult{Key: queryResponse.Key, Record: data}
		results = append(results, queryResult)
	}
 
	return results, nil
}
 
func main() {
 
	chaincode, err := contractapi.NewChaincode(new(SmartContract))
 
	if err != nil {
		fmt.Printf("Error create test chaincode: %s", err.Error())
		return
	}
 
	if err := chaincode.Start(); err != nil {
		fmt.Printf("Error starting test chaincode: %s", err.Error())
	}
}

分単位で正確にデータを収集した時刻をデータのキーとして使用していることがわかりますが、この操作の利点は、すべてのデータをクエリする場合に、キーが辞書順に並んでいるときに乱れがないことです。結果は次のとおりです。

各クエリ結果は時系列に並べられており、合理的に見えますが、単一のデータをクエリする場合は、クエリ対象のデータに対応する Key を指定する必要があるため、この方法で単一のデータをクエリするのは不便です。 、上記のキーの値は正確な分であり、各レコードがアップロードされたのが何分であるかをユーザーが正確に知ることは不可能であるため、キーの時間を日付形式に調整し、この上で各データに番号を付けることを想定しています。辞書編集上の混乱を避けるため、番号付けには固定長のデジタル ID を使用します。

スクリプトの実行間隔が5分であることを考慮すると、1日に生成できるデータの総量は300未満であるため、3桁のIDを使用して番号付けするだけで十分です。たとえば、Keyは「」です。 2022-07-27 010" (2022 年を意味します) 7 月 27 日の 10 番目のデータについては、このデザインはユーザーが単一のデータをクエリする必要性を合理的に実現していると思います。数字はその日の数字にしか対応していないため、翌日にはまた「001」から数え始める必要があるため、スクリプトが各データのKey値を書き込む際に、そのデータが正しいかどうかを判断する必要があります。現在の日に属している場合は ID が累積され、そうでない場合は ID を 1 に戻します。

変更された test.go とシェル スクリプトは次のとおりです。

test.go:

/*
SPDX-License-Identifier: Apache-2.0
*/

package main

import (
	"encoding/json"
	"fmt"

	"github.com/hyperledger/fabric-contract-api-go/contractapi"
)

type SmartContract struct {
	contractapi.Contract
}

type Data struct {
	Now	string `json:"now(L/H)"`
	Total   string `json:"total(L)"`
	Time	string	`json:"time"`
}

type QueryResult struct {
	Key    string `json:"Key"`
	Record *Data
}

func (s *SmartContract) InitLedger(ctx contractapi.TransactionContextInterface) error {
	datas := []Data{
		Data{Now:"0", Total: "0",Time:"12:00"},
	}

	for data := range datas {
		dataAsBytes, _ := json.Marshal(data)
		err := ctx.GetStub().PutState("2022-07-20 000", dataAsBytes)

		if err != nil {
			return fmt.Errorf("Failed to put to world state. %s", err.Error())
		}
	}

	return nil
}

func (s *SmartContract) AddData(ctx contractapi.TransactionContextInterface, dataNumber string, now string, total string,time string) error {
	data := Data{
		Now:	now,
		Total:   total,
		Time:	time,
	}

	dataAsBytes, _ := json.Marshal(data)

	return ctx.GetStub().PutState(dataNumber, dataAsBytes)
}

func (s *SmartContract) QueryData(ctx contractapi.TransactionContextInterface, dataNumber string) (*Data, error) {
	dataAsBytes, err := ctx.GetStub().GetState(dataNumber)

	if err != nil {
		return nil, fmt.Errorf("Failed to read from world state. %s", err.Error())
	}

	if dataAsBytes == nil {
		return nil, fmt.Errorf("%s does not exist", dataNumber)
	}

	data := new(Data)
	_ = json.Unmarshal(dataAsBytes, data)

	return data, nil
}

func (s *SmartContract) QueryAllDatas(ctx contractapi.TransactionContextInterface) ([]QueryResult, error) {
	startKey := ""
	endKey := ""

	resultsIterator, err := ctx.GetStub().GetStateByRange(startKey, endKey)

	if err != nil {
		return nil, err
	}
	defer resultsIterator.Close()

	results := []QueryResult{}

	for resultsIterator.HasNext() {
		queryResponse, err := resultsIterator.Next()

		if err != nil {
			return nil, err
		}

		data := new(Data)
		_ = json.Unmarshal(queryResponse.Value, data)

		queryResult := QueryResult{Key: queryResponse.Key, Record: data}
		results = append(results, queryResult)
	}

	return results, nil
}

func main() {

	chaincode, err := contractapi.NewChaincode(new(SmartContract))

	if err != nil {
		fmt.Printf("Error create test chaincode: %s", err.Error())
		return
	}

	if err := chaincode.Start(); err != nil {
		fmt.Printf("Error starting test chaincode: %s", err.Error())
	}
}

 スクリプト (実際のデータは使用せず、乱数でのみテストしました):

#!/bin/bash
pre=$(date "+%Y-%m-%d")    //pre记录上一条数据的采集时间
num="1"                    //num记录当前数据是这一天的第几条数据
for i in {1..20}
do
#	sudo python /home/pi/RS485_CAN_HAT_Code/485/python/query_now.py
	now=$(date "+%Y-%m-%d")
	if [ $pre != $now ]
	then
		num="1"
		pre=$now
	fi
	id=$num
	len=${#id}
	while [ $len -le 2 ]
	do
		id="0"$id
		let len+=1
	done
	let num+=1
	time=$(date "+%H:%M")
	res=$now" "$id
#	sleep 3
#	echo " " >> data.txt
#	while read rows
#	do
#		n=$rows
#		break
#	done < data.txt
#	sudo python /home/pi/RS485_CAN_HAT_Code/485/python/query_total.py
#	sleep 3
#	echo " " >> data.txt
#	while read rows
#	do
#		t=$rows
#		break
#	done < data.txt
	n=$RANDOM
	t=$RANDOM
	echo "这是第"$i"次查询到并添加的数据:"
	echo "Now(L/H):"$n" Total(L):"$t" Time:"$time
	cmd="'{\"Args\":[\"AddData\",\"$res\",\"$n\",\"$t\",\"$time\"]}'"
	echo "Add命令:"$cmd
	echo "#!/bin/bash
peer chaincode invoke -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 newtest --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c "$cmd "
exit"> add.sh 
 docker cp add.sh cli:/opt/gopath/src/github.com/hyperledger/fabric/peer/
 docker exec -it cli bash add.sh
	sleep 60
#break
done

スクリプトの実行結果:

Org1 はすべてのデータの結果をクエリします。

 Org1 クエリの単一データの結果:

おすすめ

転載: blog.csdn.net/qq_43824745/article/details/126012109