Adding examples of CCAAS and support into the test-network (#560)

- Updated the test-network with examples of runnig CCAAS
- Updating the asset transfer basic with how to run chaincode as a service.

Signed-off-by: Matthew B White <whitemat@uk.ibm.com>
This commit is contained in:
Matthew B White 2021-12-17 13:18:22 +00:00 committed by GitHub
parent ad20a5178d
commit 96623f1bd5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 6058 additions and 184 deletions

2
.gitignore vendored
View file

@ -5,7 +5,7 @@
# Vim file artifacts
.*.sw*
# installed platform-specific binaries
/bin
bin
/config
.DS_Store
.project

View file

@ -0,0 +1,31 @@
# the first stage
FROM gradle:jdk11 AS GRADLE_BUILD
ARG CC_SERVER_PORT
# copy the build.gradle and src code to the container
COPY src/ src/
COPY build.gradle ./
# Build and package our code
RUN gradle --no-daemon build shadowJar -x checkstyleMain -x checkstyleTest
# the second stage of our build just needs the compiled files
FROM openjdk:11-jre
# Setup tini to work better handle signals
ENV TINI_VERSION v0.19.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
RUN chmod +x /tini
RUN addgroup --system javauser && useradd -g javauser javauser
# copy only the artifacts we need from the first stage and discard the rest
COPY --chown=javauser:javauser --from=GRADLE_BUILD /home/gradle/build/libs/chaincode.jar /chaincode.jar
COPY --chown=javauser:javauser docker/docker-entrypoint.sh /docker-entrypoint.sh
ENV PORT $CC_SERVER_PORT
EXPOSE $CC_SERVER_PORT
USER javauser
ENTRYPOINT [ "/tini", "--", "/docker-entrypoint.sh" ]

View file

@ -14,10 +14,10 @@ version '1.0-SNAPSHOT'
dependencies {
implementation 'org.hyperledger.fabric-chaincode-java:fabric-chaincode-shim:2.+'
implementation 'org.hyperledger.fabric-chaincode-java:fabric-chaincode-shim:2.4.1'
implementation 'org.json:json:+'
implementation 'com.owlike:genson:1.5'
testImplementation 'org.hyperledger.fabric-chaincode-java:fabric-chaincode-shim:2.+'
testImplementation 'org.hyperledger.fabric-chaincode-java:fabric-chaincode-shim:2.4.1'
testImplementation 'org.junit.jupiter:junit-jupiter:5.4.2'
testImplementation 'org.assertj:assertj-core:3.11.1'
testImplementation 'org.mockito:mockito-core:2.+'

View file

@ -0,0 +1,16 @@
#!/usr/bin/env bash
#
# SPDX-License-Identifier: Apache-2.0
#
set -euo pipefail
: ${CORE_PEER_TLS_ENABLED:="false"}
: ${DEBUG:="false"}
if [ "${DEBUG,,}" = "true" ]; then
java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0.0.0.0:8000 -jar /chaincode.jar
elif [ "${CORE_PEER_TLS_ENABLED,,}" = "true" ]; then
java -jar /chaincode.jar # todo
else
java -jar /chaincode.jar
fi

View file

@ -0,0 +1,34 @@
#
# SPDX-License-Identifier: Apache-2.0
#
FROM node:16 AS builder
ARG CC_SERVER_PORT
WORKDIR /usr/src/app
# Copy node.js source and build, changing owner as well
COPY --chown=node:node . /usr/src/app
RUN npm ci && npm run package
FROM node:16 AS production
# Setup tini to work better handle signals
ENV TINI_VERSION v0.19.0
ADD https://github.com/krallin/tini/releases/download/${TINI_VERSION}/tini /tini
RUN chmod +x /tini
WORKDIR /usr/src/app
COPY --chown=node:node --from=builder /usr/src/app/dist ./dist
COPY --chown=node:node --from=builder /usr/src/app/package.json ./
COPY --chown=node:node --from=builder /usr/src/app/npm-shrinkwrap.json ./
COPY --chown=node:node docker/docker-entrypoint.sh /usr/src/app/docker-entrypoint.sh
RUN npm ci --only=production
ENV PORT $CC_SERVER_PORT
EXPOSE $CC_SERVER_PORT
ENV NODE_ENV=production
USER node
ENTRYPOINT [ "/tini", "--", "/usr/src/app/docker-entrypoint.sh" ]

View file

@ -0,0 +1,16 @@
#!/usr/bin/env bash
#
# SPDX-License-Identifier: Apache-2.0
#
set -euo pipefail
: ${CORE_PEER_TLS_ENABLED:="false"}
: ${DEBUG:="false"}
if [ "${DEBUG,,}" = "true" ]; then
npm run start:server-debug
elif [ "${CORE_PEER_TLS_ENABLED,,}" = "true" ]; then
npm run start:server
else
npm run start:server-nontls
fi

File diff suppressed because it is too large Load diff

View file

@ -12,18 +12,23 @@
"lint": "tslint -c tslint.json 'src/**/*.ts'",
"pretest": "npm run lint",
"test": "nyc mocha -r ts-node/register src/**/*.spec.ts",
"start": "fabric-chaincode-node start",
"start": "set -x && fabric-chaincode-node start",
"build": "tsc",
"build:watch": "tsc -w",
"prepublishOnly": "npm run build"
"prepublishOnly": "npm run build",
"docker": "docker build -f ./Dockerfile -t asset-transfer-basic .",
"package": "npm run build && npm shrinkwrap",
"start:server-nontls": "set -x && fabric-chaincode-node server --chaincode-address=$CHAINCODE_SERVER_ADDRESS --chaincode-id=$CHAINCODE_ID",
"start:server-debug": "set -x && NODE_OPTIONS='--inspect=0.0.0.0:9229' fabric-chaincode-node server --chaincode-address=$CHAINCODE_SERVER_ADDRESS --chaincode-id=$CHAINCODE_ID",
"start:server": "set -x && fabric-chaincode-node server --chaincode-address=$CHAINCODE_SERVER_ADDRESS --chaincode-id=$CHAINCODE_ID --chaincode-tls-key-file=/hyperledger/privatekey.pem --chaincode-tls-client-cacert-file=/hyperledger/rootcert.pem --chaincode-tls-cert-file=/hyperledger/cert.pem"
},
"engineStrict": true,
"author": "Hyperledger",
"license": "Apache-2.0",
"dependencies": {
"fabric-contract-api": "^2.0.0",
"fabric-shim": "^2.0.0",
"json-stringify-deterministic": "^1.0.0",
"fabric-contract-api": "^2.4.0",
"fabric-shim": "^2.4.0",
"json-stringify-deterministic": "^1.0.1",
"sort-keys-recursive": "^2.1.2"
},
"devDependencies": {

View file

@ -0,0 +1,204 @@
# Running Chaincode as Service with the Test Network
The chaincode-as-a-service feature is a very useful and practical way to run 'Smart Contracts'. Traditionally the Fabric Peer has taken on the role of orchestrating the complete lifecycle of the chaincode. It required access to the Docker Daemon to create images, and start containers. Java, NodeJS and Go chaincode frameworks were explicitly known to the peer including how they should be built and started.
As a result this makes it very hard to deploy into Kubernetes (K8S) style environments, or to run in any form of debug mode. Additionally, the code is being rebuilt by the peer therefore there is some degree of uncertainty about what dependencies have been pulled in.
Chaincode-as-service requires you to orchestrate the build and deployment phase yourself. Whilst this is an additional step, it gives control back. The Peer still requires a 'chaincode package' to be installed. In this case this doesn't contain code, but the information about where the chaincode is hosted. (Hostname,Port,TLS config etc)
## Fabric v2.4.1 Improvements
We need to use the latest 2.4.1 release as this contains some improvements to make this process easier. The core functionality is available in earlier releases but requires more configuration.
- The docker image for the peer contains a builder for chaincode-as-a-service preconfigured. This is named 'ccaasbuilder'. This removes the need to build your own external builder and repackage and configure the peer
- The `ccaasbuilder` applications are included in the binary tgz archive download for use in other circumstances. The `sampleconfig/core.yaml` is updated as well to refer to 'ccaasbuilder'
- The 2.4.1 Java Chaincode release has been updated to remove the need to write a custom bootstrap main class, similar to the NodeJS Chaincode. It is intended that this will be added to the go chaincode as well.
## End-to-end with the the test-network
The `test-network` and some of the chaincodes have been updated to support running chaincode-as-a-service. The commands below assume that you've got the latest fabric-samples cloned, along with the latest Fabric docker images.
It's useful to have two terminal windows open, one for starting the Fabric Network, and a second for monitoring all the docker containers.
In your 'monitoring' window, run this to watch all activity from the all the docker containers on the `fabric_test` network; this will monitor all the docker containers that are added to the `fabric-test` network. The network is usually created by the `./network.sh up` command, so remember to delay running this until at lest the network is created. It is possible to precreate the network with `docker network create fabric-test` if you wish.
```bash
# from the fabric-samples repo
./test-network/monitordocker.sh
```
In the 'Fabric Network' window, start the test network
```bash
cd test-network
./network.sh up createChannel
```
You can run other variants of this command, eg to use CouchDB or CAs, without affecting the '-as-a-service' feature. The three keys steps are:
- Build a docker image of the contract. Both `/asset-transfer-basic/chaincode-typescript` and `/asset-transfer-basic/chaincode-java` have been updated with Dockerfiles
- Install, Approve and Commit a chaincode definition. This is unchanged, but the chaincode package contains connection information (hostname,port,tls certificates etc.), not code
- Start the docker container(s) containing the contract
Note that the order listed isn't mandatory. The key thing is that the containers are running before the first transaction is set by the peer. Remember that this could be on the `commit` if the `initRequired` flag is set.
This sequence can be run as follows
```bash
./network.sh deployCCAAS -ccn basicts -ccp ../asset-transfer-basic/chaincode-typescript
```
This is very similar to the `deployCC` command, it needs the name, and path. But also needs to have the port the chaincode container is going use. As each container is on the `fabric-test` network, you might wish to alter this so there are no collisions with other chaincode containers.
You should be able to see the contract starting in the monitoring window. There will be two containers running, one for org1 and one for org2. The container names contain the organzation/peer and the name of the chaincode.
To test things are working you can invoke the 'Contract Metadata' function. For information on how to work as different organizations see [Interacting with the network](https://hyperledger-fabric.readthedocs.io/en/latest/test_network.html#interacting-with-the-network)
```bash
# Environment variables for Org1
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
# invoke the function
peer chaincode query -C mychannel -n basicts -c '{"Args":["org.hyperledger.fabric:GetMetadata"]}' | jq
```
If you don't have `jq` installed omit ` | jq`. The metadata shows the details of the deployed contract and is JSON, so jq makes it easier to read. You can repeat the above commands for org2 to confirm that is working.
To run the Java example, change the `deployCCAAS` command as follows, This will create a two new containers.
```bash
./network.sh deployCCAAS -ccn basicj -ccp ../asset-transfer-basic/chaincode-typescript
```
### Troubleshooting
If the JSON structure passed in is badly formatted JSON this error will be in the peer log
```
::Error: Failed to unmarshal json: cannot unmarshal string into Go value of type map[string]interface {} command=build
```
## How to configure each langauge
Each language can work in the '-as-a-service' mode. Note that the approaches here are based on the very latest libraries.
When starting the image you can also specify any of the TLS options or additional logging options for the respective chaincode libraries.
### Java
With the v2.4.1 Java Chaincode libraries, there are no code changes to make or build changes. The '-as-a-service' mode will be used if the environment variable `CHAINCODE_SERVER_ADDRESS` is set.
A sample docker run command could be as follows. The two key variables that are needed are the `CHAINCODE_SERVER_ADDRESS` and `CORE_CHAICODE_ID_NAME`
```
docker run --rm -d --name peer0org1_assettx_ccaas \
--network fabric_test \
-e CHAINCODE_SERVER_ADDRESS=0.0.0.0:9999 \
-e CORE_CHAINCODE_ID_NAME=<use package id here> \
assettx_ccaas_image:latest
```
### Nodejs
For NodeJS (JavaScript or TypeScript) chaincode, typically the `package.json` has `fabric-chaincode-node start` as the main start command. To run in the '-as-a-service' mode change this to `fabric-chaincode-node server --chaincode-address=$CHAINCODE_SERVER_ADDRESS --chaincode-id=$CHAINCODE_ID`
### Golang
TBC
## Debugging the Chaincode
Running in the '-as-a-service' mode offers options, similar to how the Fabric 'dev' mode works on debugging code. The restrictions of the 'dev' mode don't apply.
There is an option `-ccaasdr false` that can be provided on the `deployCCAAS` command. This will _not_ build the docker image or start a docker container. It does output the commands it would have run.
Run this command, and you'll see similar output
```
./network.sh deployCCAAS -ccn basicj -ccp ../asset-transfer-basic/chaincode-java -ccaasdr false
#....
Not building docker image; this the command we would have run
docker build -f ../asset-transfer-basic/chaincode-java/Dockerfile -t basicj_ccaas_image:latest --build-arg CC_SERVER_PORT=9999 ../asset-transfer-basic/chaincode-java
#....
Not starting docker containers; these are the commands we would have run
docker run --rm -d --name peer0org1_basicj_ccaas --network fabric_test -e CHAINCODE_SERVER_ADDRESS=0.0.0.0:9999 -e CHAINCODE_ID=basicj_1.0:59dcd73a14e2db8eab7f7683343ce27ac242b93b4e8075605a460d63a0438405 -e CORE_CHAINCODE_ID_NAME=basicj_1.0:59dcd73a14e2db8eab7f7683343ce27ac242b93b4e8075605a460d63a0438405 basicj_ccaas_image:latest
```
Depending on your directory, and what you need to debug you might need to adjust these commands.
### Building the docker image
The first thing needed is to build the docker image. Remember that so long as the peer can connect to the hostname:port given in the `connection.json` the actual packaging of the chaincode is not important to the peer. You are at liberty to adjust the dockerfiles given hgere.
To manually build the docker image for the `asset-transfer-basic/chaincode-java`
```
docker build -f ../asset-transfer-basic/chaincode-java/Dockerfile -t basicj_ccaas_image:latest --build-arg CC_SERVER_PORT=9999 ../asset-transfer-basic/chaincode-java
```
### Starting the docker container
You need to start the docker container.
NodeJs for example, could be started like this
```
docker run --rm -it -p 9229:9229 --name peer0org2_basic_ccaas --network fabric_test -e DEBUG=true -e CHAINCODE_SERVER_ADDRESS=0.0.0.0:9999 -e CHAINCODE_ID=basic_1.0:7c7dff5cdc43c77ccea028c422b3348c3c1fb5a26ace0077cf3cc627bd355ef0 -e CORE_CHAINCODE_ID_NAME=basic_1.0:7c7dff5cdc43c77ccea028c422b3348c3c1fb5a26ace0077cf3cc627bd355ef0 basic_ccaas_image:latest
```
Java for example, could be started like this
```
docker run --rm -it --name peer0org1_basicj_ccaas -p 8000:8000 --network fabric_test -e DEBUG=true -e CHAINCODE_SERVER_ADDRESS=0.0.0.0:9999 -e CHAINCODE_ID=basicj_1.0:b014a03d8eb1898535e25b4dfeeb3f8244c9f07d91a06aec03e2d19174c45e4f -e CORE_CHAINCODE_ID_NAME=basicj_1.0:b014a03d8e
b1898535e25b4dfeeb3f8244c9f07d91a06aec03e2d19174c45e4f basicj_ccaas_image:latest
```
For all languages please note:
- the name of the container needs to match what the peer has in the `connection.json`
- the peer is connecting to the chaincode container via the docker network. Therefore port 9999 does not need to forwarded to the host
- If you are going to single step in a debugger, then you are likely to hit the Fabric transaction timeout value. By default this is 30seconds, meaning the chaincode has to complete transactions in 30 seconds or less. In the `test-network/docker/docker-composer-test-net.yml` add `CORE_CHAINCODE_EXECUTETIMEOUT=300s` to the environment options of each peer.
- In the command above, the `-d` option has been removed from the command the test-network would have used, and has been replaced with `-it`. This means that docker container will not run in detached mode, and will run in the foregroud.
For Node.js please note:
- Port 9229 is forwarded however - this is the debug port used by NodeJS
- `-e DEBUG=true` will trigger the node runtime to be started in debug mode. This is encoded in the `docker/docker-entrypoint.sh` script - this is an example and you may wish to remove this in production images for security
- If you are using typescript, ensure that the typescript has been compiled with sourcemaps, otherwise a debugger will struggle matching up the source code.
For Java please note:
- Port 800 is forwarded, the debug port for the JVM
- `-e DEBUG=true` will trigger the node runtime to be started in debug mode. This is encoded in the `docker/docker-entrypoint.sh` script - this is an example and you may wish to remove this in production images for security
- In the java command with the option to start the debugger is `java -agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=0.0.0.0:8000 -jar /chaincode.jar` Note the `0.0.0.0` as the debug port needs to be bound to all network adapters so the debugger can be attached from outside the container
## Running with multiple peers
In the traditional approach, each peer that the chaincode is approved on will have a container running the chaincode. With the '-as-a-service' approach we need to achieve the same architecture.
As the `connection.json` contains the address of the running chaincode container, it can be updated to ensure that each peer connects to a different container. However the as the `connection.json` in the chaincode package, Fabric mandates that the package id is consistent amongst all peers in an organization. To achieve that
the the external builder supports a template capability. The context from this template is taken from an environment variable set on each Peer. `CHAINCODE_AS_A_SERVICE_BUILDER_CONFIG`
We can define the address to be a template in the `connection.json`
```json
{
"address": "{{.peername}}_assettransfer_ccaas:9999",
"dial_timeout": "10s",
"tls_required": false
}
```
In the peer's environment configuration we then set for org1's peer1
```
CHAINCODE_AS_A_SERVICE_BUILDER_CONFIG="{\"peername\":\"org1peer1\"}"
```
The external builder will then resolve this address to be `org1peer1_assettransfer_ccaas:9999` for the peer to use.
Each peer can have there own separate configuration, and therefore different addresses. The JSON string that is set can have any structure, so long as the templates (in golang template syntax) match.
Any value in the `connection.json` can be templated - but only the values and not the keys.

View file

@ -20,5 +20,11 @@ You can then set up the environment variables for each organization. The `./setO
export $(./setOrgEnv.sh Org2 | xargs)
```
(Note bash v4 is required for the scripts)
You will now be able to run the `peer` commands in the context of Org2. If a different command prompt you can run the same command with Org1 instead.
The `setOrgEnv` script outputs a series of `<name>=<value>` strings. These can then be fed into the export command for your current shell
The `setOrgEnv` script outputs a series of `<name>=<value>` strings. These can then be fed into the export command for your current shell
## Chaincode-as-a-service
To learn more about how to use the improvements to the Chaincode-as-a-service please see this [tutorial](./test-network/../CHAINCODE_AS_A_SERVICE_TUTORIAL.md). It is expected that this will move to augment the tutorial in the [Hyperledger Fabric ReadTheDocs](https://hyperledger-fabric.readthedocs.io/en/release-2.4/cc_service.html)

View file

@ -86,6 +86,8 @@ services:
- CORE_PEER_LOCALMSPID=Org1MSP
- CORE_OPERATIONS_LISTENADDRESS=peer0.org1.example.com:9444
- CORE_METRICS_PROVIDER=prometheus
- CHAINCODE_AS_A_SERVICE_BUILDER_CONFIG={"peername":"peer0org1"}
- CORE_CHAINCODE_EXECUTETIMEOUT=300s
volumes:
- ${DOCKER_SOCK}:/host/var/run/docker.sock
- ../organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/fabric/msp
@ -126,6 +128,8 @@ services:
- CORE_PEER_LOCALMSPID=Org2MSP
- CORE_OPERATIONS_LISTENADDRESS=peer0.org2.example.com:9445
- CORE_METRICS_PROVIDER=prometheus
- CHAINCODE_AS_A_SERVICE_BUILDER_CONFIG={"peername":"peer0org2"}
- CORE_CHAINCODE_EXECUTETIMEOUT=300s
volumes:
- ${DOCKER_SOCK}:/host/var/run/docker.sock
- ../organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/msp:/etc/hyperledger/fabric/msp

33
test-network/monitordocker.sh Executable file
View file

@ -0,0 +1,33 @@
#!/bin/bash
# This script uses the logspout and http stream tools to let you watch the docker containers
# in action.
#
# More information at https://github.com/gliderlabs/logspout/tree/master/httpstream
if [ -z "$1" ]; then
DOCKER_NETWORK=fabric_test
else
DOCKER_NETWORK="$1"
fi
if [ -z "$2" ]; then
PORT=8000
else
PORT="$2"
fi
echo Starting monitoring on all containers on the network ${DOCKER_NETWORK}
docker kill logspout 2> /dev/null 1>&2 || true
docker rm logspout 2> /dev/null 1>&2 || true
trap "docker kill logspout" SIGINT
docker run -d --rm --name="logspout" \
--volume=/var/run/docker.sock:/var/run/docker.sock \
--publish=127.0.0.1:${PORT}:80 \
--network ${DOCKER_NETWORK} \
gliderlabs/logspout
sleep 3
curl http://127.0.0.1:${PORT}/logs

View file

@ -274,6 +274,14 @@ function deployCC() {
fi
}
## Call the script to deploy a chaincode to the channel
function deployCCAAS() {
scripts/deployCCAAS.sh $CHANNEL_NAME $CC_NAME $CC_SRC_PATH $CCAAS_DOCKER_RUN $CC_VERSION $CC_SEQUENCE $CC_INIT_FCN $CC_END_POLICY $CC_COLL_CONFIG $CLI_DELAY $MAX_RETRY $VERBOSE $CCAAS_DOCKER_RUN
if [ $? -ne 0 ]; then
fatalln "Deploying chaincode-as-a-service failed"
fi
}
# Tear down running network
function networkDown() {
@ -283,10 +291,13 @@ function networkDown() {
# Don't remove the generated artifacts -- note, the ledgers are always removed
if [ "$MODE" != "restart" ]; then
# Bring down the network, deleting the volumes
docker volume rm docker_orderer.example.com docker_peer0.org1.example.com docker_peer0.org2.example.com
#Cleanup the chaincode containers
clearContainers
#Cleanup images
removeUnwantedImages
#
docker kill $(docker ps -q --filter name=ccaas) || true
# remove orderer block and other channel configuration transactions and certs
docker run --rm -v "$(pwd):/data" busybox sh -c 'cd /data && rm -rf system-genesis-block/*.block organizations/peerOrganizations organizations/ordererOrganizations'
## remove fabric ca artifacts
@ -331,6 +342,8 @@ COMPOSE_FILE_ORG3=addOrg3/docker/docker-compose-org3.yaml
#
# chaincode language defaults to "NA"
CC_SRC_LANGUAGE="NA"
# default to running the docker commands for the CCAAS
CCAAS_DOCKER_RUN=true
# Chaincode version
CC_VERSION="1.0"
# Chaincode definition sequence
@ -422,6 +435,10 @@ while [[ $# -ge 1 ]] ; do
CC_INIT_FCN="$2"
shift
;;
-ccaasdocker )
CCAAS_DOCKER_RUN="$2"
shift
;;
-verbose )
VERBOSE=true
shift
@ -445,29 +462,26 @@ fi
# Determine mode of operation and printing out what we asked for
if [ "$MODE" == "up" ]; then
infoln "Starting nodes with CLI timeout of '${MAX_RETRY}' tries and CLI delay of '${CLI_DELAY}' seconds and using database '${DATABASE}' ${CRYPTO_MODE}"
networkUp
elif [ "$MODE" == "createChannel" ]; then
infoln "Creating channel '${CHANNEL_NAME}'."
infoln "If network is not up, starting nodes with CLI timeout of '${MAX_RETRY}' tries and CLI delay of '${CLI_DELAY}' seconds and using database '${DATABASE} ${CRYPTO_MODE}"
createChannel
elif [ "$MODE" == "down" ]; then
infoln "Stopping network"
networkDown
elif [ "$MODE" == "restart" ]; then
infoln "Restarting network"
networkDown
networkUp
elif [ "$MODE" == "deployCC" ]; then
infoln "deploying chaincode on channel '${CHANNEL_NAME}'"
deployCC
elif [ "$MODE" == "deployCCAAS" ]; then
infoln "deploying chaincode-as-a-service on channel '${CHANNEL_NAME}'"
deployCCAAS
else
printHelp
exit 1
fi
if [ "${MODE}" == "up" ]; then
networkUp
elif [ "${MODE}" == "createChannel" ]; then
createChannel
elif [ "${MODE}" == "deployCC" ]; then
deployCC
elif [ "${MODE}" == "down" ]; then
networkDown
else
printHelp
exit 1
fi

View file

@ -0,0 +1,165 @@
#!/bin/bash
# installChaincode PEER ORG
function installChaincode() {
ORG=$1
setGlobals $ORG
set -x
peer lifecycle chaincode install ${CC_NAME}.tar.gz >&log.txt
res=$?
{ set +x; } 2>/dev/null
cat log.txt
verifyResult $res "Chaincode installation on peer0.org${ORG} has failed"
successln "Chaincode is installed on peer0.org${ORG}"
}
# queryInstalled PEER ORG
function queryInstalled() {
ORG=$1
setGlobals $ORG
set -x
peer lifecycle chaincode queryinstalled >&log.txt
res=$?
{ set +x; } 2>/dev/null
cat log.txt
PACKAGE_ID=$(sed -n "/${CC_NAME}_${CC_VERSION}/{s/^Package ID: //; s/, Label:.*$//; p;}" log.txt)
verifyResult $res "Query installed on peer0.org${ORG} has failed"
successln "Query installed successful on peer0.org${ORG} on channel"
}
# approveForMyOrg VERSION PEER ORG
function approveForMyOrg() {
ORG=$1
setGlobals $ORG
set -x
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "$ORDERER_CA" --channelID $CHANNEL_NAME --name ${CC_NAME} --version ${CC_VERSION} --package-id ${PACKAGE_ID} --sequence ${CC_SEQUENCE} ${INIT_REQUIRED} ${CC_END_POLICY} ${CC_COLL_CONFIG} >&log.txt
res=$?
{ set +x; } 2>/dev/null
cat log.txt
verifyResult $res "Chaincode definition approved on peer0.org${ORG} on channel '$CHANNEL_NAME' failed"
successln "Chaincode definition approved on peer0.org${ORG} on channel '$CHANNEL_NAME'"
}
# checkCommitReadiness VERSION PEER ORG
function checkCommitReadiness() {
ORG=$1
shift 1
setGlobals $ORG
infoln "Checking the commit readiness of the chaincode definition on peer0.org${ORG} on channel '$CHANNEL_NAME'..."
local rc=1
local COUNTER=1
# continue to poll
# we either get a successful response, or reach MAX RETRY
while [ $rc -ne 0 -a $COUNTER -lt $MAX_RETRY ]; do
sleep $DELAY
infoln "Attempting to check the commit readiness of the chaincode definition on peer0.org${ORG}, Retry after $DELAY seconds."
set -x
peer lifecycle chaincode checkcommitreadiness --channelID $CHANNEL_NAME --name ${CC_NAME} --version ${CC_VERSION} --sequence ${CC_SEQUENCE} ${INIT_REQUIRED} ${CC_END_POLICY} ${CC_COLL_CONFIG} --output json >&log.txt
res=$?
{ set +x; } 2>/dev/null
let rc=0
for var in "$@"; do
grep "$var" log.txt &>/dev/null || let rc=1
done
COUNTER=$(expr $COUNTER + 1)
done
cat log.txt
if test $rc -eq 0; then
infoln "Checking the commit readiness of the chaincode definition successful on peer0.org${ORG} on channel '$CHANNEL_NAME'"
else
fatalln "After $MAX_RETRY attempts, Check commit readiness result on peer0.org${ORG} is INVALID!"
fi
}
# commitChaincodeDefinition VERSION PEER ORG (PEER ORG)...
function commitChaincodeDefinition() {
parsePeerConnectionParameters $@
res=$?
verifyResult $res "Invoke transaction failed on channel '$CHANNEL_NAME' due to uneven number of peer and org parameters "
# while 'peer chaincode' command can get the orderer endpoint from the
# peer (if join was successful), let's supply it directly as we know
# it using the "-o" option
set -x
peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "$ORDERER_CA" --channelID $CHANNEL_NAME --name ${CC_NAME} "${PEER_CONN_PARMS[@]}" --version ${CC_VERSION} --sequence ${CC_SEQUENCE} ${INIT_REQUIRED} ${CC_END_POLICY} ${CC_COLL_CONFIG} >&log.txt
res=$?
{ set +x; } 2>/dev/null
cat log.txt
verifyResult $res "Chaincode definition commit failed on peer0.org${ORG} on channel '$CHANNEL_NAME' failed"
successln "Chaincode definition committed on channel '$CHANNEL_NAME'"
}
# queryCommitted ORG
function queryCommitted() {
ORG=$1
setGlobals $ORG
EXPECTED_RESULT="Version: ${CC_VERSION}, Sequence: ${CC_SEQUENCE}, Endorsement Plugin: escc, Validation Plugin: vscc"
infoln "Querying chaincode definition on peer0.org${ORG} on channel '$CHANNEL_NAME'..."
local rc=1
local COUNTER=1
# continue to poll
# we either get a successful response, or reach MAX RETRY
while [ $rc -ne 0 -a $COUNTER -lt $MAX_RETRY ]; do
sleep $DELAY
infoln "Attempting to Query committed status on peer0.org${ORG}, Retry after $DELAY seconds."
set -x
peer lifecycle chaincode querycommitted --channelID $CHANNEL_NAME --name ${CC_NAME} >&log.txt
res=$?
{ set +x; } 2>/dev/null
test $res -eq 0 && VALUE=$(cat log.txt | grep -o '^Version: '$CC_VERSION', Sequence: [0-9]*, Endorsement Plugin: escc, Validation Plugin: vscc')
test "$VALUE" = "$EXPECTED_RESULT" && let rc=0
COUNTER=$(expr $COUNTER + 1)
done
cat log.txt
if test $rc -eq 0; then
successln "Query chaincode definition successful on peer0.org${ORG} on channel '$CHANNEL_NAME'"
else
fatalln "After $MAX_RETRY attempts, Query chaincode definition result on peer0.org${ORG} is INVALID!"
fi
}
function chaincodeInvokeInit() {
parsePeerConnectionParameters $@
res=$?
verifyResult $res "Invoke transaction failed on channel '$CHANNEL_NAME' due to uneven number of peer and org parameters "
# while 'peer chaincode' command can get the orderer endpoint from the
# peer (if join was successful), let's supply it directly as we know
# it using the "-o" option
set -x
fcn_call='{"function":"'${CC_INIT_FCN}'","Args":[]}'
infoln "invoke fcn call:${fcn_call}"
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "$ORDERER_CA" -C $CHANNEL_NAME -n ${CC_NAME} "${PEER_CONN_PARMS[@]}" --isInit -c ${fcn_call} >&log.txt
res=$?
{ set +x; } 2>/dev/null
cat log.txt
verifyResult $res "Invoke execution on $PEERS failed "
successln "Invoke transaction successful on $PEERS on channel '$CHANNEL_NAME'"
}
function chaincodeQuery() {
ORG=$1
setGlobals $ORG
infoln "Querying on peer0.org${ORG} on channel '$CHANNEL_NAME'..."
local rc=1
local COUNTER=1
# continue to poll
# we either get a successful response, or reach MAX RETRY
while [ $rc -ne 0 -a $COUNTER -lt $MAX_RETRY ]; do
sleep $DELAY
infoln "Attempting to Query peer0.org${ORG}, Retry after $DELAY seconds."
set -x
peer chaincode query -C $CHANNEL_NAME -n ${CC_NAME} -c '{"Args":["org.hyperledger.fabric:GetMetadata"]}' >&log.txt
res=$?
{ set +x; } 2>/dev/null
let rc=$res
COUNTER=$(expr $COUNTER + 1)
done
cat log.txt
if test $rc -eq 0; then
successln "Query successful on peer0.org${ORG} on channel '$CHANNEL_NAME'"
else
fatalln "After $MAX_RETRY attempts, Query result on peer0.org${ORG} is INVALID!"
fi
}

View file

@ -109,6 +109,7 @@ fi
# import utils
. scripts/envVar.sh
. scripts/ccutils.sh
packageChaincode() {
set -x
@ -120,169 +121,6 @@ packageChaincode() {
successln "Chaincode is packaged"
}
# installChaincode PEER ORG
installChaincode() {
ORG=$1
setGlobals $ORG
set -x
peer lifecycle chaincode install ${CC_NAME}.tar.gz >&log.txt
res=$?
{ set +x; } 2>/dev/null
cat log.txt
verifyResult $res "Chaincode installation on peer0.org${ORG} has failed"
successln "Chaincode is installed on peer0.org${ORG}"
}
# queryInstalled PEER ORG
queryInstalled() {
ORG=$1
setGlobals $ORG
set -x
peer lifecycle chaincode queryinstalled >&log.txt
res=$?
{ set +x; } 2>/dev/null
cat log.txt
PACKAGE_ID=$(sed -n "/${CC_NAME}_${CC_VERSION}/{s/^Package ID: //; s/, Label:.*$//; p;}" log.txt)
verifyResult $res "Query installed on peer0.org${ORG} has failed"
successln "Query installed successful on peer0.org${ORG} on channel"
}
# approveForMyOrg VERSION PEER ORG
approveForMyOrg() {
ORG=$1
setGlobals $ORG
set -x
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "$ORDERER_CA" --channelID $CHANNEL_NAME --name ${CC_NAME} --version ${CC_VERSION} --package-id ${PACKAGE_ID} --sequence ${CC_SEQUENCE} ${INIT_REQUIRED} ${CC_END_POLICY} ${CC_COLL_CONFIG} >&log.txt
res=$?
{ set +x; } 2>/dev/null
cat log.txt
verifyResult $res "Chaincode definition approved on peer0.org${ORG} on channel '$CHANNEL_NAME' failed"
successln "Chaincode definition approved on peer0.org${ORG} on channel '$CHANNEL_NAME'"
}
# checkCommitReadiness VERSION PEER ORG
checkCommitReadiness() {
ORG=$1
shift 1
setGlobals $ORG
infoln "Checking the commit readiness of the chaincode definition on peer0.org${ORG} on channel '$CHANNEL_NAME'..."
local rc=1
local COUNTER=1
# continue to poll
# we either get a successful response, or reach MAX RETRY
while [ $rc -ne 0 -a $COUNTER -lt $MAX_RETRY ]; do
sleep $DELAY
infoln "Attempting to check the commit readiness of the chaincode definition on peer0.org${ORG}, Retry after $DELAY seconds."
set -x
peer lifecycle chaincode checkcommitreadiness --channelID $CHANNEL_NAME --name ${CC_NAME} --version ${CC_VERSION} --sequence ${CC_SEQUENCE} ${INIT_REQUIRED} ${CC_END_POLICY} ${CC_COLL_CONFIG} --output json >&log.txt
res=$?
{ set +x; } 2>/dev/null
let rc=0
for var in "$@"; do
grep "$var" log.txt &>/dev/null || let rc=1
done
COUNTER=$(expr $COUNTER + 1)
done
cat log.txt
if test $rc -eq 0; then
infoln "Checking the commit readiness of the chaincode definition successful on peer0.org${ORG} on channel '$CHANNEL_NAME'"
else
fatalln "After $MAX_RETRY attempts, Check commit readiness result on peer0.org${ORG} is INVALID!"
fi
}
# commitChaincodeDefinition VERSION PEER ORG (PEER ORG)...
commitChaincodeDefinition() {
parsePeerConnectionParameters $@
res=$?
verifyResult $res "Invoke transaction failed on channel '$CHANNEL_NAME' due to uneven number of peer and org parameters "
# while 'peer chaincode' command can get the orderer endpoint from the
# peer (if join was successful), let's supply it directly as we know
# it using the "-o" option
set -x
peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "$ORDERER_CA" --channelID $CHANNEL_NAME --name ${CC_NAME} "${PEER_CONN_PARMS[@]}" --version ${CC_VERSION} --sequence ${CC_SEQUENCE} ${INIT_REQUIRED} ${CC_END_POLICY} ${CC_COLL_CONFIG} >&log.txt
res=$?
{ set +x; } 2>/dev/null
cat log.txt
verifyResult $res "Chaincode definition commit failed on peer0.org${ORG} on channel '$CHANNEL_NAME' failed"
successln "Chaincode definition committed on channel '$CHANNEL_NAME'"
}
# queryCommitted ORG
queryCommitted() {
ORG=$1
setGlobals $ORG
EXPECTED_RESULT="Version: ${CC_VERSION}, Sequence: ${CC_SEQUENCE}, Endorsement Plugin: escc, Validation Plugin: vscc"
infoln "Querying chaincode definition on peer0.org${ORG} on channel '$CHANNEL_NAME'..."
local rc=1
local COUNTER=1
# continue to poll
# we either get a successful response, or reach MAX RETRY
while [ $rc -ne 0 -a $COUNTER -lt $MAX_RETRY ]; do
sleep $DELAY
infoln "Attempting to Query committed status on peer0.org${ORG}, Retry after $DELAY seconds."
set -x
peer lifecycle chaincode querycommitted --channelID $CHANNEL_NAME --name ${CC_NAME} >&log.txt
res=$?
{ set +x; } 2>/dev/null
test $res -eq 0 && VALUE=$(cat log.txt | grep -o '^Version: '$CC_VERSION', Sequence: [0-9]*, Endorsement Plugin: escc, Validation Plugin: vscc')
test "$VALUE" = "$EXPECTED_RESULT" && let rc=0
COUNTER=$(expr $COUNTER + 1)
done
cat log.txt
if test $rc -eq 0; then
successln "Query chaincode definition successful on peer0.org${ORG} on channel '$CHANNEL_NAME'"
else
fatalln "After $MAX_RETRY attempts, Query chaincode definition result on peer0.org${ORG} is INVALID!"
fi
}
chaincodeInvokeInit() {
parsePeerConnectionParameters $@
res=$?
verifyResult $res "Invoke transaction failed on channel '$CHANNEL_NAME' due to uneven number of peer and org parameters "
# while 'peer chaincode' command can get the orderer endpoint from the
# peer (if join was successful), let's supply it directly as we know
# it using the "-o" option
set -x
fcn_call='{"function":"'${CC_INIT_FCN}'","Args":[]}'
infoln "invoke fcn call:${fcn_call}"
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "$ORDERER_CA" -C $CHANNEL_NAME -n ${CC_NAME} "${PEER_CONN_PARMS[@]}" --isInit -c ${fcn_call} >&log.txt
res=$?
{ set +x; } 2>/dev/null
cat log.txt
verifyResult $res "Invoke execution on $PEERS failed "
successln "Invoke transaction successful on $PEERS on channel '$CHANNEL_NAME'"
}
chaincodeQuery() {
ORG=$1
setGlobals $ORG
infoln "Querying on peer0.org${ORG} on channel '$CHANNEL_NAME'..."
local rc=1
local COUNTER=1
# continue to poll
# we either get a successful response, or reach MAX RETRY
while [ $rc -ne 0 -a $COUNTER -lt $MAX_RETRY ]; do
sleep $DELAY
infoln "Attempting to Query peer0.org${ORG}, Retry after $DELAY seconds."
set -x
peer chaincode query -C $CHANNEL_NAME -n ${CC_NAME} -c '{"Args":["queryAllCars"]}' >&log.txt
res=$?
{ set +x; } 2>/dev/null
let rc=$res
COUNTER=$(expr $COUNTER + 1)
done
cat log.txt
if test $rc -eq 0; then
successln "Query successful on peer0.org${ORG} on channel '$CHANNEL_NAME'"
else
fatalln "After $MAX_RETRY attempts, Query result on peer0.org${ORG} is INVALID!"
fi
}
## package the chaincode
packageChaincode

View file

@ -0,0 +1,206 @@
#!/bin/bash
#
#
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
source scripts/utils.sh
CHANNEL_NAME=${1:-"mychannel"}
CC_NAME=${2}
CC_SRC_PATH=${3}
CCAAS_DOCKER_RUN=${4:-"true"}
CC_VERSION=${5:-"1.0"}
CC_SEQUENCE=${6:-"1"}
CC_INIT_FCN=${7:-"NA"}
CC_END_POLICY=${8:-"NA"}
CC_COLL_CONFIG=${9:-"NA"}
DELAY=${10:-"3"}
MAX_RETRY=${11:-"5"}
VERBOSE=${12:-"false"}
CCAAS_SERVER_PORT=9999
println "executing with the following"
println "- CHANNEL_NAME: ${C_GREEN}${CHANNEL_NAME}${C_RESET}"
println "- CC_NAME: ${C_GREEN}${CC_NAME}${C_RESET}"
println "- CC_SRC_PATH: ${C_GREEN}${CC_SRC_PATH}${C_RESET}"
println "- CC_VERSION: ${C_GREEN}${CC_VERSION}${C_RESET}"
println "- CC_SEQUENCE: ${C_GREEN}${CC_SEQUENCE}${C_RESET}"
println "- CC_END_POLICY: ${C_GREEN}${CC_END_POLICY}${C_RESET}"
println "- CC_COLL_CONFIG: ${C_GREEN}${CC_COLL_CONFIG}${C_RESET}"
println "- CC_INIT_FCN: ${C_GREEN}${CC_INIT_FCN}${C_RESET}"
println "- CCAAS_DOCKER_RUN: ${C_GREEN}${CCAAS_DOCKER_RUN}${C_RESET}"
println "- DELAY: ${C_GREEN}${DELAY}${C_RESET}"
println "- MAX_RETRY: ${C_GREEN}${MAX_RETRY}${C_RESET}"
println "- VERBOSE: ${C_GREEN}${VERBOSE}${C_RESET}"
FABRIC_CFG_PATH=$PWD/../config/
#User has not provided a name
if [ -z "$CC_NAME" ] || [ "$CC_NAME" = "NA" ]; then
fatalln "No chaincode name was provided. Valid call example: ./network.sh deployCCAS -ccn basic -ccp ../asset-transfer-basic/chaincode-go "
# User has not provided a path
elif [ -z "$CC_SRC_PATH" ] || [ "$CC_SRC_PATH" = "NA" ]; then
fatalln "No chaincode path was provided. Valid call example: ./network.sh deployCCAS -ccn basic -ccp ../asset-transfer-basic/chaincode-go "
## Make sure that the path to the chaincode exists
elif [ ! -d "$CC_SRC_PATH" ]; then
fatalln "Path to chaincode does not exist. Please provide different path."
fi
if [ "$CC_END_POLICY" = "NA" ]; then
CC_END_POLICY=""
else
CC_END_POLICY="--signature-policy $CC_END_POLICY"
fi
if [ "$CC_COLL_CONFIG" = "NA" ]; then
CC_COLL_CONFIG=""
else
CC_COLL_CONFIG="--collections-config $CC_COLL_CONFIG"
fi
# import utils
. scripts/envVar.sh
. scripts/ccutils.sh
packageChaincode() {
address="{{.peername}}_${CC_NAME}_ccaas:${CCAAS_SERVER_PORT}"
prefix=$(basename "$0")
tempdir=$(mktemp -d -t "$prefix.XXXXXXXX") || error_exit "Error creating temporary directory"
label=${CC_NAME}_${CC_VERSION}
mkdir -p "$tempdir/src"
cat > "$tempdir/src/connection.json" <<CONN_EOF
{
"address": "${address}",
"dial_timeout": "10s",
"tls_required": false
}
CONN_EOF
mkdir -p "$tempdir/pkg"
cat << METADATA-EOF > "$tempdir/pkg/metadata.json"
{
"type": "ccaas",
"label": "$label"
}
METADATA-EOF
tar -C "$tempdir/src" -czf "$tempdir/pkg/code.tar.gz" .
tar -C "$tempdir/pkg" -czf "$CC_NAME.tar.gz" metadata.json code.tar.gz
rm -Rf "$tempdir"
successln "Chaincode is packaged ${address}"
}
buildDockerImages() {
# if set don't build - useful when you want to debug yourself
if [ "$CCAAS_DOCKER_RUN" = "true" ]; then
# build the docker container
infoln "Building Chaincode-as-a-Service docker image '${CC_NAME}' '${CC_SRC_PATH}'"
set -x
docker build -f $CC_SRC_PATH/Dockerfile -t ${CC_NAME}_ccaas_image:latest --build-arg CC_SERVER_PORT=9999 $CC_SRC_PATH >&log.txt
res=$?
{ set +x; } 2>/dev/null
cat log.txt
verifyResult $res "Docker buid of chaincode-as-a-service container failed"
successln "Docker image '${CC_NAME}_ccaas_image:latest' built succesfully"
else
infoln "Not building docker image; this the command we would have run"
infoln "docker build -f $CC_SRC_PATH/Dockerfile -t ${CC_NAME}_ccaas_image:latest --build-arg CC_SERVER_PORT=9999 $CC_SRC_PATH"
fi
}
startDockerContainer() {
# start the docker container
if [ "$CCAAS_DOCKER_RUN" = "true" ]; then
infoln "Starting the Chaincode-as-a-Service docker container..."
set -x
docker run --rm -d --name peer0org1_${CC_NAME}_ccaas \
--network fabric_test \
-e CHAINCODE_SERVER_ADDRESS=0.0.0.0:${CCAAS_SERVER_PORT} \
-e CHAINCODE_ID=$PACKAGE_ID -e CORE_CHAINCODE_ID_NAME=$PACKAGE_ID \
${CC_NAME}_ccaas_image:latest
docker run --rm -d --name peer0org2_${CC_NAME}_ccaas \
--network fabric_test \
-e CHAINCODE_SERVER_ADDRESS=0.0.0.0:${CCAAS_SERVER_PORT} \
-e CHAINCODE_ID=$PACKAGE_ID -e CORE_CHAINCODE_ID_NAME=$PACKAGE_ID \
${CC_NAME}_ccaas_image:latest
res=$?
{ set +x; } 2>/dev/null
cat log.txt
verifyResult $res "Failed to start the container container '${CC_NAME}_ccaas_image:latest' "
successln "Docker container started succesfully '${CC_NAME}_ccaas_image:latest'"
else
infoln "Not starting docker containers; these are the commands we would have run"
infoln " docker run --rm -d --name peer0org1_${CC_NAME}_ccaas \
--network fabric_test \
-e CHAINCODE_SERVER_ADDRESS=0.0.0.0:${CCAAS_SERVER_PORT} \
-e CHAINCODE_ID=$PACKAGE_ID -e CORE_CHAINCODE_ID_NAME=$PACKAGE_ID \
${CC_NAME}_ccaas_image:latest"
fi
}
# Build the docker image
buildDockerImages
## package the chaincode
packageChaincode
## Install chaincode on peer0.org1 and peer0.org2
infoln "Installing chaincode on peer0.org1..."
installChaincode 1
infoln "Install chaincode on peer0.org2..."
installChaincode 2
## query whether the chaincode is installed
queryInstalled 1
## approve the definition for org1
approveForMyOrg 1
## check whether the chaincode definition is ready to be committed
## expect org1 to have approved and org2 not to
checkCommitReadiness 1 "\"Org1MSP\": true" "\"Org2MSP\": false"
checkCommitReadiness 2 "\"Org1MSP\": true" "\"Org2MSP\": false"
## now approve also for org2
approveForMyOrg 2
## check whether the chaincode definition is ready to be committed
## expect them both to have approved
checkCommitReadiness 1 "\"Org1MSP\": true" "\"Org2MSP\": true"
checkCommitReadiness 2 "\"Org1MSP\": true" "\"Org2MSP\": true"
## now that we know for sure both orgs have approved, commit the definition
commitChaincodeDefinition 1 2
## query on both orgs to see that the definition committed successfully
queryCommitted 1
queryCommitted 2
# start the container
startDockerContainer
## Invoke the chaincode - this does require that the chaincode have the 'initLedger'
## method defined
if [ "$CC_INIT_FCN" = "NA" ]; then
infoln "Chaincode initialization is not required"
else
chaincodeInvokeInit 1 2
fi
exit 0

107
test-network/scripts/pkgcc.sh Executable file
View file

@ -0,0 +1,107 @@
#!/bin/bash
#
# SPDX-License-Identifier: Apache-2.0
#
function usage() {
echo "Usage: pkgcc.sh -l <label> -a <address> [-m <META-INF directory>]"
}
function error_exit {
echo "${1:-"Unknown Error"}" 1>&2
exit 1
}
while getopts "hl:a:m:" opt; do
case "$opt" in
h)
usage
exit 0
;;
l)
label=${OPTARG}
;;
m)
metainf=${OPTARG}
;;
a)
address=${OPTARG}
;;
*)
usage
exit 1
;;
esac
done
shift $((OPTIND-1))
type=ccaas
if [ -z "$label" ] || [ -z "$address" ]; then
usage
exit 1
fi
metadir=$(basename "$metainf")
if [ -n "$metainf" ]; then
if [ "META-INF" != "$metadir" ]; then
error_exit "Invalid chaincode META-INF directory $metadir: directory name must be 'META-INF'"
elif [ ! -d "$metainf" ]; then
error_exit "Cannot find directory $metadir"
fi
fi
prefix=$(basename "$0")
tempdir=$(mktemp -d -t "$prefix.XXXXXXXX") || error_exit "Error creating temporary directory"
file=${tempdir}/connection.json
cat > "${file}" <<CONN_EOF
{
"address": "${address}",
"dial_timeout": "10s",
"tls_required": false
}
CONN_EOF
if [ -n "$DEBUG" ]; then
echo "label = $label"
echo "type = $type"
echo "file = $file"
echo "tempdir = $tempdir"
echo "metainf = $metainf"
fi
mkdir -p "$tempdir/src"
if [ -d "$file" ]; then
cp -a "$file/"* "$tempdir/src/"
elif [ -f "$file" ]; then
cp -a "$file" "$tempdir/src/"
fi
if [ -n "$metainf" ]; then
cp -a "$metainf" "$tempdir/src/"
fi
mkdir -p "$tempdir/pkg"
cat << METADATA-EOF > "$tempdir/pkg/metadata.json"
{
"type": "$type",
"label": "$label"
}
METADATA-EOF
if [ "$type" = "ccaas" ]; then
tar -C "$tempdir/src" -czf "$tempdir/pkg/code.tar.gz" .
else
tar -C "$tempdir" -czf "$tempdir/pkg/code.tar.gz" src
fi
tar -C "$tempdir/pkg" -czf "$label.tgz" metadata.json code.tar.gz
rm -Rf "$tempdir"
packageid="${label}:$(shasum -a 256 audit-trail.tgz | cut -d ' ' -f1)"
echo ${packageid}

View file

@ -69,6 +69,29 @@ function printHelp() {
println " Examples:"
println " network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-javascript/ ./ -ccl javascript"
println " network.sh deployCC -ccn mychaincode -ccp ./user/mychaincode -ccv 1 -ccl javascript"
elif [ "$USAGE" == "deployCCAAS" ]; then
println "Usage: "
println " network.sh \033[0;32mdeployCCAAS\033[0m [Flags]"
println
println " Flags:"
println " -c <channel name> - Name of channel to deploy chaincode to"
println " -ccn <name> - Chaincode name."
println " -ccv <version> - Chaincode version. 1.0 (default), v2, version3.x, etc"
println " -ccs <sequence> - Chaincode definition sequence. Must be an integer, 1 (default), 2, 3, etc"
println " -ccp <path> - File path to the chaincode. (used to find the dockerfile for building the docker image only)"
println " -ccep <policy> - (Optional) Chaincode endorsement policy using signature policy syntax. The default policy requires an endorsement from Org1 and Org2"
println " -cccg <collection-config> - (Optional) File path to private data collections configuration file"
println " -cci <fcn name> - (Optional) Name of chaincode initialization function. When a function is provided, the execution of init will be requested and the function will be invoked."
println " -ccaasdocker <true|false> - (Optional) Default is true; the chaincode docker image will be built and containers started automatically. Set to false to control this manually"
println
println " -h - Print this message"
println
println " Possible Mode and flag combinations"
println " \033[0;32mdeployCC\033[0m -ccn -ccv -ccs -ccp -cci -r -d -verbose"
println
println " Examples:"
println " network.sh deployCCAAS -ccn basicj -ccp ../asset-transfer-basic/chaincode-java"
println " network.sh deployCCAAS -ccn basict -ccp ../asset-transfer-basic/chaincode-typescript -ccaasdocker false"
else
println "Usage: "
println " network.sh <Mode> [Flags]"