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())
        }
}