最近在开发chaincode的时候遇到了一个问题,使用GetFunctionAndParameters这个函数会返回一个函数以及参数,但是运行总是出了点问题。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
function, args := stub.GetFunctionAndParameters()

	if function != "invoke" {
		return shim.Error("Unknown function call")
	}

	if len(args) < 2 {
		return shim.Error("Incorrect number of arguments. Expecting at least 2")
	}

	if args[0] == "delete" {
		// Deletes an entity from its state
		return t.delete(stub, args)
	}

我之前写chaincode的时候,参考官方写的实例,把args[0]作为要调用的函数,其余的是函数使用的参数,结果总是报一些明明奇妙的错误

1
Incorrect number of arguments. Expecting 1

或者直接函数数据内容出错。 这个不应该啊,难道数据不是这么传递的? 好吧,查看下源代码。 首先要查看的函数是

1
stub.GetFunctionAndParameters()

通过传参可以看到stubshim.ChaincodeStubInterface对象(就这么不标准的说吧),去shim包下找一找,没有看到ChaincodeStubInterface这个接口函数。 但是有个interfaces.go文件,点开查看,确实有这么个接口,对于这个函数有以下内容

1
2
3
4
5
	// GetFunctionAndParameters returns the first argument as the function
	// name and the rest of the arguments as parameters in a string array.
	// Only use GetFunctionAndParameters if the client passes arguments intended
	// to be used as strings.
	GetFunctionAndParameters() (string, []string)

到这个地方,看上面对于接口的解释就可以看明白了。这个函数将传入的参数拆分返回两部分内容,第一个参数作为函数名称,其余的是函数的参数。 但是我还有点虚,既然都看到这了,全部查看完吧。 看看那个struct实现了这个接口吧。直接找不好找啊,

1
grep -r "GetFunctionAndParameters"

恩,就在同一个目录下的chaincode.go文件里面。可以看到函数是这么写的

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
// GetFunctionAndParameters documentation can be found in interfaces.go
func (stub *ChaincodeStub) GetFunctionAndParameters() (function string, params []string) {
        allargs := stub.GetStringArgs()
        function = ""
        params = []string{}
        if len(allargs) >= 1 {
                function = allargs[0]
                params = allargs[1:]
        }
        return
}

真相大白了!获取到所有的参数,然后拆分,返回! 等等!这个stub.GetStringArgs()是获取到的我所有的参数还是其他的什么内容?来看一下

1
2
3
4
5
6
7
8
9
// GetStringArgs documentation can be found in interfaces.go
func (stub *ChaincodeStub) GetStringArgs() []string {
        args := stub.GetArgs()
        strargs := make([]string, 0, len(args))
        for _, barg := range args {
                strargs = append(strargs, string(barg))
        }
        return strargs
}

是调用GetArgs()函数,生成slice作为数组返回! 继续看下GetArgs()函数。

1
2
3
4
// GetArgs documentation can be found in interfaces.go
func (stub *ChaincodeStub) GetArgs() [][]byte {
        return stub.args
}

好简单,返回stub的参数,看来ChaincodeStub这个结构体里面应该是有这个参数的,果然如此。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
type ChaincodeStub struct {
        TxID           string
        chaincodeEvent *pb.ChaincodeEvent
        args           [][]byte
        handler        *Handler
        signedProposal *pb.SignedProposal
        proposal       *pb.Proposal

        // Additional fields extracted from the signedProposal
        creator   []byte
        transient map[string][]byte
        binding   []byte
}

好了,问题得解!