在chaincode中维护Key to store value(STATE)的正确方法。?

时间:2017-08-08 08:17:00

标签: hyperledger hyperledger-fabric smartcontracts

链码基本上将数据存储在键值对(STATE)中。

如果我必须存储学生数据,我必须传递键值,例如1001- {学生信息}。我只能创造任意数量的学生。

但问题是学生是否想要动态注册。为了管理它,学生必须传递唯一的studentId或者必须创建动态密钥。?

实现此目的的正确方法是什么。?

任何人都可以帮助我理解这个基本流程吗?

由于

1 个答案:

答案 0 :(得分:3)

由于您需要确保认可在支持同行之间保持一致,因此客户端更好,例如应用程序将生成学生ID并将其传递给链代码。沿着这条线的东西可能是很好的方式:

package main

import (
    "encoding/json"
    "fmt"

    "github.com/hyperledger/fabric/core/chaincode/shim"
    "github.com/hyperledger/fabric/protos/peer"
)

// Student
type Person struct {
    ID      string `json:"id"`
    Name    string `json:"name"`
    Faculty string `json:"faculty"`
    Address string `json:"address"`
}

// StudentAction
type StudentAction func(params []string, stub shim.ChaincodeStubInterface) peer.Response

// studentManagement the chaincode interface implementation to manage
// the ledger of person records
type studentManagement struct {
    actions map[string]StudentAction
}

// Init initialize chaincode with mapping between actions and real methods
func (pm *studentManagement) Init(stub shim.ChaincodeStubInterface) peer.Response {
    pm.actions = map[string]StudentAction{
        "addStudent": pm.AddStudent,
    }

    fmt.Println("Chaincode has been initialized")
    fmt.Println("Following actions are available")
    for action := range pm.actions {
        fmt.Printf("\t\t%s\n", action)
    }
    return shim.Success(nil)
}

// Invoke handles chaincode invocation logic, executes actual code
// for given action name
func (pm *studentManagement) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
    actionName, params := stub.GetFunctionAndParameters()

    if action, ok := pm.actions[actionName]; ok {
        return action(params, stub)
    }

    return shim.Error(fmt.Sprintf("No <%s> action defined", actionName))
}

// AddStudent inserts new person into ledger
func (pm *personManagement) AddStudent(params []string, stub shim.ChaincodeStubInterface) peer.Response {
    jsonObj := params[0]
    var student Student

    // Read person info into struct
    json.Unmarshal([]byte(jsonObj), &student)

    // Make uniqueness check 
    val, err := stub.GetState(student.ID)
    if err != nil {
        fmt.Printf("[ERROR] cannot get state, because of %s\n", err)
        return shim.Error(fmt.Sprintf("%s", err))
    }

    if val != nil {
        errMsg := fmt.Sprintf("[ERROR] student already exists, cannot create two accounts with same ID <%d>", student.ID)
        fmt.Println(errMsg)
        return shim.Error(errMsg)
    }

    fmt.Println("Adding new student", person)
    if err = stub.PutState(student.ID, []byte(jsonObj)); err != nil {
        errMsg := fmt.Sprintf("[ERROR] cannot store student record with id <%d>, due to %s", student.ID, err)
        fmt.Println(errMsg)
        return shim.Error(errMsg)
    }
    return shim.Success(nil)
}

现在一旦安装了链代码,您可以尝试以下列方式添加具有peer cli命令的新学生:

peer chaincode invoke -o localhost:7050 \
                       -n students1 -v 1.0 -C exampleChannel \
                       -c '{"Args": ["addStudent”, "{ \"id\": \”12345678\”, \"Name\": \”John Doe\”, \”Faculty\”: \”Mathematics\”, \"address\": \”MIT\”}”]}’

当然,使用SDK会更方便。