From ccc1045468cae12ee201a862cf47a83b18d8ea68 Mon Sep 17 00:00:00 2001 From: jandammans Date: Tue, 26 Jul 2022 13:18:17 +0200 Subject: [PATCH] Basic working version --- chaincode/fabcar/typescript/src/fabcar.ts | 134 ++------ chaincode/fabcar/typescript/src/index.ts | 3 +- chaincode/fabcar/typescript/src/ruleset.ts | 4 + chaincode/fabcar/typescript/src/validation.ts | 8 + fabcar/startFabric.sh | 56 +--- fabcar/typescript/src/enrollAdmin.ts | 2 +- fabcar/typescript/src/getValidationById.ts | 50 +++ fabcar/typescript/src/registerUser.ts | 12 +- install-fabric.sh | 306 ++++++++++++++++++ 9 files changed, 410 insertions(+), 165 deletions(-) create mode 100644 chaincode/fabcar/typescript/src/ruleset.ts create mode 100644 chaincode/fabcar/typescript/src/validation.ts create mode 100644 fabcar/typescript/src/getValidationById.ts create mode 100755 install-fabric.sh diff --git a/chaincode/fabcar/typescript/src/fabcar.ts b/chaincode/fabcar/typescript/src/fabcar.ts index 597da7e2..29ca6495 100644 --- a/chaincode/fabcar/typescript/src/fabcar.ts +++ b/chaincode/fabcar/typescript/src/fabcar.ts @@ -4,110 +4,44 @@ import { Context, Contract } from 'fabric-contract-api'; import { Car } from './car'; +import {Ruleset} from './ruleset'; +import {Validation} from './validation'; export class FabCar extends Contract { - public async initLedger(ctx: Context) { - console.info('============= START : Initialize Ledger ==========='); - const cars: Car[] = [ + public currentContractNumber = 0; + public async validateAge(ctx: Context, age: string) { + const rulesets: Ruleset[] = [ { - color: 'blue', - make: 'Toyota', - model: 'Prius', - owner: 'Tomoko', + minimumAge: 16, + name: 'First ruleset', }, { - color: 'red', - make: 'Ford', - model: 'Mustang', - owner: 'Brad', - }, - { - color: 'green', - make: 'Hyundai', - model: 'Tucson', - owner: 'Jin Soo', - }, - { - color: 'yellow', - make: 'Volkswagen', - model: 'Passat', - owner: 'Max', - }, - { - color: 'black', - make: 'Tesla', - model: 'S', - owner: 'Adriana', - }, - { - color: 'purple', - make: 'Peugeot', - model: '205', - owner: 'Michel', - }, - { - color: 'white', - make: 'Chery', - model: 'S22L', - owner: 'Aarav', - }, - { - color: 'violet', - make: 'Fiat', - model: 'Punto', - owner: 'Pari', - }, - { - color: 'indigo', - make: 'Tata', - model: 'Nano', - owner: 'Valeria', - }, - { - color: 'brown', - make: 'Holden', - model: 'Barina', - owner: 'Shotaro', + minimumAge: 18, + name: 'Second ruleset', }, ]; + const validation: Validation = new Validation(); + validation.id = this.getNewId(); + const minimumAge: number = Math.max(rulesets[0].minimumAge, rulesets[1].minimumAge); + const ageToValidate = Number(age); + // Validate age + validation.isValid = (minimumAge <= ageToValidate); - for (let i = 0; i < cars.length; i++) { - cars[i].docType = 'car'; - await ctx.stub.putState('CAR' + i, Buffer.from(JSON.stringify(cars[i]))); - console.info('Added <--> ', cars[i]); - } + await ctx.stub.putState('VALIDATION' + validation.id, Buffer.from(JSON.stringify(validation.toString()))); + console.log('Added <--> ', validation); + + } + public async initLedger(ctx: Context) { + console.log('============= START : Initialize Ledger ==========='); console.info('============= END : Initialize Ledger ==========='); } - public async queryCar(ctx: Context, carNumber: string): Promise { - const carAsBytes = await ctx.stub.getState(carNumber); // get the car from chaincode state - if (!carAsBytes || carAsBytes.length === 0) { - throw new Error(`${carNumber} does not exist`); - } - console.log(carAsBytes.toString()); - return carAsBytes.toString(); - } - - public async createCar(ctx: Context, carNumber: string, make: string, model: string, color: string, owner: string) { - console.info('============= START : Create Car ==========='); - - const car: Car = { - color, - docType: 'car', - make, - model, - owner, - }; - - await ctx.stub.putState(carNumber, Buffer.from(JSON.stringify(car))); - console.info('============= END : Create Car ==========='); - } - - public async queryAllCars(ctx: Context): Promise { + public async queryAllValidations(ctx: Context): Promise { const startKey = ''; const endKey = ''; const allResults = []; + for await (const {key, value} of ctx.stub.getStateByRange(startKey, endKey)) { const strValue = Buffer.from(value).toString('utf8'); let record; @@ -122,19 +56,17 @@ export class FabCar extends Contract { console.info(allResults); return JSON.stringify(allResults); } - - public async changeCarOwner(ctx: Context, carNumber: string, newOwner: string) { - console.info('============= START : changeCarOwner ==========='); - - const carAsBytes = await ctx.stub.getState(carNumber); // get the car from chaincode state - if (!carAsBytes || carAsBytes.length === 0) { - throw new Error(`${carNumber} does not exist`); + public async getValidationById(ctx: Context, validationId: string): Promise { + const validationrAsBytes = await ctx.stub.getState(validationId); // get the validation from chaincode state + if (!validationrAsBytes || validationrAsBytes.length === 0) { + throw new Error(`${validationId} does not exist`); } - const car: Car = JSON.parse(carAsBytes.toString()); - car.owner = newOwner; - - await ctx.stub.putState(carNumber, Buffer.from(JSON.stringify(car))); - console.info('============= END : changeCarOwner ==========='); + console.log(validationrAsBytes.toString()); + return validationrAsBytes.toString(); + } + private getNewId(): number { + this.currentContractNumber++; + return this.currentContractNumber; } } diff --git a/chaincode/fabcar/typescript/src/index.ts b/chaincode/fabcar/typescript/src/index.ts index c0a2fcf6..b89157d2 100644 --- a/chaincode/fabcar/typescript/src/index.ts +++ b/chaincode/fabcar/typescript/src/index.ts @@ -2,7 +2,6 @@ * SPDX-License-Identifier: Apache-2.0 */ -import { FabCar } from './fabcar'; -export { FabCar } from './fabcar'; +import {FabCar} from './fabcar'; export const contracts: any[] = [ FabCar ]; diff --git a/chaincode/fabcar/typescript/src/ruleset.ts b/chaincode/fabcar/typescript/src/ruleset.ts new file mode 100644 index 00000000..da7fda55 --- /dev/null +++ b/chaincode/fabcar/typescript/src/ruleset.ts @@ -0,0 +1,4 @@ +export class Ruleset { + public minimumAge: number; + public name: string; +} diff --git a/chaincode/fabcar/typescript/src/validation.ts b/chaincode/fabcar/typescript/src/validation.ts new file mode 100644 index 00000000..e18da047 --- /dev/null +++ b/chaincode/fabcar/typescript/src/validation.ts @@ -0,0 +1,8 @@ +export class Validation { + public executeDate: Date = new Date(); + public id: number; + public isValid: boolean; + public toString(): string { + return '{id: ' + this.id + '; executeDate: ' + this.executeDate + '; isValid: ' + this.isValid + '}' ; + } +} diff --git a/fabcar/startFabric.sh b/fabcar/startFabric.sh index 8ce18cb3..c6742ba4 100755 --- a/fabcar/startFabric.sh +++ b/fabcar/startFabric.sh @@ -10,7 +10,7 @@ set -e # don't rewrite paths for Windows Git Bash users export MSYS_NO_PATHCONV=1 starttime=$(date +%s) -CC_SRC_LANGUAGE=${1:-"go"} +CC_SRC_LANGUAGE=${1:-"typescript"} CC_SRC_LANGUAGE=`echo "$CC_SRC_LANGUAGE" | tr [:upper:] [:lower:]` if [ "$CC_SRC_LANGUAGE" = "go" -o "$CC_SRC_LANGUAGE" = "golang" ] ; then @@ -45,30 +45,6 @@ cat <&2 + echo "$1" >&2 + exit "${_ret}" +} + + +begins_with_short_option() +{ + local first_option all_short_options='fc' + first_option="${1:0:1}" + test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0 +} + + + +print_help() +{ + printf 'Usage: %s [-f|--fabric-version ] [-c|--ca-version ] [] ... [] ...\n' "$0" + printf '\t%s\n' " Component to install, one or more of docker | binary | samples | podman First letter of component also accepted; If none specified docker | binary | samples is assumed" + printf '\t%s\n' "-f, --fabric-version: FabricVersion (default: '2.4.4')" + printf '\t%s\n' "-c, --ca-version: Fabric CA Version (default: '1.5.5')" +} + + +parse_commandline() +{ + _positionals_count=0 + while test $# -gt 0 + do + _key="$1" + case "$_key" in + -f|--fabric-version) + test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 + _arg_fabric_version="$2" + shift + ;; + --fabric-version=*) + _arg_fabric_version="${_key##--fabric-version=}" + ;; + -f*) + _arg_fabric_version="${_key##-f}" + ;; + -c|--ca-version) + test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 + _arg_ca_version="$2" + shift + ;; + -h|--help) + print_help + exit 0 + ;; + -h*) + print_help + exit 0 + ;; + --ca-version=*) + _arg_ca_version="${_key##--ca-version=}" + ;; + -c*) + _arg_ca_version="${_key##-c}" + ;; + *) + _last_positional="$1" + _positionals+=("$_last_positional") + _positionals_count=$((_positionals_count + 1)) + ;; + esac + shift + done +} + + +handle_passed_args_count() +{ + local _required_args_string="'comp'" + # test "${_positionals_count}" -ge 1 || _PRINT_HELP=yes die "FATAL ERROR: Not enough positional arguments - we require at least 1 (namely: $_required_args_string), but got only ${_positionals_count}." 1 +} + + +assign_positional_args() +{ + local _positional_name _shift_for=$1 + _positional_names="_arg_comp " + _our_args=$((${#_positionals[@]} - 1)) + for ((ii = 0; ii < _our_args; ii++)) + do + _positional_names="$_positional_names _arg_comp[$((ii + 1))]" + done + + shift "$_shift_for" + for _positional_name in ${_positional_names} + do + test $# -gt 0 || break + eval "$_positional_name=\${1}" || die "Error during argument parsing, possibly an Argbash bug." 1 + shift + done +} + +# End of ARGBASH code + +# dockerPull() pulls docker images from fabric and chaincode repositories +# note, if a docker image doesn't exist for a requested release, it will simply +# be skipped, since this script doesn't terminate upon errors. + +singleImagePull() { + #three_digit_image_tag is passed in, e.g. "1.4.7" + three_digit_image_tag=$1 + shift + #two_digit_image_tag is derived, e.g. "1.4", especially useful as a local tag for two digit references to most recent baseos, ccenv, javaenv, nodeenv patch releases + two_digit_image_tag=$(echo "$three_digit_image_tag" | cut -d'.' -f1,2) + while [[ $# -gt 0 ]] + do + image_name="$1" + echo "====> hyperledger/fabric-$image_name:$three_digit_image_tag" + ${CONTAINER_CLI} pull "hyperledger/fabric-$image_name:$three_digit_image_tag" + ${CONTAINER_CLI} tag "hyperledger/fabric-$image_name:$three_digit_image_tag" "hyperledger/fabric-$image_name" + ${CONTAINER_CLI} tag "hyperledger/fabric-$image_name:$three_digit_image_tag" "hyperledger/fabric-$image_name:$two_digit_image_tag" + shift + done +} + +cloneSamplesRepo() { + # clone (if needed) hyperledger/fabric-samples and checkout corresponding + # version to the binaries and docker images to be downloaded + if [ -d test-network ]; then + # if we are in the fabric-samples repo, checkout corresponding version + echo "==> Already in fabric-samples repo" + elif [ -d fabric-samples ]; then + # if fabric-samples repo already cloned and in current directory, + # cd fabric-samples + echo "===> Changing directory to fabric-samples" + cd fabric-samples + else + echo "===> Cloning hyperledger/fabric-samples repo" + git clone -b main https://github.com/hyperledger/fabric-samples.git && cd fabric-samples + fi + + if GIT_DIR=.git git rev-parse v${VERSION} >/dev/null 2>&1; then + echo "===> Checking out v${VERSION} of hyperledger/fabric-samples" + git checkout -q v${VERSION} + else + echo "fabric-samples v${VERSION} does not exist, defaulting to main. fabric-samples main branch is intended to work with recent versions of fabric." + git checkout -q main + fi +} + +# This will download the .tar.gz +download() { + local BINARY_FILE=$1 + local URL=$2 + local DEST_DIR=$(pwd) + echo "===> Downloading: " "${URL}" + if [ -d fabric-samples ]; then + DEST_DIR="fabric-samples" + fi + echo "===> Will unpack to: ${DEST_DIR}" + curl -L --retry 5 --retry-delay 3 "${URL}" | tar xz -C ${DEST_DIR}|| rc=$? + if [ -n "$rc" ]; then + echo "==> There was an error downloading the binary file." + return 22 + else + echo "==> Done." + fi +} + +pullBinaries() { + echo "===> Downloading version ${FABRIC_TAG} platform specific fabric binaries" + download "${BINARY_FILE}" "https://github.com/hyperledger/fabric/releases/download/v${VERSION}/${BINARY_FILE}" + if [ $? -eq 22 ]; then + echo + echo "------> ${FABRIC_TAG} platform specific fabric binary is not available to download <----" + echo + exit + fi + + echo "===> Downloading version ${CA_TAG} platform specific fabric-ca-client binary" + download "${CA_BINARY_FILE}" "https://github.com/hyperledger/fabric-ca/releases/download/v${CA_VERSION}/${CA_BINARY_FILE}" + if [ $? -eq 22 ]; then + echo + echo "------> ${CA_TAG} fabric-ca-client binary is not available to download (Available from 1.1.0-rc1) <----" + echo + exit + fi +} + +pullImages() { + command -v ${CONTAINER_CLI} >& /dev/null + NODOCKER=$? + if [ "${NODOCKER}" == 0 ]; then + FABRIC_IMAGES=(peer orderer ccenv tools) + case "$VERSION" in + 2.*) + FABRIC_IMAGES+=(baseos) + shift + ;; + esac + + echo "FABRIC_IMAGES:" "${FABRIC_IMAGES[@]}" + echo "===> Pulling fabric Images" + singleImagePull "${FABRIC_TAG}" "${FABRIC_IMAGES[@]}" + echo "===> Pulling fabric ca Image" + CA_IMAGE=(ca) + singleImagePull "${CA_TAG}" "${CA_IMAGE[@]}" + echo "===> List out hyperledger images" + ${CONTAINER_CLI} images | grep hyperledger + else + echo "=========================================================" + echo "${CONTAINER_CLI} not installed, bypassing download of Fabric images" + echo "=========================================================" + fi +} + + +# Main code starts here +parse_commandline "$@" +handle_passed_args_count +assign_positional_args 1 "${_positionals[@]}" + + +VERSION=$_arg_fabric_version +CA_VERSION=$_arg_ca_version + +# prior to 1.2.0 architecture was determined by uname -m +if [[ $VERSION =~ ^1\.[0-1]\.* ]]; then + export FABRIC_TAG=${MARCH}-${VERSION} + export CA_TAG=${MARCH}-${CA_VERSION} +else + # starting with 1.2.0, multi-arch images will be default + : "${CA_TAG:="$CA_VERSION"}" + : "${FABRIC_TAG:="$VERSION"}" +fi + +BINARY_FILE=hyperledger-fabric-${ARCH}-${VERSION}.tar.gz +CA_BINARY_FILE=hyperledger-fabric-ca-${ARCH}-${CA_VERSION}.tar.gz + +# if nothing has been specified, assume everything +if [[ ${_arg_comp[@]} =~ ^$ ]]; then + echo "No options selected: Getting all samples, binaries, and docker images" + echo "Abort now if not the intention" + sleep 3 # just to give a chance to abort if this wasn't intended + _arg_comp=('samples','binary','docker') +fi + +# Process samples first then the binaries. So if the fabric-samples dir is present +# the binaries will go there +if [[ "${_arg_comp[@]}" =~ (^| |,)s(amples)? ]]; then + echo + echo "Clone hyperledger/fabric-samples repo" + echo + cloneSamplesRepo +fi + +if [[ "${_arg_comp[@]}" =~ (^| |,)b(inary)? ]]; then + echo + echo "Pull Hyperledger Fabric binaries" + echo + pullBinaries +fi + +if [[ "${_arg_comp[@]}" =~ (^| |,)p(odman)? ]]; then + echo + echo "Pull Hyperledger Fabric podman images" + echo + CONTAINER_CLI=podman + pullImages +fi + +if [[ "${_arg_comp[@]}" =~ (^| |,)d(ocker)? ]]; then + echo + echo "Pull Hyperledger Fabric docker images" + echo + CONTAINER_CLI=docker + pullImages +fi