Fabric 2.xチェーンコードの総合応用
6878 ワード
前節ではFabric 2.xチェーンコードが基本的に理解された後、本節では学生情報上のチェーンを例に、Fabric 2を説明する.xチェーンコードの総合応用.コードは、学生情報のチェーンアップ、学生情報の照会(keyによる)、key区間の学生情報の照会、学生情報の修正、履歴情報の取得などを含む.
package main
import (
"encoding/json"
"fmt"
"github.com/hyperledger/fabric-contract-api-go/contractapi"
"strconv"
"time"
)
// ,
type Student struct {
contractapi.Contract
}
// ( )
type StudentInfo struct {
Number string `json:"number"`
Name string `json:"name"`
Age string `json:"age"`
Address string `json:"address"`
}
// QueryResult structure used for handling result of query
type QueryResult struct {
Key string `json:"Key"`
Record *StudentInfo
}
type QueryHistoryResult struct {
TxId string `json:"tx_id"`
Value string `json:"value"`
IsDel string `json:"is_del"`
OnChainTime string `json:"on_chain_time"`
}
//
func (s *Student) InitLedger(ctx contractapi.TransactionContextInterface) error {
StudentInfos := []StudentInfo{
{Number: "2020001", Name: " ", Age: "23", Address: " "},
{Number: "2020002", Name: " ", Age: "24", Address: " "},
{Number: "2020003", Name: " ", Age: "25", Address: " "},
{Number: "2020004", Name: " ", Age: "26", Address: " "},
{Number: "2020005", Name: " ", Age: "27", Address: " "},
{Number: "2020006", Name: " ", Age: "28", Address: " "},
{Number: "2020007", Name: " ", Age: "29", Address: " "},
{Number: "2020008", Name: " ", Age: "30", Address: " "},
{Number: "2020009", Name: " ", Age: "31", Address: " "},
{Number: "2020010", Name: " ", Age: "32", Address: " "},
}
for _, StudentInfo := range StudentInfos {
StudentInfoAsBytes, _ := json.Marshal(StudentInfo)
err := ctx.GetStub().PutState(StudentInfo.Number, StudentInfoAsBytes)
if err != nil {
return fmt.Errorf("Failed to put to world state. %s", err.Error())
}
}
return nil
}
//
func (s *Student) CreateStudentInfo(ctx contractapi.TransactionContextInterface, number string, name string, age string, address string) error {
StudentInfo := StudentInfo{
Number: number,
Name: name,
Age: age,
Address: address,
}
StudentInfoAsBytes, _ := json.Marshal(StudentInfo)
return ctx.GetStub().PutState(StudentInfo.Number, StudentInfoAsBytes)
}
//
func (s *Student) QueryStudentInfo(ctx contractapi.TransactionContextInterface, StudentInfoNumber string) (*StudentInfo, error) {
StudentInfoAsBytes, err := ctx.GetStub().GetState(StudentInfoNumber)
if err != nil {
return nil, fmt.Errorf("Failed to read from world state. %s", err.Error())
}
if StudentInfoAsBytes == nil {
return nil, fmt.Errorf("%s does not exist", StudentInfoNumber)
}
stuInfo := new(StudentInfo)
// : Unmarshal(data []byte, v interface{}) ( )
err = json.Unmarshal(StudentInfoAsBytes, stuInfo) //stuInfo := new(StudentInfo),stuInfo
if err != nil {
return nil, fmt.Errorf("Failed to read from world state. %s", err.Error())
}
return stuInfo, nil
}
// ( key , )
func (s *Student) QueryAllStudentInfos(ctx contractapi.TransactionContextInterface, startNum, endNum string) ([]QueryResult, error) {
resultsIterator, err := ctx.GetStub().GetStateByRange(startNum, endNum)
if err != nil {
return nil, err
}
defer resultsIterator.Close()
results := []QueryResult{}
for resultsIterator.HasNext() {
queryResponse, err := resultsIterator.Next()
if err != nil {
return nil, err
}
StudentInfo := new(StudentInfo)
_ = json.Unmarshal(queryResponse.Value, StudentInfo)
queryResult := QueryResult{Key: queryResponse.Key, Record: StudentInfo}
results = append(results, queryResult)
}
return results, nil
}
//
func (s *Student) ChangeStudentInfo(ctx contractapi.TransactionContextInterface, number string, name string, age string, address string) error {
stuInfo, err := s.QueryStudentInfo(ctx, number)
if err != nil {
return err
}
stuInfo.Number = number
stuInfo.Name = name
stuInfo.Age = age
stuInfo.Address = address
StudentInfoAsBytes, _ := json.Marshal(stuInfo)
return ctx.GetStub().PutState(number, StudentInfoAsBytes)
}
//
func (s *Student) GetHistory(ctx contractapi.TransactionContextInterface, number string) ([]QueryHistoryResult, error) {
resultsIterator, err := ctx.GetStub().GetHistoryForKey(number)
if err != nil {
return nil, err
}
defer resultsIterator.Close()
//results := []QueryResult{}
//results := make([]QueryResult, 0)
results := make([]QueryHistoryResult, 0)
for resultsIterator.HasNext() {
if queryResponse, err := resultsIterator.Next();err==nil{
res := QueryHistoryResult{}
res.TxId=queryResponse.TxId
res.Value=string(queryResponse.Value)
res.IsDel=strconv.FormatBool(queryResponse.IsDelete)
res.OnChainTime=time.Unix(queryResponse.Timestamp.Seconds,0).Format("2006-01-02 15:04:05")
results= append(results, res)
}
if err!=nil {
return nil,err
}
}
return results, nil
}
func main() {
chaincode, err := contractapi.NewChaincode(new(Student))
if err != nil {
fmt.Printf("Error create fabStudentInfo chaincode: %s", err.Error())
return
}
if err := chaincode.Start(); err != nil {
fmt.Printf("Error starting fabStudentInfo chaincode: %s", err.Error())
}
}