基本示例
本示例以一个基本的智能合约用例为例,只包含智能合约的必须部分,没有实现任何业务逻辑。
package main import ( "errors" "fmt" "strconv" "github.com/hyperledger/fabric-contract-api-go/contractapi" ) // ABstore Chaincode implementation type ABstore struct { contractapi.Contract } func main() { cc, err := contractapi.NewChaincode(new(ABstore)) if err != nil { panic(err.Error()) } if err := cc.Start(); err != nil { fmt.Printf("Error starting ABstore chaincode: %s", err) } }
官方示例
Hyperledger Fabric 提供了很多官方智能合约样例,详情请参见 fabric 官方示例。本示例以 Hyperledger Fabric 官方提供的 ABstore 样例为例。该示例的 Init 函数用于初始化两个 key/value 键值对,Invoke 函数用于根据不同业务逻辑进行细分调用,最终调用以下业务逻辑接口:
1. Init:用于初始化键值对。
2. Invoke:用于 key 之间的 value 转移。
3. Delete:用于删除一个键值对。
4. Query:用于查询 key 所对应的值。
Init 函数示例
Init 函数在智能合约实例化以及升级的时候会被调用。本例通过调用 API PutState 将数据写到账本中。具体代码如下:
// Init用于初始化两个键值对,用户输入的参数为KEY1_NAME, VALUE1, KEY2_NAME, VALUE2 func (t *ABstore) Init(ctx contractapi.TransactionContextInterface, A string, Aval int, B string, Bval int) error { fmt.Println("ABstore Init") var err error // Initialize the chaincode fmt.Printf("Aval = %d, Bval = %d\\n", Aval, Bval) // Write the state to the ledger err = ctx.GetStub().PutState(A, []byte(strconv.Itoa(Aval))) if err != nil { return err } err = ctx.GetStub().PutState(B, []byte(strconv.Itoa(Bval))) if err != nil { return err } return nil }
Invoke 函数示例
业务逻辑 invoke 函数主要用于实现业务逻辑中的资产转移。本例中通过调用 API GetState 获取到 KEY 对应的资产总值,通过调用用户业务逻辑实现资产转移,通过调用 API PutState 将用户最终资产写入账本。具体代码如下:
// invoke实现两个键之间的value转移,输入为KEY1_NAME, KEY2_NAME,VALUE func (t *ABstore) Invoke(ctx contractapi.TransactionContextInterface, A, B string, X int) error { var err error var Aval int var Bval int // Get the state from the ledger // TODO: will be nice to have a GetAllState call to ledger Avalbytes, err := ctx.GetStub().GetState(A) if err != nil { return fmt.Errorf("Failed to get state") } if Avalbytes == nil { return fmt.Errorf("Entity not found") } Aval, _ = strconv.Atoi(string(Avalbytes)) Bvalbytes, err := ctx.GetStub().GetState(B) if err != nil { return fmt.Errorf("Failed to get state") } if Bvalbytes == nil { return fmt.Errorf("Entity not found") } Bval, _ = strconv.Atoi(string(Bvalbytes)) // Perform the execution Aval = Aval - X Bval = Bval + X fmt.Printf("Aval = %d, Bval = %d\\n", Aval, Bval) // Write the state back to the ledger err = ctx.GetStub().PutState(A, []byte(strconv.Itoa(Aval))) if err != nil { return err } err = ctx.GetStub().PutState(B, []byte(strconv.Itoa(Bval))) if err != nil { return err } return nil }
Delete 函数示例
业务逻辑 delete 函数主要用于实现业务逻辑中的账户删除功能,本例通过调用 API DelState 删除对应账户。具体代码如下:
// delete用于从账本中删除指定的键,输入为KEY_NAME func (t *ABstore) Delete(ctx contractapi.TransactionContextInterface, A string) error { // Delete the key from the state in ledger err := ctx.GetStub().DelState(A) if err != nil { return fmt.Errorf("Failed to delete state") } return nil }
Query 函数示例
业务逻辑 query 函数主要用于实现业务逻辑中的账户查询功能,本例通过调用 API GetState 查询对应账户的资产。具体代码如下:
// query主要是查询键对应的值,输入为KEY_NAME func (t *ABstore) Query(ctx contractapi.TransactionContextInterface, A string) (string, error) { var err error // Get the state from the ledger Avalbytes, err := ctx.GetStub().GetState(A) if err != nil { jsonResp := "{\\"Error\\":\\"Failed to get state for " + A + "\\"}" return "", errors.New(jsonResp) } if Avalbytes == nil { jsonResp := "{\\"Error\\":\\"Nil amount for " + A + "\\"}" return "", errors.New(jsonResp) } jsonResp := "{\\"Name\\":\\"" + A + "\\",\\"Amount\\":\\"" + string(Avalbytes) + "\\"}" fmt.Printf("Query Response:%s\\n", jsonResp) return string(Avalbytes), nil }