Skip to content

Commit

Permalink
[FAB-2718] Enable Java chaincode invoke
Browse files Browse the repository at this point in the history
 - ChaincodeBase updates:
   - query() method removed
   - run() return type changed to Reponse to mirror
     golang chaincode.
   - updated SimpleSample java chaincode
   - deleted bdd
   - introduce example02 'clone' in Java
   - Parameterized TestExecuteInvokeTransaction so
     that is runs w/ both Java and Go chaincode.
   - Added TestChaincodeInitializeInitError test.

NOTES:
   - more cleanup is still needed, but this gets
     Java chaincode deployment going.
   - the other java chain samples need cleanup
   - there might be some features in the shim
     copy in fabric-sdk-java that should be merged
     into this version.

Change-Id: Ie254a1430d53e4ca037ae4b3d2e51747e668752b
Signed-off-by: Luis Sanchez <sanchezl@us.ibm.com>
  • Loading branch information
Luis Sanchez committed Apr 6, 2017
1 parent cacb292 commit adebfad
Show file tree
Hide file tree
Showing 19 changed files with 1,185 additions and 695 deletions.
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,8 @@ orderer-docker: build/image/orderer/$(DUMMY)
configtxgen: GO_TAGS+= nopkcs11
configtxgen: build/bin/configtxgen

javaenv: build/image/javaenv/$(DUMMY)

buildenv: build/image/buildenv/$(DUMMY)

build/image/testenv/$(DUMMY): build/image/buildenv/$(DUMMY)
Expand Down
22 changes: 19 additions & 3 deletions core/chaincode/chaincodetest.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ logging:
status: warning
stop: warning
login: warning
vm: warning
chaincode: warning
vm: debug
chaincode: debug


###############################################################################
Expand Down Expand Up @@ -331,7 +331,7 @@ vm:
file: /path/to/ca.pem
key:
file: /path/to/server-key.pem

attachStdout: true
###############################################################################
#
# Chaincode section
Expand Down Expand Up @@ -361,10 +361,24 @@ chaincode:
# of platforms are expanded. For now, we can just use baseos
runtime: $(BASE_DOCKER_NS)/fabric-baseos:$(ARCH)-$(BASE_VERSION)

java:
# This is an image based on java:openjdk-8 with addition compiler
# tools added for java shim layer packaging.
# This image is packed with shim layer libraries that are necessary
# for Java chaincode runtime.
Dockerfile: |
from $(DOCKER_NS)/fabric-javaenv:$(ARCH)-$(PROJECT_VERSION)
# timeout in millisecs for starting up a container and waiting for Register
# to come through. 1sec should be plenty for chaincode unit tests
startuptimeout: 1000

# timeout in millisecs for invokes and initialize commands
# this timeout is used by all chaincodes in all the channels including
# system chaincodes. Default is 30000ms (30 seconds)
executetimeout: 30000


#timeout in millisecs for deploying chaincode from a remote repository.
deploytimeout: 60000

Expand Down Expand Up @@ -393,6 +407,8 @@ chaincode:
escc: enable
vscc: enable

logLevel: debug

