LoginSignup
4
5

More than 5 years have passed since last update.

[Hyperledger fabric] init時に他のChaincodeのworld state (KVSの中身)を引き継ぐ

Posted at

一応 gistにも張っておいた。

仕組みは簡単。

  • KVSの全ての値の組み合わせをjsonで返す関数 get_all を実装しておく。
  • initの引数に、chaincodeのハッシュ値が指定されたら、そのchaincodeのget_allを呼び出し、KVSにコピーする。
  • 今の時点では古いchaincodeを無効にするとかそういうことは省略。

これで途中でchaincode書き換えたいってことになっても大丈夫。

なお、jsonの読み書きに際してはgolang は ゆるふわに JSON を扱えまぁす!をめっちゃ参考にさせていただきました。

いろいろ自信ない部分がいっぱいなので突っ込み求めて晒しておきます。

get_all関数

migrate_worldstate.go
func (t *SimpleChaincode) Query(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {
  if function == "get_all" {
        if len(args) != 0 {
            fmt.Printf("Incorrect number of arguments passed"); return nil, errors.New("QUERY: Incorrect number of arguments passed")
        }
        return t.get_all(stub)
    }
    return nil, errors.New("QUERY: No such function.")
}

func (t *SimpleChaincode) get_all(stub *shim.ChaincodeStub) ([]byte, error) {

    var tupples [][]string

    keysIter, err := stub.RangeQueryState("", "~")
    if err != nil {
        return nil, errors.New("Unable to start the iterator")
    }

    defer keysIter.Close()

    for keysIter.HasNext() {
        key, val, iterErr := keysIter.Next()
        if iterErr != nil {
            return nil, fmt.Errorf("keys operation failed. Error accessing state: %s", err)
        }
        tupple := []string{ key , string(val) }
        tupples=append(tupples, tupple)

    }

    marshalledTupples, err := json.Marshal(tupples)
    return []byte(marshalledTupples), nil
}

init部分

migrate_worldstate.go
func (t *SimpleChaincode) Init(stub *shim.ChaincodeStub, function string, args []string) ([]byte, error) {

  if len(args) == 1 {
        // migrate from old chaincode. args[0] should have chaincode address
        val, err := stub.QueryChaincode(args[0],"get_all", []string{} )
        if err != nil {
            return nil, errors.New("Unable to call chaincode " + args[0])
        }

        var states interface{}
        err = json.Unmarshal(val, &states)
        if err != nil {
            return nil, errors.New("Unable to marshal chaincode return value " + string(val))
        }

        for _, stateIf := range states.([]interface{}){
            state := stateIf.([]interface{})
            stateKey := state[0].(string)
            stateVal := state[1].(string)
            if stateKey == "" {
                return nil, errors.New("Unable to PutState: missing statekey [ " + stateKey +" , "+ string(stateVal) + " ]")
            }
            err = stub.PutState(stateKey, []byte(stateVal))
            if err != nil {
                return nil, errors.New("Unable to PutState [ " + stateKey +" , "+ string(stateVal) + " ]")
            }
        }
    }

    return nil, nil
}
4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5