Skip to content

Commit

Permalink
Adding examples of CCAAS and support into the test-network
Browse files Browse the repository at this point in the history
- 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 <[email protected]>
  • Loading branch information
mbwhite committed Dec 14, 2021
1 parent 72559df commit b3f69eb
Show file tree
Hide file tree
Showing 12 changed files with 677 additions and 20 deletions.
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# Vim file artifacts
.*.sw*
# installed platform-specific binaries
/bin
bin
/config
.DS_Store
.project
Expand Down
66 changes: 66 additions & 0 deletions TEMP_CCAAS_TUTORIAL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
# 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 where explicitly known to the peer including how they should be built and started.

As a result this makes it very hard to deploy into K8S style environments, or to run in any form of debug mode. Plus the code is being rebuilt by the peer so production deployments can have 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 stills 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)

## Prereqs

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 isn't quite as easy to use.

- ... clone samples repo etc.. TBC


## Start the test network

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

```bash
# from the fabric-samples repo
./test-network/monitordocker.sh
```

All the containers on the `fabric-test` network will be monitored; remember to terminate this as it starts a docker image on the `fabric-test` network.


In the 'Fabric Network' window, start the test network

```bash
cd test-network
./network.sh up createChannel
```

Once this has started, you can run the 'Chaincode-as-a-service'. This will do the following.

- Build a docker container of the contract, in this example `/asset-transfer-basic/chaincode-typescript`
- Install, Approve and Commit a chaincode definition. This is unchanged, but the chaincode package contains connection inforamtion, not code
- Start the docker container containing the contract

```
./network.sh deployCCAAS -ccn basic -ccp ../asset-transfer-basic/chaincode-typescript -cport 9999
```

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.

To test things are working you can invoke the 'Contract Metadata' function.

```bash
# set the environment variables to work as org1
export $(./setOrgEnv.sh | xargs)

# invoke the function
peer chaincode query -C mychannel -n basic -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.


## Debug and standalone running

TBC
23 changes: 23 additions & 0 deletions asset-transfer-basic/chaincode-java/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# 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-slim
# copy only the artifacts we need from the first stage and discard the rest
COPY --from=GRADLE_BUILD /home/gradle/build/libs/chaincode.jar /chaincode.jar


ENV PORT $CC_SERVER_PORT
EXPOSE $CC_SERVER_PORT

# set the startup command to execute the jar
CMD ["java", "-jar", "/chaincode.jar"]
4 changes: 2 additions & 2 deletions asset-transfer-basic/chaincode-java/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -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.+'
Expand Down
34 changes: 34 additions & 0 deletions asset-transfer-basic/chaincode-typescript/Dockerfile
Original file line number Diff line number Diff line change
@@ -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" ]
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash
#
# SPDX-License-Identifier: Apache-2.0
#
set -euo pipefail
: ${CORE_PEER_TLS_ENABLED:="false"}

if [ "${CORE_PEER_TLS_ENABLED,,}" = "true" ]; then
npm run start:server
else
npm run start:server-nontls
fi
14 changes: 9 additions & 5 deletions asset-transfer-basic/chaincode-typescript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,22 @@
"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": "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": {
Expand Down
2 changes: 2 additions & 0 deletions test-network/docker/docker-compose-test-net.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ 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"}
volumes:
- ${DOCKER_SOCK}:/host/var/run/docker.sock
- ../organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/fabric/msp
Expand Down Expand Up @@ -126,6 +127,7 @@ 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"}
volumes:
- ${DOCKER_SOCK}:/host/var/run/docker.sock
- ../organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/msp:/etc/hyperledger/fabric/msp
Expand Down
33 changes: 33 additions & 0 deletions test-network/monitordocker.sh
Original file line number Diff line number Diff line change
@@ -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
44 changes: 32 additions & 12 deletions test-network/network.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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 $CC_SERVER_PORT $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() {
Expand All @@ -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 prune -f
#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
Expand Down Expand Up @@ -331,6 +342,10 @@ COMPOSE_FILE_ORG3=addOrg3/docker/docker-compose-org3.yaml
#
# chaincode language defaults to "NA"
CC_SRC_LANGUAGE="NA"
# default port to 9999
CC_SERVER_PORT=9999
# default to running the docker commands for the CCAAS
CCAAS_DOCKER_RUN=true
# Chaincode version
CC_VERSION="1.0"
# Chaincode definition sequence
Expand Down Expand Up @@ -422,6 +437,14 @@ while [[ $# -ge 1 ]] ; do
CC_INIT_FCN="$2"
shift
;;
-cport )
CC_SERVER_PORT="$2"
shift
;;
-cdr )
CC_DOCKER_RUN="$2"
shift
;;
-verbose )
VERBOSE=true
shift
Expand All @@ -445,29 +468,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}'"
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
elif [ "$MODE" == "deployCCAAS" ]; then
infoln "deploying chaincode-as-a-service on channel '${CHANNEL_NAME}'"
deployCCAAS
else
printHelp
exit 1
fi

Loading

0 comments on commit b3f69eb

Please sign in to comment.