十一、ブロックチェーン学習-Hyperledger Fabric(release-1.0に基づく)チェーンコード開発-marbles管理
17506 ワード
チェーンコード開発-marbles管理 1.概要 2.marbleビーズ管理 2.1実装機能 2.2 chaincodeチェーンコード 2.3試験類 を作成する 2.4走試験類 3ローカルテスト環境を構築し、チェーンコード をテストする. 3.1マウントチェーンコード 3.2ネットワーク環境を起動する 3.3 chaincodeコンテナコンパイルチェーンコード提供チェーンコードサービス に入る. 3.4 cli容器取付チェーンコードインスタンス化チェーンコード に入る. 3.5テストチェーンコード 4ネットワークを閉じる 1.概要
前の10の文章の紹介によると、fabricのネットワーク環境とチェーンコード開発の導入デバッグの過程は基本的に理解されている.この記事では、チェーンコードの開発と呼び出しデバッグの導入を再強化します.
2.marbleビーズ管理
marble
2.1実装機能ビーズ作成 弾珠照会 弾珠削除 弾珠取引 弾珠操作履歴照会 ユーザーのビーズリスト を問い合わせる
2.2 chaincodeチェーンコード
markbels.go
2.3試験クラスの作成
markbels_test.go
2.4ランニングテストクラス
marbles.goとmarblesに入ります.test.goのディレクトリは$GOPATH/myに入れましたchaincode/marblesディレクトリの下
marblesを変更してみてください.test.goは他の方法をテストします
3ローカルテスト環境を構築し、チェーンコードをテストする
fabric-samplesプロジェクトのchaincode-docker-devmode環境テストの使用
3.1マウントチェーンコード
作成されたmarbles.goとmarbles_test.goファイルの移動先
コンテナへのマウントが容易
3.2ネットワーク環境の起動
chaincode-docker-devmodeディレクトリに移動
docker-composeによるネットワーク環境の起動
起動完了後のコンテナリスト
3.3 chaincode容器に入ってチェーンコードをコンパイルしてチェーンコードサービスを提供する
新しい端末を起動
容器に入る
マウントgoファイルディレクトリに移動
コンパイラ
コンパイル完了後にチェーンコードサービスを開始
3.4 cli容器に入ってチェーンコードを実例化する
新しい端末を起動してcliコンテナに入ります
チェーンコードのインストール
イニシャルチェーンコード
3.5テストチェーンコード
3つのビーズを作成
玉を調べる
範囲クエリー
玉を譲り渡す
再照会marble-1:ownerがWXになるかどうか
ownerのすべてのビーズを検索
ビーズ修正履歴の表示:結果として、初期化されたトランザクションと譲渡されたトランザクションを問い合わせることができます.
4ネットワークのシャットダウン
ネットワークを最初に起動した端末で2回control+cを押した後に実行
すべてのコンテナを停止して閉じる
前の10の文章の紹介によると、fabricのネットワーク環境とチェーンコード開発の導入デバッグの過程は基本的に理解されている.この記事では、チェーンコードの開発と呼び出しデバッグの導入を再強化します.
2.marbleビーズ管理
marble
//
type Marble struct {
//
ObjectType string `json:"objectType"`
//
Name string `json:"name"`
//
Color string `json:"color"`
//
Size int `json:"size"`
//
Owner string `json:"owner"`
}
2.1実装機能
2.2 chaincodeチェーンコード
markbels.go
package main
//
import (
"fmt"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/protos/peer"
"time"
"bytes"
"strconv"
"encoding/json"
)
//
type MarblesChaincode struct{
}
//
type Marble struct {
//
ObjectType string `json:"objectType"`
//
Name string `json:"name"`
//
Color string `json:"color"`
//
Size int `json:"size"`
//
Owner string `json:"owner"`
}
//
func (t *MarblesChaincode) Init(stub shim.ChaincodeStubInterface) peer.Response {
//
fmt.Println("MarblesChaincode ")
return shim.Success(nil)
}
// invoke
func (t *MarblesChaincode) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
//
fn, args := stub.GetFunctionAndParameters()
//
if fn == "initMarble" {
//
return t.initMarble(stub,args)
}else if fn == "readMarble" {
//
return t.readMarble(stub,args)
}else if fn == "deleteMarble" {
//
return t.deleteMarble(stub,args)
}else if fn == "transferMarble" {
//
return t.transferMarble(stub,args)
}else if fn == "getMarbleByRange" {
//
return t.getMarbleByRange(stub,args)
}else if fn == "queryMarblesByOwner" {
//
return t.queryMarblesByOwner(stub,args)
}else if fn == "queryHistoryForMarble" {
//
return t.queryHistoryForMarble(stub,args)
}
//
return shim.Error(fn +" !")
}
// marble args: name color size owner
func (t *MarblesChaincode) initMarble(stub shim.ChaincodeStubInterface,args []string) peer.Response {
// marble
name := args[0]
// name marble
marbleBytes, err := stub.GetState(name)
//
if err != nil {
return shim.Error(err.Error())
}
// marbleBytes
if marbleBytes != nil {
return shim.Error(" "+ name + " ");
}
//
color := args[1]
size,err := strconv.Atoi(args[2])
owner := args[3]
//
marble := &Marble{"marble",name,color,size,owner}
// marble json
marbleJsonStr, err := json.Marshal(marble)
if err != nil {
return shim.Error(err.Error())
}
// PutState json
err = stub.PutState(name,marbleJsonStr)
if err != nil {
return shim.Error(err.Error())
}
fmt.Println(" !!")
//
indexName := "owner~record"
indexKey, err := stub.CreateCompositeKey(indexName,[]string{ owner,string(marbleJsonStr)})
if err != nil{
return shim.Error(err.Error())
}
err = stub.PutState(indexKey,[]byte{0x00})
if err != nil{
return shim.Error(err.Error())
}
fmt.Println(indexKey)
return shim.Success(nil)
}
// marble args: marbleName
func (t *MarblesChaincode) readMarble(stub shim.ChaincodeStubInterface,args []string) peer.Response {
// marble name
name := args[0]
// name marble
marbleBytes, err := stub.GetState(name)
if err != nil {
return shim.Error(err.Error())
}
if marbleBytes == nil {
return shim.Error(name + " ")
}
//
return shim.Success(marbleBytes)
}
// marble args: marbleName
func (t *MarblesChaincode) deleteMarble(stub shim.ChaincodeStubInterface,args []string) peer.Response {
// markble name
name := args[0]
//
marbleBytes, err := stub.GetState(name)
if err != nil {
return shim.Error(err.Error())
}
if marbleBytes == nil {
return shim.Error(name + " ")
}
//
err = stub.DelState(name)
if err != nil {
return shim.Error(err.Error())
}
fmt.Println(name + " !")
return shim.Success(nil)
}
// marble args: marbleName newOwner
func (t *MarblesChaincode) transferMarble(stub shim.ChaincodeStubInterface,args []string) peer.Response {
//
marbleName := args[0]
newOwner := args[1]
//
marbleBytes, err := stub.GetState(marbleName)
if err != nil{
return shim.Error(err.Error())
}
if marbleBytes == nil {
return shim.Error(marbleName + " ")
}
// Marble
marbleInfo := Marble{}
err = json.Unmarshal(marbleBytes,&marbleInfo)
if err != nil {
return shim.Error(err.Error())
}
//
marbleInfo.Owner = newOwner
// json
newMarbleBytes,err := json.Marshal(marbleInfo)
if err != nil {
return shim.Error(err.Error())
}
//
err = stub.PutState(marbleName,newMarbleBytes)
if err != nil {
return shim.Error(err.Error())
}
fmt.Println(marbleName +" "+ newOwner+ " ")
return shim.Success(nil)
}
// marble args:startMarble endMarble
func (t *MarblesChaincode) getMarbleByRange(stub shim.ChaincodeStubInterface, args []string) peer.Response {
//
startMarble := args[0]
endMarble := args[1]
//
resultIterator, err := stub.GetStateByRange(startMarble,endMarble)
if err!=nil {
return shim.Error(err.Error())
}
defer resultIterator.Close();
var buffer bytes.Buffer
buffer.WriteString("[")
isWriteSplit := false
// resultIterator
for resultIterator.HasNext() {
item,err := resultIterator.Next()
if err!= nil {
return shim.Error(err.Error())
}
if isWriteSplit==true {
buffer.WriteString(",")
}
buffer.WriteString("{\"key\":")
buffer.WriteString("\""+item.Key+"\"")
buffer.WriteString(",\"record\":")
buffer.WriteString(string(item.Value))
buffer.WriteString("}")
isWriteSplit = true
}
buffer.WriteString("]")
//
return shim.Success(buffer.Bytes())
}
//
func (t *MarblesChaincode) queryMarblesByOwner(stub shim.ChaincodeStubInterface,args []string) peer.Response {
// couchdb
// couchdb cli couchdb
// couchdb cli 。
// chaincode-docker-devmode script.sh cli channel channel
// sleep 10s couchdb
owner := args[0]
fmt.Println(" "+owner+" ")
queryString := fmt.Sprintf("{\"selector\":{\"owner\": \"%s\" }}",owner)
resultIterator,err := stub.GetQueryResult(queryString)
if err != nil {
return shim.Error(err.Error())
}
defer resultIterator.Close();
var buffer bytes.Buffer
buffer.WriteString("[")
isWriteSplit := false
// resultIterator
for resultIterator.HasNext() {
item,err := resultIterator.Next()
if err!= nil {
return shim.Error(err.Error())
}
if isWriteSplit==true {
buffer.WriteString(",")
}
buffer.WriteString("{\"key\":")
buffer.WriteString("\""+item.Key+"\"")
buffer.WriteString(",\"record\":")
buffer.WriteString(string(item.Value))
buffer.WriteString("}")
isWriteSplit = true
}
buffer.WriteString("]")
//
return shim.Success(buffer.Bytes())
}
//
func (t *MarblesChaincode) queryHistoryForMarble(stub shim.ChaincodeStubInterface,args []string) peer.Response {
//
marbleName := args[0]
//
resultIterator,err := stub.GetHistoryForKey(marbleName)
if err != nil {
return shim.Error(err.Error())
}
defer resultIterator.Close()
var buffer bytes.Buffer
buffer.WriteString("[")
isWriteSplit := false
// resultIterator
for resultIterator.HasNext() {
item,err := resultIterator.Next()
if err!= nil {
return shim.Error(err.Error())
}
if isWriteSplit==true {
buffer.WriteString(",")
}
buffer.WriteString("{\"TxId\":")
buffer.WriteString("\""+item.TxId+"\"")
buffer.WriteString(",\"Timestamp\":")
buffer.WriteString(time.Unix(item.Timestamp.Seconds,int64(item.Timestamp.Nanos)).String())
buffer.WriteString(",\"Value\":")
buffer.WriteString(string(item.Value))
buffer.WriteString(",\"IsDelete\":")
buffer.WriteString(strconv.FormatBool(item.IsDelete))
buffer.WriteString("}")
isWriteSplit = true
}
buffer.WriteString("]")
//
return shim.Success(buffer.Bytes())
}
// main
func main (){
err := shim.Start(new (MarblesChaincode))
if err != nil {
fmt.Printf("Error start MarblesChaincode")
}
}
2.3試験クラスの作成
markbels_test.go
package main
import(
"fmt"
"testing"
"github.com/hyperledger/fabric/core/chaincode/shim"
)
func checkInit(t *testing.T,stub *shim.MockStub,args [][]byte) {
res := stub.MockInit("1",args)
if (res.Status != shim.OK){
fmt.Println(string(res.Message))
t.FailNow()
}
}
func checkInvoke(t *testing.T,stub *shim.MockStub,args [][]byte) {
res := stub.MockInvoke("1",args)
if (res.Status != shim.OK){
fmt.Println(string(res.Message))
t.FailNow()
}
}
func checkReadMarble(t *testing.T,stub *shim.MockStub, name string) {
res := stub.MockInvoke("1",[][]byte{[]byte("readMarble"),[]byte(name)})
if(res.Status != shim.OK){
fmt.Println(string(res.Message))
t.FailNow()
}
if(res.Payload == nil){
fmt.Println("checkReadMarble",name,"failed to get value")
t.FailNow()
}
fmt.Println(string(res.Payload))
}
func checkReadMarbleByRange(t *testing.T,stub *shim.MockStub, startKey string,endKey string) {
res := stub.MockInvoke("1",[][]byte{[]byte("getMarbleByRange"),[]byte(startKey),[]byte(endKey)})
if(res.Status != shim.OK){
fmt.Println(string(res.Message))
t.FailNow()
}
if(res.Payload == nil){
fmt.Println("checkReadMarbleByRange",startKey,endKey,"failed to get value")
t.FailNow()
}
fmt.Println(string(res.Payload))
}
func checkQueryMarblesByOwner(t *testing.T,stub *shim.MockStub, owner string) {
res := stub.MockInvoke("1",[][]byte{[]byte("queryMarblesByOwner"),[]byte(owner)})
if(res.Status != shim.OK){
fmt.Println(string(res.Message))
t.FailNow()
}
if(res.Payload == nil){
fmt.Println("checkQueryMarblesByOwner",owner,"failed to get value")
t.FailNow()
}
fmt.Println(string(res.Payload))
}
func checkQueryMarblesHistoryByKey(t *testing.T,stub *shim.MockStub, marbleName string) {
res := stub.MockInvoke("1",[][]byte{[]byte("queryHistoryForMarble"),[]byte(marbleName)})
if(res.Status != shim.OK){
fmt.Println(string(res.Message))
t.FailNow()
}
if(res.Payload == nil){
fmt.Println("checkReadMarbleByRange",marbleName,"failed to get value")
t.FailNow()
}
fmt.Println(string(res.Payload))
}
func Test_MarblesChaincode(t *testing.T) {
hello := new(MarblesChaincode)
stub := shim.NewMockStub("marble",hello)
checkInit(t,stub,nil)
// name color size owner
checkInvoke(t,stub,[][]byte{[]byte("initMarble"),[]byte("marble-1"),[]byte("red"),[]byte("10"),[]byte("LH")})
checkInvoke(t,stub,[][]byte{[]byte("initMarble"),[]byte("marble-2"),[]byte("yellow"),[]byte("11"),[]byte("LH")})
checkInvoke(t,stub,[][]byte{[]byte("initMarble"),[]byte("marble-3"),[]byte("blue"),[]byte("12"),[]byte("WX")})
checkQueryMarblesByOwner(t,stub,"WX")
// checkReadMarble(t,stub,"marble-1")
// checkInvoke(t,stub,[][]byte{[]byte("transferMarble"),[]byte("marble-1"),[]byte("WX")})
// checkInvoke(t,stub,[][]byte{[]byte("transferMarble"),[]byte("marble-1"),[]byte("LH")})
// checkInvoke(t,stub,[][]byte{[]byte("deleteMarble"),[]byte("marble-1")})
// checkQueryMarblesHistoryByKey(t,stub,"marble-1")
// checkInvoke(t,stub,[][]byte{[]byte("initMarble"),[]byte("marble-4"),[]byte("green"),[]byte("12"),[]byte("WX")})
// checkReadMarbleByRange(t,stub,"marble-1","marble-4")
// checkReadMarble(t,stub,"marble-1")
// checkInvoke(t,stub,[][]byte{[]byte("initMarble"),[]byte("marble-1"),[]byte("red"),[]byte("10"),[]byte("LH")})
// checkReadMarble(t,stub,"marble-2")
}
2.4ランニングテストクラス
marbles.goとmarblesに入ります.test.goのディレクトリは$GOPATH/myに入れましたchaincode/marblesディレクトリの下
cd $GOPATH/my_chaincode/marbles
go test marbles_test.go -v marbles.go --tags=nopkcs11
marblesを変更してみてください.test.goは他の方法をテストします
3ローカルテスト環境を構築し、チェーンコードをテストする
fabric-samplesプロジェクトのchaincode-docker-devmode環境テストの使用
3.1マウントチェーンコード
作成されたmarbles.goとmarbles_test.goファイルの移動先
$GOAPTH/src/github.com/hyperledger/fabric-samples/chaincode
コンテナへのマウントが容易
3.2ネットワーク環境の起動
chaincode-docker-devmodeディレクトリに移動
cd $GOPATH/src/github.com/hyperledger/fabric-samples/chaincode-docker-devmode
docker-composeによるネットワーク環境の起動
docker-compose -f docker-compose-simple.yaml up
起動完了後のコンテナリスト
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a7b22f7351fa hyperledger/fabric-tools "/bin/bash -c ./scri…" 7 seconds ago Up 5 seconds cli
d761b06a034a hyperledger/fabric-ccenv "/bin/bash -c 'sleep…" 7 seconds ago Up 5 seconds chaincode
7b329ef1311f hyperledger/fabric-peer "peer node start --p…" 8 seconds ago Up 6 seconds 0.0.0.0:7051->7051/tcp, 0.0.0.0:7053->7053/tcp peer
6302ffa111e2 hyperledger/fabric-orderer "orderer" 9 seconds ago Up 7 seconds 0.0.0.0:7050->7050/tcp orderer
3.3 chaincode容器に入ってチェーンコードをコンパイルしてチェーンコードサービスを提供する
新しい端末を起動
容器に入る
docker exec -it chaincode /bin/bash
マウントgoファイルディレクトリに移動
cd marbles/
コンパイラ
go build
コンパイル完了後にチェーンコードサービスを開始
CORE_PEER_ADDRESS=peer:7051 CORE_CHAINCODE_ID_NAME=mycc:0 ./marbles
3.4 cli容器に入ってチェーンコードを実例化する
新しい端末を起動してcliコンテナに入ります
docker exec -it cli /bin/bash
チェーンコードのインストール
peer chaincode install -p chaincodedev/chaincode/marbles -n mycc -v 0
イニシャルチェーンコード
peer chaincode instantiate -n mycc -v 0 -c '{"Args":[]}' -C myc
3.5テストチェーンコード
3つのビーズを作成
peer chaincode invoke -n mycc -c '{"Args":["initMarble","marble-1","red","10","LH"]}' -C myc
peer chaincode invoke -n mycc -c '{"Args":["initMarble","marble-2","yellow","11","LH"]}' -C myc
peer chaincode invoke -n mycc -c '{"Args":["initMarble","marble-3","blue","12","WX"]}' -C myc
玉を調べる
peer chaincode query -n mycc -c '{"Args":["readMarble","marble-1"]}' -C myc
範囲クエリー
peer chaincode query -n mycc -c '{"Args":["getMarbleByRange","marble-1","marble-3"]}' -C myc
玉を譲り渡す
peer chaincode invoke -n mycc -c '{"Args":["transferMarble","marble-1","WX"]}' -C myc
再照会marble-1:ownerがWXになるかどうか
peer chaincode query -n mycc -c '{"Args":["readMarble","marble-1"]}' -C myc
ownerのすべてのビーズを検索
peer chaincode query -n mycc -c '{"Args":["queryMarblesByOwner","WX"]}' -C myc
ビーズ修正履歴の表示:結果として、初期化されたトランザクションと譲渡されたトランザクションを問い合わせることができます.
peer chaincode query -n mycc -c '{"Args":["queryHistoryForMarble","marble-1"]}' -C myc
4ネットワークのシャットダウン
ネットワークを最初に起動した端末で2回control+cを押した後に実行
docker-compose -f docker-compose-simple.yaml down
すべてのコンテナを停止して閉じる