Commit fd498d2f authored by Gabor Hosszu's avatar Gabor Hosszu
Browse files

Use repeated bytes instead of repeated string for chaincode call args



This allows applications to easily pass arbitrary blobs without having
to serialize them to strings.  At the same time, we also consolidate
the function argument to be part of the repeated bytes args.

For convenience and to simplify porting of existing chaincode to the
new argument format, we introduce helper functions in the shim which
cast between ([][]byte) and (string, []string).

Change-Id: I67562523a208727157c4767e86e1ef437e997f13
Signed-off-by: default avatarGabor Hosszu <gabor@digitalasset.com>
parent c950903f
......@@ -349,8 +349,7 @@ Feature: Network of Peers
# @doNotDecompose
# @wip
# Arg[0] = a, base64 = 'YQ=='
# sha256 = 'acfb280369a87a57b1954210081d78943f1a0adb5368184984e8852a42c14df8'
# sha256 = '53a54f606b9cc14ae2825cc50736b183cf8d6fd0131b9d3176997efcf77d775f'
# calculated using all the args
Scenario: chaincode map single peer content generated ID
Given we compose "docker-compose-1.yml"
......@@ -364,10 +363,10 @@ Feature: Network of Peers
When I invoke chaincode "map" function name "put" on "vp0" with "sha256"
| arg1 |arg2|
| YQ== | 10 |
| a | 10 |
Then I should have received a transactionID
Then I wait up to "25" seconds for transaction to be committed to all peers
Then I check the transaction ID if it is "acfb280369a87a57b1954210081d78943f1a0adb5368184984e8852a42c14df8"
Then I check the transaction ID if it is "cbe63379a50f0c9d798951e5ccdf70a5c341acda508d7fa1345841d977825f71"
Scenario: chaincode example 01 single peer rejection message
Given we compose "docker-compose-1-exp.yml"
......
......@@ -20,6 +20,7 @@ import re
import time
import copy
from datetime import datetime, timedelta
import base64
import sys, requests, json
......@@ -194,7 +195,6 @@ def getArgsFromContext(context):
if 'table' in context:
# There is ctor arguments
args = context.table[0].cells
return args
@when(u'I deploy chaincode "{chaincodePath}" with ctor "{ctor}" to "{containerName}"')
......@@ -239,7 +239,8 @@ def deployChainCodeToContainer(context, chaincode, containerName):
def createChaincodeSpec(context, chaincode):
chaincode = validateChaincodeDictionary(chaincode)
args = to_bytes(prepend(chaincode["constructor"], chaincode["args"]))
# Create a ChaincodeSpec structure
chaincodeSpec = {
"type": getChaincodeTypeValue(chaincode["language"]),
"chaincodeID": {
......@@ -247,8 +248,7 @@ def createChaincodeSpec(context, chaincode):
"name" : chaincode["name"]
},
"ctorMsg": {
"function" : chaincode["constructor"],
"args" : chaincode["args"]
"args" : args
},
}
......@@ -365,14 +365,12 @@ def invokeChaincode(context, devopsFunc, functionName, containerName, idGenAlg=N
if 'table' in context:
# There is ctor arguments
args = context.table[0].cells
args = to_bytes(prepend(functionName, args))
for idx, attr in enumerate(attributes):
attributes[idx] = attr.strip()
context.chaincodeSpec['ctorMsg']['function'] = functionName
context.chaincodeSpec['ctorMsg']['args'] = args
context.chaincodeSpec['attributes'] = attributes
#If idGenAlg is passed then, we still using the deprecated devops API because this parameter can't be passed in the new API.
if idGenAlg != None:
invokeUsingDevopsService(context, devopsFunc, functionName, containerName, idGenAlg)
......@@ -424,6 +422,7 @@ def invokeMasterChaincode(context, devopsFunc, chaincodeName, functionName, cont
args = []
if 'table' in context:
args = context.table[0].cells
args = to_bytes(prepend(functionName, args))
typeGolang = 1
chaincodeSpec = {
"type": typeGolang,
......@@ -431,7 +430,6 @@ def invokeMasterChaincode(context, devopsFunc, chaincodeName, functionName, cont
"name" : chaincodeName
},
"ctorMsg": {
"function" : functionName,
"args" : args
}
}
......@@ -646,7 +644,7 @@ def step_impl(context, chaincodeName, functionName):
if 'table' in context:
# There is ctor arguments
args = context.table[0].cells
context.chaincodeSpec['ctorMsg']['function'] = functionName
args = to_bytes(prepend(functionName, args))
context.chaincodeSpec['ctorMsg']['args'] = args #context.table[0].cells if ('table' in context) else []
# Invoke the POST
chaincodeOpPayload = createChaincodeOpPayload("query", context.chaincodeSpec)
......@@ -678,8 +676,7 @@ def query_common(context, chaincodeName, functionName, value, failOnError):
containerDataList = bdd_test_util.getContainerDataValuesFromContext(context, aliases, lambda containerData: containerData)
# Update the chaincodeSpec ctorMsg for invoke
context.chaincodeSpec['ctorMsg']['function'] = functionName
context.chaincodeSpec['ctorMsg']['args'] = [value]
context.chaincodeSpec['ctorMsg']['args'] = to_bytes([functionName, value])
# Invoke the POST
# Make deep copy of chaincodeSpec as we will be changing the SecurityContext per call.
chaincodeOpPayload = createChaincodeOpPayload("query", copy.deepcopy(context.chaincodeSpec))
......@@ -819,3 +816,11 @@ def compose_op(context, op):
else:
parseComposeOutput(context)
print("After {0}ing, the container service list is = {1}".format(op, [containerData.composeService for containerData in context.compose_containers]))
def to_bytes(strlist):
return [base64.standard_b64encode(s.encode('ascii')) for s in strlist]
def prepend(elem, l):
if l is None or l == "":
return [elem]
return [elem] + l
......@@ -17,9 +17,8 @@
package noop
import (
"encoding/base64"
"bytes"
"errors"
"fmt"
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/core/chaincode/shim"
......@@ -95,12 +94,8 @@ func (t *SystemChaincode) Query(stub *shim.ChaincodeStub, function string, args
if nil != merr {
return nil, merr
}
var data = newCCIS.ChaincodeSpec.CtorMsg.Args[0]
var dataInByteForm, b64err = base64.StdEncoding.DecodeString(data)
if b64err != nil {
return nil, fmt.Errorf("Error in decoding from Base64: %s", b64err)
}
return dataInByteForm, nil
var dataInByteForm = newCCIS.ChaincodeSpec.CtorMsg.Args
return bytes.Join(dataInByteForm, []byte{}), nil
default:
return nil, errors.New("Unsupported operation")
}
......
......@@ -21,6 +21,7 @@ import (
"testing"
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/protos"
)
......@@ -115,7 +116,7 @@ func (ml mockLedger) GetTransactionByID(txID string) (*protos.Transaction, error
if txID == "noSuchTX" {
return nil, fmt.Errorf("Some error")
}
newCCIS := &protos.ChaincodeInvocationSpec{ChaincodeSpec: &protos.ChaincodeSpec{CtorMsg: &protos.ChaincodeInput{Function: "execute", Args: []string{something}}}}
newCCIS := &protos.ChaincodeInvocationSpec{ChaincodeSpec: &protos.ChaincodeSpec{CtorMsg: &protos.ChaincodeInput{Args: shim.ToChaincodeArgs("execute", something)}}}
pl, _ := proto.Marshal(newCCIS)
return &protos.Transaction{Payload: pl}, nil
}
......@@ -243,7 +243,7 @@ func (chaincodeSupport *ChaincodeSupport) deregisterHandler(chaincodehandler *Ha
}
// Based on state of chaincode send either init or ready to move to ready state
func (chaincodeSupport *ChaincodeSupport) sendInitOrReady(context context.Context, txid string, chaincode string, f *string, initArgs []string, timeout time.Duration, tx *pb.Transaction, depTx *pb.Transaction) error {
func (chaincodeSupport *ChaincodeSupport) sendInitOrReady(context context.Context, txid string, chaincode string, initArgs [][]byte, timeout time.Duration, tx *pb.Transaction, depTx *pb.Transaction) error {
chaincodeSupport.runningChaincodes.Lock()
//if its in the map, there must be a connected stream...nothing to do
var chrte *chaincodeRTEnv
......@@ -257,7 +257,7 @@ func (chaincodeSupport *ChaincodeSupport) sendInitOrReady(context context.Contex
var notfy chan *pb.ChaincodeMessage
var err error
if notfy, err = chrte.handler.initOrReady(txid, f, initArgs, tx, depTx); err != nil {
if notfy, err = chrte.handler.initOrReady(txid, initArgs, tx, depTx); err != nil {
return fmt.Errorf("Error sending %s: %s", pb.ChaincodeMessage_INIT, err)
}
if notfy != nil {
......@@ -411,9 +411,8 @@ func (chaincodeSupport *ChaincodeSupport) Launch(context context.Context, t *pb.
//build the chaincode
var cID *pb.ChaincodeID
var cMsg *pb.ChaincodeInput
var f *string
var cLang pb.ChaincodeSpec_Type
var initargs []string
var initargs [][]byte
cds := &pb.ChaincodeDeploymentSpec{}
if t.Type == pb.Transaction_CHAINCODE_DEPLOY {
......@@ -424,7 +423,6 @@ func (chaincodeSupport *ChaincodeSupport) Launch(context context.Context, t *pb.
cID = cds.ChaincodeSpec.ChaincodeID
cMsg = cds.ChaincodeSpec.CtorMsg
cLang = cds.ChaincodeSpec.Type
f = &cMsg.Function
initargs = cMsg.Args
} else if t.Type == pb.Transaction_CHAINCODE_INVOKE || t.Type == pb.Transaction_CHAINCODE_QUERY {
ci := &pb.ChaincodeInvocationSpec{}
......@@ -522,8 +520,8 @@ func (chaincodeSupport *ChaincodeSupport) Launch(context context.Context, t *pb.
}
if err == nil {
//send init (if (f,args)) and wait for ready state
err = chaincodeSupport.sendInitOrReady(context, t.Txid, chaincode, f, initargs, chaincodeSupport.ccStartupTimeout, t, depTx)
//send init (if (args)) and wait for ready state
err = chaincodeSupport.sendInitOrReady(context, t.Txid, chaincode, initargs, chaincodeSupport.ccStartupTimeout, t, depTx)
if err != nil {
chaincodeLogger.Errorf("sending init failed(%s)", err)
err = fmt.Errorf("Failed to init chaincode(%s)", err)
......
......@@ -28,6 +28,7 @@ import (
"path/filepath"
"github.com/hyperledger/fabric/core/chaincode/shim"
"github.com/hyperledger/fabric/core/container"
"github.com/hyperledger/fabric/core/container/ccintf"
"github.com/hyperledger/fabric/core/crypto"
......@@ -338,8 +339,8 @@ func executeDeployTransaction(t *testing.T, url string) {
var ctxt = context.Background()
f := "init"
args := []string{"a", "100", "b", "200"}
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Path: url}, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}}
args := shim.ToChaincodeArgs(f, "a", "100", "b", "200")
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Path: url}, CtorMsg: &pb.ChaincodeInput{Args: args}}
_, err = deploy(ctxt, spec)
chaincodeID := spec.ChaincodeID.Name
if err != nil {
......@@ -423,8 +424,8 @@ func checkFinalState(uuid string, chaincodeID string) error {
func invokeExample02Transaction(ctxt context.Context, cID *pb.ChaincodeID, args []string, destroyImage bool) error {
f := "init"
argsDeploy := []string{"a", "100", "b", "200"}
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Function: f, Args: argsDeploy}}
argsDeploy := shim.ToChaincodeArgs(f, "a", "100", "b", "200")
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Args: argsDeploy}}
_, err := deploy(ctxt, spec)
chaincodeID := spec.ChaincodeID.Name
if err != nil {
......@@ -445,7 +446,8 @@ func invokeExample02Transaction(ctxt context.Context, cID *pb.ChaincodeID, args
}
f = "invoke"
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}}
invokeArgs := append([]string{f}, args...)
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Args: shim.ToChaincodeArgs(invokeArgs...)}}
_, uuid, _, err := invoke(ctxt, spec, pb.Transaction_CHAINCODE_INVOKE)
if err != nil {
return fmt.Errorf("Error invoking <%s>: %s", chaincodeID, err)
......@@ -458,8 +460,8 @@ func invokeExample02Transaction(ctxt context.Context, cID *pb.ChaincodeID, args
// Test for delete state
f = "delete"
delArgs := []string{"a"}
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Function: f, Args: delArgs}}
delArgs := shim.ToChaincodeArgs(f, "a")
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Args: delArgs}}
_, uuid, _, err = invoke(ctxt, spec, pb.Transaction_CHAINCODE_INVOKE)
if err != nil {
return fmt.Errorf("Error deleting state in <%s>: %s", chaincodeID, err)
......@@ -538,14 +540,14 @@ func exec(ctxt context.Context, chaincodeID string, numTrans int, numQueries int
var spec *pb.ChaincodeSpec
if typ == pb.Transaction_CHAINCODE_INVOKE {
f := "invoke"
args := []string{"a", "b", "10"}
args := shim.ToChaincodeArgs(f, "a", "b", "10")
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: chaincodeID}, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}}
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: chaincodeID}, CtorMsg: &pb.ChaincodeInput{Args: args}}
} else {
f := "query"
args := []string{"a"}
args := shim.ToChaincodeArgs(f, "a")
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: chaincodeID}, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}}
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: &pb.ChaincodeID{Name: chaincodeID}, CtorMsg: &pb.ChaincodeInput{Args: args}}
}
_, _, _, err := invoke(ctxt, spec, typ)
......@@ -613,9 +615,9 @@ func TestExecuteQuery(t *testing.T) {
cID := &pb.ChaincodeID{Path: url}
f := "init"
args := []string{"a", "100", "b", "200"}
args := shim.ToChaincodeArgs(f, "a", "100", "b", "200")
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}}
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Args: args}}
_, err = deploy(ctxt, spec)
chaincodeID := spec.ChaincodeID.Name
......@@ -759,9 +761,9 @@ func TestExecuteInvalidQuery(t *testing.T) {
cID := &pb.ChaincodeID{Path: url}
f := "init"
args := []string{"a", "100"}
args := shim.ToChaincodeArgs(f, "a", "100")
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}}
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Args: args}}
_, err = deploy(ctxt, spec)
chaincodeID := spec.ChaincodeID.Name
......@@ -776,9 +778,9 @@ func TestExecuteInvalidQuery(t *testing.T) {
time.Sleep(time.Second)
f = "query"
args = []string{"b", "200"}
args = shim.ToChaincodeArgs(f, "b", "200")
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}}
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Args: args}}
// This query should fail as it attempts to put state
_, _, _, err = invoke(ctxt, spec, pb.Transaction_CHAINCODE_QUERY)
......@@ -832,9 +834,9 @@ func TestChaincodeInvokeChaincode(t *testing.T) {
cID1 := &pb.ChaincodeID{Path: url1}
f := "init"
args := []string{"a", "100", "b", "200"}
args := shim.ToChaincodeArgs(f, "a", "100", "b", "200")
spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID1, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}}
spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID1, CtorMsg: &pb.ChaincodeInput{Args: args}}
_, err = deploy(ctxt, spec1)
chaincodeID1 := spec1.ChaincodeID.Name
......@@ -853,9 +855,9 @@ func TestChaincodeInvokeChaincode(t *testing.T) {
cID2 := &pb.ChaincodeID{Path: url2}
f = "init"
args = []string{"e", "0"}
args = shim.ToChaincodeArgs(f, "e", "0")
spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}}
spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Args: args}}
_, err = deploy(ctxt, spec2)
chaincodeID2 := spec2.ChaincodeID.Name
......@@ -872,9 +874,9 @@ func TestChaincodeInvokeChaincode(t *testing.T) {
// Invoke second chaincode, which will inturn invoke the first chaincode
f = "invoke"
args = []string{"e", "1"}
args = shim.ToChaincodeArgs(f, "e", "1")
spec2 = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}}
spec2 = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Args: args}}
// Invoke chaincode
var uuid string
_, uuid, _, err = invoke(ctxt, spec2, pb.Transaction_CHAINCODE_INVOKE)
......@@ -946,9 +948,9 @@ func TestChaincodeInvokeChaincodeErrorCase(t *testing.T) {
cID1 := &pb.ChaincodeID{Path: url1}
f := "init"
args := []string{"a", "100", "b", "200"}
args := shim.ToChaincodeArgs(f, "a", "100", "b", "200")
spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID1, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}}
spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID1, CtorMsg: &pb.ChaincodeInput{Args: args}}
_, err = deploy(ctxt, spec1)
chaincodeID1 := spec1.ChaincodeID.Name
......@@ -967,9 +969,9 @@ func TestChaincodeInvokeChaincodeErrorCase(t *testing.T) {
cID2 := &pb.ChaincodeID{Path: url2}
f = "init"
args = []string{""}
args = shim.ToChaincodeArgs(f)
spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}}
spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Args: args}}
_, err = deploy(ctxt, spec2)
chaincodeID2 := spec2.ChaincodeID.Name
......@@ -986,9 +988,9 @@ func TestChaincodeInvokeChaincodeErrorCase(t *testing.T) {
// Invoke second chaincode, which will inturn invoke the first chaincode but pass bad params
f = chaincodeID1
args = []string{"invoke", "a"} //expect {"invoke", "a","b","10"}
args = shim.ToChaincodeArgs(f, "invoke", "a")
spec2 = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}}
spec2 = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Args: args}}
// Invoke chaincode
_, _, _, err = invoke(ctxt, spec2, pb.Transaction_CHAINCODE_INVOKE)
......@@ -1023,9 +1025,9 @@ func chaincodeQueryChaincode(user string) error {
cID1 := &pb.ChaincodeID{Path: url1}
f := "init"
args := []string{"a", "100", "b", "200"}
args := shim.ToChaincodeArgs(f, "a", "100", "b", "200")
spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID1, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}, SecureContext: user}
spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID1, CtorMsg: &pb.ChaincodeInput{Args: args}, SecureContext: user}
_, err := deploy(ctxt, spec1)
chaincodeID1 := spec1.ChaincodeID.Name
......@@ -1041,9 +1043,9 @@ func chaincodeQueryChaincode(user string) error {
cID2 := &pb.ChaincodeID{Path: url2}
f = "init"
args = []string{"sum", "0"}
args = shim.ToChaincodeArgs(f, "sum", "0")
spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}, SecureContext: user}
spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Args: args}, SecureContext: user}
_, err = deploy(ctxt, spec2)
chaincodeID2 := spec2.ChaincodeID.Name
......@@ -1057,9 +1059,9 @@ func chaincodeQueryChaincode(user string) error {
// Invoke second chaincode, which will inturn query the first chaincode
f = "invoke"
args = []string{chaincodeID1, "sum"}
args = shim.ToChaincodeArgs(f, chaincodeID1, "sum")
spec2 = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}, SecureContext: user}
spec2 = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Args: args}, SecureContext: user}
// Invoke chaincode
var retVal []byte
_, _, retVal, err = invoke(ctxt, spec2, pb.Transaction_CHAINCODE_INVOKE)
......@@ -1080,9 +1082,9 @@ func chaincodeQueryChaincode(user string) error {
// Query second chaincode, which will inturn query the first chaincode
f = "query"
args = []string{chaincodeID1, "sum"}
args = shim.ToChaincodeArgs(f, chaincodeID1, "sum")
spec2 = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}, SecureContext: user}
spec2 = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Args: args}, SecureContext: user}
// Invoke chaincode
_, _, retVal, err = invoke(ctxt, spec2, pb.Transaction_CHAINCODE_QUERY)
......@@ -1169,9 +1171,9 @@ func TestChaincodeQueryChaincodeErrorCase(t *testing.T) {
cID1 := &pb.ChaincodeID{Path: url1}
f := "init"
args := []string{"a", "100", "b", "200"}
args := shim.ToChaincodeArgs(f, "a", "100", "b", "200")
spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID1, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}}
spec1 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID1, CtorMsg: &pb.ChaincodeInput{Args: args}}
_, err = deploy(ctxt, spec1)
chaincodeID1 := spec1.ChaincodeID.Name
......@@ -1190,9 +1192,9 @@ func TestChaincodeQueryChaincodeErrorCase(t *testing.T) {
cID2 := &pb.ChaincodeID{Path: url2}
f = "init"
args = []string{""}
args = shim.ToChaincodeArgs(f)
spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}}
spec2 := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Args: args}}
_, err = deploy(ctxt, spec2)
chaincodeID2 := spec2.ChaincodeID.Name
......@@ -1209,9 +1211,9 @@ func TestChaincodeQueryChaincodeErrorCase(t *testing.T) {
// Invoke second chaincode, which will inturn invoke the first chaincode but pass bad params
f = chaincodeID1
args = []string{"query", "c"} //expect {"query", "a"}
args = shim.ToChaincodeArgs(f, "query", "c")
spec2 = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}}
spec2 = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID2, CtorMsg: &pb.ChaincodeInput{Args: args}}
// Invoke chaincode
_, _, _, err = invoke(ctxt, spec2, pb.Transaction_CHAINCODE_QUERY)
......@@ -1332,10 +1334,10 @@ func TestRangeQuery(t *testing.T) {
url := "github.com/hyperledger/fabric/examples/chaincode/go/map"
cID := &pb.ChaincodeID{Path: url}
args := []string{}
f := "init"
args := shim.ToChaincodeArgs(f)
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}}
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Args: args}}
_, err = deploy(ctxt, spec)
chaincodeID := spec.ChaincodeID.Name
......@@ -1349,9 +1351,9 @@ func TestRangeQuery(t *testing.T) {
// Invoke second chaincode, which will inturn invoke the first chaincode
f = "keys"
args = []string{}
args = shim.ToChaincodeArgs(f)
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Function: f, Args: args}}
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Args: args}}
_, _, _, err = invoke(ctxt, spec, pb.Transaction_CHAINCODE_QUERY)
if err != nil {
......@@ -1403,7 +1405,8 @@ func TestGetEvent(t *testing.T) {
url := "github.com/hyperledger/fabric/examples/chaincode/go/eventsender"
cID := &pb.ChaincodeID{Path: url}
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Function: "init", Args: []string{}}}
f := "init"
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Args: shim.ToChaincodeArgs(f)}}
_, err = deploy(ctxt, spec)
chaincodeID := spec.ChaincodeID.Name
......@@ -1417,9 +1420,9 @@ func TestGetEvent(t *testing.T) {
time.Sleep(time.Second)
args := []string{"i", "am", "satoshi"}
args := shim.ToChaincodeArgs("", "i", "am", "satoshi")
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Function: "", Args: args}}
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, CtorMsg: &pb.ChaincodeInput{Args: args}}
var ccevt *pb.ChaincodeEvent
ccevt, _, _, err = invoke(ctxt, spec, pb.Transaction_CHAINCODE_INVOKE)
......
......@@ -1236,21 +1236,19 @@ func (handler *Handler) setChaincodeSecurityContext(tx *pb.Transaction, msg *pb.
msg.SecurityContext.Binding = binding
msg.SecurityContext.Metadata = tx.Metadata
if tx.Type == pb.Transaction_CHAINCODE_INVOKE || tx.Type == pb.Transaction_CHAINCODE_QUERY {
cis := &pb.ChaincodeInvocationSpec{}
if err := proto.Unmarshal(tx.Payload, cis); err != nil {
chaincodeLogger.Errorf("Failed getting payload [%s]", err)
return err
}
ctorMsgRaw, err := proto.Marshal(cis.ChaincodeSpec.GetCtorMsg())
if err != nil {
chaincodeLogger.Errorf("Failed getting ctorMsgRaw [%s]", err)
return err
}
cis := &pb.ChaincodeInvocationSpec{}
if err := proto.Unmarshal(tx.Payload, cis); err != nil {
chaincodeLogger.Errorf("Failed getting payload [%s]", err)
return err
}
msg.SecurityContext.Payload = ctorMsgRaw
ctorMsgRaw, err := proto.Marshal(cis.ChaincodeSpec.GetCtorMsg())
if err != nil {
chaincodeLogger.Errorf("Failed getting ctorMsgRaw [%s]", err)
return err
}
msg.SecurityContext.Payload = ctorMsgRaw
msg.SecurityContext.TxTimestamp = tx.Timestamp
}
return nil
......@@ -1258,7 +1256,7 @@ func (handler *Handler) setChaincodeSecurityContext(tx *pb.Transaction, msg *pb.
//if initArgs is set (should be for "deploy" only) move to Init
//else move to ready
func (handler *Handler) initOrReady(txid string, f *string, initArgs []string, tx *pb.Transaction, depTx *pb.Transaction) (chan *pb.ChaincodeMessage, error) {
func (handler *Handler) initOrReady(txid string, initArgs [][]byte, tx *pb.Transaction, depTx *pb.Transaction) (chan *pb.ChaincodeMessage, error) {
var ccMsg *pb.ChaincodeMessage
var send bool
......@@ -1269,13 +1267,9 @@ func (handler *Handler) initOrReady(txid string, f *string, initArgs []string, t
notfy := txctx.responseNotifier
if f != nil || initArgs != nil {
if initArgs != nil {
chaincodeLogger.Debug("sending INIT")
var f2 string
if f != nil {
f2 = *f
}
funcArgsMsg := &pb.ChaincodeInput{Function: f2, Args: initArgs}
funcArgsMsg := &pb.ChaincodeInput{Args: initArgs}
var payload []byte
if payload, funcErr = proto.Marshal(funcArgsMsg); funcErr != nil {
handler.deleteTxContext(txid)
......
......@@ -21,6 +21,7 @@ import (
"fmt"
"io/ioutil"
"github.com/golang/protobuf/proto"
"github.com/hyperledger/fabric/core/util"
pb "github.com/hyperledger/fabric/protos"
)
......@@ -34,11 +35,14 @@ import (