Hyperledger fabric0.6的链码接口整理

来源:互联网 发布:淘宝的竖向分类怎么弄 编辑:程序博客网 时间:2024/05/22 13:21

1.Chaincode接口必须被所有的链上代码实现,fabric运行交易通过调用这些指定的函数

 type Chaincode interface{       // 在容器建立连接之后再部署交易期间调用Init函数,准许链上代码初始化内部数据
    Init(stub ChaincodeStubInterface, function string, args []string) ([]byte, error)
    // 每次调用交易都会调用Invoke接口. 链上代码可能会改变状态变量
    Invoke(stub ChaincodeStubInterface, function string, args []string) ([]byte, error)
    // 查询交易时调用Query接口. 链上代码仅仅读(而不是修改)它的状态变量并其返回结果
    Query(stub ChaincodeStubInterface, function string, args []string) ([]byte, error)
}
2. ChaincodeStubInterface用来部署链上代码apps来进入和修改他们的账本

type ChaincodeStubInterface interface {
    // Get the arguments to the stub call as a 2D byte array
    // 获取stub调用的参数来作为一个2维字节数组
    GetArgs() [][]byte
    // Get the arguments to the stub call as a string array
    // 获取stub调用的参数来作为一个字符数组
    GetStringArgs() []string
    // 获取交易的ID
    GetTxID() string
    // InvokeChaincode 本地调用指定的链上代码,`Invoke`使用相同的交易,也就说链上代码调用
    // 链上代码不会创建一个新的交易消息
    InvokeChaincode(chaincodeName string, args [][]byte) ([]byte, error)
    // InvokeChaincode 本地调用指定的链上代码,`Query`使用相同的交易,也就说链上代码调用
    // 链上代码不会创建一个新的交易消息
    QueryChaincode(chaincodeName string, args [][]byte) ([]byte, error)
    // GetState通过Key来返回数组的特定值
    GetState(key string) ([]byte, error)
    // PutState向账本中写入特定的键和值
    PutState(key string, value []byte) error
    // DelState从账本中移除指定的键和值
    DelState(key string) error
    // RangeQueryState函数可以通过chaincode调用来查询状态范围内的键。假设startKey和endKey
    // 在词典中,将返回一个迭代器,它可以用来遍历startKey和endKey之间的所有键。
    // 迭代器返回键的顺序是随机的。
    RangeQueryState(startKey, endKey string) (StateRangeQueryIteratorInterface, error)
    // CreateTable创建一张新表,给出表名和列定义
    CreateTable(name string, columnDefinitions []*ColumnDefinition) error
    // GetTable如果表存在,返回指定的一张表,如果表不存在ErrTableNotFound错误
    GetTable(tableName string) (*Table, error)
    // DeleteTable删除表和实体相关的所有行
    DeleteTable(tableName string) error
    // InsertRow 插入一个新行进入指定的表
    // 返回 -
    // 如果行成功插入返回true和no error
    // 如果已经存在给定的行就返回false和no error
    // 如果指定的表名不存在返回false和TableNotFoundError
    // 如果出现一个没有预料到的错误条件返回false和error
    InsertRow(tableName string, row Row) (bool, error)
    // ReplaceRow 在指定的表中更新行.
    // 返回 -
    // 如果行成功更新就返回false和no error
    // 如果给出的行不存在相应的键就返回false和no error
    // 如果指定的表名不存在返回false和TableNotFoundError
    // 如果出现一个没有预料到的错误条件返回false和error
    ReplaceRow(tableName string, row Row) (bool, error)
    // 通过键从指定的表中获取行
    GetRow(tableName string, key []Column) (Row, error)
    // 基于特定的key来返回多行。例如,给出表| A | B | C | D |,A,C和D是键,可以使用[A,C]调用GetRows来返回所有具有A,
    // C和任何D值的行作为它们的键。 GetRows也可以用A调用,返回所有具有A和C和D作为其键值的行。
    GetRows(tableName string, key []Column) (<-chan Row, error)
    //DeleteRow从指定的表中通过key来删除特定的行
    DeleteRow(tableName string, key []Column) error
    // ReadCertAttribute用来从交易证书中读取指定的属性
    // *attributeName* 是这个函数的入参.
    // 例如:
    //  attrValue,error:=stub.ReadCertAttribute("position")
    ReadCertAttribute(attributeName string) ([]byte, error)
    // VerifyAttribute用于验证事务证书是否具有名称为* attribute Name *和value * attributeValue *的属性,
    // attributeName和attributeValue是此函数接收的输入参数
    // 例如:
    //    containsAttr, error := stub.VerifyAttribute("position", "Software Engineer")
    VerifyAttribute(attributeName string, attributeValue []byte) (bool, error)
    // VerifyAttributes与VerifyAttribute相同,但它检查属性列表及其相应的值,而不是单个属性/值对
    // 例如:
    //    containsAttrs, error:= stub.VerifyAttributes(&attr.Attribute{"position",  "Software Engineer"}, &attr.Attribute{"company", "ACompany"})
    VerifyAttributes(attrs ...*attr.Attribute) (bool, error)
    // VerifySignature核实交易的签名,如果正确返回true,否则返回false
    VerifySignature(certificate, signature, message []byte) (bool, error)
    // GetCallerCertificate 返回调用者证书
    GetCallerCertificate() ([]byte, error)
    // GetCallerMetadata 返回调用方元数据
    GetCallerMetadata() ([]byte, error)
    // GetBinding 返回交易捆绑
    GetBinding() ([]byte, error)
    // GetPayload 返回交易的payload, payload是一个定义在fabric/protos/chaincode.proto
    // 中的ChaincodeSpecwhich
    GetPayload() ([]byte, error)
    // GetTxTimestamp返回交易创建的时间戳,这个时间戳是peer收到交易的当前时间。
    // 请注意,此时间戳可能与其他对等端peer的时间不同
    GetTxTimestamp() (*timestamp.Timestamp, error)
    // SetEvent保存当交易组成一个块时要发送的事件
    SetEvent(name string, payload []byte) error
}