###############################################################################
#
# Ledger section - ledger configuration encompases both the blockchain
Expand Down
158 changes: 133 additions & 25 deletions core/chaincode/exectransaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package chaincode
import (
"encoding/json"
"fmt"
"math/rand"
"net"
"os"
"path/filepath"
Expand Down Expand Up @@ -317,7 +318,7 @@ func deploy2(ctx context.Context, cccid *ccprovider.CCContext, chaincodeDeployme

// Invoke a chaincode.
func invoke(ctx context.Context, chainID string, spec *pb.ChaincodeSpec, blockNumber uint64) (ccevt *pb.ChaincodeEvent, uuid string, retval []byte, err error) {
return invokeWithVersion(ctx, chainID, "0", spec, blockNumber)
return invokeWithVersion(ctx, chainID, spec.GetChaincodeId().Version, spec, blockNumber)
}

// Invoke a chaincode with version (needed for upgrade)
Expand Down Expand Up @@ -569,13 +570,13 @@ func checkFinalState(cccid *ccprovider.CCContext) error {
}

// Invoke chaincode_example02
func invokeExample02Transaction(ctxt context.Context, cccid *ccprovider.CCContext, cID *pb.ChaincodeID, args []string, destroyImage bool) error {
func invokeExample02Transaction(ctxt context.Context, cccid *ccprovider.CCContext, cID *pb.ChaincodeID, chaincodeType pb.ChaincodeSpec_Type, args []string, destroyImage bool) error {

var nextBlockNumber uint64

f := "init"
argsDeploy := util.ToChaincodeArgs(f, "a", "100", "b", "200")
spec := &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: argsDeploy}}
spec := &pb.ChaincodeSpec{Type: chaincodeType, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: argsDeploy}}
_, err := deploy(ctxt, cccid, spec, nextBlockNumber)
nextBlockNumber++
ccID := spec.ChaincodeId.Name
Expand All @@ -598,7 +599,7 @@ func invokeExample02Transaction(ctxt context.Context, cccid *ccprovider.CCContex

f = "invoke"
invokeArgs := append([]string{f}, args...)
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: util.ToChaincodeArgs(invokeArgs...)}}
spec = &pb.ChaincodeSpec{ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: util.ToChaincodeArgs(invokeArgs...)}}
_, uuid, _, err := invoke(ctxt, cccid.ChainID, spec, nextBlockNumber)
nextBlockNumber++
if err != nil {
Expand All @@ -614,7 +615,7 @@ func invokeExample02Transaction(ctxt context.Context, cccid *ccprovider.CCContex
// Test for delete state
f = "delete"
delArgs := util.ToChaincodeArgs(f, "a")
spec = &pb.ChaincodeSpec{Type: 1, ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: delArgs}}
spec = &pb.ChaincodeSpec{ChaincodeId: cID, Input: &pb.ChaincodeInput{Args: delArgs}}
_, _, _, err = invoke(ctxt, cccid.ChainID, spec, nextBlockNumber)
if err != nil {
return fmt.Errorf("Error deleting state in <%s>: %s", cccid.Name, err)
Expand All @@ -623,34 +624,56 @@ func invokeExample02Transaction(ctxt context.Context, cccid *ccprovider.CCContex
return nil
}

const (
chaincodeExample02GolangPath = "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02"
chaincodeExample02JavaPath = "../../examples/chaincode/java/chaincode_example02"
chaincodeExample06JavaPath = "../../examples/chaincode/java/chaincode_example06"
)

func TestExecuteInvokeTransaction(t *testing.T) {
chainID := util.GetTestChainID()

lis, err := initPeer(chainID)
if err != nil {
t.Fail()
t.Logf("Error creating peer: %s", err)
testCases := []struct {
chaincodeType pb.ChaincodeSpec_Type
chaincodePath string
}{
{pb.ChaincodeSpec_GOLANG, chaincodeExample02GolangPath},
{pb.ChaincodeSpec_JAVA, chaincodeExample02JavaPath},
}

defer finitPeer(lis, chainID)
for _, tc := range testCases {
t.Run(tc.chaincodeType.String(), func(t *testing.T) {

var ctxt = context.Background()
chainID := util.GetTestChainID()

cccid := ccprovider.NewCCContext(chainID, "example02", "0", "", false, nil, nil)
url := "github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02"
ccID := &pb.ChaincodeID{Name: "example02", Path: url, Version: "0"}
lis, err := initPeer(chainID)
if err != nil {
t.Fail()
t.Logf("Error creating peer: %s", err)
}

args := []string{"a", "b", "10"}
err = invokeExample02Transaction(ctxt, cccid, ccID, args, true)
if err != nil {
t.Fail()
t.Logf("Error invoking transaction: %s", err)
} else {
fmt.Print("Invoke test passed\n")
t.Log("Invoke test passed")
defer finitPeer(lis, chainID)

var ctxt = context.Background()
chaincodeName := generateChaincodeName(tc.chaincodeType)
chaincodeVersion := "1.0.0.0"
cccid := ccprovider.NewCCContext(chainID, chaincodeName, chaincodeVersion, "", false, nil, nil)
ccID := &pb.ChaincodeID{Name: chaincodeName, Path: tc.chaincodePath, Version: chaincodeVersion}

args := []string{"a", "b", "10"}
err = invokeExample02Transaction(ctxt, cccid, ccID, tc.chaincodeType, args, true)
if err != nil {
t.Fail()
t.Logf("Error invoking transaction: %s", err)
} else {
fmt.Print("Invoke test passed\n")
t.Log("Invoke test passed")
}

theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: ccID}})

})
}

theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: &pb.ChaincodeSpec{ChaincodeId: ccID}})
}

// Test the execution of an invalid transaction.
Expand All @@ -674,7 +697,7 @@ func TestExecuteInvokeInvalidTransaction(t *testing.T) {

//FAIL, FAIL!
args := []string{"x", "-1"}
err = invokeExample02Transaction(ctxt, cccid, ccID, args, false)
err = invokeExample02Transaction(ctxt, cccid, ccID, pb.ChaincodeSpec_GOLANG, args, false)

//this HAS to fail with expectedDeltaStringPrefix
if err != nil {
Expand Down Expand Up @@ -1509,6 +1532,76 @@ func TestChaincodeInvokesSystemChaincode(t *testing.T) {
theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec})
}

