I'm trying to create a Hyperledger Fabric chaincode function/method which accepts an indeterminate number of inputs (i.e. variadic function).
I'm working in Go.
Here is what I have:
38 type Prod struct {
39 ProdID string `json:"prodID"`
40 Attributes []string `json:"attributes"`
41 }
420 func (s *SmartContract) Ver2(ctx contractapi.TransactionContextInterface, prodID string, input...string) error {
421 //create Prod struct
422 var p Prod
423 //set values based on input:
424 p.ProdID = prodID
425 p.Attributes = make([]string,len(input))
426 for i:=0; i<len(input); i++ {
427 p.Attributes[i]=input[i]
428 }
429 //convert Go struct into JSON format
430 assetJSON, err := json.Marshal(p)
431 if err != nil {
432 return fmt.Errorf("Problem encountered during marshaling: %v\n", err)
433 }
434 //write data to ledger
435 return ctx.GetStub().PutState(prodID, assetJSON)
436 }
When I try to call this chaincode with the following code
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile /home/hans/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n scm -c '{"Args":["Ver2","BB","ok","maybe","test"]}'
I get this error:
Error: endorsement failure during invoke. response: status:500 message:"Error managing parameter param1. Conversion error. Value ok was not passed in expected format []string"
Is there a problem with my code or is this a limitation of the Fabric api that I am using?
I've tried searching online, but haven't stumbled on any relevant discussion or documentation around variadic functions in chaincode.
I got a similar (albeit non-chaincode) working version here: https://play.golang.org/p/-7NX8-Uf88p
For what it's worth, I succeeded in making a variadic helper function which I can call from another chaincode function, but the variadic input cannot be modified without updating the chaincode. (So not very useful to me.)
For reference, those two functions are listed below:
394 func (s *Prod) VeriTest(ctx contractapi.TransactionContextInterface, prodID string, attr ...string) {
395 s.ProdID = prodID
396 s.Attributes = make([]string, len(attr))
397 for i:=0; i<len(attr); i++ {
398 s.Attributes[i]=attr[i]
399 }
400 }
401
402 //Ver: Proof of Concept - linked to VeriTest above
403 func (s *SmartContract) Ver(ctx contractapi.TransactionContextInterface) error {
404 //create Prod struct
405 var p Prod
406 //call VeriTest on Prod
407 p.VeriTest(ctx,"AA","test","string","five")
408 //convert Go struct into JSON format
409 assetJSON, err := json.Marshal(p)
410 if err != nil {
411 return err
412 }
413 //write data to ledger
414 return ctx.GetStub().PutState("AA", assetJSON)
415 }
The issue you are having is due to the fact that you are not properly encoding the []string parameter when calling peer chaincode invoke
.
The way you are calling it is sending an array of string parameters, but what you are trying to do is send one string parameter and then a second parameter which is an array of strings.
In order to do this, you will need to encode the second parameter as a JSON array:
peer chaincode invoke ... -n scm -c '{"Args":["Ver2","BB","[\"ok\",\"maybe\",\"test\"]"}'
The last thing for a working solution is to change the type of the attr
parameter from a variadic ...string
to an array []string
.
(I omitted the other invoke params with the ...
for clarity)