3.StateRangeQueryIteratorInterface允许在一个链上代码在状态上迭代一定范围的键值

type StateRangeQueryIteratorInterface interface {
    // HasNext如果查询迭代器范围内包含额外的键和值就返回true
    HasNext() bool
    // Next在迭代器范围内返回下一个键和值
    Next() (string, []byte, error)
    // Close 关闭范围查询迭代器,当从迭代器中读完被释放资源的时候被调用
    Close() error
}

4.chaincode_example02解析

package main
import (
    "errors"
    "fmt"
    "strconv"
    "github.com/hyperledger/fabric/core/chaincode/shim"
)
// SimpleChaincode 样例链上代码实现
type SimpleChaincode struct {
}
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
    var A, B string    // 字符实体
    var Aval, Bval int // 资产持股
    var err error
    if len(args) != 4 {
        return nil, errors.New("Incorrect number of arguments. Expecting 4")
    }
    // 初始化链上代码
    A = args[0]
    Aval, err = strconv.Atoi(args[1])
    if err != nil {
        return nil, errors.New("Expecting integer value for asset holding")
    }
    B = args[2]
    Bval, err = strconv.Atoi(args[3])
    if err != nil {
        return nil, errors.New("Expecting integer value for asset holding")
    }
    fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)
    // 写状态到账本
    err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
    if err != nil {
        return nil, err
    }
    err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
    if err != nil {
        return nil, err
    }
    return nil, nil
}
// 支持从A到B支付X股
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
    if function == "delete" {
        // Deletes an entity from its state
        // 从他的状态中删除entity
        return t.delete(stub, args)
    }
    var A, B string    // 字符实体
    var Aval, Bval int // 持股资产
    var X int          // 交易值
    var err error
    if len(args) != 3 {
        return nil, errors.New("Incorrect number of arguments. Expecting 3")
    }
    A = args[0]
    B = args[1]
    // 从账本中获取状态
    // TODO: will be nice to have a GetAllState call to ledger
    Avalbytes, err := stub.GetState(A)
    if err != nil {
        return nil, errors.New("Failed to get state")
    }
    if Avalbytes == nil {
        return nil, errors.New("Entity not found")
    }
    Aval, _ = strconv.Atoi(string(Avalbytes))
    Bvalbytes, err := stub.GetState(B)
    if err != nil {
        return nil, errors.New("Failed to get state")
    }
    if Bvalbytes == nil {
        return nil, errors.New("Entity not found")
    }
    Bval, _ = strconv.Atoi(string(Bvalbytes))
    // 执行execution
    X, err = strconv.Atoi(args[2])
    if err != nil {
        return nil, errors.New("Invalid transaction amount, expecting a integer value")
    }
    Aval = Aval - X
    Bval = Bval + X
    fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)
    // 写状态到账本
    err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
    if err != nil {
        return nil, err
    }
    err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
    if err != nil {
        return nil, err
    }
    return nil, nil
}
// 从账本中删除实体
func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, args []string) ([]byte, error) {
    if len(args) != 1 {
        return nil, errors.New("Incorrect number of arguments. Expecting 1")
    }
    A := args[0]
    // 从账本的状态中删除密钥
    err := stub.DelState(A)
    if err != nil {
        return nil, errors.New("Failed to delete state")
    }
    return nil, nil
}
// Query callback representing the query of a chaincode
// Query 查询链上代码
func (t *SimpleChaincode) Query(stub shim.ChaincodeStubInterface, function string, args []string) ([]byte, error) {
    if function != "query" {
        return nil, errors.New("Invalid query function name. Expecting \"query\"")
    }
    var A string // 字符实体
    var err error
    if len(args) != 1 {
        return nil, errors.New("Incorrect number of arguments. Expecting name of the person to query")
    }
    A = args[0]
    // 从账本中获取状态
    Avalbytes, err := stub.GetState(A)
    if err != nil {
        jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}"
        return nil, errors.New(jsonResp)
    }
    if Avalbytes == nil {
        jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}"
        return nil, errors.New(jsonResp)
    }
    jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}"
    fmt.Printf("Query Response:%s\n", jsonResp)
    return Avalbytes, nil
}
func main() {
    // ChainCode 调用 err := shim.Start(new(SimpleChaincode))
    // 接入到ChainCodeSupportServer
    err := shim.Start(new(SimpleChaincode))
    if err != nil {
        fmt.Printf("Error starting Simple chaincode: %s", err)
    }
}
原创粉丝点击