Skip to content

Commit

Permalink
[FAB-2461] inputs are optional when calculating hash
Browse files Browse the repository at this point in the history
Matched the logic used to compute hash when installing
a golang chaincode.

Added some behave tests that can be run using:
  $ make behave-peer-chaincode
or simply:
  $ cd peer/chaincode && behave

Change-Id: If9747101c48754b26ce9c463f2adb7caef3220ad
Signed-off-by: Luis Sanchez <sanchezl@us.ibm.com>
  • Loading branch information
Luis Sanchez committed Feb 28, 2017
1 parent 21ce6b2 commit f9cc882
Show file tree
Hide file tree
Showing 5 changed files with 174 additions and 9 deletions.
3 changes: 3 additions & 0 deletions Makefile
Expand Up @@ -133,6 +133,9 @@ behave: behave-deps
@echo "Running behave tests"
@cd bddtests; behave $(BEHAVE_OPTS)

behave-peer-chaincode: build/bin/peer peer-docker orderer-docker
@cd peer/chaincode && behave

linter: buildenv
@echo "LINT: Running code checks.."
@$(DRUN) hyperledger/fabric-buildenv:$(DOCKER_TAG) ./scripts/golinter.sh
Expand Down
23 changes: 14 additions & 9 deletions core/chaincode/platforms/java/hash.go
Expand Up @@ -32,8 +32,11 @@ import (
"github.com/hyperledger/fabric/common/util"
ccutil "github.com/hyperledger/fabric/core/chaincode/platforms/util"
pb "github.com/hyperledger/fabric/protos/peer"
logging "github.com/op/go-logging"
)

var logger = logging.MustGetLogger("java/hash")