func TestChaincodeInitializeInitError(t *testing.T) {
testCases := []struct {
name string
chaincodeType pb.ChaincodeSpec_Type
chaincodePath string
args []string
}{
{"NotSuccessResponse", pb.ChaincodeSpec_GOLANG, chaincodeExample02GolangPath, []string{"init", "not", "enough", "args"}},
{"NotSuccessResponse", pb.ChaincodeSpec_JAVA, chaincodeExample02JavaPath, []string{"init", "not", "enough", "args"}},
{"RuntimeException", pb.ChaincodeSpec_JAVA, chaincodeExample06JavaPath, []string{"runtimeException"}},
}

channelID := util.GetTestChainID()

for _, tc := range testCases {
t.Run(tc.name+"_"+tc.chaincodeType.String(), func(t *testing.T) {

// initialize peer
if listener, err := initPeer(channelID); err != nil {
t.Errorf("Error creating peer: %s", err)
} else {
defer finitPeer(listener, channelID)
}

var nextBlockNumber uint64

// the chaincode to install and instanciate
chaincodeName := generateChaincodeName(tc.chaincodeType)
chaincodePath := tc.chaincodePath
chaincodeVersion := "1.0.0.0"
chaincodeType := tc.chaincodeType
chaincodeDeployArgs := util.ArrayToChaincodeArgs(tc.args)

// new chaincode context for passing around parameters
chaincodeCtx := ccprovider.NewCCContext(channelID, chaincodeName, chaincodeVersion, "", false, nil, nil)

// attempt to deploy chaincode
_, err := deployChaincode(context.Background(), chaincodeCtx, chaincodeType, chaincodePath, chaincodeDeployArgs, nextBlockNumber)

// deploy should of failed
if err == nil {
t.Fatal("Deployment should have failed.")
}
t.Log(err)

})
}
}

func deployChaincode(ctx context.Context, chaincodeCtx *ccprovider.CCContext, chaincodeType pb.ChaincodeSpec_Type, path string, args [][]byte, nextBlockNumber uint64) ([]byte, error) {

chaincodeSpec := &pb.ChaincodeSpec{
ChaincodeId: &pb.ChaincodeID{
Name: chaincodeCtx.Name,
Version: chaincodeCtx.Version,
Path: path,
},
Type: chaincodeType,
Input: &pb.ChaincodeInput{
Args: args,
},
}

result, err := deploy(ctx, chaincodeCtx, chaincodeSpec, nextBlockNumber)
if err != nil {
return nil, fmt.Errorf("Error deploying <%s:%s>: %s", chaincodeSpec.ChaincodeId.Name, chaincodeSpec.ChaincodeId.Version, err)
}
return result, nil
}

var signer msp.SigningIdentity

func TestMain(m *testing.M) {
Expand All @@ -1527,3 +1620,18 @@ func TestMain(m *testing.M) {
SetupTestConfig()
os.Exit(m.Run())
}

var rng *rand.Rand = rand.New(rand.NewSource(time.Now().UnixNano()))

func generateChaincodeName(chaincodeType pb.ChaincodeSpec_Type) string {
prefix := "cc_"
switch chaincodeType {
case pb.ChaincodeSpec_GOLANG:
prefix = "cc_go_"
case pb.ChaincodeSpec_JAVA:
prefix = "cc_java_"
case pb.ChaincodeSpec_NODE:
prefix = "cc_js_"
}
return fmt.Sprintf("%s%06d", prefix, rng.Intn(999999))
}
2 changes: 1 addition & 1 deletion core/chaincode/multichains_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func TestExecuteInvokeOnManyChains(t *testing.T) {
args := []string{"a", "b", "10"}
for _, c := range chains {
cccid := ccprovider.NewCCContext(c, "example02", "0", "", false, nil, nil)
err = invokeExample02Transaction(ctxt, cccid, chaincodeID, args, false)
err = invokeExample02Transaction(ctxt, cccid, chaincodeID, pb.ChaincodeSpec_GOLANG, args, false)
if err != nil {
t.Fail()
t.Logf("Error invoking transaction: %s", err)
Expand Down
26 changes: 16 additions & 10 deletions core/chaincode/shim/java/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -89,16 +89,21 @@ task copyToLib(type: Copy) {


task copyProtos(type:Copy){

from ("${rootDir}/protos/peer"){
include '**/chaincode_event.proto'
include '**/chaincode.proto'
include '**/chaincode_shim.proto'
include '**/proposal.proto'
include '**/proposal_response.proto'
}
into "${projectDir}/src/main/proto/peer"

into "peer", {
from ("${rootDir}/protos/peer"){
include 'chaincode_event.proto'
include 'chaincode.proto'
include 'chaincode_shim.proto'
include 'proposal.proto'
include 'proposal_response.proto'
}
}
into "common", {
from ("${rootDir}/protos/common"){
include 'common.proto'
}
}
into "${projectDir}/src/main/proto"
}

tasks['build'].mustRunAfter tasks['copyProtos']
Expand All @@ -108,6 +113,7 @@ build.finalizedBy(publishToMavenLocal)

dependencies {
compile 'com.google.protobuf:protobuf-java:3.0.0'
compile 'com.google.protobuf:protobuf-java-util:3.0.0'
compile 'io.grpc:grpc-all:0.13.2'
compile 'commons-cli:commons-cli:1.3.1'
compile 'io.netty:netty-tcnative-boringssl-static:1.1.33.Fork21:' + tcnative_classifier
Expand Down
Loading

0 comments on commit adebfad

Please sign in to comment.