https://godoc.org/gopkg.in/hyperledger/fabric.v1/core/chaincode/shim
2. 主要api链码主要通过shim.ChaincodeStub所提供的方法进行操作。
2.1 参数读取API-GetFunctionAndParameters函数: GetFunctionAndParameters:
作用:提取调用链码交易中的方法名和参数,其中第一个参数是方法名称,其他参数则为函数入参
返回值:其返回值有两个 第一个是 方法名 ,第二个是 入参的数组
func (stub *ChaincodeStub) GetFunctionAndParameters() (function string, params []string)
比如在前面第八篇中的helloworld.go的实例中.
func (t *HelloWorld) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
// 通过GetFunctionAndParameters 来获取到要调用的 函数 和 参数
fn, args := stub.GetFunctionAndParameters()
// 判断是调用了哪个方法
if (fn == "set"){
return t.set(stub,args)
}else if (fn == "get"){
return t.get(stub,args)
}
// 如果不是 set 也不是 get 则报错
return shim.Error("Invoke err must set or get")
}
一般 会通过fn来分发请求到其他业务实现的函数中。
2.2 获取链码交易的参数API-GetStringArgs函数: GetStringArgs:
作用:提取调用链码交易中的参数
返回值:交易中的入参
func (stub *ChaincodeStub) GetStringArgs() []string
比如在前面第八篇中的helloworld.go的实例中.
// 实现接口方法
func (t *HelloWorld) Init(stub shim.ChaincodeStubInterface) peer.Response {
// 通过GetStringArgs 获取到输入的参数
args := stub.GetStringArgs()
// 通过PutState 给srt 赋值
// 这样就是 在初始化时 需要传入两个参数 一个是 srt 一个是 hellowrold 这样就在初始化时个srt 赋值了helloworld
err := stub.PutState(args[0],[]byte(args[1]))
// 判断是否报错
if (err != nil){
return shim.Error(err.Error())
}
// 成功完成初始化
return shim.Success(nil)
}
2.3 与账本状态交互的API
2.3.1 在账本中增加键值对-PutState
函数: PutState:
参数:两个参数 第一个是 key 第二个是value
作用:在账本中增加或修改键值对
返回值:err
func (stub *ChaincodeStub) PutState(key string, value []byte) error
比如在前面第八篇中的helloworld.go的实例中.
// 通过PutState 给srt 赋值
// 这样就是 在初始化时 需要传入两个参数 一个是 srt 一个是 hellowrold 这样就在初始化时个srt 赋值了helloworld
err := stub.PutState(args[0],[]byte(args[1]))
2.3.2 查找账本中key对应的-GetState
函数: GetState:
参数:一个参数 要查询的 key
作用:查找账本中key对应的value
返回值:value的byte,err
func (stub *ChaincodeStub) GetState(key string) ([]byte, error)
比如在前面第八篇中的helloworld.go的实例中.
// 通过GetState 获取srt值
value, err := stub.GetState(args[0])
2.3.3 删除键值对-DelState
函数: DelState:
参数:一个参数 要删除的 key
作用:删除账本中的某个键值对
返回值:err
func (stub *ChaincodeStub) DelState(key string) error
2.3.4 获取指定范围key的values-GetStateByRange
函数:GetStateByRange
参数:两个 startKey 和 endKey
作用:删除账本中的某个键值对
返回值:返回值两个 范围内的value和 err
func (stub *ChaincodeStub) GetPrivateDataByRange(collection, startKey, endKey string) (StateQueryIteratorInterface, error)
这里的区间为[startKey,endKey)
也就是说
err := stub.PutState("srt1","1")
err := stub.PutState("srt2","2")
err := stub.PutState("srt3","3")
resultIterator,err := stub.GetStateByRange("srt1","str3")
defer resultIterator.Close();
for resultIterator.Next() {
item, _ := resultIterator.Next();
fmt.Printf(string(item.Value))
}
这里会输出1,2 不会输出3
1
2
2.3.5 查询某个key的历史记录-GetHistoryForKey
函数:GetHistoryForKey
参数:要查询的key
作用:查询某个key的历史记录
返回值:返回值两个 key的历史记录 和 err
func (stub *ChaincodeStub) GetHistoryForKey(key string) (HistoryQueryIteratorInterface, error)
比如
historyIterator,err := stub.GetHistoryForKey("str")
defer historyIterator.Close();
for historyIterator.Next() {
item, _ := historyIterator.Next();
fmt.Printf(string(item.TxId))
fmt.Printf(string(item.Value))
}
2.3.6 创建复合键-CreateCompositeKey
函数:CreateCompositeKey
参数:创建复合键
作用:可以通过创建复合键来帮助区分某一类数据
返回值:复合键key 和 err
func (stub *ChaincodeStub) CreateCompositeKey(objectType string, attributes []string) (string, error)
比如
indexName := "sex~name"
indexKey, err := stub.CreateCompositeKey(indexName,[]string{"body","xiaowang"})
stub.PutState(indexKey,[]byte{0x00})
fmt.Printf(indexKey)
indexKey, err := stub.CreateCompositeKey(indexName,[]string{"girl","xiaoli"})
stub.PutState(indexKey,[]byte{0x00})
fmt.Printf(indexKey)
输出
sex~nameboyxiaowang
sex~namegirlxiaoli
2.3.7 根据复合键某一局部值 查找匹配的数据以及拆分复合键-GetStateByPartialCompositeKey,SplitCompositeKey
函数:GetStateByPartialCompositeKey
参数:objectType-复合键 ,attributes-需匹配的参数
作用:查询符合attributes要求的复合键的值
返回值:复合键key 和 err
func (stub *ChaincodeStub) GetStateByPartialCompositeKey(objectType string, attributes []string) (StateQueryIteratorInterface, error)
函数:SplitCompositeKey
参数:compositeKey-复合键
作用:拆分复合键 为对应的属性
func (stub *ChaincodeStub) SplitCompositeKey(compositeKey string) (string, []string, error)
比如查询boy信息
indexName := "sex~name"
resultIterator,err := stub.GetStateByPartialCompositeKey(indexName ,[]string{"boy"})
defer resultIterator.Close();
for resultIterator.HasNext() {
item,_ := resultIterator.Next()
objectType,compositeKeyParts,err := stub.SplitCompositeKey(item.Key)
fmt.Println("objectType:"+objectType)
fmt.Println("sex:"+compositeKeyParts[0])
fmt.Println("name:"+compositeKeyParts[1])
}
会输出
objectType:sex~name
sex: boy
name:xiaowang
2.3.8 对数据库进行查询(1.0版本仅支持couchDB)-GetQueryResult
函数:GetQueryResult
参数:query-查询指令
作用:对数据进行查询 1.0版本仅支持couchDB
返回值:StateQueryIteratorInterface-返回结果集 error-错误信息
func (stub *ChaincodeStub) GetQueryResult(query string) (StateQueryIteratorInterface, error)
比如
resultIterator, err := stub.GetQueryResult("{\"selector\":\"sex\":\"boy\"}")
2.3.9 调用另一个链码中的invoke方法-InvokeChaincode
函数:InvokeChaincode
参数:chaincodeName-链码名称 args-参数 channel-channel 名称
作用: 调用另一个链码中的invoke方法-
返回值:StateQueryIteratorInterface-返回结果集 error-错误信息
func (stub *ChaincodeStub) InvokeChaincode(chaincodeName string, args [][]byte, channel string) pb.Response
比如
调用chaincode_example002中的a向b转账
trans := [][]byte{[]byte("invoke"),[]byte("a"),[]byte("b"),[]byte("11")}
stub.InvokeChaincode("mycc",trans,"mychannel")