func getCodeFromHTTP(path string) (codegopath string, err error) {

codegopath, err = ioutil.TempDir("", "javachaincode")
Expand Down Expand Up @@ -70,11 +73,6 @@ func collectChaincodeFiles(spec *pb.ChaincodeSpec, tw *tar.Writer) (string, erro
return "", errors.New("Cannot collect chaincode files from empty chaincode path")
}

input := spec.Input
if input == nil || len(input.Args) == 0 {
return "", errors.New("Cannot collect chaincode files from empty input")
}

codepath := chaincodeID.Path

var ishttp bool
Expand Down Expand Up @@ -103,11 +101,18 @@ func collectChaincodeFiles(spec *pb.ChaincodeSpec, tw *tar.Writer) (string, erro
return "", fmt.Errorf("code does not exist %s", err)
}

inputbytes, err := proto.Marshal(input)
if err != nil {
return "", fmt.Errorf("Error marshalling constructor: %s", err)
var hash []byte

//install will not have inputs and we don't have to collect hash for it
if spec.Input == nil || len(spec.Input.Args) == 0 {
logger.Debugf("not using input for hash computation for %v ", chaincodeID)
} else {
inputbytes, err2 := proto.Marshal(spec.Input)
if err2 != nil {
return "", fmt.Errorf("Error marshalling constructor: %s", err)
}
hash = util.GenerateHashFromSignature(codepath, inputbytes)
}
hash := util.GenerateHashFromSignature(codepath, inputbytes)

hash, err = ccutil.HashFilesInDir("", codepath, hash, tw)
if err != nil {
Expand Down
24 changes: 24 additions & 0 deletions peer/chaincode/features/environment.py
@@ -0,0 +1,24 @@
from behave import *
import os
import subprocess

# set the default step matcher
use_step_matcher("re")

def before_all(context):
# set some handy values
context.go_path = os.environ['GOPATH']
context.fabric_dir = os.path.join(context.go_path, 'src/github.com/hyperledger/fabric')
context.peer_exe = os.path.join(context.fabric_dir, 'build/bin/peer')
context.sample_chaincode = {
'golang':'github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02',
'java':'examples/chaincode/java/SimpleSample'
}

def after_scenario(context, scenario):
if getattr(context, 'peer_container_id', None):
subprocess.check_output(['docker', 'rm', '--force', '--volumes', context.peer_container_id], stderr=subprocess.STDOUT)
if getattr(context, 'orderer_container_id', None):
subprocess.check_output(['docker', 'rm', '--force', '--volumes', context.orderer_container_id], stderr=subprocess.STDOUT)
if getattr(context, 'network_id', None):
subprocess.check_output(['docker', 'network', 'rm', context.network_id], stderr=subprocess.STDOUT)
26 changes: 26 additions & 0 deletions peer/chaincode/features/install.feature
@@ -0,0 +1,26 @@
Feature: Install chaincode via CLI

Scenario Outline: Install first version chaincode via CLI

Given a fabric peer and orderer
When a <lang> chaincode is installed via the CLI
Then the chaincode is installed on the peer

Examples:
| lang |
| go |
| java |

Scenario Outline: Install chaincode with new version

Only the first version of a chaincode (identified by chaincode name) can be
installed. Subsequent versions must be upgraded instead.

Given a fabric peer and orderer
When version one of a <lang> chaincode is installed via the CLI
Then installing version two of the same chaincode via the CLI will fail

Examples:
| lang |
| go |
| java |
107 changes: 107 additions & 0 deletions peer/chaincode/features/steps/steps.py
@@ -0,0 +1,107 @@
from behave import *
import os
import random
import subprocess
import tempfile
import time
import socket

@given(u'a fabric peer and orderer')
def step_impl(context):

# create network
context.network_name = 'behave_' + ''.join(random.choice('0123456789') for i in xrange(7))
context.network_id = subprocess.check_output([
'docker', 'network', 'create', context.network_name
]).strip()

# start orderer
context.orderer_container_id = subprocess.check_output([
'docker', 'run', '-d', '-p', '7050',
'--expose', '7050',
'--network', context.network_name,
'--network-alias', 'orderer',
'--env', 'ORDERER_GENERAL_LISTENADDRESS=0.0.0.0',
'hyperledger/fabric-orderer'
]).strip()
context.orderer_address = subprocess.check_output(['docker', 'port', context.orderer_container_id, '7050']).strip()

# start peer
context.peer_container_id = subprocess.check_output([
'docker', 'run', '-d', '-p', '7051',
'--network', context.network_name,
'--network-alias', 'vp0',
'--env', 'CORE_PEER_ADDRESSAUTODETECT=true',
'--env', 'CORE_PEER_ID=vp0',
'--env', 'CORE_PEER_COMMITTER_LEDGER_ORDERER=orderer:7050',
'--volume', '/var/run/docker.sock:/var/run/docker.sock',
'hyperledger/fabric-peer'
]).strip()
context.peer_address = subprocess.check_output(['docker', 'port', context.peer_container_id, '7051']).strip()
time.sleep(1)

# setup env for peer cli commands
context.peer_env = os.environ.copy()
context.peer_env['CORE_PEER_ADDRESS'] = context.peer_address
context.peer_env['CORE_PEER_COMMITTER_LEDGER_ORDERER'] = context.orderer_address

@when(r'a (?P<lang>java|go|golang|car) chaincode is installed via the CLI')
def step_impl(context, lang):
context.chaincode_lang = 'golang' if lang == 'go' else lang
context.chaincode_id_name = lang + '_cc_' + ''.join(random.choice('0123456789') for i in xrange(7))
context.chaincode_id_version = '1000'
try:
print(subprocess.check_output([
context.peer_exe, 'chaincode', 'install',
'--logging-level', 'debug',
'--name', context.chaincode_id_name,
'--path', context.sample_chaincode[context.chaincode_lang],
'--version', context.chaincode_id_version,
'--lang', context.chaincode_lang
], cwd=context.fabric_dir, stderr=subprocess.STDOUT, env=context.peer_env))
except subprocess.CalledProcessError as e:
print(e.output)
print('CORE_PEER_ADDRESS = ' + context.peer_env['CORE_PEER_ADDRESS'])
print('CORE_PEER_COMMITTER_LEDGER_ORDERER = ' + context.peer_env['CORE_PEER_COMMITTER_LEDGER_ORDERER'])
raise

@step(u'the chaincode is installed on the peer')
def step_impl(context):
print(subprocess.check_output([
'docker', 'exec', context.peer_container_id, 'ls', '-l', '/var/hyperledger/production/chaincodes/' + context.chaincode_id_name + '.' + context.chaincode_id_version
]))

@step(r'version (?P<version>\S+) of a (?P<lang>java|go|golang|car) chaincode is installed via the CLI')
def step_impl(context, version, lang):
context.chaincode_lang = 'golang' if lang == 'go' else lang
context.chaincode_id_name = lang + '_cc_' + ''.join(random.choice('0123456789') for i in xrange(7))
context.chaincode_id_version = version
try:
print(subprocess.check_output([
context.peer_exe, 'chaincode', 'install',
'--logging-level', 'debug',
'--name', context.chaincode_id_name,
'--path', context.sample_chaincode[context.chaincode_lang],
'--version', context.chaincode_id_version,
'--lang', context.chaincode_lang
], cwd=context.fabric_dir, stderr=subprocess.STDOUT, env=context.peer_env))
except subprocess.CalledProcessError as e:
print(e.output)
raise

@step(r'installing version (?P<version>\S+) of the same chaincode via the CLI will fail')
def step_impl(context, version):
assert getattr(context, 'chaincode_id_name', None), 'No chaincode previously installed.'
context.chaincode_id_version = version
try:
print(subprocess.check_output([
context.peer_exe, 'chaincode', 'install',
'--logging-level', 'debug',
'--name', context.chaincode_id_name,
'--path', context.sample_chaincode[context.chaincode_lang],
'--version', context.chaincode_id_version,
'--lang', context.chaincode_lang
], cwd=context.fabric_dir, stderr=subprocess.STDOUT, env=context.peer_env))
except subprocess.CalledProcessError as e:
print(e.output)
raise

0 comments on commit f9cc882

Please sign in to comment.