您的位置:首页 > 其它

Hyperledger fabric0.6的链码接口整理

2017-06-29 14:39 337 查看
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)

    }

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: