ファブリック公式ドキュメント: https://hyperledger-fabric.readthedocs.io/en/release-2.2/
API ドキュメント: https://pkg.go.dev/github.com/hyperledger/fabric-chaincode-go/shim#Chaincode
0.序文
このセクションでは、ファブリックでの単純な GO チェーン コードの記述を完了し、データ ストレージとデータ表示を実装し、テストしました。
1.チェーンコードの書き込み
チェーンコードの記述は主に次の手順に分かれます。
- 開発前の準備
- 書き込み初期化関数
- Invoke関数を書く
- ビジネス関数を作成する
ステップバイステップで実行してみましょう!
1.1 開発前の準備
まず最初に、純粋なチェーン コードの開発には追加の環境は必要なく、直接の開発とテストに必要な GO 言語開発環境のみが必要であることを明確にする必要があります。以前に構成されたファブリック環境は主にコンポーネント ネットワークとチェーン コードの展開に使用されるため、このセクションでは追加の考慮事項は行われません。
本題に入りましょう!まず、新しいプロジェクトを開きます。
//新建目录
mkdir fabric_test
cd fabric_test
//创建编写代码的源文件
go mod init
touch test.go
次に、必要なパッケージと必要な構造をコードにインポートします。
package main
import (
"github.com/hyperledger/fabric-chaincode-go/shim"
"github.com/hyperledger/fabric-protos-go/peer"
)
// 作为 Chaincode shim 方法的接收者
type TestChaincode struct {
}
この2つのパッケージにはファブリックブロックチェーンのAPIのほとんどが含まれており、APIを呼び出すことで保存や閲覧などのさまざまな機能を実現できます。Chaincode shim メソッドのレシーバーとして、TestChaincode 構造体が必要です (名前は自分で指定できます)。
公式ドキュメントを見ると、ChaIncode インターフェースには init メソッドと invoke メソッドが含まれていることがわかりますが、チェーン コードではこのインターフェースを実装する必要があるため、Init 関数と invoke 関数を実装する必要があります。
[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムがある可能性があります。画像を保存して直接アップロードすることをお勧めします (img-JS4b1J0w-1676978416413)(https://gitee.com/yu88888/myimage/raw) /マスター/イメージ/イメージ -20211225192909374.png)]
1.2 Init関数の記述
Init メソッドは、チェーン コードを初期化するときに呼び出されます。このメソッドには、初期化に必要ないくつかの関数を記述することができます。Init 関数はパラメータも受け入れることができることに注意してください。次に、簡単な Init 関数を記述します。
func (t *TestChaincode) Init(stub shim.ChaincodeStubInterface) peer.Response {
// 获取参数
args := stub.GetStringArgs()
if len(args) != 2 {
return shim.Error("Incorrect arguments. Expecting a key and a value")
}
// 通过调用stub.PutState()来存储参数
err := stub.PutState(args[0], []byte(args[1]))
if err != nil {
return shim.Error(fmt.Sprintf("Failed to create asset: %s", args[0]))
}
//返回结果
return shim.Success(nil)
}
1.3 Invoke関数の作成
Invoke 関数は、チェーン コードが呼び出されるたびに呼び出されます。Invoke 関数を記述するときは、まずメソッド名とパラメーターを取得し、メソッド名に基づいて別のビジネス メソッドを呼び出すのが一般的な方法です。この例では、 setメソッドとgetメソッドです。
func (t *SimpleAsset) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
//获取方法名字和参数
fn, args := stub.GetFunctionAndParameters()
var result string
var err error
if fn == "set" {
result, err = set(stub, args)
} else if fn == "get"{
result, err = get(stub, args)
}
if err != nil {
return shim.Error(err.Error())
}
return shim.Success([]byte(result))
}
1.4 ビジネス関数の作成
このセクションでは主に、最も単純な set 関数と get 関数を実装します。
// Set stores the asset (both key and value) on the ledger. If the key exists,
// it will override the value with the new one
func set(stub shim.ChaincodeStubInterface, args []string) (string, error) {
if len(args) != 2 {
return "", fmt.Errorf("Incorrect arguments. Expecting a key and a value")
}
err := stub.PutState(args[0], []byte(args[1]))
if err != nil {
return "", fmt.Errorf("Failed to set asset: %s", args[0])
}
return args[1], nil
}
// Get returns the value of the specified asset key
func get(stub shim.ChaincodeStubInterface, args []string) (string, error) {
if len(args) != 1 {
return "", fmt.Errorf("Incorrect arguments. Expecting a key")
}
value, err := stub.GetState(args[0])
if err != nil {
return "", fmt.Errorf("Failed to get asset: %s with error: %s", args[0], err)
}
if value == nil {
return "", fmt.Errorf("Asset not found: %s", args[0])
}
return string(value), nil
}
最後に、main 関数が必要です。
// main function starts up the chaincode in the container during instantiate
func main() {
if err := shim.Start(new(SimpleAsset)); err != nil {
fmt.Printf("Error starting SimpleAsset chaincode: %s", err)
}
}
2. テスト
テストでは shimtest パッケージを使用します。そのドキュメントは https://pkg.go.dev/github.com/hyperledger/[email protected]/shimtest です。
単体テストではネットワーク ノードを開始する必要はありません。テスト ファイルを通じて、チェーン コードのインターフェイスをローカルで呼び出してテストできます。原則として、shimtest パッケージの API を使用して新しい MockStub クラスを作成します。