Fabric 2.x鏈碼之基本使用

Fabric 2.0之後對鏈碼做了較大改進,在接下來的幾篇博客中加以說明。本節主要講解Fabric 2.x鏈碼的基本使用。基本鏈碼如下所示:

package main

import (
        "errors"
        "fmt"
        "github.com/hyperledger/fabric-contract-api-go/contractapi"
)

type SimpleContract struct {
        contractapi.Contract
}

//上鍊
func (sc *SimpleContract)Create(ctx contractapi.TransactionContextInterface,key string,value string)error  {
        existing, err := ctx.GetStub().GetState(key)
        if err!=nil {
                return  errors.New("查詢失敗!")
        }
        if existing !=nil{
                return fmt.Errorf("添加數據錯誤!%s已經存在。",key)
        }
        err = ctx.GetStub().PutState(key, []byte(value))
        if err!=nil {
                return errors.New("添加數據失敗!")
        }
        return nil
}
//更新
func (sc *SimpleContract)Update(ctx contractapi.TransactionContextInterface,key string,value string)error  {
        bytes, err := ctx.GetStub().GetState(key)
        if err!=nil {
                return  errors.New("查詢失敗!")
        }
        if bytes==nil {
                return fmt.Errorf("沒有查詢到%s對應的數據",key)
        }
        err = ctx.GetStub().PutState(key, []byte(value))
        if err!=nil {
                return errors.New("更新失敗:"+err.Error())
        }
        return nil
}
//查詢
func (sc *SimpleContract)Read(ctx contractapi.TransactionContextInterface,key string)(string,error)  {
        bytes, err := ctx.GetStub().GetState(key)
        if err!=nil {
                return "",errors.New("查詢失敗!")
        }
        if bytes==nil {
                return "", fmt.Errorf("數據不存在,讀到的%s對應的數據爲空!",key)
        }
        return string(bytes),nil
}
func main() {
        contract := new(SimpleContract)
        cc, err := contractapi.NewChaincode(contract)
        if err!=nil {
                panic("創建智能合約失敗:"+err.Error())
        }
        if err:=cc.Start();err!=nil {
                panic("啓動智能合約失敗:"+err.Error())
        }
}

注:Fabric 2.0的鏈碼與1.x相比,主要區別爲:

1、導入包的不同

     1.x導入的包爲:

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

     2.0導入的包爲:

              "github.com/hyperledger/fabric-contract-api-go/contractapi"

2、方法結構不同

    Fabric 2.0鏈碼沒有  Invoke(stub shim.ChaincodeStubInterface) pb.Response{ }方法。

3、方法中調用形式參數類型、返回值不同

    1.x方法爲:

           createCar1(APIstub shim.ChaincodeStubInterface, args []string) pb.Response { }

    2.0方法爲:

           Create(ctx contractapi.TransactionContextInterface,key string,value string)error { }

附錄:

1.x對應的鏈碼

package mian

/* Imports
 * 4 utility libraries for formatting, handling bytes, reading and writing JSON, and string manipulation
 * 2 specific Hyperledger Fabric specific libraries for Smart Contracts
 */
import (
	"encoding/json"
	"fmt"
	"strconv"

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

// Define the Smart Contract structure
type SmartContract1 struct {
}

// Define the Car1 structure, with 4 properties.  Structure tags are used by encoding/json library
type Car1 struct {
	Make   string `json:"make"`
	Model  string `json:"model"`
	Colour string `json:"colour"`
	Owner  string `json:"owner"`
}

/*
 * The Init method is called when the Smart Contract "fabCar1" is instantiated by the blockchain network
 * Best practice is to have any Ledger initialization in separate function -- see initLedger()
 */
func (s *SmartContract1) Init(APIstub shim.ChaincodeStubInterface) sc.Response {
	return shim.Success(nil)
}

/*
 * The Invoke method is called as a result of an application request to run the Smart Contract "fabCar1"
 * The calling application program has also specified the particular smart contract function to be called, with arguments
 */
func (s *SmartContract1) Invoke(APIstub shim.ChaincodeStubInterface) sc.Response {

	// Retrieve the requested Smart Contract function and arguments
	function, args := APIstub.GetFunctionAndParameters()
	// Route to the appropriate handler function to interact with the ledger appropriately
	if function == "queryCar1" {
		return s.queryCar1(APIstub, args)
	} else if function == "initLedger" {
		return s.initLedger(APIstub)
	} else if function == "createCar1" {
		return s.createCar1(APIstub, args)
	}
	return shim.Error("Invalid Smart Contract function name.")
}

func (s *SmartContract1) queryCar1(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1")
	}

	Car1AsBytes, _ := APIstub.GetState(args[0])
	return shim.Success(Car1AsBytes)
}

func (s *SmartContract1) initLedger(APIstub shim.ChaincodeStubInterface) sc.Response {
	Car1s := []Car1{
		Car1{Make: "Toyota", Model: "Prius", Colour: "blue", Owner: "Tomoko"},
		Car1{Make: "Ford", Model: "Mustang", Colour: "red", Owner: "Brad"},
		Car1{Make: "Hyundai", Model: "Tucson", Colour: "green", Owner: "Jin Soo"},
		Car1{Make: "Volkswagen", Model: "Passat", Colour: "yellow", Owner: "Max"},
		Car1{Make: "Tesla", Model: "S", Colour: "black", Owner: "Adriana"},
		Car1{Make: "Peugeot", Model: "205", Colour: "purple", Owner: "Michel"},
		Car1{Make: "Chery", Model: "S22L", Colour: "white", Owner: "Aarav"},
		Car1{Make: "Fiat", Model: "Punto", Colour: "violet", Owner: "Pari"},
		Car1{Make: "Tata", Model: "Nano", Colour: "indigo", Owner: "Valeria"},
		Car1{Make: "Holden", Model: "Barina", Colour: "brown", Owner: "Shotaro"},
	}

	i := 0
	for i < len(Car1s) {
		fmt.Println("i is ", i)
		Car1AsBytes, _ := json.Marshal(Car1s[i])
		APIstub.PutState("Car1"+strconv.Itoa(i), Car1AsBytes)
		fmt.Println("Added", Car1s[i])
		i = i + 1
	}

	return shim.Success(nil)
}

func (s *SmartContract1) createCar1(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {

	if len(args) != 5 {
		return shim.Error("Incorrect number of arguments. Expecting 5")
	}

	var Car1 = Car1{Make: args[1], Model: args[2], Colour: args[3], Owner: args[4]}

	Car1AsBytes, _ := json.Marshal(Car1)
	APIstub.PutState(args[0], Car1AsBytes)

	return shim.Success(nil)
}



// The main function is only relevant in unit test mode. Only included here for completeness.
func main() {

	// Create a new Smart Contract
	err := shim.Start(new(SmartContract1))
	if err != nil {
		fmt.Printf("Error creating new Smart Contract: %s", err)
	}
}


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章