diff --git a/.github/workflows/scan.yaml b/.github/workflows/scan.yaml index 2c4e4231..3f11f287 100644 --- a/.github/workflows/scan.yaml +++ b/.github/workflows/scan.yaml @@ -25,7 +25,7 @@ jobs: ref: ${{ inputs.ref }} - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 with: - node-version: 18 + node-version: "lts/*" - name: Install run: node common/scripts/install-run-rush.js install - name: Build packages diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index 910369c8..9d25d6e9 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -42,7 +42,7 @@ jobs: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 with: - node-version: "18.x" + node-version: "20.x" - name: Install/Rebuild/UnitTest run: | set -xev @@ -80,7 +80,7 @@ jobs: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - uses: actions/setup-node@2028fbc5c25fe9cf00d9f06a71cc4710d4507903 # v6.0.0 with: - node-version: "18.x" + node-version: "20.x" - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: name: nodeenv-docker-image diff --git a/COMPATIBILITY.md b/COMPATIBILITY.md index 1a7f2402..335c1d8d 100644 --- a/COMPATIBILITY.md +++ b/COMPATIBILITY.md @@ -12,7 +12,8 @@ This table shows the summary of the compatibility of the Node chaincode packages | v2.2 | 12 | 12 | amd64 | | v2.5.0 - v2.5.4 | 18 | 18 | amd64, arm64 | | v2.5.5 - v2.5.7 | 18 | 20 | amd64, arm64 | -| v2.5.8+ | 18 | 22 | amd64, arm64 | +| v2.5.8 | 18 | 22 | amd64, arm64 | +| v2.5.9+ | 20 | 24 | amd64, arm64 | The Node runtime provided by the chaincode Docker image determines the maximum Node version (and features) that smart contract code can exploit when using the default Node chaincode container. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 13762e1b..191c64b9 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -22,52 +22,47 @@ The following [Rush categories](https://rushjs.io/pages/maintainer/add_to_repo/) ### Pre-requisites -* node v18 => recommend to use [nvm](https://github.com/nvm-sh/nvm) -* rush => `npm install -g @microsoft/rush` +- node 20+ => recommend to use [nvm](https://github.com/nvm-sh/nvm) +- rush => `npm install -g @microsoft/rush` > As an alternative to installing rush on your system, you can also have node install it for executing single commands similar to what is done in CI, for example from the `libraries/fabric-shim` directory you could add or update a dependency by running `node ../../common/scripts/install-run-rush.js add --package @grpc/grpc-js@latest` > Note that npm v6 has some bugs that mean adding new dependencies etc are not properly picked up. Longer term we should consider moving to yarn or pnpm. However in practice this isn't a serious problem and has been possible to be worked around by issuing `rm ./common/config/rush/npm-shrinkwrap.json` and then `rush update` -The fv and e2e tests require a set of docker images of Fabric Peers, Orderers and CAs. To ensure you have the correct images ensure these have been dowloaded and tagged. `rush edge-docker` will do this for you. - -They also need to have the `nodeenv` image present - this is build as part of the `rush rebuild` so please ensure this has been run first. It is advisable to clean up the docker containers and images between test runs to avoid any odd behaviour. Commands to help do this are below. +They also need to have the `nodeenv` image present - this is build as part of the `rush rebuild` so please ensure this has been run first. It is advisable to clean up the docker containers and images between test runs to avoid any odd behaviour. Commands to help do this are below. ## Using the repo -* Clone the repo, and ensure you are using node v18, and have rush installed -* `rush update` is needed to ensure everything is correctly linked and updated. - - For example, after updating dependencies in `libraries/fabric-shim/package.json` run `rush update` which will delegate to `pnpm` to update the appropriate project files. - - Note - you could also use `rush add` to have rush manage the `package.json` updates. -* `rush edge-docker` will pull down and tag the very latest docker images for the peers, orderes etc to test against +- Clone the repo, and ensure you are using node v18, and have rush installed +- `rush update` is needed to ensure everything is correctly linked and updated. + - For example, after updating dependencies in `libraries/fabric-shim/package.json` run `rush update` which will delegate to `pnpm` to update the appropriate project files. + - Note - you could also use `rush add` to have rush manage the `package.json` updates. At this point the repo is fully ready for use and running tests, etc. A full sequence of build-test that is equivalent to the CI pipeline is -* `rush rebuild` will run the linting, and unit tests across the codebase, as well as building the docker images, and jsdoc API docs -* `rush start-verdaccio` & `rush stop-verdaccio` will start/stop verdaccio (used for local hosting of NPM modules) -* `rush start-fabric` & `rush stop-fabric` will start/stop the test fabric ready for running FV tests -* `rush test:fv` will run the fv tests, ensure that both the fabric and verdaccio have already been started -* `rush test:e2e` to run e2e tests across the repos +- `rush rebuild` will run the linting, and unit tests across the codebase, as well as building the docker images, and jsdoc API docs +- `rush start-verdaccio` & `rush stop-verdaccio` will start/stop verdaccio (used for local hosting of NPM modules) +- `rush start-fabric` & `rush stop-fabric` will start/stop the test fabric ready for running FV tests +- `rush test:fv` will run the fv tests, ensure that both the fabric and verdaccio have already been started +- `rush test:e2e` to run e2e tests across the repos For more specific purposes during development the following are useful: -* `rush publish --include-all --pack --release-folder ./tarballs --publish` -If you want to get a set of `.tar.gz` files of the node modules to use for local testing this command will put them into the `tarballs` directory -* `rush rebuild --to fvtests` to run the unit tests for the core modules, but not the docker or jsdoc -* `rush rebuild --to fabric-contract-api` to build, lint and run just the `fabric-contract-api` -* `rush logs` will show the location of all the log files +- `rush publish --include-all --pack --release-folder ./tarballs --publish` + If you want to get a set of `.tar.gz` files of the node modules to use for local testing this command will put them into the `tarballs` directory +- `rush rebuild --to fvtests` to run the unit tests for the core modules, but not the docker or jsdoc +- `rush rebuild --to fabric-contract-api` to build, lint and run just the `fabric-contract-api` +- `rush logs` will show the location of all the log files To clean up docker -* `docker kill $(docker ps -q) && docker rm $(docker ps -aq)` will remove the running containers -* `docker rmi $(docker images 'dev-*' -q) --force` will remove the images for the chaincode containers +- `docker kill $(docker ps -q) && docker rm $(docker ps -aq)` will remove the running containers +- `docker rmi $(docker images 'dev-*' -q) --force` will remove the images for the chaincode containers ## Mechanics of Contributing The codebase is maintained in [github](https://github.com/hyperledger/fabric-chaincode-node), with a CI pipeline run with [Github Actions](https://github.com/hyperledger/fabric-chaincode-node/actions). Issues are handled in [Github Issues](https://github.com/hyperledger/fabric-chaincode-node/issues). - - ## Code of Conduct Guidelines See our [Code of Conduct Guidelines](https://github.com/hyperledger/fabric-chaincode-node/blob/main/CODE_OF_CONDUCT.md). diff --git a/TUTORIAL.md b/TUTORIAL.md index 1a49de07..bf2fa011 100644 --- a/TUTORIAL.md +++ b/TUTORIAL.md @@ -15,7 +15,7 @@ The dependencies of `fabric-contract-api` and `fabric-shim` will be required. "name": "chaincode", "description": "My first exciting chaincode implemented in node.js", "engines": { - "node": ">=18" + "node": ">=20" }, "scripts": { "test": "mocha....." @@ -33,6 +33,7 @@ The dependencies of `fabric-contract-api` and `fabric-shim` will be required. } ``` + Remember to add in any additional business logic, and testing libraries needed Adding `fabric-shim` as a dependency, gives a command `fabric-chaincode-node` that is the script to run for `npm start`. @@ -45,7 +46,6 @@ Adding `fabric-shim` as a dependency, gives a command `fabric-chaincode-node` th }, ``` - ### 2: How is chaincode deployed? Chaincode is deployed by the peer in response to issuing a number of (usually CLI) commands. For node.js chaincode the location of the chaincode npm project is required (the directory that the package.json is in). This does not need to be an installed project, but has to have all the code, and the package.json. @@ -54,7 +54,7 @@ A docker image is built for this chaincode, the package.json and code copied in. After the install there is a 'bootstrap' process that starts the chaincode up (more details later). The constructors of the exported Contracts will be run at this point; these constructors are for setting the name and optional setup of the 'error/monitoring functions', (again more later). This instance of the contract will existing whilst this chaincode docker image is up. -When chaincode is instantiated or updated, the `init()` function in the chaincode is called. As with the `invoke()` call from the client, a fn name and parameters can be passed. Remember therefore to have specific functions to call on `init()` and `update()` in order to do any data initialisation or migration that might be needed. These two functions have been abstracted away to focus on specific function implementations. +When chaincode is instantiated or updated, the `init()` function in the chaincode is called. As with the `invoke()` call from the client, a fn name and parameters can be passed. Remember therefore to have specific functions to call on `init()` and `update()` in order to do any data initialisation or migration that might be needed. These two functions have been abstracted away to focus on specific function implementations. It is strongly recommended to use the npm shrinkwrap mechanism so the versions of the modules that are used are fixed. @@ -77,7 +77,7 @@ module.exports.contracts = [UpdateValues, RemoveValues]; ``` This exports two classes that together form the Contract. There can be other code that within the model that is used in a support role. -*Note that the 'contracts' word is mandatory.* +_Note that the 'contracts' word is mandatory._ ### 4: What do these classes need to contain? @@ -159,7 +159,6 @@ Then you can invoke the chaincode via this command. $ peer chaincode invoke --orderer localhost:7050 --channelID mychannel -c '{"Args":["UpdateValuesContract:getAssetValue"]}' -n mycontract4 ``` - ## Additional support provided by the SmartContract class In case you ask for a function to be executed, it could be that this doesn't exist. @@ -167,7 +166,6 @@ If so, you can provide you own function to be executed, the default is to throw For example - ``` /** * Sets a name so that the functions in this particular class can @@ -206,14 +204,14 @@ async aroundTransaction(ctx, fn, parameters) { ### Structure of the Transaction Context -In Fabric, there is a *stub* api that provides chaincode with functionality. +In Fabric, there is a _stub_ api that provides chaincode with functionality. No functionality has been removed, but a new approach to providing abstractions on this to facilitate programming. -*user additions*: additional properties can be added to the object to support for example common handling of the data serialization. +_user additions_: additional properties can be added to the object to support for example common handling of the data serialization. The context object contains -- `ctx.stub` the same stub instance as in earlier versions for compatibility +- `ctx.stub` the same stub instance as in earlier versions for compatibility - `ctx.identity` and instance of the Client Identity object You are at liberty to create a subclass of the Context to provide additional functions, or per-transaction context storage. For example @@ -249,29 +247,29 @@ class ScenarioContext extends Context { Definitions as per https://www.ietf.org/rfc/rfc2119.txt -- All the functions that are present in the prototype of a class that extends *Contract* will be invokable -- The exports from the node module *MUST* include *contracts* that is an array of constructors (1 or more) -- Each class *MAY* call in it's constructor pass a name. This is prefixed to each of the function names by an _ (underscore) -- Each class *MAY* define functions that are executed before and functions that are executed after the invoked function. +- All the functions that are present in the prototype of a class that extends _Contract_ will be invokable +- The exports from the node module _MUST_ include _contracts_ that is an array of constructors (1 or more) +- Each class _MAY_ call in it's constructor pass a name. This is prefixed to each of the function names by an \_ (underscore) +- Each class _MAY_ define functions that are executed before and functions that are executed after the invoked function. - These are part of the same fabric transaction - They are scoped per name -- Each class *MAY* define a function that would be executed if a matching function name does not exist; otherwise a 'no function exists' error will be thrown +- Each class _MAY_ define a function that would be executed if a matching function name does not exist; otherwise a 'no function exists' error will be thrown - If too many parameters are passed, they will be discarded - If too few parameters are passed, the remainder will be set to undefined - - as per node.js language standard + - as per node.js language standard - Having duplicate function names in a single class is an error - Any function that is dynamically added will not be registered as an invokable function -- There is no specific function that is invoked per Fabric's *init* chaincode spi. The instantiate flow can pass function name and parameters; therefore consider -a dedicated function that will be called for new chaincode deployments, and for upgrade deployments. +- There is no specific function that is invoked per Fabric's _init_ chaincode spi. The instantiate flow can pass function name and parameters; therefore consider + a dedicated function that will be called for new chaincode deployments, and for upgrade deployments. ## Restrictions on programming in side a Contract function Hyperledger Fabric's consensus algorithm permits the ability to use general purpose languages; rather than a more restrictive language. But the following restrictions apply - Functions should not create random variables, or use any function whose return values are functions of the current time or location of execution - - i.e. the function will be executed in another context (i.e. peer process). This could potentially be in a different time zone in a different locale. + - i.e. the function will be executed in another context (i.e. peer process). This could potentially be in a different time zone in a different locale. - Functions should be aware that they may read state, and write state. But they are producing a set of changes that will be applied to the state. The implication is that updates to the state -may not be read back. + may not be read back. ``` let v1 = getState("key"); diff --git a/apis/fabric-contract-api/package.json b/apis/fabric-contract-api/package.json index 4768ff7c..b9f3cfc1 100644 --- a/apis/fabric-contract-api/package.json +++ b/apis/fabric-contract-api/package.json @@ -22,7 +22,7 @@ "Fabric Shim" ], "engines": { - "node": ">=18" + "node": ">=20" }, "license": "Apache-2.0", "types": "./types/index.d.ts", @@ -70,6 +70,6 @@ "typescript": "~5.8.3", "typescript-eslint": "^8.46.0", "@eslint/js": "^9.37.0", - "@tsconfig/node18": "~18.2.4" + "@tsconfig/node20": "~20.1.6" } } diff --git a/apis/fabric-contract-api/tsconfig.json b/apis/fabric-contract-api/tsconfig.json index 5ca12efe..c40b79af 100644 --- a/apis/fabric-contract-api/tsconfig.json +++ b/apis/fabric-contract-api/tsconfig.json @@ -5,7 +5,7 @@ */ { "$schema": "https://json.schemastore.org/tsconfig", - "extends": "@tsconfig/node18/tsconfig.json", + "extends": "@tsconfig/node20/tsconfig.json", "compilerOptions": { "types": ["./types/"], "declaration": true, diff --git a/apis/fabric-shim-api/package.json b/apis/fabric-shim-api/package.json index 3aa0d8c2..03db5073 100644 --- a/apis/fabric-shim-api/package.json +++ b/apis/fabric-shim-api/package.json @@ -18,13 +18,14 @@ "Fabric Shim" ], "engines": { - "node": ">=18" + "node": ">=20" }, "types": "./types/index.d.ts", "license": "Apache-2.0", "devDependencies": { "@types/long": "^4.0.1", "eslint": "^9.37.0", - "@eslint/js": "^9.37.0" + "@eslint/js": "^9.37.0", + "@tsconfig/node20": "~20.1.6" } } diff --git a/apis/fabric-shim-api/tsconfig.json b/apis/fabric-shim-api/tsconfig.json index 1e383873..7994d8c9 100644 --- a/apis/fabric-shim-api/tsconfig.json +++ b/apis/fabric-shim-api/tsconfig.json @@ -4,22 +4,17 @@ * SPDX-License-Identifier: Apache-2.0 */ { - "compilerOptions": { - "types": ["./types/"], - "alwaysStrict": true, - "module": "commonjs", - "declaration": true, - "sourceMap": true, - "strict": true, - "target": "es2017", - "lib": [ - "esnext", - ] - }, - "files": [ - "types/index.d.ts" - ], - "exclude": [ - "node_modules/**/*" - ] + "$schema": "https://json.schemastore.org/tsconfig", + "extends": "@tsconfig/node20/tsconfig.json", + "compilerOptions": { + "types": ["./types/"], + "declaration": true, + "declarationMap": true, + "erasableSyntaxOnly": true, + "isolatedModules": true, + "sourceMap": true, + "strict": true + }, + "files": ["types/index.d.ts"], + "exclude": ["node_modules/**/*"] } diff --git a/common/config/rush/pnpm-lock.yaml b/common/config/rush/pnpm-lock.yaml index e68580fd..f45b7f3f 100644 --- a/common/config/rush/pnpm-lock.yaml +++ b/common/config/rush/pnpm-lock.yaml @@ -55,9 +55,9 @@ importers: '@sinonjs/referee-sinon': specifier: ~5.0.0 version: 5.0.0 - '@tsconfig/node18': - specifier: ~18.2.4 - version: 18.2.4 + '@tsconfig/node20': + specifier: ~20.1.6 + version: 20.1.6 '@types/chai': specifier: ^4.2.22 version: 4.3.20 @@ -482,7 +482,7 @@ packages: resolution: {integrity: sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==} '@rush-temp/fabric-contract-api@file:projects/fabric-contract-api.tgz': - resolution: {integrity: sha512-BJNPGVGLrkHnaqXVLjrBYXVMe7LFKu1o42pcp/wcfjDen172hUVTZqmYamkMdAqW1uj9ITAZ/e2map2/HbsOzg==, tarball: file:projects/fabric-contract-api.tgz} + resolution: {integrity: sha512-yxvb8RGA9irJ5lCSuJHRBTvNZBFEzZddOkIdbOh6ZmICGVXk1ubXvrLA1qzUZIdBuf0xXIvBJkZMfYyx7CjDvw==, tarball: file:projects/fabric-contract-api.tgz} version: 0.0.0 '@rush-temp/fabric-e2e-tests@file:projects/fabric-e2e-tests.tgz': @@ -490,7 +490,7 @@ packages: version: 0.0.0 '@rush-temp/fabric-ledger@file:projects/fabric-ledger.tgz': - resolution: {integrity: sha512-YpIIAI4u1Yl0JuBdl8vChZRvDRcP1ZdHMipFhB/8EJ0nRRhENi/UZTY0b0x4LjLJckncxqNBsiXUgDVn84ungw==, tarball: file:projects/fabric-ledger.tgz} + resolution: {integrity: sha512-mFP94YQbuucJ5RvA8Uhq7zHCFlfes5AbAKRtRDPWtsyhlyh5HrtaIgs4ejoslI17Eu2jiUG+zc27d0eGGO22iw==, tarball: file:projects/fabric-ledger.tgz} version: 0.0.0 '@rush-temp/fabric-nodeenv@file:projects/fabric-nodeenv.tgz': @@ -498,7 +498,7 @@ packages: version: 0.0.0 '@rush-temp/fabric-shim-api@file:projects/fabric-shim-api.tgz': - resolution: {integrity: sha512-HJT4lTrBR7eHQ+8UYEGxkgyH1VcF5UvR3IgP8IpI/aZI0Jx2VO3U/KIJ1a49wANhEXOd3/npi5v1TaqDMqnW7Q==, tarball: file:projects/fabric-shim-api.tgz} + resolution: {integrity: sha512-54FRZhX8+yFGI2JltDE1KPifnZyi7WrCTSK4fVcQ8WDtxlP1cS/Wap15O0OWZ1AMLCz4PTQ62NueeQTHdYoP4A==, tarball: file:projects/fabric-shim-api.tgz} version: 0.0.0 '@rush-temp/fabric-shim-docs@file:projects/fabric-shim-docs.tgz': @@ -506,7 +506,7 @@ packages: version: 0.0.0 '@rush-temp/fabric-shim@file:projects/fabric-shim.tgz': - resolution: {integrity: sha512-GAAsLorv5OsSoim7dW/5weY3DzoHsy3aFQ/1bEde2zjZ6yEDz6ZFob5cQInQqhk659FTWQuLEWzzYS6bJnZxuQ==, tarball: file:projects/fabric-shim.tgz} + resolution: {integrity: sha512-YQR0GMh+3eR5m4929n5bansCu3mSmTqFrAkigAnSd1B+Qg0zNA2k3tWUqUDHAhusv5Y3vi/DXgf0TZEO4JkNIw==, tarball: file:projects/fabric-shim.tgz} version: 0.0.0 '@rush-temp/fvtests@file:projects/fvtests.tgz': @@ -597,8 +597,8 @@ packages: '@tsconfig/node16@1.0.4': resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} - '@tsconfig/node18@18.2.4': - resolution: {integrity: sha512-5xxU8vVs9/FNcvm3gE07fPbn9tl6tqGGWA9tSlwsUEkBxtRnTsNmwrV8gasZ9F/EobaSv9+nu8AxUKccw77JpQ==} + '@tsconfig/node20@20.1.6': + resolution: {integrity: sha512-sz+Hqx9zwZDpZIV871WSbUzSqNIsXzghZydypnfgzPKLltVJfkINfUeTct31n/tTSa9ZE1ZOfKdRre1uHHquYQ==} '@types/chai-as-promised@7.1.8': resolution: {integrity: sha512-ThlRVIJhr69FLlh6IctTXFkmhtP3NpMZ2QGq69StYLyKZFp/HOp1VdKZj7RvfNWYYcJ1xlbLGLLWj1UvP5u/Gw==} @@ -4990,7 +4990,7 @@ snapshots: '@rush-temp/fabric-contract-api@file:projects/fabric-contract-api.tgz': dependencies: '@eslint/js': 9.38.0 - '@tsconfig/node18': 18.2.4 + '@tsconfig/node20': 20.1.6 ajv: 6.12.6 ajv-cli: 3.3.0 ajv-formats: 2.1.1(ajv@6.12.6) @@ -5030,7 +5030,7 @@ snapshots: dependencies: '@eslint/js': 9.38.0 '@rushstack/eslint-config': 0.5.8(eslint@9.38.0)(typescript@5.8.3) - '@tsconfig/node18': 18.2.4 + '@tsconfig/node20': 20.1.6 '@types/chai': 4.3.20 '@types/chai-as-promised': 7.1.8 '@types/mocha': 9.1.1 @@ -5064,6 +5064,7 @@ snapshots: '@rush-temp/fabric-shim-api@file:projects/fabric-shim-api.tgz': dependencies: '@eslint/js': 9.38.0 + '@tsconfig/node20': 20.1.6 '@types/long': 4.0.2 eslint: 9.38.0 transitivePeerDependencies: @@ -5082,7 +5083,7 @@ snapshots: '@fidm/x509': 1.2.1 '@grpc/grpc-js': 1.14.0 '@hyperledger/fabric-protos': 0.2.2 - '@tsconfig/node18': 18.2.4 + '@tsconfig/node20': 20.1.6 '@types/node': 18.19.130 ajv: 6.12.6 caniuse-lite: 1.0.30001751 @@ -5268,7 +5269,7 @@ snapshots: '@tsconfig/node16@1.0.4': {} - '@tsconfig/node18@18.2.4': {} + '@tsconfig/node20@20.1.6': {} '@types/chai-as-promised@7.1.8': dependencies: diff --git a/docker/fabric-nodeenv/Dockerfile b/docker/fabric-nodeenv/Dockerfile index dd323722..13513035 100644 --- a/docker/fabric-nodeenv/Dockerfile +++ b/docker/fabric-nodeenv/Dockerfile @@ -2,7 +2,7 @@ # # SPDX-License-Identifier: Apache-2.0 # -ARG NODE_IMAGE_TAG=22-alpine +ARG NODE_IMAGE_TAG=24-alpine FROM node:${NODE_IMAGE_TAG} RUN apk add --no-cache \ make \ diff --git a/docs/_jsdoc/tutorials/using-contractinterface.md b/docs/_jsdoc/tutorials/using-contractinterface.md index 4c9337a1..7d395fbd 100644 --- a/docs/_jsdoc/tutorials/using-contractinterface.md +++ b/docs/_jsdoc/tutorials/using-contractinterface.md @@ -1,5 +1,3 @@ - - This outlines the theory of the how the new node module works; with the fabric samples project you will find scenario-based approaches. ## Writing the chaincode @@ -15,7 +13,7 @@ The dependencies of `fabric-contract-api` and `fabric-shim` will be required. "name": "chaincode", "description": "My first exciting chaincode implemented in node.js", "engines": { - "node": ">=18" + "node": ">=20" }, "scripts": { "test":"mocha..... @@ -33,6 +31,7 @@ The dependencies of `fabric-contract-api` and `fabric-shim` will be required. } ``` + Remember to add in any additional business logic, and testing libraries needed Adding `fabric-shim` as a dependency, gives a command `fabric-chaincode-node` that is the script to run for `npm start`. @@ -45,7 +44,6 @@ Adding `fabric-shim` as a dependency, gives a command `fabric-chaincode-node` th }, ``` - ### 2: How is chaincode deployed? Chaincode is deployed by the peer in response to issuing a number of (usually CLI) commands. For node.js chaincode the location of the chaincode npm project is required (the directory that the package.json is in). This does not need to be an installed project, but has to have all the code, and the package.json. @@ -54,7 +52,7 @@ A docker image is built for this chaincode, the package.json and code copied in. After the install there is a 'bootstrap' process that starts the chaincode up (more details later). The constructors of the exported Contracts will be run at this point; these constructors are for setting the name and optional setup of the 'error/monitoring functions', (again more later). This instance of the contract will existing whilst this chaincode docker image is up. -When chaincode is instantiated or updated, the `init()` function is the chaincode is called. As with the `invoke()` call from the client, a fn name and parameters can be passed. Remember therefore to have specific functions to call on `init()` and `update()` in order to do any data initialisation or migration that might be needed. These two functions have been abstracted away to focus on specific function implementations. +When chaincode is instantiated or updated, the `init()` function is the chaincode is called. As with the `invoke()` call from the client, a fn name and parameters can be passed. Remember therefore to have specific functions to call on `init()` and `update()` in order to do any data initialisation or migration that might be needed. These two functions have been abstracted away to focus on specific function implementations. It is strongly recommended to use the npm shrinkwrap mechanism so the versions of the modules that are used are fixed. @@ -77,7 +75,7 @@ module.exports.contracts = [UpdateValues,RemoveValues]; ``` This exports two classes that together form the Contract. There can be other code that within the model that is used in a support role. -*Note that the 'contracts' word is mandatory.* +_Note that the 'contracts' word is mandatory._ ### 4: What do these classes need to contain? @@ -160,7 +158,6 @@ Then you can invoke the chaincode via this command. $ peer chaincode invoke --orderer localhost:7050 --channelID mychannel -c '{"Args":["UpdateValuesContract:getAssetValue"]}' -n mycontract4 ``` - ## Additional support provided by the SmartContract class In the case where you ask for a function to be executed, it could be the case that this doesn't exist. @@ -168,7 +165,6 @@ You can provide you own function to be executed in this case, the default is to For example - ``` /** * Sets a name so that the functions in this particular class can @@ -181,7 +177,7 @@ For example /** The function to invoke if something unkown comes in. * */ - async unknownTransaction(ctx){ + async unknownTransaction(ctx){ throw new Error('a custom error message') } @@ -208,14 +204,14 @@ For example ### Structure of the Transaction Context -In Fabric, there is a *stub* api that provides chaincode with functionality. +In Fabric, there is a _stub_ api that provides chaincode with functionality. No functionality has been removed, but a new approach to providing abstractions on this to facilitate programming. -*user additions*: additional properties can be added to the object to support for example common handling of the data serialization. +_user additions_: additional properties can be added to the object to support for example common handling of the data serialization. The context object contains -- `ctx.stub` the same stub instance as in earlier versions for compatibility +- `ctx.stub` the same stub instance as in earlier versions for compatibility - `ctx.identity` and instance of the Client Identity object You are at liberty to create a subclass of the Context to provide additional functions, or per-transaction context storage. For example @@ -252,29 +248,29 @@ class ScenarioContext extends Context{ Definitions as per https://www.ietf.org/rfc/rfc2119.txt -- All the functions that are present in the prototype of a class that extends *Contract* will be invokable -- The exports from the node module *MUST* include *contracts* that is an array of constructors (1 or more) -- Each class *MAY* call in it's constructor pass a name. This is prefixed to each of the function names by an _ (underscore) -- Each class *MAY* define functions that are executed before and functions that are executed after the invoked function. +- All the functions that are present in the prototype of a class that extends _Contract_ will be invokable +- The exports from the node module _MUST_ include _contracts_ that is an array of constructors (1 or more) +- Each class _MAY_ call in it's constructor pass a name. This is prefixed to each of the function names by an \_ (underscore) +- Each class _MAY_ define functions that are executed before and functions that are executed after the invoked function. - These are part of the same fabric transaction - They are scoped per name -- Each class *MAY* define a function that would be executed if a matching function name does not exist; otherwise a 'no function exists' error will be thrown +- Each class _MAY_ define a function that would be executed if a matching function name does not exist; otherwise a 'no function exists' error will be thrown - If too many parameters are passed, they will be discarded - If too few parameters are passed, then the remainder will be set to undefined - - as per node.js language standard + - as per node.js language standard - Duplicate function names in a single class is an error - Any function that is dynamically added will not be registered as an invokable function -- There are no specific function that is invoked per Fabric's *init* chaincode spi. The instantiate flow can pass function name and parameters; therefore consider -a dedicated function that will be called for new chaincode deployments, and for upgrade deployments. +- There are no specific function that is invoked per Fabric's _init_ chaincode spi. The instantiate flow can pass function name and parameters; therefore consider + a dedicated function that will be called for new chaincode deployments, and for upgrade deployments. ## Restrictions on programming in side a Contract function Hyperledger Fabric's consensus algorithm permits the ability to use general purpose languages; rather than a more restrictive language. But the following restrictions apply - Functions should not create random variables, or use any function whose return values are functions of the current time or location of execution - - i.e. the function will be executed in another context (i.e. peer process). This could potentially be in a different time zone in a different locale. + - i.e. the function will be executed in another context (i.e. peer process). This could potentially be in a different time zone in a different locale. - Functions should be away that they may read state, and write state. But they are producing a set of changes that will be applied to the state. The implication is that updates to the state -may not be read back. + may not be read back. ``` let v1 = getState("key") @@ -288,11 +284,3 @@ v2=="world" // is false, v2 is "hello" In any subsequent invocation, the value would be seen to be updated. Note that if you have use any Flux architecture implications such as Redux, the above restrictions will be familiar. - - - - - - - - diff --git a/libraries/fabric-ledger/package.json b/libraries/fabric-ledger/package.json index b2a24826..fc55ac86 100644 --- a/libraries/fabric-ledger/package.json +++ b/libraries/fabric-ledger/package.json @@ -23,7 +23,7 @@ "Fabric Ledger" ], "engines": { - "node": ">=18" + "node": ">=20" }, "license": "Apache-2.0", "nyc": { @@ -72,6 +72,6 @@ "typescript-eslint": "^8.46.0", "@eslint/js": "^9.37.0", "ts-node": "~10.9.2", - "@tsconfig/node18": "~18.2.4" + "@tsconfig/node20": "~20.1.6" } } diff --git a/libraries/fabric-ledger/tsconfig.json b/libraries/fabric-ledger/tsconfig.json index bf377a7a..37ba7b2a 100644 --- a/libraries/fabric-ledger/tsconfig.json +++ b/libraries/fabric-ledger/tsconfig.json @@ -5,7 +5,7 @@ */ { "$schema": "https://json.schemastore.org/tsconfig", - "extends": "@tsconfig/node18/tsconfig.json", + "extends": "@tsconfig/node20/tsconfig.json", "compilerOptions": { "declaration": true, "declarationMap": true, diff --git a/libraries/fabric-shim/package.json b/libraries/fabric-shim/package.json index 826c7b07..7c52ac19 100644 --- a/libraries/fabric-shim/package.json +++ b/libraries/fabric-shim/package.json @@ -29,7 +29,7 @@ "Fabric Shim" ], "engines": { - "node": ">=18" + "node": ">=20" }, "types": "./types/index.d.ts", "license": "Apache-2.0", @@ -84,6 +84,6 @@ "typescript": "~5.8.3", "typescript-eslint": "^8.46.0", "@eslint/js": "^9.37.0", - "@tsconfig/node18": "~18.2.4" + "@tsconfig/node20": "~20.1.6" } } diff --git a/libraries/fabric-shim/tsconfig.json b/libraries/fabric-shim/tsconfig.json index e11650ef..a1fba4ea 100644 --- a/libraries/fabric-shim/tsconfig.json +++ b/libraries/fabric-shim/tsconfig.json @@ -5,7 +5,7 @@ */ { "$schema": "https://json.schemastore.org/tsconfig", - "extends": "@tsconfig/node18/tsconfig.json", + "extends": "@tsconfig/node20/tsconfig.json", "compilerOptions": { "types": ["./types/"], "declaration": true, diff --git a/rush.json b/rush.json index 53a749e9..e6b1ff27 100644 --- a/rush.json +++ b/rush.json @@ -24,7 +24,7 @@ * Specify one of: "pnpmVersion", "npmVersion", or "yarnVersion". See the Rush documentation * for details about these alternatives. */ - "pnpmVersion": "10.18.3", + "pnpmVersion": "10.19.0", /** * Options that are only used when the PNPM package manager is selected */ @@ -62,7 +62,7 @@ * Specify a SemVer range to ensure developers use a Node.js version that is appropriate * for your repo. */ - "nodeSupportedVersionRange": ">=18", + "nodeSupportedVersionRange": ">=20", /** * Odd-numbered major versions of Node.js are experimental. Even-numbered releases * spend six months in a stabilization period before the first Long Term Support (LTS) version. diff --git a/test/chaincodes/annotations/package.json b/test/chaincodes/annotations/package.json index f577a833..1a71de56 100644 --- a/test/chaincodes/annotations/package.json +++ b/test/chaincodes/annotations/package.json @@ -2,7 +2,7 @@ "name": "ts_chaincode", "description": "Chaincode testing typescript functionality and annotations", "engines": { - "node": ">=18" + "node": ">=20" }, "scripts": { "build": "tsc", @@ -20,7 +20,7 @@ "fabric-shim": "2.5.9" }, "devDependencies": { - "@tsconfig/node18": "^18.2.4", + "@tsconfig/node20": "^20.1.6", "@types/node": "^18.19.130", "typescript": "~5.8.3" } diff --git a/test/chaincodes/annotations/tsconfig.json b/test/chaincodes/annotations/tsconfig.json index e4bf98dd..b8c3cb72 100644 --- a/test/chaincodes/annotations/tsconfig.json +++ b/test/chaincodes/annotations/tsconfig.json @@ -1,6 +1,6 @@ { "$schema": "https://json.schemastore.org/tsconfig", - "extends": "@tsconfig/node18/tsconfig.json", + "extends": "@tsconfig/node20/tsconfig.json", "compilerOptions": { "declaration": true, "declarationMap": true, diff --git a/test/chaincodes/clientidentity/package.json b/test/chaincodes/clientidentity/package.json index 725495e1..904df671 100644 --- a/test/chaincodes/clientidentity/package.json +++ b/test/chaincodes/clientidentity/package.json @@ -2,7 +2,7 @@ "name": "chaincode", "description": "Chaincode testing ClientIdentity functionality", "engines": { - "node": ">=18" + "node": ">=20" }, "scripts": { "start": "fabric-chaincode-node start" diff --git a/test/chaincodes/crosschaincode/package.json b/test/chaincodes/crosschaincode/package.json index 17ddda4c..2a40a2a5 100644 --- a/test/chaincodes/crosschaincode/package.json +++ b/test/chaincodes/crosschaincode/package.json @@ -2,7 +2,7 @@ "name": "chaincode", "description": "Chaincode testing cross chaincode functionality", "engines": { - "node": ">=18" + "node": ">=20" }, "scripts": { "start": "set -x && CORE_CHAINCODE_LOGGING_LEVEL=debug fabric-chaincode-node start" diff --git a/test/chaincodes/crosschaincode2/package.json b/test/chaincodes/crosschaincode2/package.json index 7f41866c..46b2a923 100644 --- a/test/chaincodes/crosschaincode2/package.json +++ b/test/chaincodes/crosschaincode2/package.json @@ -2,7 +2,7 @@ "name": "chaincode", "description": "Chaincode testing cross chaincode functionality", "engines": { - "node": ">=18" + "node": ">=20" }, "scripts": { "start": "fabric-chaincode-node start" diff --git a/test/chaincodes/crud/package.json b/test/chaincodes/crud/package.json index 1059b765..d0529b1a 100644 --- a/test/chaincodes/crud/package.json +++ b/test/chaincodes/crud/package.json @@ -2,7 +2,7 @@ "name": "chaincode", "description": "Chaincode testing crud functionality", "engines": { - "node": ">=18" + "node": ">=20" }, "scripts": { "start": "set -x && CORE_CHAINCODE_LOGGING_LEVEL=debug fabric-chaincode-node start" diff --git a/test/chaincodes/events/package.json b/test/chaincodes/events/package.json index 15391b60..1f971288 100644 --- a/test/chaincodes/events/package.json +++ b/test/chaincodes/events/package.json @@ -2,7 +2,7 @@ "name": "chaincode", "description": "Chaincode testing events functionality", "engines": { - "node": ">=18" + "node": ">=20" }, "scripts": { "start": "set -x && CORE_CHAINCODE_LOGGING_LEVEL=debug fabric-chaincode-node start" diff --git a/test/chaincodes/ledger/package.json b/test/chaincodes/ledger/package.json index f72b4667..f8034fab 100644 --- a/test/chaincodes/ledger/package.json +++ b/test/chaincodes/ledger/package.json @@ -2,7 +2,7 @@ "name": "chaincode", "description": "Chaincode testing ledger functionality", "engines": { - "node": ">=18" + "node": ">=20" }, "scripts": { "start": "fabric-chaincode-node start" diff --git a/test/chaincodes/privateData/package.json b/test/chaincodes/privateData/package.json index 627e1a17..ae62e52c 100644 --- a/test/chaincodes/privateData/package.json +++ b/test/chaincodes/privateData/package.json @@ -2,7 +2,7 @@ "name": "chaincode", "description": "Chaincode testing private data functionality", "engines": { - "node": ">=18" + "node": ">=20" }, "scripts": { "start": "fabric-chaincode-node start" diff --git a/test/chaincodes/query/package.json b/test/chaincodes/query/package.json index 45369690..bf2a1267 100644 --- a/test/chaincodes/query/package.json +++ b/test/chaincodes/query/package.json @@ -2,7 +2,7 @@ "name": "chaincode", "description": "Chaincode testing query functionality", "engines": { - "node": ">=18" + "node": ">=20" }, "scripts": { "start": "fabric-chaincode-node start" diff --git a/test/chaincodes/scenario/package.json b/test/chaincodes/scenario/package.json index cc310e5c..5ee0ccb5 100644 --- a/test/chaincodes/scenario/package.json +++ b/test/chaincodes/scenario/package.json @@ -2,7 +2,7 @@ "name": "chaincode", "description": "My first exciting chaincode implemented in node.js", "engines": { - "node": ">=18" + "node": ">=20" }, "scripts": { "start": "fabric-chaincode-node start" diff --git a/test/fv/package.json b/test/fv/package.json index d462bfd9..c36a2c50 100644 --- a/test/fv/package.json +++ b/test/fv/package.json @@ -6,7 +6,7 @@ "testFabricThirdParty": "0.4.15", "docsLatestVersion": "release-1.4", "engines": { - "node": ">=18" + "node": ">=20" }, "engineStrict": true, "license": "Apache-2.0",