diff --git a/.github/workflows/deploy_docs.yml b/.github/workflows/deploy_docs.yml new file mode 100644 index 0000000000..e9c9c87e27 --- /dev/null +++ b/.github/workflows/deploy_docs.yml @@ -0,0 +1,36 @@ +# Copyright IBM Corp. All Rights Reserved. +# +# SPDX-License-Identifier: CC-BY-4.0 + +name: Deploy Docs (Github Pages) + +on: + push: + branches: + - main + paths: + - 'docs/**' + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +jobs: + deploy-docs: + runs-on: ubuntu-latest + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v3 + + - name: Use Python 3.x + uses: actions/setup-python@v4 + with: + python-version: '3.10' + cache: 'pip' # caching pip dependencies + + - name: Install dependencies + run: pip install -r requirements.txt + working-directory: docs + + - name: Build and publish + run: git pull && mkdocs gh-deploy + working-directory: docs diff --git a/docs/.gitignore b/docs/.gitignore new file mode 100644 index 0000000000..45ddf0ae39 --- /dev/null +++ b/docs/.gitignore @@ -0,0 +1 @@ +site/ diff --git a/docs/CODEOWNERS b/docs/CODEOWNERS new file mode 100644 index 0000000000..1607d09e51 --- /dev/null +++ b/docs/CODEOWNERS @@ -0,0 +1 @@ +* @VRamakrishna diff --git a/docs/LICENSE b/docs/LICENSE new file mode 100644 index 0000000000..da6ab6cc8f --- /dev/null +++ b/docs/LICENSE @@ -0,0 +1,396 @@ +Attribution 4.0 International + +======================================================================= + +Creative Commons Corporation ("Creative Commons") is not a law firm and +does not provide legal services or legal advice. Distribution of +Creative Commons public licenses does not create a lawyer-client or +other relationship. Creative Commons makes its licenses and related +information available on an "as-is" basis. Creative Commons gives no +warranties regarding its licenses, any material licensed under their +terms and conditions, or any related information. Creative Commons +disclaims all liability for damages resulting from their use to the +fullest extent possible. + +Using Creative Commons Public Licenses + +Creative Commons public licenses provide a standard set of terms and +conditions that creators and other rights holders may use to share +original works of authorship and other material subject to copyright +and certain other rights specified in the public license below. The +following considerations are for informational purposes only, are not +exhaustive, and do not form part of our licenses. + + Considerations for licensors: Our public licenses are + intended for use by those authorized to give the public + permission to use material in ways otherwise restricted by + copyright and certain other rights. Our licenses are + irrevocable. Licensors should read and understand the terms + and conditions of the license they choose before applying it. + Licensors should also secure all rights necessary before + applying our licenses so that the public can reuse the + material as expected. Licensors should clearly mark any + material not subject to the license. This includes other CC- + licensed material, or material used under an exception or + limitation to copyright. More considerations for licensors: + wiki.creativecommons.org/Considerations_for_licensors + + Considerations for the public: By using one of our public + licenses, a licensor grants the public permission to use the + licensed material under specified terms and conditions. If + the licensor's permission is not necessary for any reason--for + example, because of any applicable exception or limitation to + copyright--then that use is not regulated by the license. Our + licenses grant only permissions under copyright and certain + other rights that a licensor has authority to grant. Use of + the licensed material may still be restricted for other + reasons, including because others have copyright or other + rights in the material. A licensor may make special requests, + such as asking that all changes be marked or described. + Although not required by our licenses, you are encouraged to + respect those requests where reasonable. More considerations + for the public: + wiki.creativecommons.org/Considerations_for_licensees + +======================================================================= + +Creative Commons Attribution 4.0 International Public License + +By exercising the Licensed Rights (defined below), You accept and agree +to be bound by the terms and conditions of this Creative Commons +Attribution 4.0 International Public License ("Public License"). To the +extent this Public License may be interpreted as a contract, You are +granted the Licensed Rights in consideration of Your acceptance of +these terms and conditions, and the Licensor grants You such rights in +consideration of benefits the Licensor receives from making the +Licensed Material available under these terms and conditions. + + +Section 1 -- Definitions. + + a. Adapted Material means material subject to Copyright and Similar + Rights that is derived from or based upon the Licensed Material + and in which the Licensed Material is translated, altered, + arranged, transformed, or otherwise modified in a manner requiring + permission under the Copyright and Similar Rights held by the + Licensor. For purposes of this Public License, where the Licensed + Material is a musical work, performance, or sound recording, + Adapted Material is always produced where the Licensed Material is + synched in timed relation with a moving image. + + b. Adapter's License means the license You apply to Your Copyright + and Similar Rights in Your contributions to Adapted Material in + accordance with the terms and conditions of this Public License. + + c. Copyright and Similar Rights means copyright and/or similar rights + closely related to copyright including, without limitation, + performance, broadcast, sound recording, and Sui Generis Database + Rights, without regard to how the rights are labeled or + categorized. For purposes of this Public License, the rights + specified in Section 2(b)(1)-(2) are not Copyright and Similar + Rights. + + d. Effective Technological Measures means those measures that, in the + absence of proper authority, may not be circumvented under laws + fulfilling obligations under Article 11 of the WIPO Copyright + Treaty adopted on December 20, 1996, and/or similar international + agreements. + + e. Exceptions and Limitations means fair use, fair dealing, and/or + any other exception or limitation to Copyright and Similar Rights + that applies to Your use of the Licensed Material. + + f. Licensed Material means the artistic or literary work, database, + or other material to which the Licensor applied this Public + License. + + g. Licensed Rights means the rights granted to You subject to the + terms and conditions of this Public License, which are limited to + all Copyright and Similar Rights that apply to Your use of the + Licensed Material and that the Licensor has authority to license. + + h. Licensor means the individual(s) or entity(ies) granting rights + under this Public License. + + i. Share means to provide material to the public by any means or + process that requires permission under the Licensed Rights, such + as reproduction, public display, public performance, distribution, + dissemination, communication, or importation, and to make material + available to the public including in ways that members of the + public may access the material from a place and at a time + individually chosen by them. + + j. Sui Generis Database Rights means rights other than copyright + resulting from Directive 96/9/EC of the European Parliament and of + the Council of 11 March 1996 on the legal protection of databases, + as amended and/or succeeded, as well as other essentially + equivalent rights anywhere in the world. + + k. You means the individual or entity exercising the Licensed Rights + under this Public License. Your has a corresponding meaning. + + +Section 2 -- Scope. + + a. License grant. + + 1. Subject to the terms and conditions of this Public License, + the Licensor hereby grants You a worldwide, royalty-free, + non-sublicensable, non-exclusive, irrevocable license to + exercise the Licensed Rights in the Licensed Material to: + + a. reproduce and Share the Licensed Material, in whole or + in part; and + + b. produce, reproduce, and Share Adapted Material. + + 2. Exceptions and Limitations. For the avoidance of doubt, where + Exceptions and Limitations apply to Your use, this Public + License does not apply, and You do not need to comply with + its terms and conditions. + + 3. Term. The term of this Public License is specified in Section + 6(a). + + 4. Media and formats; technical modifications allowed. The + Licensor authorizes You to exercise the Licensed Rights in + all media and formats whether now known or hereafter created, + and to make technical modifications necessary to do so. The + Licensor waives and/or agrees not to assert any right or + authority to forbid You from making technical modifications + necessary to exercise the Licensed Rights, including + technical modifications necessary to circumvent Effective + Technological Measures. For purposes of this Public License, + simply making modifications authorized by this Section 2(a) + (4) never produces Adapted Material. + + 5. Downstream recipients. + + a. Offer from the Licensor -- Licensed Material. Every + recipient of the Licensed Material automatically + receives an offer from the Licensor to exercise the + Licensed Rights under the terms and conditions of this + Public License. + + b. No downstream restrictions. You may not offer or impose + any additional or different terms or conditions on, or + apply any Effective Technological Measures to, the + Licensed Material if doing so restricts exercise of the + Licensed Rights by any recipient of the Licensed + Material. + + 6. No endorsement. Nothing in this Public License constitutes or + may be construed as permission to assert or imply that You + are, or that Your use of the Licensed Material is, connected + with, or sponsored, endorsed, or granted official status by, + the Licensor or others designated to receive attribution as + provided in Section 3(a)(1)(A)(i). + + b. Other rights. + + 1. Moral rights, such as the right of integrity, are not + licensed under this Public License, nor are publicity, + privacy, and/or other similar personality rights; however, to + the extent possible, the Licensor waives and/or agrees not to + assert any such rights held by the Licensor to the limited + extent necessary to allow You to exercise the Licensed + Rights, but not otherwise. + + 2. Patent and trademark rights are not licensed under this + Public License. + + 3. To the extent possible, the Licensor waives any right to + collect royalties from You for the exercise of the Licensed + Rights, whether directly or through a collecting society + under any voluntary or waivable statutory or compulsory + licensing scheme. In all other cases the Licensor expressly + reserves any right to collect such royalties. + + +Section 3 -- License Conditions. + +Your exercise of the Licensed Rights is expressly made subject to the +following conditions. + + a. Attribution. + + 1. If You Share the Licensed Material (including in modified + form), You must: + + a. retain the following if it is supplied by the Licensor + with the Licensed Material: + + i. identification of the creator(s) of the Licensed + Material and any others designated to receive + attribution, in any reasonable manner requested by + the Licensor (including by pseudonym if + designated); + + ii. a copyright notice; + + iii. a notice that refers to this Public License; + + iv. a notice that refers to the disclaimer of + warranties; + + v. a URI or hyperlink to the Licensed Material to the + extent reasonably practicable; + + b. indicate if You modified the Licensed Material and + retain an indication of any previous modifications; and + + c. indicate the Licensed Material is licensed under this + Public License, and include the text of, or the URI or + hyperlink to, this Public License. + + 2. You may satisfy the conditions in Section 3(a)(1) in any + reasonable manner based on the medium, means, and context in + which You Share the Licensed Material. For example, it may be + reasonable to satisfy the conditions by providing a URI or + hyperlink to a resource that includes the required + information. + + 3. If requested by the Licensor, You must remove any of the + information required by Section 3(a)(1)(A) to the extent + reasonably practicable. + + 4. If You Share Adapted Material You produce, the Adapter's + License You apply must not prevent recipients of the Adapted + Material from complying with this Public License. + + +Section 4 -- Sui Generis Database Rights. + +Where the Licensed Rights include Sui Generis Database Rights that +apply to Your use of the Licensed Material: + + a. for the avoidance of doubt, Section 2(a)(1) grants You the right + to extract, reuse, reproduce, and Share all or a substantial + portion of the contents of the database; + + b. if You include all or a substantial portion of the database + contents in a database in which You have Sui Generis Database + Rights, then the database in which You have Sui Generis Database + Rights (but not its individual contents) is Adapted Material; and + + c. You must comply with the conditions in Section 3(a) if You Share + all or a substantial portion of the contents of the database. + +For the avoidance of doubt, this Section 4 supplements and does not +replace Your obligations under this Public License where the Licensed +Rights include other Copyright and Similar Rights. + + +Section 5 -- Disclaimer of Warranties and Limitation of Liability. + + a. UNLESS OTHERWISE SEPARATELY UNDERTAKEN BY THE LICENSOR, TO THE + EXTENT POSSIBLE, THE LICENSOR OFFERS THE LICENSED MATERIAL AS-IS + AND AS-AVAILABLE, AND MAKES NO REPRESENTATIONS OR WARRANTIES OF + ANY KIND CONCERNING THE LICENSED MATERIAL, WHETHER EXPRESS, + IMPLIED, STATUTORY, OR OTHER. THIS INCLUDES, WITHOUT LIMITATION, + WARRANTIES OF TITLE, MERCHANTABILITY, FITNESS FOR A PARTICULAR + PURPOSE, NON-INFRINGEMENT, ABSENCE OF LATENT OR OTHER DEFECTS, + ACCURACY, OR THE PRESENCE OR ABSENCE OF ERRORS, WHETHER OR NOT + KNOWN OR DISCOVERABLE. WHERE DISCLAIMERS OF WARRANTIES ARE NOT + ALLOWED IN FULL OR IN PART, THIS DISCLAIMER MAY NOT APPLY TO YOU. + + b. TO THE EXTENT POSSIBLE, IN NO EVENT WILL THE LICENSOR BE LIABLE + TO YOU ON ANY LEGAL THEORY (INCLUDING, WITHOUT LIMITATION, + NEGLIGENCE) OR OTHERWISE FOR ANY DIRECT, SPECIAL, INDIRECT, + INCIDENTAL, CONSEQUENTIAL, PUNITIVE, EXEMPLARY, OR OTHER LOSSES, + COSTS, EXPENSES, OR DAMAGES ARISING OUT OF THIS PUBLIC LICENSE OR + USE OF THE LICENSED MATERIAL, EVEN IF THE LICENSOR HAS BEEN + ADVISED OF THE POSSIBILITY OF SUCH LOSSES, COSTS, EXPENSES, OR + DAMAGES. WHERE A LIMITATION OF LIABILITY IS NOT ALLOWED IN FULL OR + IN PART, THIS LIMITATION MAY NOT APPLY TO YOU. + + c. The disclaimer of warranties and limitation of liability provided + above shall be interpreted in a manner that, to the extent + possible, most closely approximates an absolute disclaimer and + waiver of all liability. + + +Section 6 -- Term and Termination. + + a. This Public License applies for the term of the Copyright and + Similar Rights licensed here. However, if You fail to comply with + this Public License, then Your rights under this Public License + terminate automatically. + + b. Where Your right to use the Licensed Material has terminated under + Section 6(a), it reinstates: + + 1. automatically as of the date the violation is cured, provided + it is cured within 30 days of Your discovery of the + violation; or + + 2. upon express reinstatement by the Licensor. + + For the avoidance of doubt, this Section 6(b) does not affect any + right the Licensor may have to seek remedies for Your violations + of this Public License. + + c. For the avoidance of doubt, the Licensor may also offer the + Licensed Material under separate terms or conditions or stop + distributing the Licensed Material at any time; however, doing so + will not terminate this Public License. + + d. Sections 1, 5, 6, 7, and 8 survive termination of this Public + License. + + +Section 7 -- Other Terms and Conditions. + + a. The Licensor shall not be bound by any additional or different + terms or conditions communicated by You unless expressly agreed. + + b. Any arrangements, understandings, or agreements regarding the + Licensed Material not stated herein are separate from and + independent of the terms and conditions of this Public License. + + +Section 8 -- Interpretation. + + a. For the avoidance of doubt, this Public License does not, and + shall not be interpreted to, reduce, limit, restrict, or impose + conditions on any use of the Licensed Material that could lawfully + be made without permission under this Public License. + + b. To the extent possible, if any provision of this Public License is + deemed unenforceable, it shall be automatically reformed to the + minimum extent necessary to make it enforceable. If the provision + cannot be reformed, it shall be severed from this Public License + without affecting the enforceability of the remaining terms and + conditions. + + c. No term or condition of this Public License will be waived and no + failure to comply consented to unless expressly agreed to by the + Licensor. + + d. Nothing in this Public License constitutes or may be interpreted + as a limitation upon, or waiver of, any privileges and immunities + that apply to the Licensor or You, including from the legal + processes of any jurisdiction or authority. + + +======================================================================= + +Creative Commons is not a party to its public +licenses. Notwithstanding, Creative Commons may elect to apply one of +its public licenses to material it publishes and in those instances +will be considered the “Licensor.” The text of the Creative Commons +public licenses is dedicated to the public domain under the CC0 Public +Domain Dedication. Except for the limited purpose of indicating that +material is shared under a Creative Commons public license or as +otherwise permitted by the Creative Commons policies published at +creativecommons.org/policies, Creative Commons does not authorize the +use of the trademark "Creative Commons" or any other trademark or logo +of Creative Commons without its prior written consent including, +without limitation, in connection with any unauthorized modifications +to any of its public licenses or any other arrangements, +understandings, or agreements concerning use of licensed material. For +the avoidance of doubt, this paragraph does not form part of the +public licenses. + +Creative Commons may be contacted at creativecommons.org. + diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000000..fde2befb01 --- /dev/null +++ b/docs/README.md @@ -0,0 +1,61 @@ +# Welcome to the documentation template + +This repository serves as a template for creating documentation for Hyperledger projects. The template utilizes MkDocs (documentation at [mkdocs.org](https://www.mkdocs.org)) and the theme Material for MkDocs (documentation at [Material for MkDocs](https://squidfunk.github.io/mkdocs-material/)). Material adds a number of extra features to MkDocs, and Hyperledger repositories can take advantage of the theme's [Insiders](https://squidfunk.github.io/mkdocs-material/insiders/) capabilities. + +[Material for MkDocs]: https://squidfunk.github.io/mkdocs-material/ +[Mike]: https://github.com/jimporter/mike + +## Prerequisites + +To test the documents and update the published site, the following tools are needed: + +- A Bash shell +- git +- Python 3 +- The [Material for Mkdocs] theme. +- The [Mike] MkDocs plugin for publishing versions to gh-pages. + - Not used locally, but referenced in the `mkdocs.yml` file and needed for + deploying the site to gh-pages. + +### git +`git` can be installed locally, as described in the [Install Git Guide from GitHub](https://github.com/git-guides/install-git). + +### Python 3 +`Python 3` can be installed locally, as described in the [Python Getting Started guide](https://www.python.org/about/gettingstarted/). + +### Mkdocs + +The Mkdocs-related items can be installed locally, as described in the [Material +for Mkdocs] installation instructions. The short, case-specific version of those +instructions follow: + +```bash +pip install -r requirements.txt +``` + +### Verify Setup + +To verify your setup, check that you can run `mkdocs` by running the command `mkdocs --help` to see the help text. + +## Useful MkDocs Commands + +The commands you will usually use with `mkdocs` are: + +* `mkdocs serve` - Start the live-reloading docs server. +* `mkdocs build` - Build the documentation site. +* `mkdocs -h` - Print help message and exit. +* `mkdocs gh-deploy` - Build and push documents to `gh-pages` branch, and publish to URL configured in `mkdocs.yml`. + +## Adding Content + +The basic process for adding content to the site is: + +- Create a new markdown file under the `docs` folder +- Add the new file to the table of contents (`nav` section in the `mkdocs.yml` file) + +## Repository layout + + mkdocs.yml # The configuration file. + docs/ + index.md # The documentation homepage. + ... # Other markdown pages, images and other files. diff --git a/docs/docs/architecture.md b/docs/docs/architecture.md new file mode 100644 index 0000000000..b38b477ecf --- /dev/null +++ b/docs/docs/architecture.md @@ -0,0 +1,15 @@ +The Cacti integrated architecture is illustrated below. + + + +This consists of a set of modules, services (offering standard APIs), and libraries that offer a selection of cross-network transaction pipelines, which can be constructed by picking and choosing from the collection. + +The integrated architecture was generated by fusing the pre-existing Cactus and Weaver architectures, identifying and re-labeling common (or overlapping) components and calling out unique components separately. + +For reference, here is the Cactus architecture. + + + +And here is the Weaver architecture. + + diff --git a/docs/docs/cactus/_images/build-script-decision-tree-2021-03-06.png b/docs/docs/cactus/_images/build-script-decision-tree-2021-03-06.png new file mode 100644 index 0000000000..22cf33d8fc Binary files /dev/null and b/docs/docs/cactus/_images/build-script-decision-tree-2021-03-06.png differ diff --git a/docs/docs/cactus/_images/hyperledger-cactus-watch-script-tutorial-2021-03-06.gif b/docs/docs/cactus/_images/hyperledger-cactus-watch-script-tutorial-2021-03-06.gif new file mode 100644 index 0000000000..2735870f79 Binary files /dev/null and b/docs/docs/cactus/_images/hyperledger-cactus-watch-script-tutorial-2021-03-06.gif differ diff --git a/docs/docs/cactus/_images/related-work-categories.png b/docs/docs/cactus/_images/related-work-categories.png new file mode 100644 index 0000000000..c773260f13 Binary files /dev/null and b/docs/docs/cactus/_images/related-work-categories.png differ diff --git a/docs/docs/cactus/_images/run-transaction-endpoint-enroll.png b/docs/docs/cactus/_images/run-transaction-endpoint-enroll.png new file mode 100644 index 0000000000..76310b39e2 Binary files /dev/null and b/docs/docs/cactus/_images/run-transaction-endpoint-enroll.png differ diff --git a/docs/docs/cactus/_images/run-transaction-endpoint-transact-cactuskeychainref.png b/docs/docs/cactus/_images/run-transaction-endpoint-transact-cactuskeychainref.png new file mode 100644 index 0000000000..20647e8258 Binary files /dev/null and b/docs/docs/cactus/_images/run-transaction-endpoint-transact-cactuskeychainref.png differ diff --git a/docs/docs/cactus/_images/run-transaction-endpoint-transact-pollfortxreceipt.png b/docs/docs/cactus/_images/run-transaction-endpoint-transact-pollfortxreceipt.png new file mode 100644 index 0000000000..c7d4296abe Binary files /dev/null and b/docs/docs/cactus/_images/run-transaction-endpoint-transact-pollfortxreceipt.png differ diff --git a/docs/docs/cactus/_images/run-transaction-endpoint-transact-privatekey.png b/docs/docs/cactus/_images/run-transaction-endpoint-transact-privatekey.png new file mode 100644 index 0000000000..1ff8188248 Binary files /dev/null and b/docs/docs/cactus/_images/run-transaction-endpoint-transact-privatekey.png differ diff --git a/docs/docs/cactus/_images/run-transaction-endpoint-transact-signed.png b/docs/docs/cactus/_images/run-transaction-endpoint-transact-signed.png new file mode 100644 index 0000000000..967eb22b71 Binary files /dev/null and b/docs/docs/cactus/_images/run-transaction-endpoint-transact-signed.png differ diff --git a/docs/docs/cactus/_images/run-transaction-endpoint-transact.png b/docs/docs/cactus/_images/run-transaction-endpoint-transact.png new file mode 100644 index 0000000000..dc51fe46fd Binary files /dev/null and b/docs/docs/cactus/_images/run-transaction-endpoint-transact.png differ diff --git a/docs/docs/cactus/_images/run-transaction-endpoint-transact1.png b/docs/docs/cactus/_images/run-transaction-endpoint-transact1.png new file mode 100644 index 0000000000..91a13a4290 Binary files /dev/null and b/docs/docs/cactus/_images/run-transaction-endpoint-transact1.png differ diff --git a/docs/docs/cactus/_images/run-transaction-endpoint.png b/docs/docs/cactus/_images/run-transaction-endpoint.png new file mode 100644 index 0000000000..4ad53b872d Binary files /dev/null and b/docs/docs/cactus/_images/run-transaction-endpoint.png differ diff --git a/docs/docs/cactus/_images/run-transaction-endpoint1.png b/docs/docs/cactus/_images/run-transaction-endpoint1.png new file mode 100644 index 0000000000..8e6a76a599 Binary files /dev/null and b/docs/docs/cactus/_images/run-transaction-endpoint1.png differ diff --git a/docs/docs/cactus/build.md b/docs/docs/cactus/build.md new file mode 100644 index 0000000000..ac86ed3abe --- /dev/null +++ b/docs/docs/cactus/build.md @@ -0,0 +1,223 @@ +Hyperledger Cactus Build Instructions +===================================== + +This is the place to start if you want to give Cactus a spin on your local machine or if you are planning on contributing. + +> This is not a guide for `using` Cactus for your projects that have business logic but rather a guide for people who want to make changes to the code of Cactus. If you are just planning on using Cactus as an npm dependency for your project, then you might not need this guide at all. + +The project uses Typescript for both back-end and front-end components. + +Developers guide +---------------- + +This is a video guide to setup Hyperledger Cactus on your local machine. + +### Installing git + +[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/RJhifrmSiNA/0.jpg)](https://www.youtube.com/watch?v=RJhifrmSiNA) + +### Installing and configuring docker + +[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/V8YBQoxdyiE/0.jpg)](https://www.youtube.com/watch?v=V8YBQoxdyiE) + +### Installing npm and node + +[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/94xoV9Vfu14/0.jpg)](https://www.youtube.com/watch?v=94xoV9Vfu14) + +### Installing jdk 8 + +[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/V8YBQoxdyiE/0.jpg)](https://youtube.com/watch?v=t4y57Qvrdcc) + +### Installing VSCode and plugins + +[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/RHQLhZRlAR0/0.jpg)](https://www.youtube.com/watch?v=RHQLhZRlAR0) + +### Clone the repository + +[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/n_HiEwgzPsM/0.jpg)](https://www.youtube.com/watch?v=n_HiEwgzPsM) + +### Compiling all packages + +[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/5v82MAHPQmM/0.jpg)](https://www.youtube.com/watch?v=5v82MAHPQmM) + +### Testing all packages + +[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/mVuk8txh-JE/0.jpg)](https://www.youtube.com/watch?v=mVuk8txh-JE) + +### Compiling a specific packages + +[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/e7vkd9i-I4c/0.jpg)](https://www.youtube.com/watch?v=e7vkd9i-I4c) + +### Testing a specific package + +[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/Jzw9JQZu6c8/0.jpg)](https://www.youtube.com/watch?v=Jzw9JQZu6c8) + +### Package structure - OpenAPI + +[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/5uuRTc3X4MM/0.jpg)](https://www.youtube.com/watch?v=5uuRTc3X4MM) + +### Package structure - Web Services + +[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/DAML56rx5yQ/0.jpg)](https://www.youtube.com/watch?v=DAML56rx5yQ) + +### Package structure - Main and Factory Plugin class + +[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/w0bmkpge2Dw/0.jpg)](https://www.youtube.com/watch?v=w0bmkpge2Dw) + +### Package structure - Test class + +[![IMAGE ALT TEXT HERE](https://img.youtube.com/vi/3XpBYhN-8qs/0.jpg)](https://www.youtube.com/watch?v=3XpBYhN-8qs) + +Fast Developer Flow / Code Iterations +---------------------------------------------------------------------------------------------------------- + +We put a lot of thought and effort into making sure that fast developer iterations can be achieved (please file a bug if you feel otherwise) while working **on** the framework. + +If you find yourself waiting too much for builds to finish, most of the time that can be helped by using the `npm run watch` script which can automatically recompile packages as you modify them (and only the packages that you have modified, not everything). + +It also supports re-running the OpenAPI generator when you update any `openapi.json` spec files that we use to describe our endpoints. + +The `npm run watch` script in action: + +![Fast Developer Flow / Code Iterations](_images/hyperledger-cactus-watch-script-tutorial-2021-03-06.gif) + +Getting Started +---------------------------------------------------------------- + +* Use preset environment: + + * [VSCode docker container](#./.devcontainer) + +* … or install OS level dependencies manually: + + * Windows Only + + * WSL2 or any virtual machine running Ubuntu 20.04 LTS + + * Git + + * NodeJS v16.14.2, npm v8.5.0 (we recommend using the Node Version Manager (nvm) if available for your OS) + + nvm install 16.14.2 + nvm use 16.14.2 + + * Yarn + + * `npm run install-yarn` (from within the project directory) + + * [Docker Engine](https://docs.docker.com/engine/install/ubuntu/). Make sure that Docker is working and running, for example, running `docker ps -aq` + + * Docker Compose + + * OpenJDK (Corda support Java 8 JDK but do not currently support Java 9 or higher) + + * `sudo apt install openjdk-8-jdk-headless` + + * Indy SDK (optional) + + * [Installing the SDK](https://github.com/hyperledger/indy-sdk#installing-the-sdk) + + * [Build the SDK from source](https://github.com/hyperledger/indy-sdk#how-to-build-indy-sdk-from-source) + +* Clone the repository + + +git clone https://github.com/hyperledger/cactus.git + +Windows specific gotcha: `File paths too long` error when cloning. To fix: Open PowerShell with administrative rights and then run the following: + +git config \--system core.longpaths true + +* Change directories to the project root + + +cd cactus + +* Run this command to enable corepack (Corepack is included by default with all Node.js installs, but is currently opt-in.) + + +npm run enable-corepack + +* Run the initial configuration script (can take a long time, 10+ minutes on a low-spec laptop) + + +yarn run configure + +At this point you should have all packages built for development. + +You can start making your changes (use your own fork and a feature branch) or just run existing tests and debug them to see how things fit together. + +For example you can _run a ledger single status endpoint test_ via the REST API with this command: + +npx tap \--ts \--timeout\=600 packages/cactus-test-plugin-htlc-eth-besu/src/test/typescript/integration/plugin-htlc-eth-besu/get-single-status-endpoint.test.ts + +_You can also start the API server_ and verify more complex scenarios with an arbitrary list of plugins loaded into Cactus. This is useful for when you intend to develop your plugin either as a Cactus maintained plugin or one on your own. + +npm run generate-api-server-config + +Notice how this task created a .config.json file in the project root with an example configuration that can be used a good starting point for you to make changes to it specific to your needs or wants. + +The most interesting part of the `.config.json` file is the plugins array which takes a list of plugin package names and their options (which can be anything that you can fit into a generic JSON object). + +Notice that to include a plugin, all you need is specify it’s npm package name. This is important since it allows you to have your own plugins in their respective, independent Github repositories and npm packages where you do not have to seek explicit approval from the Cactus maintainers to create/maintain your plugin at all. + +Once you are satisfied with the `.config.json` file’s contents you can just: + +npm run start:api-server + +After starting the API server, you will see in the logs that plugins were loaded and that the API is reachable on the port you specified (4000 by default). The Web UI (Cockpit) is disabled by default but can be enabled by changing the property value ‘cockpitEnabled’ to true and it is reachable through port on the port your config specified (3000 by default). + +> You may need to enable manually the CORS patterns in the configuration file. This may be slightly inconvenient, but something we are unable to compromise on despite valuing developer experience very much. We have decided that the software should be `secure by default` above all else and allow for customization/degradation of security as an opt-in feature rather than starting from that state. + +At this point, with the running API server, you can + +* Test the REST API directly with tools like cURL or Postman + +* Develop your own applications against it with the `Cactus API Client(s)` + +* Create and test your own plugins + + +### Random Windows specific issues not covered here + +We recommend that you use WSL2 or any Linux VM (or bare metal). We test most frequently on Ubuntu 20.04 LTS + +Build Script Decision Tree +-------------------------------------------------------------------------------------- + +The `npm run watch` script should cover 99% of the cases when it comes to working on Cactus code and having it recompile, but for that last 1% you’ll need to get your hands dirty with the rest of the build scripts. Usually this is only needed when you are adding new dependencies (npm packages) as part of something that you are implementing. + +There are a lot of different build scripts in Cactus in order to provide contributors fine(r) grained control over what parts of the framework they wish build. + +> Q: Why the complexity of so many build scripts? +> +> A: We could just keep it simple with a single build script that builds everything always, but that would be a nightmare to wait for after having changed a single line of code for example. + +To figure out which script could work for rebuilding Cactus, please follow the following decision tree (and keep in mind that we have `npm run watch` too) + +![Build Script Decision Tree](_images/build-script-decision-tree-2021-03-06.png) + +Configuring SSH to use upterm +-------------------------------------------------------------------------------------------- + +Upload your public key onto github if not done so already. A public key is necessary to join the ssh connection to use upterm. For a comprehensive guide, see the [Generating a new SSH key and adding it to the ssh-agent](https://docs.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh/generating-a-new-ssh-key-and-adding-it-to-the-ssh-agent). + +Locate the `ci.yml` within `.github/workflows` and add to the `ci.yml` code listed below: + +* name: Setup upterm session uses: lhotari/action-upterm@v1 with: repo-token: ${{ secrets.GITHUB\_TOKEN }} + + +Keep in mind that the SSH upterm session should come after the checkout step (uses: actions/checkout@v3.1.0) to ensure that the CI doesn’t hang without before the debugging step occurs. Editing the `ci.yml` will create a new upterm session within `.github/workflows` by adding a new build step. For more details, see the [Debug your GitHub Actions by using ssh](https://github.com/marketplace/actions/debugging-with-ssh). + +By creating a PR for the edited `ci.yml` file, this will the CI to run their tests. There are two ways to navigate to CIs. + +1. Go to the PR and click the `checks` tab + +2. Go to the `Actions` tab within the main Hyperledger Cactus Repository + + +Click on the `CI Cactus workflow`. There should be a new job you’ve created be listed underneath the `build (ubuntu-20.04)` jobs. Click on the the new job (what’s you’ve named your build) and locate the SSH Session within the `Setup Upterm Session` dropdown. Copy the SSH command that start with `ssh` and ends in `.dev` (ex. ssh \*\*\*\*\*\*\*\*\*\*:\*\*\*\*\*\*\*\*\*\*\*@uptermd.upterm.dev). Open your OS and paste the SSH command script in order to begin an upterm session. + +[Previous](introduction.md "Welcome to Hyperledger Cactus documentation!") [Next](examples.md "Examples") + +* * * diff --git a/docs/docs/cactus/code-of-conduct.md b/docs/docs/cactus/code-of-conduct.md new file mode 100644 index 0000000000..e2fe51c0e1 --- /dev/null +++ b/docs/docs/cactus/code-of-conduct.md @@ -0,0 +1,8 @@ +Code of Conduct Guidelines +====================================================================================== + +Please review the Hyperledger [Code of Conduct](https://wiki.hyperledger.org/community/hyperledger-project-code-of-conduct) before participating and abide by these community standards. + +[Previous](governance.md "Governance") [Next](contributing.md "Contributing") + +* * * diff --git a/docs/docs/cactus/contributing.md b/docs/docs/cactus/contributing.md new file mode 100644 index 0000000000..b3b7d421a6 --- /dev/null +++ b/docs/docs/cactus/contributing.md @@ -0,0 +1,513 @@ +Contributing +========================================================== + +Thank you for your interest to contribute to Hyperledger Cactus! :tada: + +First things first, please review the [Hyperledger Code of Conduct](https://wiki.hyperledger.org/display/HYP/Hyperledger+Code+of+Conduct) before participating. + +There are many ways to contribute to Hyperledger Cactus, both as a user and as a developer. + +As a user, this can include: + +* [Making Feature/Enhancement Proposals](https://github.com/hyperledger/cactus/issues/new?assignees=&labels=enhancement&template=feature_request.md&title=) + +* [Reporting bugs](https://github.com/hyperledger/cactus/issues/new?assignees=&labels=bug&template=bug_report.md&title=) + + +As a developer: + +* if you only have a little time, consider picking up a [“help-wanted”](https://github.com/hyperledger/cactus/labels/help%20wanted) or [“good-first-issue”](https://github.com/hyperledger/cactus/labels/good%20first%20issue) task + +* If you can commit to full-time development, then please contact us on our [Rocketchat channel](https://chat.hyperledger.org/channel/cactus) to work through logistics! + + +Git Know How / Reading List +-------------------------------------------------------------------------------------- + +This section is for you if you do not know your way around advanced git concepts such as + +* rebasing (interactive or otherwise) + +* splitting commits/PRs + +* when to use and not to use force push + + +A word on the controversial topic of force pushes: In many git guides you will read that force push is basically forbidden. This is true 99% of the time, BUT if you are the only person working on a branch (which is most of time true for a feature/fix branch of yours that you are planning to submit as a PR) then force pushing is not just allowed but necessary to avoid messy git commit logs. The question you need to ask yourself before force pushing is this: Am I going to destroy someone else’s work on the remote branch? If nobody else is working on the branch then the answer is of course no and force push can be used safely. If others are working with you on the branch on the other hand, it is considered polite to ask and warn them in advance prior to force pushing so that they can take the necessary precautions on their side as well. + +A handy tool to avoid destroying other’s work accidentally is the new(ish) git feature called `--force-with-lease`: Using `git push --force-with-lease` instead of vanilla `--force` is highly recommended: https://softwareengineering.stackexchange.com/a/312710 + +The rustlang documentation has an excellent write-up and additional links on pretty much everything you need to know. The only difference between their PR requirements and Cactus’ is that we do encourage people referencing github issues in commit messages. Quoting the most relevant parts below (and thanks to the Rust maintainers for this). + +> Pull requests are the primary mechanism we use to change Rust. GitHub itself has some great documentation on using the Pull Request feature. We use the “fork and pull” model described here, where contributors push changes to their personal fork and create pull requests to bring those changes into the source repository. +> +> Please make pull requests against the main branch. +> +> Rust follows a no merge policy, meaning, when you encounter merge conflicts you are expected to always rebase instead of merge. E.g. always use rebase when bringing the latest changes from the main branch to your feature branch. Also, please make sure that fixup commits are squashed into other related commits with meaningful commit messages. +> +> GitHub allows closing issues using keywords. This feature should be used to keep the issue tracker tidy. + +Source: https://github.com/rust-lang/rust/blob/53702a67e2ae8a404169a0329f6a38d73bf7494d/CONTRIBUTING.md#pull-requests + +Further reading: + +* https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-collaborative-development-models + +* https://help.github.com/en/github/collaborating-with-issues-and-pull-requests/about-pull-requests + + +PR Checklist - Contributor/Developer +-------------------------------------------------------------------------------------------------------- + +**To avoid issues in the future, do not install dependencies globally. Ensure all dependencies are kept self-contained.** + +1. Fork [hyperledger/cactus](https://github.com/hyperledger/cactus) via Github UI + + * If you are using the Git client on the Windows operating system, you will need to enable long paths for git which you can do in PowerShell by executing the command below. To clarify, this may also apply if you are using any Git GUI application on Windows such as `Github Desktop` or others. + + git config \--global core.longpaths true + +2. Clone the fork to your local machine + +3. (Optional) [Create local branch](#create-local-branch) for minimizing code conflicts when you want to contribute multiple changes regarding different issues in parallel. + +4. Complete the desired changes and where possible test locally + + 1. You can run the full CI suite on Mac/Linux/WSL by running the script at `./tools/ci.sh` + + 2. If you do not have your environment set up for running bash scripts, do not worry, all pull requests will automatically have the same script executed for it when opened. The only downside is the slower feedback loop. + +5. Make sure you have set up your git signatures + + 1. Note: Always sign your commits using the `git commit -S` + + 2. For more information see [here](https://gist.github.com/tkuhrt/10211ae0a26a91a8c030d00344f7d11b) + +6. Think about/decide on what your commit message will be. + + 1. The commit message syntax might be hard to remember at first so you we invite you to use the `npm run commit` command which upon execution presents you with a series of prompts that you can fill out and have your input validated in realtime, making it impossible (or at least much harder) to produce an invalid commit message that the commit lint bot on Github will flag with an error. + + 1. The use of this tool described above is entirely optional in case you need a crutch. + + 2. Note that running the `npm run commit` command will also attempt to perform the actual commit at the end unless you kill the process with `Ctrl + C` or whatever is your terminal’s shortcut for the same action. + + 3. The `npm run commit` command will also attempt to sign the produced commit so make sure that it is set up properly prior to using it. + +7. Commit your changes + + 1. Make sure your commit message follows the formatting requirements (details above) and here: [Conventional Commits syntax](https://www.conventionalcommits.org/en/v1.0.0-beta.4/#specification); this aids in release notes generation which we intend to automate + + 2. Be aware that we are using git commit hooks for the automation of certain mundane tasks such as applying the required code style and formatting so your code will be wrapped at 80 characters each line automatically. If you wish to see how your changes will be altered by the formatter you can run the `npm run prettier` command from a terminal or install an IDE extension for the `Prettier` tool that can do the same (VSCode has one that is known to work). + +8. Ensure your branch is rebased onto the `upstream` main branch where `upstream` is fancy git talk for the main Cactus repo on Github (the one you created your fork from). + + 1. **Do not** duplicate your pull request after it has been reviewed. Duplication here means closing the existing PR and then opening a brand new one which does not contain the review history anymore. If you encounter issues with version control that you do not know how to solve the maintainers will be happy to assist to ensure that you do not need to open a new pull request from scratch. + + 1. The only exception from the rule above is if you mistakenly named your branch to contain special characters and somehow ended up in a state where it has become impossible to push changes to the remote due to this (which has happened before with branch names like `refactor(core-api): x` that had to be renamed to `refactor-core-api-x` and then a new PR had to be created in that case because GitHub does not let you rename the remote branch that your pull request is tied to) + + 2. If you are having trouble, there are many great resources out there (so we will not write another here). + + 1. If you are having trouble locating a suitable guide specifically on the mechanics of rebasing, we can recommend [this one](https://thoughtbot.com/blog/git-interactive-rebase-squash-amend-rewriting-history). Thanks to Rafael for the link! + + 2. If you went through that tutorial and still not quite sure what’s up, give this one a shot as well: https://about.gitlab.com/blog/2020/11/23/keep-git-history-clean-with-interactive-rebase/ + + 3. If merge conflicts arise, you must fix these at rebase time since omitting this step does not magically make the conflicts go away, just pushes it over the fence to the maintainer who will attempt to merge your pull request at a later point in time. + + 4. If the above happens, at that point said maintainer will most likely ask you (if not already) to perform the rebase anyway since as the author of a change you are best positioned to resolve any conflicts on the code level. Occassionally maintainers may do the merge/conflict resolution themselves, but do not count on this nor try to make a habit out of relying on the potential kindness. + + 5. After successful rebasing, take another look at your commit(s). Ideally there should be just one in each pull request, but also on the other hand each commit should be as small, simple and self contained as possible, so there can be cases where it makes sense to submit a PR with multiple commits if for example you also had to change something in the test tooling while implementing a feature (in which case there could be a commit for the feature itself and another for the necessary changes to the test tooling package). What we respectfully ask though is that you try to avoid these situations and submit most of your PRs with a single, self contained commit that does not touch multiple things. This significantly reduces the cognitive load required to review the changes which in turn makes everyone happier: the maintainers will have an easier job reviewing, which means they’ll be doing it faster which will (probably) cause you joy in turn. + +9. Push your changes to your main (or whatever you named your feature branch, that is entirely up to you at the end of the day) + +10. Initiate a pull request from your fork to the base repository + +11. Remember: Opening a pull request is like saying “Hey maintainers, I have this change finalized and ready for you to spend time on reviewing it.” The word `finalized` here is understood to imply that you are not planning on doing any more changes on the branch apart from when being asked to by the reviewers. + +12. It is perfectly acceptable to open a pull request and mark it as `draft` (a GitHub feature) which then signals to the maintainers that if they have time, they are welcome to look at the change, but it may or may not be in its final form yet so you are not responsible for potential loss of time on their end if the review has to be performed multiple times on account of changes. Once you promote your draft PR to a real one, the comments from the point above apply however. + +13. If your pull request contains a significant change, we recommend that you apply the similarly named github label on in it as well. It is okay if you do not do this, if we detect that the change is indeed significant, we will apply the label. If you do it in advance however, it will probably speed up the proceedings by removing one communication roundtrip from the review process of your pull request. + +14. Await CI, DCO & linting quality checks, as well as any feedback from reviewers + +15. If you need to update your pull request either because you discovered an issue or because you were asked to do so we ask that you: + +16. try to add the change in a way that does not produce additional commits on the PR but instead do an `git commit --amend --signoff` on your local branch and then a force push to the remote branch of yours (the PR essentially). Again, if the change you are doing does not fit within any one of the existing commits of your PR, then it is justified to add a new commit and this is up to your discretion (maintainers may respectfully ask you to squash if they see otherwise) + +17. The rule of thumb for any and all things in git/Cactus is to maintain a clean, tidy commit log/history that enables everyone to easily look up changes and find accurate answers to the basic questions of `Who? / What? / When / Why?`. If you have ever been in a situation when you tried to figure out the original point a bug was introduced (and tried to figure out why the offending change was made in the first place) and the git blame just lead you to a 10 megabyte large patch with the message ‘merge xyz’, then you know exactly what it is we are trying to avoid here. :-) + + +PR Checklist - Maintainer/Reviewer +---------------------------------------------------------------------------------------------------- + +Ensure all the following conditions are met (on top of you agreeing with the change itself) + +1. All automated checks that are not explicitly called out here are also passing/green. + +2. Branch is rebased onto main and there are no dangling/duplicate commits. + +3. Commits appear simple and self contained. Simple is always relative to the mangitude of the change itself of course. A 1k line change can still be simple if all it does is rename some commonly used variable in each place its being used. + +4. If the contributors are having trouble with git basic functionality such as rebasing / force pushing, DCO, do your best to help them out, when in doubt feel free to reach out to Peter (who is the one insisting an all these git rules so he deserves to be the primary contact for all git related issues). + + 1. Remember that we want to foster a welcoming community so if someone is new to git try to be extra patient with them on this front. + +5. Ensure the commit messages are according to the standard format. + + 1. Remember that if you select ‘squash’ on the Github UI when accepting the pull request, Github will (by default) offer up the title of the pull request as the new commit message for your squash commit. This is not good unless the title happens to be a valid commit message, but in the likely event of it not being as such, you must take special care to type in a valid commit message right there and then on the Github UI. + + 2. To avoid the hassle/potential issues with the above, it is recommended that you always use ‘rebase’ when accepting a pull request even if there are multiple commits that you’d otherwise like to see squashed. + + 3. If you are adamant that you do not want to merge a PR with multiple commits, that is completely understandable and fair game. The recommended approach there is to ask the contributor to break the pull request up to multiple pull requests by doing an interactive rebase on their branch and cherry picking/re-ordering things accordingly. This is a fairly advanced git use case so you might want to help them out with it (or ask Peter who is the one constantly nagging everyone about these git rules…) + + +To protect the Hyperledger Cactus source code, GitHub pull requests are accepted from forked repositories only. There are also quality standards identified and documented here that will be enhanced over time. + +Create local branch +------------------------------------------------------------------------ + +> Whenever you begin work on a new feature or bugfix, it’s important that you create a new branch. + +1. Clone your fork to your local machine + +2. Setup your local fork to keep up-to-date (optional) + + \# Add 'upstream' repo to list of remotes + git remote add upstream https://github.com/hyperledger/cactus.git + + \# Verify the new remote named 'upstream' + git remote \-v + + \# Checkout your main branch and rebase to upstream. + \# Run those commands whenever you want to synchronize with main branch + git fetch upstream + git checkout main + git rebase upstream/main + +3. Create your branch. + + \# Checkout the main branch - you want your new branch to come from main + git checkout main + + \# Create a new branch named \`\` (give simple informative name) + git branch + +4. Checkout your branch and add/modify files. + + git checkout + git rebase main + \# Happy coding ! + +5. Commit changes to your branch. + + \# Commit and push your changes to your fork + git add \-A + git commit \-s \-m "\[optional scope\]: " + git push origin + +6. Once you’ve committed and pushed all of your changes to GitHub, go to the page for your fork on GitHub, select your development branch, and click the pull request button. + +7. Repeat step 3 to 6 when you need to prepare posting new pull request. + + +NOTE: Once you submitted pull request to Cactus repository, step 6 is not necessary when you made further changes with `git commit --amend` since your amends will be sent automatically. + +NOTE: You can refer original tutorial [‘GitHub Standard Fork & Pull Request Workflow’](https://gist.github.com/Chaser324/ce0505fbed06b947d962) + +### Directory structure + +Whenever you begin to use your codes on Hyperledger Cactus, you should follow the directory strecture on Hyperledger Cactus. The current directory structure is described as the following: + +> * contrib/ : Contributions from each participants, which are not directly dependent on Cactus code. +> +> * Fujitsu-ConnectionChain/ +> +> * Accenture-BIF/ +> +> * docs/ +> +> * API/ +> +> * business-logic-plugin.md +> +> * ledger-plugin.md +> +> * routing-interface.md +> +> * examples/ +> +> * example01-car-trade/ +> +> * src/ +> +> * plugins/ +> +> * business-logic-plugin/ +> +> * lib/ : libraries for building Business Logic Plugin +> +> * ledger-plugin/ : Codes of Ledger Plugin +> +> * (ledger-name)/ : Including the ledger name (e.g. Ethereum, Fabric, …) +> +> * verifier/ +> +> * src/ : Source codes of Verifier on Ledger Plugin +> +> * unit-test/ : Unit test codes of Verifier on Ledger Plugin (single driver / driver and docker env / …) +> +> * validator/ +> +> * src/ : Source codes of Validator on Ledger Plugin +> +> * unit-test/ : Unit test codes of Validator on Ledger Plugin (single driver / driver and docker env / …) +> +> * routing-interface/ +> +> * whitepaper/ +> +> * test/ +> +> * docker-env/ +> +> * kubernetes-env/ +> + +Test Automation +---------------------------------------------------------------- + +> Mantra: Testable code is maintainable code + +### Summary + +We are all about automating the developer flow wherever possible and a big part of this is automated testing of course. + +Whenever contributing a change it is important to have test coverage for the specific change that you are making. This is especially important for bugs and absolutely essential for security related changes/fixes. + +Writing testable code is very important to us as not doing so can (and will) snowball into an avalanche of technical debt that will eventually destroy code quality and drive people away who would otherwise be happy to contribute and use the software. So, we want to make sure that does not happen with all this. + +This also means that occassionally, when making a change that looks simple on the surface you may find that the reviewer of your pull request asks you to do additional, seemingly unrelated changes that have nothing to do with the actual feature/bug that you just implemented/fixed, but instead are designed to ensure that tests can be written for it or for related code. + +This can feel like a chore (because it is) but we respectfully ask everyone to try their best in accomodating this because it really helps steering the ship on the long run. + +One of the simplest examples for the above is when you have a class that does something, anything, and it depends on some shared resource to achieve it. The shared resource can be the file system or a network port that is open for TCP connections for example. You can implement your class hardcoding the port number and functionally it will be correct (if you did that part right) _BUT_ if your class does not allow for the customization of said port through the constructor or a setter method, then one of our more obsessive maintainers (like Peter) will immediately be onto you asking for a change so that the port can be customized at runtime, allowing test cases to pass in port 0 that makes the test executable in parallel with other tests without being flaky. + +If you oppose this idea, said maintainers will happily refer you to this writing or conjure up an entirely new essay right there on the pull request. + +### Test Case Core Principles + +There are other principles specific per unit and integration tests, but the list below applies to all tests regardless of their nature. + +`All test cases must be...` + +* Self contained programs that can be executed on their own if necessary + + * This ensures that if you are iterating on a single test case while trying to make it pass, you will always have the freedom to run just that one test instead of running the full suite of which the execution time will grow rapidly as we add test coverage, so, better nip that in the bud with this principle. + +* Excluded from the public API surface of the package they are in by ensuring that the test classes/types/interfaces are NOT exported through the `public-api.ts` file of that particular package. + + * The only exception from this is if a package is itself designed for tests for which a delightful example is the `test-tooling` package which as the name suggests is entirely designated for providing utilities for writing tests and therefore in the case of this package it is allowed and even expected that it will expose test related classes/types in it’s public API surface. Do note however that indirectly the principle still applies, meaning that any package must not depend on the `test-tooling` package as an npm `dependency` but rather it must declare it as a `devDependency` in the relevant section of the `package.json` file. + +* Compatible with the [TestAnythingProtocol](https://testanything.org/) + + * The NodeJS implementation of said protocol is in the `node-tap` npm package: + + * [Assertions API](https://node-tap.org/docs/api/asserts/) of Node TAP + + * Simplest possible test case: + + const test, { Test } \= require("tape"); + import \* as publicApi from "../../../main/typescript/public-api"; + + test("Module can be loaded", (t: Test) \=> { + t.ok(publicApi); + t.end(); // yaay, test coverage + }); + + * An [end to end test case](#./packages/cactus-test-plugin-consortium-manual/src/test/typescript/integration/plugin-consortium-manual/security-isolation-via-api-server-ports.ts) showcasing everything in action that is being preached in this document about test automation + +* Focus/verify a single bug-fix/feature/etc. + +* Clearly separated from non-test (aka `main`) source code. This means in practice that we ask that your test cases are either in the + + 1. `./src/test/...` tree of the package that you are testing OR + + 2. your test cases are in the `./src/test/...` tree (yes same name) BUT in an entirely separate package if the dependencies necessitate so. An example to when you would need a separate testing package is if you are developing a ledger plugin that has REST API endpoints shipping with it and you wish to verify in a test that the plugin can be loaded to the `ApiServer` and then called via the web service/SDK. In this case, you cannot place your test case in the ledger plugin’s package because you want to avoid having to pull in the API server as a dependency of your ledger plugin package (to ensure that there will be no circular dependencies). + +* Executable with unlimited parallelism (so if I have a 128 test cases and run all of them in parallel on my new 128 CPU core computer, then every single test case runs at the same time) + + * This is important because it weeds out flakyness and hardcoded references to shared resources (Remember the rant about network ports in the previous section?) + + * _BUT_ it is also very important because we (as in humanity) spent the last decade making the average CPUs ship with more and more cores as increasing frequency failed in the late 2000s as a performance increasing strategy. + + What this means is that to utilize the average consumer laptop that most people will have for development, you will need your test cases to run in parallel which will save time for everyone working on the code and faster turnaround times make for a better developer experience which makes for a happier community around our open source project. It’s all connected. ;-) + +* Test cases don’t depend on code outside of the `./src/*` directory trees of the packages. + + * Do not depend on any of the example code in your test cases. + + * If you need to import code that is not JS/JSON/TS you can still do so via the Typescript compiler’s relevant feature that allows importing arbitrary files. + + +Working with the Code +---------------------------------------------------------------------------- + +There are additional details about this in the [BUILD.md](#./BUILD.md) file in the project root as well. + +We use Lerna for managing the [monorepo](https://blog.npmjs.org/post/186494959890/monorepos-and-npm) that is Cactus. + +> We heavily rely on Docker for testing the ledger plugins. + +### Running/Debugging the tests + +Make sure to have the build succeed prior to attempting to run the tests. If you just checked out the project, it is best to just to just run the CI script which will do a full build and run all tests for you. If it fails you can open a bug in the issue tracker. + +Assuming you have built the sources, below are the different methods to run the tests: + +#### Running a single test case + +You execute unit and integration tests in the same way, but here are examples for both them separately anyway: + +* An integration test: + + yarn jest packages/cactus-test-plugin-consortium-manual/src/test/typescript/integration/plugin-consortium-manual/get-consortium-jws-endpoint.test.ts + +* A unit test: + + npx jest packages/cactus-common/src/test/typescript/unit/objects/get-all-method-names.test.ts + + You can also run tests via the VS Code user interface. To do so, make sure you rename `template.launch.json` to \`\`launch.json\`. Under the “Run and Debug” window of VS Code, select “JEST: Current TS file” to test the currently opened file. + + +#### Running all test cases (unit+integration) + +npm run test:all + +#### Running unit tests only + +npm run test:unit + +#### Running integration tests only + +npm run test:integration + +#### What is npx used for? + +`npx` is a standard top level binary placed on the path by NodeJS at installation time. We use it to avoid having to place every node module (project dependencies) on the OS path or to install them globally (`npm install some-pkg -g`) + +Read more about npx here: https://blog.npmjs.org/post/162869356040/introducing-npx-an-npm-package-runner + +#### What’s the equivalent of npx for Yarn? + +Yarn itself. E.g. `npx lerna clean` becomes `yarn lerna clean`. + +#### Debugging a test case + +Open the `.vscode/template.launch.json` file and either copy it with a name of `launch.json` (if you don’t already have such a file) or just cherry pick the example Visual Studio Code debug tasks that you’d like to use. For debugging a single test case, you need the debug task from the template launch.json file that is called `TAP: Current TS Test File`. Prior to running that debug task you must have your VSCode editor opened to the test file that you wish to run. Breakpoints will work as long as you are debugging code in the same package. + +> Source map support is partial at this point but actively being worked on. + +### All-In-One Docker Images for Ledger Connector Plugins + +If you are working on a new ledger connector you’ll need an `all-in-one` docker image as well, which will allow the expected level of test automation. If your chosen ledger’s maintainers provide an adequate docker image, then you might not need to develop this yourself, but this is rarely the case so YMMV. + +To see an existing set of examples for `besu` and `quorum` images take a peek at the `tools/docker/besu-all-in-one` and `tools/docker/quorum-all-in-one` folders. These produce the `ghcr.io/hyperledger/cactus-besu-all-in-one` and `ghcr.io/hyperledger/cactus-quorum-all-in-one` images respectively. Both of these are used in the test cases that are written for the specific ledger connector plugins at: + +* `packages/cactus-test-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/deploy-contract-via-web-service.test.ts` + +* `packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts` + + +The specific classes that utilize the `all-in-one` images can be found in the `test-tooling` package under these paths: + +* `packages/cactus-test-tooling/src/main/typescript/besu/besu-test-ledger.ts` + +* `packages/cactus-test-tooling/src/main/typescript/quorum/quorum-test-ledger.ts` + + +#### Test Automation of Ledger Plugins + +Ledger plugin tests are written the same way as any other test (which is difficult to achieve, but we thrive to get it done). + +The only difference between a ledger connector plugin test case and any unit test is that the ledger connector plugin’s test case will pull up a docker container from one of the `all-in-one` images that we maintain as part of Cactus and then use that `all-in-one-*` container to verify things such as the ability of the ledger connector plugin to deploy a contract to said ledger. + +As a generic best practice, the test cases should never re-use any `all-in-one` ledger container for the execution of multiple test cases because that will almost surely lead to flaky/unstable test cases over the long run and needless complexity, ordering dependencies and so on. It is recommended that if you have two test cases for a ledger connector plugin, they both pull up a newly created container from scratch, execute the test scenario and then tear down and delete the container completely. + +An example for a ledger connector plugin and it’s test automation implemented the way it is explained above: `packages/cactus-test-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/deploy-contract-via-web-service.test.ts` + +> This test case is also an example of how to run an ApiServer independently with a single ledger plugin which is how the test case is set up to begin with. + +Another option if you want to perform some tests manually is to run the API server with a configuration of your choice: + +\# Starting from the project root directory + +chmod +x ./packages/cactus-cmd-api-server/dist/lib/main/typescript/cmd/cactus-api.js + +./packages/cactus-cmd-api-server/dist/lib/main/typescript/cmd/cactus-api.js \--config-file\=.config.json + +You can run this test case the same way you would run any other test case (which is also a requirement in itself for each test case): + +npx tap \--ts \--timeout\=600 packages/cactus-test-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/deploy-contract-via-web-service.test.ts + +You can specify an arbitrary set of test cases to run in a single execution via glob patterns. Examples of these glob patterns can be observed in the root directory’s `package.json` file which has npm scripts for executing all tests with a single command (the CI script uses these): + +"test:all": "tap --ts --jobs=1 --timeout=600 \\"packages/cactus-\*/src/test/typescript/{unit,integration}/\\"", +"test:unit": "tap --ts --timeout=600 \\"packages/cactus-\*/src/test/typescript/unit/\\"", +"test:integration": "tap --ts --jobs=1 --timeout=600 \\"packages/cactus-\*/src/test/typescript/integration/\\"" + +Following a similar pattern if you have a specific folder where your test cases are, you can run everything in that folder by specifying the appropriate glob patterns (asterisks and double asterisks as necessary depending on the folder being a flat structure or with sub-directories and tests nested deep within them). + +For example this can work as well: + +\# Starting from the project root +cd packages/cactus-test-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum +npx tap \--ts \--jobs\=1 \--timeout\=600 \\"./\\" + +> Be aware that glob patterns need quoting in some operating system’s shell environments and not necessarily on others. In the npm scripts Cactus uses we quote all of them to ensure a wider shell compatibility. + +### Building the API Client(S) + +You do not need to do anything special to have the API Client sources generated and compiled. It is all part of the `npm run build:dev:backend` task which you can run yourself or as part of the CI script (`./tools/ci.sh`). + +The API client code is automatically generated from the respective `openapi.json` file of each package that exposes ay web serices (REST/SocketIO/gRPC/etc.) and can be dependend on by other packages where applicable. There’s a dedicated `@hyperledger/cactus-api-client` package that is meant to contain common functionality among the rest of API clients. The concept here is similar to abstract classes and their sub-class implementations. + +Each `openapi.json` produces its own API client via the code generator that also contains relevant model definitions, such as interfaces describing the request/response bodies of all possible operations and validation constraints as well. + +The API clients are designed to be a universal components, meaning that it runs just fine in browser and also NodeJS environments. This is very important as we do not wish to maintain two (or more) separate API client codebases for the various platforms and we also want as much of it being generated automatically as possible (currently this is close to 100%). + +### Adding new dependencies + +Example: + +\# Adds "got" as a dependency to the cactus common package +\# Note that you must specify the fully qualified package name as present in +\# the package.json file +yarn workspace @hyperledger/cactus-common add got \--save-exact + +You need to know which package of the monorepo will be using the package and then run the `yarn workspace` command with an additional parameters specifying the package name and the dependency name. See [Yarn Workspaces Documentation](https://classic.yarnpkg.com/en/docs/cli/workspace/) for the official Yarn documentation for further details and examples. + +After adding new dependencies, you might need to [Reload VSCode Window After Adding Dependencies](#reload-vscode-window-after-adding-dependencies) + +> **Always specify the `--save-exact` when installing new dependencies to ensure [reproducible builds](https://reproducible-builds.org/)** + +### Reload VSCode Window After Adding Dependencies + +If you added a new dependency and VSCode is showing an error when you try to import it, then sometimes the issue is just a matter of nudging VSCode to reload the Typescript definitions from scratch so that it “notices” the new dependency you just added. + +The recommended way of doing this is by hitting the `F1` key (or whatever you have bound the command menu to) and then searching and selecting `Developer: Reload Window` As a simpler alternative you can also just quit and relaunch the VSCode application of course. + +### On Reproducible Builds + +As a best practice, any given revision (commit hash) stored in version control should produce the exact same build artifacts regardless of when or where the build was performed. This can only be achieved if npm dependency versions are locked down instead of being automatically upgraded by npm (which makes the build time and machine dependent). + +Bottom line: Do not use the the `^`, `~` and `*` syntax elements while declaring your npm dependencies. + +Further details: + +* https://reproducible-builds.org/ + +* https://spin.atomicobject.com/2016/12/16/reproducible-builds-npm-yarn/ + + +[Previous](code-of-conduct.md "Code of Conduct Guidelines") [Next](whitepaper.md "Hyperledger Cactus White Paper") + +* * * diff --git a/docs/docs/cactus/examples.md b/docs/docs/cactus/examples.md new file mode 100644 index 0000000000..a1b44465d2 --- /dev/null +++ b/docs/docs/cactus/examples.md @@ -0,0 +1,10 @@ +Examples +================================================== + +This section shows the sample applications that are provisioned by the Hyperledger Cactus. + +* [Supply Chain App](examples/supply-chain-app.md) + +[Previous](build.md "Hyperledger Cactus Build Instructions") [Next](examples/supply-chain-app.md "Hyperledger Cactus Example - Supply Chain App") + +* * * diff --git a/docs/docs/cactus/examples/supply-chain-app.md b/docs/docs/cactus/examples/supply-chain-app.md new file mode 100644 index 0000000000..71409a80e7 --- /dev/null +++ b/docs/docs/cactus/examples/supply-chain-app.md @@ -0,0 +1,128 @@ +Example - Supply Chain App +========================================================================================================================== + +Usage +-------------------------------------------- + +1. Execute the following from: + + docker run \\ + \--rm \\ + \--privileged \\ + \-p 3000:3000 \\ + \-p 3100:3100 \\ + \-p 3200:3200 \\ + \-p 4000:4000 \\ + \-p 4100:4100 \\ + \-p 4200:4200 \\ + ghcr.io/hyperledger/cactus-example-supply-chain-app:2022-04-05--feat-1579 + +2. Observe the example application pulling up in the logs + + 1. the test ledger containers, + + 2. a test consortium with multiple members and their Cactus nodes + +3. Wait for the output to show the message `INFO (api-server): Cactus Cockpit reachable http://0.0.0.0:3200` + +4. Visit http://0.0.0.0:3200 in your web browser with Javascript enabled + + +Building and running the container locally +---------------------------------------------------------------------------------------------------------------------- + +\# Change directories to the project root + +\# Build the docker image and tag it as "scaeb" for supply chain app example backend +DOCKER\_BUILDKIT\=1 docker build \-f ./examples/supply-chain-app/Dockerfile . \-t scaeb + +\# Run the built image with ports mapped to the host machine as you see fit +\# The --privileged flag is required because we use Docker-in-Docker for pulling +\# up ledger containers from within the container in order to have the example +\# be completely self-contained where you don't need to worry about running +\# multiple different ledgers jus this one container. +docker run \--rm \-it \--privileged \-p 3000:3000 \-p 3100:3100 \-p 3200:3200 \-p 4000:4000 \-p 4100:4100 \-p 4200:4200 scaeb + +Building the image with a specific npm package version: + +DOCKER\_BUILDKIT\=1 docker build \\ + \--build-arg NPM\_PKG\_VERSION\=jwt-supply-chain \\ + \--file ./examples/supply-chain-app/Dockerfile \\ + \--tag scaeb \\ + ./ + +Running the Example Application Locally +---------------------------------------------------------------------------------------------------------------- + +> Make sure you have all the dependencies set up as explained in `BUILD.md` + +On the terminal, issue the following commands: + +1. `npm run install-yarn` + +2. `yarn configure` + +3. `yarn start:example-supply-chain` + + +Debugging the Example Application Locally +-------------------------------------------------------------------------------------------------------------------- + +On the terminal, issue the following commands (steps 1 to 6) and then perform the rest of the steps manually. + +1. `npm run install-yarn` + +2. `yarn configure` + +3. `yarn build:dev` + +4. `cd ./examples/supply-chain-app/` + +5. `yarn --no-lockfile` + +6. `cd ../../` + +7. Locate the `.vscode/template.launch.json` file + +8. Within that file locate the entry named `"Example: Supply Chain App"` + +9. Copy the VSCode debug definition object from 2) to your `.vscode/launch.json` file + +10. At this point the VSCode `Run and Debug` panel on the left should have an option also titled `"Example: Supply Chain App"` which starts the application + +11. When the application finishes loading, the JWT token generated is displayed on the terminal + +12. Visit http://localhost:3200 in a web browser with Javascript enabled and insert the token when prompted + + +Live Reloading the GUI Application +------------------------------------------------------------------------------------------------------ + +1. `npm run install-yarn` + +2. `yarn configure` + +3. `yarn build:dev` + +4. Locate the `.vscode/template.launch.json` file + +5. Within that file locate the entry named `"Example: Supply Chain App"` + +6. Copy the VSCode debug definition object from 2) to your `.vscode/launch.json` file + +7. At this point the VSCode `Run and Debug` panel on the left should have an option also titled `"Example: Supply Chain App"` which starts the application + +8. `cd ./examples/cactus-example-supply-chain-frontend/` + +9. `yarn serve:proxy` + +10. When the application finishes loading, the JWT token generated is displayed on the terminal + +11. Visit http://localhost:8000 in a web browser with Javascript enabled and insert the token when prompted + +12. At this point if you modify the source code of the GUI application under the `./examples/cactus-example-supply-chain-frontend/` path it will automatically reload the browser window (you will need to paste in the JWT again when this happens) + + +[Previous](../examples.md "Examples") [Next](../governance.md "Governance") + +* * * diff --git a/docs/docs/cactus/governance.md b/docs/docs/cactus/governance.md new file mode 100644 index 0000000000..a30538e1c9 --- /dev/null +++ b/docs/docs/cactus/governance.md @@ -0,0 +1,72 @@ +Governance +====================================================== + +Hyperledger Cactus is managed under an open governance model as described in the Hyperledger charter. Cactus is led by a set of maintainers, who can be found in the MAINTAINERS.md file. + +**Maintainers** + +Cactus is led by the project’s maintainers. The maintainers are responsible for reviewing and merging all patches submitted for review, and they guide the overall technical direction of the project within the guidelines established by the Hyperledger Technical Steering Committee (TSC). + +**Becoming a Maintainer** + +The project’s maintainers will, from time-to-time, consider adding or removing a maintainer. An existing maintainer can submit a change set to the MAINTAINERS.md file. A nominated contributor may become a maintainer by a three-quarters approval of the proposal by the existing maintainers. Once approved, the change set is then merged and the individual is added to (or alternatively, removed from) the maintainers group. + +Maintainers may be removed by explicit resignation, for prolonged inactivity (3 or more months), or for some infraction of the code of conduct or by consistently demonstrating poor judgement. A maintainer removed for inactivity should be restored following a sustained resumption of contributions and reviews (a month or more) demonstrating a renewed commitment to the project. We require that maintainers that will be temporarily inactive do so “gracefully” and update other maintainers on their status and time availability rather than appearing to “fall off the face of the earth.” + +**Releases** + +A majority of the maintainers may decide to create a release of Cactus. Any broader rules of Hyperledger pertaining to releases must be followed. Once the project is mature, there will be a stable LTS (long term support) release branch, as well as the main branch for upcoming new features. + +**Making Feature/Enhancement Proposals** + +Code changes that are either bug fixes, direct and small improvements, or things that are on the roadmap (see below) can be issued as PRs in a relatively quick time period, although we recommend creating a Github ticket to track even bugs and small improvements. For more substantial changes, however, a feature/enhancement proposal is required. These proceed through the approval process like typical PRs, and require the same “2 + 1” approval policy for acceptance. + +In particular, all contributors to the project should have enough time to voice an opinion on feature/enhancement proposals before they are accepted. So the maintainers will determine some “comment period” between proposal submission and acceptance so that contributors have enough time to voice their opinions. + +Significant changes can be marked as such via the predefined label with the same name. This is a tool that helps maintainers identify the most important issues/discussions to be had at any given time through the GitHub web interface. + +To easily access the list of significant changes, navigate to the label: https://github.com/hyperledger/cactus/labels/Significant\_Change + +We also recommend reading our CONTRIBUTING.md file (https://github.com/hyperledger/cactus/blob/main/CONTRIBUTING.md) for more information about contributing. + +**Approving Pull Requests** + +Maintainers designated for review are required to review PRs in a timely manner (all circumstances considered, of course). Any pull request must be reviewed by at least two maintainers, and if a PR is submitted by a maintainer, these two reviewers must be different from the original submitter. + +The technical requirements for submitting/approving/merging pull requests are further detailed in the CONTRIBUTING.md file where it is laid out in detail how to ensure git commit graph tidiness. + +**Reviewing Pull Requests** + +We are strongly committed to processing pull requests from everyone in a fair manner meaning that pull requests are to be reviewed in order of submission. Reviewing PRs in order of submission does not guarantee nor necessitate accepting/merging said PRs in order of submission since some PRs may require lengthy feedback loops while others may pass the muster without any change requests or feedback at all, depending on the nature of the change being proposed. Security related pull requests may be fast tracked even against the “in order of submission” principle if it appears that a vulnerability makes a pull request a time sensitive issue where the sooner we propagate a fix the better it is. + +**Maintainers Meeting** + +The maintainers hold regular maintainers meetings, which are open to everyone. The purpose of the maintainers meeting is to plan for and review the progress of releases, and to discuss the technical and operational direction of the project. + +Please see the wiki for maintainer meeting details. + +One point to mention about meetings is that new feature/enhancement proposals as described above should be presented to a maintainers meeting for consideration, feedback, and acceptance. + +**Roadmap** + +The Cactus maintainers are required to maintain a roadmap. There is a technical roadmap, with all of the issues as they directly relate to code, and a more public-friendly roadmap that anyone can digest. The required features to be implemented will be maintained as issues at the official github repository of Cactus with tag string ‘for current release’ or ‘for future release’. The task which is not volunteered to work, will be dispatched to specific contributors following consensus among the majority of maintainers. + +The technical roadmap is implicitly derived from the Github “milestones” feature. To access the list of milestones for Cactus use this link: https://github.com/hyperledger/cactus/milestones + +**Communications** + +We use the Cactus email list for long-form communications and RocketChat for short, informal announcements and other communications. We encourage all communication, whenever possible, to be public and in the clear (i.e. rather than sending an email directly to a person or two, send it out to the whole list if it pertains to the project). + +**Future Changes** + +The governance of Cactus may change as the project evolves. In particular, if the project becomes large, we will incorporate tiered maintainership, with top-level maintainers, subprojects, subproject maintainers, release managers, and so forth. We emphasize that this document is intended to be “living” and will be updated periodically. + +We require that changes to this document require a three-quarters approval of the existing maintainers. Note that this may also be changed in the future if deemed necessary. + +**Attribution** + +This document is based on the Hyperledger Fabric governance document, with some substantial changes. + +[Previous](examples/supply-chain-app.md "Hyperledger Cactus Example - Supply Chain App") [Next](code-of-conduct.md "Code of Conduct Guidelines") + +* * * diff --git a/docs/docs/cactus/introduction.md b/docs/docs/cactus/introduction.md new file mode 100644 index 0000000000..5476aa3b34 --- /dev/null +++ b/docs/docs/cactus/introduction.md @@ -0,0 +1,28 @@ +Welcome to Hyperledger Cactus documentation! +========================================================================================================================= + +Hyperledger Cactus aims to provide Decentralized, Secure and Adaptable Integration between Blockchain Networks. Hyperledger Cactus is currently undergoing a major refactoring effort to enable the desired to-be architecture which will enable plug-in based collaborative development to increase the breadth of use cases & Ledgers supported. + +**What is Cactus?** + +A pluggable, enterprise-grade framework to transact on multiple distributed ledgers without introducing yet another competing blockchain. + +> * Cactus allows developers to abstract the application layer from the DLT addressing protocol fragmentation, lowering coupling and reducing implementation risks​ +> +> * Cactus allows different DLT networks to interact with each other, through atomic transactions and state commits, this eliminates information silos and increases network’s value​ +> + +**Why use Cactus?** + +> * Maximize flexibility and future-proofing through plug-in architecture. ​ +> +> * Avoid needing explicit action from users to have a secure Cactus deployment. Policies such as vaults are built into the SDK​ +> +> * Keys and other credentials are not stored in source, configuration files, or environment variables​ +> +> * Preserving Ledger Features Horizontal Scalability.​ +> + +[Next](build.md "Hyperledger Cactus Build Instructions") + +* * * diff --git a/docs/docs/cactus/packages.md b/docs/docs/cactus/packages.md new file mode 100644 index 0000000000..4f509dfc18 --- /dev/null +++ b/docs/docs/cactus/packages.md @@ -0,0 +1,23 @@ +Cactus Components +==================================================================== + +This section contains the components to form Hyperledger Cactus. + +* [Api Client](packages/cactus-api-client.md) +* [CMD Api Server](packages/cactus-cmd-api-server.md) +* [Cactus Common](packages/cactus-common.md) +* [Cactus Core](packages/cactus-core.md) +* [Consortium Manual](packages/cactus-plugin-consortium-manual.md) +* [Keychain Vault](packages/cactus-plugin-keychain-vault.md) +* [Connector Besu](packages/cactus-plugin-ledger-connector-besu.md) +* [Connector Corda](packages/cactus-plugin-ledger-connector-corda.md) +* [Connector Fabric](packages/cactus-plugin-ledger-connector-fabric.md) +* [Connector Quorum](packages/cactus-plugin-ledger-connector-quorum.md) +* [Test Api Client](packages/cactus-test-api-client.md) +* [Test CMD Api Server](packages/cactus-test-cmd-api-server.md) +* [Test Connector Quorum](packages/cactus-test-plugin-ledger-connector-quorum.md) +* [Test Tooling](packages/cactus-test-tooling.md) + +[Previous](regulatory-and-industry-initiatives-reading-list.md "Regulatory and Industry Initiatives Reading List") [Next](packages/cactus-api-client.md "@hyperledger/cactus-api-client") + +* * * diff --git a/docs/docs/cactus/packages/cactus-api-client.md b/docs/docs/cactus/packages/cactus-api-client.md new file mode 100644 index 0000000000..3690aef39c --- /dev/null +++ b/docs/docs/cactus/packages/cactus-api-client.md @@ -0,0 +1,140 @@ +`@hyperledger/cactus-api-client` +================================================================================================ + +Summary +------------------------------------------------ + +The Hyperledger Cactus API Client package is designed to be a generic extension with convenience features wrapped around the \[**typescript-axios** flavored API clients\][(https://github.com/OpenAPITools/openapi-generator/blob/v5.2.1/docs/generators/typescript-axios.md](https://github.com/OpenAPITools/openapi-generator/blob/v5.2.1/docs/generators/typescript-axios.md)) that we auto-generate and ship with each web service-enabled plugin such as the API clients of the + +* [**Manual Consortium Plugin** Typescript Axios API Client](https://github.com/hyperledger/cactus/tree/main/packages/cactus-plugin-consortium-manual/src/main/typescript/generated/openapi/typescript-axios) + +* [**Besu Connector** Typescript Axios API Client](https://github.com/hyperledger/cactus/tree/main/packages/cactus-plugin-ledger-connector-besu/src/main/typescript/generated/openapi/typescript-axios) + +* [**Corda Connector** Typescript Axios API Client](https://github.com/hyperledger/cactus/tree/main/packages/cactus-plugin-ledger-connector-corda/src/main/typescript/generated/openapi/typescript-axios) + +* [**Fabric Connector** Typescript Axios API Client](https://github.com/hyperledger/cactus/tree/main/packages/cactus-plugin-ledger-connector-fabric/src/main/typescript/generated/openapi/typescript-axios) + +* [**Quorum Connector** Typescript Axios API Client](https://github.com/hyperledger/cactus/tree/main/packages/cactus-plugin-ledger-connector-quorum/src/main/typescript/generated/openapi/typescript-axios) + +* [**API Server** Typescript Axios API Client](https://github.com/hyperledger/cactus/tree/main/packages/cactus-cmd-api-server/src/main/typescript/generated/openapi/typescript-axios) + +* [**Vault Keychain Plugin** Typescript Axios API Client](https://github.com/hyperledger/cactus/tree/main/packages/cactus-plugin-keychain-vault/src/main/typescript/generated/openapi/typescript-axios) + + +The code generation for the listed code folders above is done by the [OpenAPI Generator](https://github.com/OpenAPITools/openapi-generator) tool that can convert OpenAPI V3 json specifications of ours straight into the program code of the API clients. + +The above means that the `ApiClient` class is not the one containing the implementation responsible for executing all the supported API calls by a Cactus node (which would make it a monolith, something that we try to avoid as it is the opposite of a flexible plugin architecture) + +For example you can use the `@hyperledger/cactus-api-client` node package to perform Cactus node discovery based on ledger IDs (that can be obtained from the `ConsortiumDatabase` as defined by the [generated models](https://github.com/hyperledger/cactus/blob/main/packages/cactus-core-api/src/main/typescript/generated/openapi/typescript-axios/api.ts) of the `@hyperledger/cactus-core-api` package. + +> While you can generate API Clients for the Cactus API specifications in any supported langauge of the [OpenAPI Generator](https://github.com/OpenAPITools/openapi-generator) the features provided by this package will have to be developed separately (if not already done by the Cactus maintainers). Currently the only implementation of the abstract API Client and its features (node discovery) is in Typescript (e.g. the `@hyperledger/cactus-api-client` package). + +Usage +-------------------------------------------- + +### Routing to Cactus Node with connector to specific ledger + +Let’s say you have a consortium with several members who all have their own ledgers deployed as well. The `ConsortiumDatabase` will therefore contain the entities pertaining to these entities (such as the ledgers or the members themselves) meaning that if you are developing an application that needs to perform operations on one of the ledgers in the consortium then you have a couple of different ways of obtaining an API client to do just that: + +#### Leverage the `ConsortiumDatabase` for discovery + +import { ApiClient } from "@hyperledger/cactus-api-client"; + +import { ConsortiumDatabase, Ledger, LedgerType } from "@hyperledger/cactus-core-api"; + +import { PluginRegistry } from "@hyperledger/cactus-core"; + +import { DefaultApi as QuorumApi } from "@hyperledger/cactus-plugin-ledger-connector-quorum"; + +const mainFn \= async () \=> { + const ledgerId \= "theIdOfYourLedgerInTheConsortiumDatabase"; + + // How you obtain a consortium provider is dependent on which consortium + // plugin you use and your exact deployment scenario + const consortiumProvider: IAsyncProvider \= ...; + const consortiumDatabase: ConsortiumDatabase \= await consortiumProvider.get(); + const consortium \= consortiumDatabase.consortium\[0\]; + + const mainApiClient \= new ApiClient({ basePath: consortium.mainApiHost }); + + // This client is now configured to point to a node that has a connector to + // the ledger referenced by \`ledgerId\` + const apiClient \= await mainApiClient.ofLedger(ledgerId, QuorumApi); + + // Use the client to perform any supported operation on the ledger +}; + +mainFn(); + +#### Use a provided `mainApiHost` and `ledgerId` + +import { ApiClient } from "@hyperledger/cactus-api-client"; + +import { ConsortiumDatabase, Ledger, LedgerType } from "@hyperledger/cactus-core-api"; + +import { PluginRegistry } from "@hyperledger/cactus-core"; + +import { DefaultApi as QuorumApi } from "@hyperledger/cactus-plugin-ledger-connector-quorum"; + +const mainFn \= async () \=> { + const ledgerId \= "theIdOfYourLedgerInTheConsortiumDatabase"; + const consortiumMainApiHost \= "https://cactus.example.com"; + + const mainApiClient \= new ApiClient({ basePath: consortiumMainApiHost }); + + // This client is now configured to point to a node that has a connector to + // the ledger referenced by \`ledgerId\` + const apiClient \= await mainApiClient.ofLedger(ledgerId, QuorumApi); +} + +mainFn(); + +#### Use the API host of a node directly + +import { ApiClient } from "@hyperledger/cactus-api-client"; + +import { ConsortiumDatabase, Ledger, LedgerType } from "@hyperledger/cactus-core-api"; + +import { PluginRegistry } from "@hyperledger/cactus-core"; + +import { DefaultApi as QuorumApi } from "@hyperledger/cactus-plugin-ledger-connector-quorum"; + +const mainFn \= async () \=> { + const nodeApiHost \= "https://my-node.cactus.example.com"; + + const mainApiClient \= new ApiClient({ basePath: nodeApiHost }); + + // This client is now configured to point to a node that has a connector to the ledger of your choice + const apiClient \= await mainApiClient.extendWith(QuorumApi); +} + +mainFn(); + +Public API Surface +---------------------------------------------------------------------- + +### `DefaultConsortiumProvider` + +Builds the default Consortium provider that can be used by this object to retrieve the Cactus Consortium metadata object when necessary (one such case is when we need information about the consortium nodes to perform routing requests to a specific ledger via a connector plugin, but later other uses could be added as well). + +The DefaultConsortiumProvider class leverages the simplest consortium plugin that we have at the time of this writing: @hyperledger/cactus-plugin-consortium-manual which holds the consortium metadata as pre-configured by the consortium operators. + +The pattern we use in the ApiClient class is that you can inject your own `IAsyncProvider` implementation which then will be used for routing information and in theory you can implement completely arbitrary consortium management in your own consortium plugins which then Cactus can use and leverage for the routing. This allows us to support any exotic consortium management algorithms that people may come up with such as storing the consortium definition in a multi-sig smart contract or have the list of consortium nodes be powered by some sort of automatic service discovery or anything else that people might think of. + +### `ApiClient` + +Class responsible for providing additional functionality to the DefaultApi classes of the generated clients (OpenAPI generator / typescript-axios). + +Each package (plugin) can define it’s own OpenAPI spec which means that they all can ship with their own `DefaultApi` class that is generated directly from the respective OpenAPI spec of the package/plugin. + +The functionality provided by this class is meant to be common traints that can be useful for all of those different `DefaultApi` implementations. + +One such common trait is the client side component of the routing that decides which Cactus node to point the `ApiClient` towards (which is in itself ends up being the act of routing). + +@see — https ://github.com/OpenAPITools/openapi-generator/blob/v5.0.0-beta2/modules/openapi-generator/src/main/resources/typescript-axios/apiInner.mustache#L337 + +@see — https ://github.com/OpenAPITools/openapi-generator/blob/v5.0.0/docs/generators/typescript-axios.md + +[Previous](../packages.md "Cactus Components") [Next](cactus-cmd-api-server.md "@hyperledger/cactus-cmd-api-server") + +* * * diff --git a/docs/docs/cactus/packages/cactus-cmd-api-server.md b/docs/docs/cactus/packages/cactus-cmd-api-server.md new file mode 100644 index 0000000000..fbe8838175 --- /dev/null +++ b/docs/docs/cactus/packages/cactus-cmd-api-server.md @@ -0,0 +1,441 @@ +`@hyperledger/cactus-cmd-api-server` +======================================================================================================== + +* [Summary](#summary) + +* [Usage](#usage) + + * [Basic Example](#basic-example) + + * [Remote Plugin Imports at Runtime Example](#remote-plugin-imports-at-runtime-example) + + * [Complete Example](#complete-example) + +* [Deployment Scenarios](#deployment-scenarios) + + * [Production Deployment Example](#production-deployment-example) + + * [Low Resource Deployment Example](#low-resource-deployment-example) + +* [Containerization](#containerization) + + * [Building the container image locally](#building-the-container-image-locally) + + * [Running the container image locally](#running-the-container-image-locally) + + * [Testing API calls with the container](#testing-api-calls-with-the-container) + +* [Prometheus Exporter](#prometheus-exporter) + + * [Usage Prometheus](#usage-prometheus) + + * [Prometheus Integration](#prometheus-integration) + + * [Shutdown Hook](#shutdown-hook) + + * [Helper code](#helper-code) - [response.type.ts](#responsetypets) - [data-fetcher.ts](#data-fetcherts) - [metrics.ts](#metricsts) + +* [FAQ](#faq) + + * [What is the difference between a Cactus Node and a Cactus API Server?](#what-is-the-difference-between-a-cactus-node-and-a-cactus-api-server) + + * [Is the API server horizontally scalable?](#is-the-api-server-horizontally-scalable) + + * [Does the API server automatically protect me from malicious plugins?](#does-the-api-server-automatically-protect-me-from-malicious-plugins) + + * [Can I use the API server with plugins deployed as a service?](#can-i-use-the-api-server-with-plugins-deployed-as-a-service) + + +Summary +------------------------------------------------ + +This package is part of the Hyperledger Cactus blockchain integration framework and is used as a shell/container of sort for housing different Cactus plugins (which all live in their own npm packages as well). + +The API server gives you for free the following benefits, should you choose to use it: + +1. Automatic wiring of API endpoints for Cactus plugins which implement the `IPluginWebService` Typescript interface + +2. Lightweight inversion of control container provided to plugins in the form of the `PluginRegistry` so that plugins can depend on each other in a way that each plugin instance can be uniquely identified and obtained by other plugins. A great example of this in action is ledger connector plugins frequently using the `PluginRegistry` to look up instances of keychain plugins to get access to secrets that are needed for the connector plugins to accomplish certain tasks such as cryptographically signing some information or SSH-ing into a server instance in order to upload and deploy binary (or otherwise) artifacts of smart contracts. + + +Usage +-------------------------------------------- + +Like with most parts of the framework in Cactus, using the `ApiServer` is optional. + +To see the `ApiServer` in action, the end to end tests of the framework are a great place to start. A few excerpts that regularly occur in said tests can be seen below as well for the reader’s convenience. + +One of our design principles for the framework is **secure by default** which means that the API servers + +1. assumes TLS is enabled by default and + +2. cross-origin resource sharing is disabled completely + + +### Basic Example + +```js +#!/usr/bin/env node + +import { ApiServer } from "../api-server"; +import { ConfigService } from "../config/config-service"; +import { Logger, LoggerProvider } from "@hyperledger/cactus-common"; + +const log: Logger \= LoggerProvider.getOrCreate({ + label: "cactus-api", + level: "INFO", +}); + +const main \= async () \=> { + const configService \= new ConfigService(); + const config \= await configService.getOrCreate(); + const serverOptions \= config.getProperties(); + + LoggerProvider.setLogLevel(serverOptions.logLevel); + + if (process.argv\[2\].includes("help")) { + const helpText \= ConfigService.getHelpText(); + console.log(helpText); + log.info(\`Effective Configuration:\`); + log.info(JSON.stringify(serverOptions, null, 4)); + } else { + const apiServer \= new ApiServer({ config: serverOptions }); + await apiServer.start(); + } +}; + +export async function launchApp(): Promise { + try { + await main(); + log.info(\`Cactus API server launched OK \`); + } catch (ex) { + log.error(\`Cactus API server crashed: \`, ex); + process.exit(1); + } +} + +if (require.main \=== module) { + launchApp(); +} +``` + +### Remote Plugin Imports at Runtime Example + +```js +import { PluginImportType, PluginImportAction } from "@hyperledger/cactus-core-api"; +import { ApiServer } from "@hyperledger/cactus-cmd-api-server"; +import { ConfigService } from "@hyperledger/cactus-cmd-api-server"; +import { Logger, LoggerProvider } from "@hyperledger/cactus-common"; + +const main \= async () \=> { + + const configService \= new ConfigService(); + const apiServerOptions \= await configService.newExampleConfig(); + // If there is no configuration file on the file system, just set it to empty string + apiServerOptions.configFile \= ""; + // Enable CORS for + apiServerOptions.apiCorsDomainCsv \= "your.domain.example.com"; + apiServerOptions.apiPort \= 3000; + apiServerOptions.cockpitPort \= 3100; + apiServerOptions.grpcPort \= 5000; + // Disble TLS (or provide TLS certs for secure HTTP if you are deploying to production) + apiServerOptions.apiTlsEnabled \= false; + apiServerOptions.plugins \= \[ + { + // npm package name of the plugin you are installing + // Since this will be imported at runtime, you are responsible for + // installing the package yourself prior to launching the API server. + packageName: "@hyperledger/cactus-plugin-keychain-vault", + // The REMOTE value means that a different plugin factory will be imported and + // called to obtain the plugin instance. This way plugins can support them + // being imported by the API server regardless of the language the plugin + // was written in. + type: PluginImportType.REMOTE, + // The INSTALL value means that the plugin will be installed instead of + // only instantiate it + action: PluginImportAction.INSTALL, + // The options that will be passed in to the plugin factory + options: { + keychainId: "\_keychainId\_", + instanceId: "\_instanceId\_", + remoteConfig: configuration, + }, + }, + \]; + const config \= await configService.newExampleConfigConvict(apiServerOptions); + + const apiServer \= new ApiServer({ + config: config.getProperties(), + }); + + // start the API server here and you are ready to roll +}; + +export async function launchApp(): Promise { + try { + await main(); + log.info(\`Cactus API server launched OK \`); + } catch (ex) { + log.error(\`Cactus API server crashed: \`, ex); + process.exit(1); + } +} + +if (require.main \=== module) { + launchApp(); +} +``` + +### Complete Example + +For a complete example of how to use the API server, read all the code of the supply chain example’s backend package: + +https://github.com/hyperledger/cactus/tree/main/examples/cactus-example-supply-chain-backend/src/main/typescript + +Deployment Scenarios +-------------------------------------------------------------------------- + +There’s a set of building blocks (members, nodes, API server processes, plugin instances) that you can use when defining (founding) a consortium and these building blocks relate to each other in a way that can be expressed with an entity relationship diagram which can be seen below. The composability rules can be deducted from how the diagram elements (entities) are connected (related) to each other, e.g. the API server process can have any number of plugin instances in it and a node can contain any number of API server processes, and so on until the top level construct is reached: the consortium. + +> Consortium management does not relate to achieving consensus on data/transactions involving individual ledgers, merely about consensus on the metadata of a consortium. + +![deployment-entity-relationship-diagram.png](https://github.com/hyperledger/cactus/raw/4a337be719a9d2e2ccb877edccd7849f4be477ec/whitepaper/deployment-entity-relationship-diagram.png) + +Now, with these composability rules in mind, let us demonstrate a few different deployment scenarios (both expected and exotic ones) to showcase the framework’s flexibility in this regard. + +### Production Deployment Example + +Many different configurations are possible here as well. One way to have two members form a consortium and both of those members provide highly available, high throughput services is to have a deployment as shown on the below figure. What is important to note here is that this consortium has 2 nodes, 1 for each member and it is irrelevant how many API servers those nodes have internally because they all respond to requests through the network host/web domain that is tied to the node. One could say that API servers do not have a distinguishable identity relative to their peer API servers, only the higher-level nodes do. + +![deployment-production-example.png](https://github.com/hyperledger/cactus/raw/4a337be719a9d2e2ccb877edccd7849f4be477ec/whitepaper/deployment-production-example.png) + +### Low Resource Deployment Example + +This is an example to showcase how you can pull up a full consortium even from within a single operating system process (API server) with multiple members and their respective nodes. It is not something that’s recommended for a production grade environment, ever, but it is great for demos and integration tests where you have to simulate a fully functioning consortium with as little hardware footprint as possible to save on time and cost. + +The individual nodes/API servers are isolated by listening on seperate TCP ports of the machine they are hosted on: + +![deployment-low-resource-example.png](https://github.com/hyperledger/cactus/raw/4a337be719a9d2e2ccb877edccd7849f4be477ec/whitepaper/deployment-low-resource-example.png) + +Containerization +------------------------------------------------------------------ + +### Building the container image locally + +In the Cactus project root say: + +DOCKER\_BUILDKIT\=1 docker build \-f ./packages/cactus-cmd-api-server/Dockerfile . \-t cas \-t cactus-api-server + +Build with a specific version of the npm package: + +DOCKER\_BUILDKIT\=1 docker build \--build-arg NPM\_PKG\_VERSION\=main \-f ./packages/cactus-cmd-api-server/Dockerfile . \-t cas \-t cactus-api-server + +### Running the container image locally + +Before running the examples here you need to build the image locally. See section [Building the container image locally](#building-the-container-image-locally) for details on how to do that. + +Once you’ve built the container, the following commands should work: + +* Launch container - no plugins, default configuration + + docker run \\ + \--rm \\ + \--publish 3000:3000 \\ + \--publish 4000:4000 \\ + \--env AUTHORIZATION\_PROTOCOL\='NONE' \\ + \--env AUTHORIZATION\_CONFIG\_JSON\='{}' \\ + \--env GRPC\_TLS\_ENABLED\=false \\ + cas + +* Launch container with plugins of your choice (keychain, consortium connector, etc.) + + docker run \\ + \--rm \\ + \--publish 3000:3000 \\ + \--publish 4000:4000 \\ + \--env AUTHORIZATION\_PROTOCOL\='NONE' \\ + \--env AUTHORIZATION\_CONFIG\_JSON\='{}' \\ + \--env GRPC\_TLS\_ENABLED\=false \\ + cas \\ + ./node\_modules/.bin/cactusapi \\ + \--plugins\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-fabric", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": { "connectionProfile": {}, "instanceId": "some-unique-instance-id"}}\]' + +* Launch container with plugin configuration as an **environment variable**: + + docker run \\ + \--rm \\ + \--publish 3000:3000 \\ + \--publish 4000:4000 \\ + \--env AUTHORIZATION\_PROTOCOL\='NONE' \\ + \--env AUTHORIZATION\_CONFIG\_JSON\='{}' \\ + \--env GRPC\_TLS\_ENABLED\=false \\ + \--env PLUGINS\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}\]' \\ + cas + +* Launch container with plugin configuration as a **CLI argument**: + + docker run \\ + \--rm \\ + \--publish 3000:3000 \\ + \--publish 4000:4000 \\ + \--env AUTHORIZATION\_PROTOCOL\='NONE' \\ + \--env AUTHORIZATION\_CONFIG\_JSON\='{}' \\ + \--env GRPC\_TLS\_ENABLED\=false \\ + cas \\ + ./node\_modules/.bin/cactusapi \\ + \--plugins\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}\]' + +* Launch container with **configuration file** mounted from host machine: + + echo '\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}\]' \> cactus.json + + docker run \\ + \--rm \\ + \--publish 3000:3000 \\ + \--publish 4000:4000 \\ + \--env AUTHORIZATION\_PROTOCOL\='NONE' \\ + \--env AUTHORIZATION\_CONFIG\_JSON\='{}' \\ + \--env GRPC\_TLS\_ENABLED\=false \\ + \--mount type\=bind,source\="$(pwd)"/cactus.json,target\=/cactus.json \\ + cas \\ + ./node\_modules/.bin/cactusapi \\ + \--config-file\=/cactus.json + + +### Testing API calls with the container + +Don’t have a Besu network on hand to test with? Test or develop against our Besu All-In-One container! + +1. Terminal Window 1 (Ledger) + + docker run \--publish 8545:8545 hyperledger/cactus-besu-all-in-one:latest + +2. Terminal Window 2 (Cactus API Server) + + docker run \\ + \--network host \\ + \--rm \\ + \--publish 3000:3000 \\ + \--publish 4000:4000 \\ + \--env AUTHORIZATION\_PROTOCOL\='NONE' \\ + \--env AUTHORIZATION\_CONFIG\_JSON\='{}' \\ + \--env GRPC\_TLS\_ENABLED\=false \\ + \--env PLUGINS\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-besu-connector-instance-id"}}\]' \\ + cas + +3. Terminal Window 3 (curl - replace eth accounts as needed) + + curl \--location \--request POST 'http://127.0.0.1:4000/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-besu/run-transaction' \\ + --header 'Content-Type: application/json' \\ + --data-raw '{ + "web3SigningCredential": { + "ethAccount": "627306090abaB3A6e1400e9345bC60c78a8BEf57", + "secret": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3", + "type": "PRIVATE\_KEY\_HEX" + }, + "consistencyStrategy": { + "blockConfirmations": 0, + "receiptType": "NODE\_TX\_POOL\_ACK" + }, + "transactionConfig": { + "from": "627306090abaB3A6e1400e9345bC60c78a8BEf57", + "to": "f17f52151EbEF6C7334FAD080c5704D77216b732", + "value": 1, + "gas": 10000000 + } + }' + +4. The above should produce a response that looks similar to this: + + { + "success": true, + "data": { + "transactionReceipt": { + "blockHash": "0x7c97c038a5d3bd84613fe23ed442695276d5d2df97f4e7c4f10ca06765033ffd", + "blockNumber": 1218, + "contractAddress": null, + "cumulativeGasUsed": 21000, + "from": "0x627306090abab3a6e1400e9345bc60c78a8bef57", + "gasUsed": 21000, + "logs": \[\], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "status": true, + "to": "0xf17f52151ebef6c7334fad080c5704d77216b732", + "transactionHash": "0xc7fcb46c735bdc696d500bfc70c72595a2b8c31813929e5c61d9a5aec3376d6f", + "transactionIndex": 0 + } + } + } + + +Prometheus Exporter +------------------------------------------------------------------------ + +This class creates a prometheus exporter, which scrapes the total Cactus node count. + +### Usage Prometheus + +The prometheus exporter object is initialized in the `ApiServer` class constructor itself, so instantiating the object of the `ApiServer` class, gives access to the exporter object. You can also initialize the prometheus exporter object seperately and then pass it to the `IApiServerConstructorOptions` interface for `ApiServer` constructor. + +`getPrometheusMetricsV1` function returns the prometheus exporter metrics, currently displaying the total plugins imported, which currently refreshes to match the plugin count, everytime `setTotalPluginImports` method is called. + +### Prometheus Integration + +To use Prometheus with this exporter make sure to install [Prometheus main component](https://prometheus.io/download/). Once Prometheus is setup, the corresponding scrape\_config needs to be added to the prometheus.yml + +\- job\_name: 'consortium\_manual\_exporter' + metrics\_path: /api/v1/api-server/get-prometheus-exporter-metrics + scrape\_interval: 5s + static\_configs: + - targets: \['{host}:{port}'\] + +Here the `host:port` is where the prometheus exporter metrics are exposed. The test cases (For example, packages/cactus-plugin-consortium-manual/src/test/typescript/unit/consortium/get-node-jws-endpoint-v1.test.ts) exposes it over `0.0.0.0` and a random port(). The random port can be found in the running logs of the test case and looks like (42379 in the below mentioned URL) `Metrics URL: http://0.0.0.0:42379/api/v1/api-server/get-prometheus-exporter-metrics/get-prometheus-exporter-metrics` + +Once edited, you can start the prometheus service by referencing the above edited prometheus.yml file. On the prometheus graphical interface (defaulted to http://localhost:9090), choose **Graph** from the menu bar, then select the **Console** tab. From the **Insert metric at cursor** drop down, select **cactus\_api\_server\_total\_plugin\_imports** and click **execute** + +### Shutdown Hook + +The API config contains a flag: + + { + "enableShutdownHook": true + } + +This allows for graceful shutdown of the API server after a SIGINT via cli CTRL + C. This hook can be disabled by passing in false either via the TypeScript constructor or the JSON config file. + +### Helper code + +#### response.type.ts + +This file contains the various responses of the metrics. + +#### data-fetcher.ts + +This file contains functions encasing the logic to process the data points. + +#### metrics.ts + +This file lists all the prometheus metrics and what they are used for. + +FAQ +---------------------------------------- + +### What is the difference between a Cactus Node and a Cactus API Server? + +The node is what has an identity within your PKI and can be made up of 1-N API server instances that all share the same configuration/identity of the node. See deployment scenarios above for a much more detailed explanation. + +### Is the API server horizontally scalable? + +**Yes, 100%.** Keep in mind though that the API server can be loaded up with arbitrary plugins meaning that if you write a plugin that has a central database that can only do 1 transaction per second, then it will not help you much that the API server itself is horizontally scalable because deploying a thousand instances of the API server will just result in you having a thousand instances of your plugin all waiting for that underlying database with its 1 TPS throughput hogging your system. When we say that the API server is horizontally scalable, we mean that the API server itself is designed not to have any such state mentioned in the example above. You are responsible for only deploying plugins in the API server that are horizontally scalable as well. In short, your whole system is only horizontally scalable if all components of it are horizontally scalable. + +### Does the API server automatically protect me from malicious plugins? + +**No.** If you install a third-party plugin that wasn’t vetted by anyone and that plugin happens to have malicious code in it to steal your private keys, it can do so. You are responsible for making sure that the plugins you install have no known security vulnerabilities or backdoors e.g. they are considered “secure”. The double quotes around “secure” is meant to signify the fact that no software is ever really truly secure, just merely lacking of known vulnerabilities at any given point in time. + +### Can I use the API server with plugins deployed as a service? + +**Yes.** You can deploy your plugin written in any language, anywhere as long as it is accessible over the network and does come with a Typescript API client that you can use to install into the API server as a proxy for an in-process plugin implementation. + +[Previous](cactus-api-client.md "@hyperledger/cactus-api-client") [Next](cactus-common.md "@hyperledger/cactus-common") + +* * * diff --git a/docs/docs/cactus/packages/cactus-common.md b/docs/docs/cactus/packages/cactus-common.md new file mode 100644 index 0000000000..d3f73629f9 --- /dev/null +++ b/docs/docs/cactus/packages/cactus-common.md @@ -0,0 +1,13 @@ +`@hyperledger/cactus-common` +======================================================================================= + +> TODO: description + +Usage +-------------------------------------------- + +// TODO: DEMONSTRATE API + +[Previous](cactus-cmd-api-server.md "@hyperledger/cactus-cmd-api-server") [Next](cactus-core.md "@hyperledger/cactus-core") + +* * * diff --git a/docs/docs/cactus/packages/cactus-core.md b/docs/docs/cactus/packages/cactus-core.md new file mode 100644 index 0000000000..91475dc7c0 --- /dev/null +++ b/docs/docs/cactus/packages/cactus-core.md @@ -0,0 +1,17 @@ +`@hyperledger/cactus-core` +=================================================================================== + +This module is responsible for providing the backbone for the rest of the packages when it comes to the features of Cactus. + +The main difference between this and the `cactus-common` package is that this one does not guarantee it’s features to work in the browser. + +The main difference from the `cactus-core-api` package is that this is meant to contain actual implementations while `cactus-core-api` is meant to be strictly about defining interfaces. Based on that latter constraint we may move the `PluginRegistry` out of that package and into this one in the near future. + +Usage +-------------------------------------------- + +// TODO: DEMONSTRATE API + +[Previous](cactus-common.md "@hyperledger/cactus-common") [Next](cactus-plugin-consortium-manual.md "@hyperledger/cactus-plugin-consortium-manual") + +* * * diff --git a/docs/docs/cactus/packages/cactus-plugin-consortium-manual.md b/docs/docs/cactus/packages/cactus-plugin-consortium-manual.md new file mode 100644 index 0000000000..6ceb752371 --- /dev/null +++ b/docs/docs/cactus/packages/cactus-plugin-consortium-manual.md @@ -0,0 +1,45 @@ +`@hyperledger/cactus-plugin-consortium-manual` +=========================================================================================================================== + +Prometheus Exporter +------------------------------------------------------------------------ + +This class creates a prometheus exporter, which scrapes the total Cactus node count. + +### Usage Prometheus + +The prometheus exporter object is initialized in the `PluginConsortiumManual` class constructor itself, so instantiating the object of the `PluginConsortiumManual` class, gives access to the exporter object. You can also initialize the prometheus exporter object seperately and then pass it to the `IPluginConsortiumManualOptions` interface for `PluginConsortiumManual` constructor. + +`getPrometheusMetricsV1` function returns the prometheus exporter metrics, currently displaying the total cactus node count, which currently refreshes to match the node count in the consortium, everytime `updateMetricNodeCount` method of the `PluginConsortiumManual` class is called. + +### Prometheus Integration + +To use Prometheus with this exporter make sure to install [Prometheus main component](https://prometheus.io/download/). Once Prometheus is setup, the corresponding scrape\_config needs to be added to the prometheus.yml + +\- job\_name: 'consortium\_manual\_exporter' + metrics\_path: api/v1/plugins/@hyperledger/cactus-plugin-consortium-manual/get-prometheus-exporter-metrics + scrape\_interval: 5s + static\_configs: + - targets: \['{host}:{port}'\] + +Here the `host:port` is where the prometheus exporter metrics are exposed. The test cases (For example, packages/cactus-plugin-consortium-manual/src/test/typescript/unit/consortium/get-node-jws-endpoint-v1.test.ts) exposes it over `0.0.0.0` and a random port(). The random port can be found in the running logs of the test case and looks like (42379 in the below mentioned URL) `Metrics URL: http://0.0.0.0:42379/api/v1/plugins/@hyperledger/cactus-plugin-consortium-manual/get-prometheus-exporter-metrics` + +Once edited, you can start the prometheus service by referencing the above edited prometheus.yml file. On the prometheus graphical interface (defaulted to http://localhost:9090), choose **Graph** from the menu bar, then select the **Console** tab. From the **Insert metric at cursor** drop down, select **cactus\_consortium\_manual\_total\_node\_count** and click **execute** + +### Helper code + +#### response.type.ts + +This file contains the various responses of the metrics. + +#### data-fetcher.ts + +This file contains functions encasing the logic to process the data points. + +#### metrics.ts + +This file lists all the prometheus metrics and what they are used for. + +[Previous](cactus-core.md "@hyperledger/cactus-core") [Next](cactus-plugin-keychain-vault.md "@hyperledger/cactus-plugin-keychain-vault") + +* * * diff --git a/docs/docs/cactus/packages/cactus-plugin-keychain-vault.md b/docs/docs/cactus/packages/cactus-plugin-keychain-vault.md new file mode 100644 index 0000000000..440986e911 --- /dev/null +++ b/docs/docs/cactus/packages/cactus-plugin-keychain-vault.md @@ -0,0 +1,45 @@ +`@hyperledger/cactus-plugin-keychain-vault` +===================================================================================================================== + +Prometheus Exporter +------------------------------------------------------------------------ + +This class creates a prometheus exporter, which scrapes the transactions (total transaction count) for the use cases incorporating the use of Keychain vault plugin. + +### Usage + +The prometheus exporter object is initialized in the `PluginKeychainVault` class constructor itself, so instantiating the object of the `PluginKeychainVault` class, gives access to the exporter object. You can also initialize the prometheus exporter object seperately and then pass it to the `IPluginKeychainVaultOptions` interface for `PluginKeychainVault` constructor. + +`getPrometheusMetricsV1` function returns the prometheus exporter metrics, currently displaying the total key count, which currently increments everytime the `set()` and `delete()` method of the `PluginKeychainVault` class is called. + +### Prometheus Integration + +To use Prometheus with this exporter make sure to install [Prometheus main component](https://prometheus.io/download/). Once Prometheus is setup, the corresponding scrape\_config needs to be added to the prometheus.yml + +\- job\_name: 'keychain\_vault\_exporter' + metrics\_path: api/v1/plugins/@hyperledger/cactus-plugin-keychain-vault/get-prometheus-exporter-metrics + scrape\_interval: 5s + static\_configs: + - targets: \['{host}:{port}'\] + +Here the `host:port` is where the prometheus exporter metrics are exposed. The test cases (For example, packages/cactus-plugin-keychain-vault/src/test/typescript/integration/plugin-keychain-vault.test.ts) exposes it over `0.0.0.0` and a random port(). The random port can be found in the running logs of the test case and looks like (42379 in the below mentioned URL) `Metrics URL: http://0.0.0.0:42379/api/v1/plugins/@hyperledger/cactus-plugin-keychain-plugin/get-prometheus-exporter-metrics` + +Once edited, you can start the prometheus service by referencing the above edited prometheus.yml file. On the prometheus graphical interface (defaulted to http://localhost:9090), choose **Graph** from the menu bar, then select the **Console** tab. From the **Insert metric at cursor** drop down, select **cactus\_keychain\_vault\_total\_key\_count** and click **execute** + +### Helper code + +#### response.type.ts + +This file contains the various responses of the metrics. + +#### data-fetcher.ts + +This file contains functions encasing the logic to process the data points + +#### metrics.ts + +This file lists all the prometheus metrics and what they are used for. + +[Previous](cactus-plugin-consortium-manual.md "@hyperledger/cactus-plugin-consortium-manual") [Next](cactus-plugin-ledger-connector-besu.md "@hyperledger/cactus-plugin-ledger-connector-besu") + +* * * diff --git a/docs/docs/cactus/packages/cactus-plugin-ledger-connector-besu.md b/docs/docs/cactus/packages/cactus-plugin-ledger-connector-besu.md new file mode 100644 index 0000000000..87184d4614 --- /dev/null +++ b/docs/docs/cactus/packages/cactus-plugin-ledger-connector-besu.md @@ -0,0 +1,314 @@ +`@hyperledger/cactus-plugin-ledger-connector-besu` +=================================================================================================================================== + +This plugin provides `Cactus` a way to interact with Besu networks. Using this we can perform: + +* Deploy Smart-contracts through bytecode. + +* Build and sign transactions using different keystores. + +* Invoke smart-contract functions that we have deployed on the network. + + +Summary +------------------------------------------------ + +* [Getting Started](#getting-started) + +* [Architecture](#architecture) + +* [Usage](#usage) + +* [Prometheus Exporter](#prometheus-exporter) + +* [Runing the tests](#running-the-tests) + +* [Built With](#built-with) + +* [Contributing](#contributing) + +* [License](#license) + +* [Acknowledgments](#acknowledgments) + + +Getting Started +---------------------------------------------------------------- + +Clone the git repository on your local machine. Follow these instructions that will get you a copy of the project up and running on your local machine for development and testing purposes. + +### Prerequisites + +In the root of the project to install the dependencies execute the command: + +npm run configure + +### Compiling + +In the project root folder, run this command to compile the plugin and create the dist directory: + +npm run tsc + +### Architecture + +The sequence diagrams for various endpoints are mentioned below + +#### run-transaction-endpoint + +![run-transaction-endpoint sequence diagram](../_images/run-transaction-endpoint.png) The above diagram shows the sequence diagram of run-transaction-endpoint. User A (One of the many Users) interacts with the API Client which in turn, calls the API server. API server then executes transact() method which is explained in detailed in the subsequent diagrams. ![run-transaction-endpoint transact() method](../_images/run-transaction-endpoint-transact.png) The above diagram shows the sequence diagram of transact() method of the PluginLedgerConnectorBesu class. The caller to this function, which in reference to the above sequence diagram is API server, sends RunTransactionRequest object as an argument to the transact() method. Based on the type of Web3SigningCredentialType, corresponsing responses are sent back to the caller. +![run-transaction-endpoint transactCactusKeychainRef() method](../_images/run-transaction-endpoint-transact-cactuskeychainref.png) The above diagram shows transactCactusKeychainReference() method being called by the transact() method of the PluginLedgerConnector class when the Web3SigningCredentialType is CACTUSKEYCHAINREF. This method inturn calls transactPrivateKey() which calls the signTransaction() method of web3 library. ![runtransaction-endpoint transactPrivateKey() method](../_images/run-transaction-endpoint-transact-privatekey.png) The above diagram shows transactPrivateKey() method being called by the transact() method of the PluginLedgerConnector class when the Web3SigningCredentialType is PRIVATEKEYHEX. This method then calls the signTransaction() method of the web3 library. ![run-transaction-endpoint transactSigned() method](../_images/run-transaction-endpoint-transact-signed.png) The above diagram shows transactSigned() method being called by the transact() method of the PluginLedgerConnector class when the Web3SigningCredentialType is NONE. This method calls the sendSignedTransaction() of the web3 library and then calls pollForTxReceipt() method. ![run-transaction-endpoint pollForTxReceipt() method](../_images/run-transaction-endpoint-transact-pollfortxreceipt.png) The above diagram shows pollForTxReceipt() method which is called by the transactSigned() method as described in the previous sequence diagram. This method waits for the block confirmation in a loop and then sends the corresponding response back to the caller. + +### Usage + +To use this import public-api and create new **PluginFactoryLedgerConnector**. Then use it to create a connector. + +const factory \= new PluginFactoryLedgerConnector({ + pluginImportType: PluginImportType.LOCAL, + }); + const connector: PluginLedgerConnectorBesu \= await factory.create({ + rpcApiHttpHost, + instanceId: uuidv4(), + pluginRegistry: new PluginRegistry(), + }); + +You can make calls through the connector to the plugin API: + +async invokeContract(req: InvokeContractV1Request):Promise; +async transactSigned(rawTransaction: string): Promise; +async transactPrivateKey(req: RunTransactionRequest): Promise; +async transactCactusKeychainRef(req: RunTransactionRequest):Promise; +async deployContract(req: DeployContractSolidityBytecodeV1Request):Promise; +async signTransaction(req: SignTransactionRequest):Promise>; + +Call example to deploy a contract: + +const deployOut \= await connector.deployContract({ + web3SigningCredential: { + ethAccount: firstHighNetWorthAccount, + secret: besuKeyPair.privateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + bytecode: SmartContractJson.bytecode, + gas: 1000000, +}); + +The field “type” can have the following values: + +enum Web3SigningCredentialType { + CACTUSKEYCHAINREF \= 'CACTUS\_KEYCHAIN\_REF', + GETHKEYCHAINPASSWORD \= 'GETH\_KEYCHAIN\_PASSWORD', + PRIVATEKEYHEX \= 'PRIVATE\_KEY\_HEX', + NONE \= 'NONE' +} + +### Transaction Privacy Feature + +Private transactions using Besu are currently enabled. + +The privateFor and privateFrom fields must be populated, more information about Besu Private Transactions [here](https://besu.hyperledger.org/en/stable/Concepts/Privacy/Private-Transactions/). + +Call example to deploy a private contract: + + const deployOut \= await connector1.deployContract({ + bytecode: SmartContract.bytecode, + contractAbi: SmartContract.abi, + contractName: SmartContract.contractName, + constructorArgs: \[\], + privateTransactionConfig: { + privateFrom: SendingTesseraPublicKey, + privateFor: \[ + Member1TesseraPrivateKey, + Member2TesseraPrivateKey, + \], + }, + web3SigningCredential: { + secret:SendingBesuPrivateKey, + type: Web3SigningCredentialType.PrivateKeyHex, + }, + gas: 3000000 + }); + +> Extensive documentation and examples in the [readthedocs](https://readthedocs.org/projects/hyperledger-cactus/) (WIP) + +### Building/running the container image locally + +In the Cactus project root say: + +DOCKER\_BUILDKIT\=1 docker build \-f ./packages/cactus-plugin-ledger-connector-besu/Dockerfile . \-t cplcb + +Build with a specific version of the npm package: + +DOCKER\_BUILDKIT\=1 docker build \--build-arg NPM\_PKG\_VERSION\=1.0.0 \-f ./packages/cactus-plugin-ledger-connector-besu/Dockerfile . \-t cplcb + +#### Running the container + +Launch container with plugin configuration as an **environment variable**: + +docker run \\ + \--rm \\ + \--publish 3000:3000 \\ + \--publish 4000:4000 \\ + \--env PLUGINS\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "rpcApiWsHost":"ws://localhost:8546", "instanceId": "some-unique-besu-connector-instance-id"}}\]' \\ + cplcb + +Launch container with plugin configuration as a **CLI argument**: + +docker run \\ + \--rm \\ + \--publish 3000:3000 \\ + \--publish 4000:4000 \\ + cplcb \\ + ./node\_modules/.bin/cactusapi \\ + \--plugins\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "rpcApiWsHost":"ws://localhost:8546", "instanceId": "some-unique-besu-connector-instance-id"}}\]' + +Launch container with **configuration file** mounted from host machine: + +echo '\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "rpcApiWsHost":"ws://localhost:8546", "instanceId": "some-unique-besu-connector-instance-id"}}\]' \> cactus.json + +docker run \\ + \--rm \\ + \--publish 3000:3000 \\ + \--publish 4000:4000 \\ + \--mount type\=bind,source\="$(pwd)"/cactus.json,target\=/cactus.json \\ + cplcb \\ + ./node\_modules/.bin/cactusapi \\ + \--config-file\=/cactus.json + +#### Testing API calls with the container + +Don’t have a Besu network on hand to test with? Test or develop against our Besu All-In-One container! + +**Terminal Window 1 (Ledger)** + +docker run \\ + \--publish 0.0.0.0:8545:8545/tcp \\ + \--publish 0.0.0.0:8546:8546/tcp \\ + \--publish 0.0.0.0:8888:8888/tcp \\ + \--publish 0.0.0.0:9001:9001/tcp \\ + \--publish 0.0.0.0:9545:9545/tcp \\ + ghcr.io/hyperledger/cactus-besu-all-in-one:2022-05-12-2330a96 + +**Terminal Window 2 (Cactus API Server)** + +docker run \\ + \--network host \\ + \--rm \\ + \--publish 3000:3000 \\ + \--publish 4000:4000 \\ + \--env AUTHORIZATION\_PROTOCOL\='NONE' \\ + \--env AUTHORIZATION\_CONFIG\_JSON\='{}' \\ + \--env GRPC\_TLS\_ENABLED\=false \\ + \--env PLUGINS\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-besu", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "rpcApiWsHost":"ws://localhost:8546", "instanceId": "some-unique-besu-connector-instance-id"}}\]' \\ + cplcb + +**Terminal Window 3 (curl - replace eth accounts as needed)** + +curl \--location \--request POST 'http://127.0.0.1:4000/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-besu/run-transaction' \\ +--header 'Content-Type: application/json' \\ +--data-raw '{ + "web3SigningCredential": { + "ethAccount": "627306090abaB3A6e1400e9345bC60c78a8BEf57", + "secret": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3", + "type": "PRIVATE\_KEY\_HEX" + }, + "consistencyStrategy": { + "blockConfirmations": 0, + "receiptType": "NODE\_TX\_POOL\_ACK" + }, + "transactionConfig": { + "from": "627306090abaB3A6e1400e9345bC60c78a8BEf57", + "to": "f17f52151EbEF6C7334FAD080c5704D77216b732", + "value": 1, + "gas": 10000000 + } +}' + +The above should produce a response that looks similar to this: + +{ + "success": true, + "data": { + "transactionReceipt": { + "blockHash": "0x7c97c038a5d3bd84613fe23ed442695276d5d2df97f4e7c4f10ca06765033ffd", + "blockNumber": 1218, + "contractAddress": null, + "cumulativeGasUsed": 21000, + "from": "0x627306090abab3a6e1400e9345bc60c78a8bef57", + "gasUsed": 21000, + "logs": \[\], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "status": true, + "to": "0xf17f52151ebef6c7334fad080c5704d77216b732", + "transactionHash": "0xc7fcb46c735bdc696d500bfc70c72595a2b8c31813929e5c61d9a5aec3376d6f", + "transactionIndex": 0 + } + } +} + +Prometheus Exporter +------------------------------------------------------------------------ + +This class creates a prometheus exporter, which scrapes the transactions (total transaction count) for the use cases incorporating the use of Besu connector plugin. + +### Prometheus Exporter Usage + +The prometheus exporter object is initialized in the `PluginLedgerConnectorBesu` class constructor itself, so instantiating the object of the `PluginLedgerConnectorBesu` class, gives access to the exporter object. You can also initialize the prometheus exporter object seperately and then pass it to the `IPluginLedgerConnectorBesuOptions` interface for `PluginLedgerConnectoBesu` constructor. + +`getPrometheusMetricsV1` function returns the prometheus exporter metrics, currently displaying the total transaction count, which currently increments everytime the `transact()` method of the `PluginLedgerConnectorBesu` class is called. + +### Prometheus Integration + +To use Prometheus with this exporter make sure to install [Prometheus main component](https://prometheus.io/download/). Once Prometheus is setup, the corresponding scrape\_config needs to be added to the prometheus.yml + +\- job\_name: 'besu\_ledger\_connector\_exporter' + metrics\_path: api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-besu/get-prometheus-exporter-metrics + scrape\_interval: 5s + static\_configs: + - targets: \['{host}:{port}'\] + +Here the `host:port` is where the prometheus exporter metrics are exposed. The test cases (For example, packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts) exposes it over `0.0.0.0` and a random port(). The random port can be found in the running logs of the test case and looks like (42379 in the below mentioned URL) `Metrics URL: http://0.0.0.0:42379/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-besu/get-prometheus-exporter-metrics` + +Once edited, you can start the prometheus service by referencing the above edited prometheus.yml file. On the prometheus graphical interface (defaulted to http://localhost:9090), choose **Graph** from the menu bar, then select the **Console** tab. From the **Insert metric at cursor** drop down, select **cactus\_besu\_total\_tx\_count** and click **execute** + +### Helper code + +#### response.type.ts + +This file contains the various responses of the metrics. + +#### data-fetcher.ts + +This file contains functions encasing the logic to process the data points + +#### metrics.ts + +This file lists all the prometheus metrics and what they are used for. + +Running the tests +-------------------------------------------------------------------- + +To check that all has been installed correctly and that the pugin has no errors run the tests: + +* Run this command at the project’s root: + + +npm run test:plugin-ledger-connector-besu + +Contributing +---------------------------------------------------------- + +We welcome contributions to Hyperledger Cactus in many forms, and there’s always plenty to do! + +Please review [CONTIRBUTING.md](#../../CONTRIBUTING.md) to get started. + +License +------------------------------------------------ + +This distribution is published under the Apache License Version 2.0 found in the [LICENSE](#../../LICENSE) file. + +Acknowledgments +---------------------------------------------------------------- + +[Previous](cactus-plugin-keychain-vault.md "@hyperledger/cactus-plugin-keychain-vault") [Next](cactus-plugin-ledger-connector-corda.md "@hyperledger/cactus-plugin-ledger-connector-corda") + +* * * diff --git a/docs/docs/cactus/packages/cactus-plugin-ledger-connector-corda.md b/docs/docs/cactus/packages/cactus-plugin-ledger-connector-corda.md new file mode 100644 index 0000000000..d4e55a8f53 --- /dev/null +++ b/docs/docs/cactus/packages/cactus-plugin-ledger-connector-corda.md @@ -0,0 +1,580 @@ +`@hyperledger/cactus-plugin-ledger-connector-corda` +====================================================================================================================================== + +Summary +------------------------------------------------ + +The Corda connector is written in Kotlin and ships as a Spring Boot JVM application that accepts API requests and translates those into Corda RPC calls. + +Deploying the Corda connector therefore involves also deploying the mentioned JVM application **in addition** to deploying the Cactus API server with the desired plugins configured. + +Concepts +-------------------------------------------------- + +### Contract Invocation JSON DSL + +One of our core design principles for Hyperledger Cactus is to have low impact deployments meaning that changes to the ledgers themselves should be kept to a minimum or preferably have no need for any at all. With this in mind, we had to solve the challenge of providing users with the ability to invoke Corda flows as dynamically as possible within the confines of the strongly typed JVM contrasted with the weakly typed Javascript language runtime of NodeJS. + +Corda might release some convenience features to ease this in the future, but in the meantime we have the _Contract Invocation JSON DSL_ which allows developers to specify truly arbitrary JVM types as part of their contract invocation arguments even if otherwise these types would not be possible to serialize or deserialize with traditional tooling such as the excellent [Jackson JSON Java library](https://github.com/FasterXML/jackson) or similar ones. + +### Expressing Primitive vs Reference Types with the DLS + +The features of the DSL include expressing whether a contract invocation parameter is a reference or a primitive JVM data types. This is a language feature that Javascript has as well to some extent, but for those in need of a refresher, here’s a writeup from a well known Q/A website that I found on the internet: [What’s the difference between primitive and reference types?](https://stackoverflow.com/a/32049775/698470) + +To keep it simple, the following types are primitive data types in the Java Virtual Machine (JVM) and everything else not included in the list below can be safely considered a reference type: + +* boolean + +* byte + +* short + +* char + +* int + +* long + +* float + +* double + + +If you’d like to further clarify how this works and feel like an exciting adventure then we recommend that you dive into the source code of the [deserializer implementation of the JSON DSL](https://github.com/hyperledger/cactus/blob/main/packages/cactus-plugin-ledger-connector-corda/src/main-server/kotlin/gen/kotlin-spring/src/main/kotlin/org/hyperledger/cactus/plugin/ledger/connector/corda/server/impl/JsonJvmObjectDeserializer.kt) and take a look at the following points of interest in the code located there: + +* `val exoticTypes: Map>` + +* `fun instantiate(jvmObject: JvmObject)` + + +### Flow Invocation Types + +Can be **dynamic** or **tracked dynamic** and the corresponding enum values are defined as: + +/\*\* + \* Determines which flow starting method will be used on the back-end when invoking the flow. Based on the value here the plugin back-end might invoke the rpc.startFlowDynamic() method or the rpc.startTrackedFlowDynamic() method. Streamed responses are aggregated and returned in a single response to HTTP callers who are not equipped to handle streams like WebSocket/gRPC/etc. do. + \* @export + \* @enum {string} + \*/ +export enum FlowInvocationType { + TRACKEDFLOWDYNAMIC \= 'TRACKED\_FLOW\_DYNAMIC', + FLOWDYNAMIC \= 'FLOW\_DYNAMIC' +} + +[Official Corda Java Docs - startFlowDynamic()](https://api.corda.net/api/corda-os/4.7/html/api/kotlin/corda/net.corda.core.messaging/-corda-r-p-c-ops/start-flow-dynamic.html) + +[Official Corda Java Docs - startTrackedFlowDynamic()](https://api.corda.net/api/corda-os/4.7/html/api/kotlin/corda/net.corda.core.messaging/-corda-r-p-c-ops/start-tracked-flow-dynamic.html) + +Usage +-------------------------------------------- + +Take a look at how the API client can be used to run transactions on a Corda ledger: `packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts` + +### Invoke Contract (flow) with no parameters + +Below, we’ll demonstrate invoking a simple contract with no parameters. + +**The contract source:** + +package com.example.organization.samples.application.flows; + +class SomeCoolFlow { + // constructor with no arguments + public SomeCoolFlow() { + this.doSomething(); + } + + public doSomething(): void { + throw new RuntimeException("Method not implemented."); + } +} + +**Steps to build your request:** + +1. Find out the fully qualified class name of your contract (flow) and set this as the value for the request parameter `flowFullClassName` + +2. Decide on your flow invocation type which largely comes down to answering the question of: Does your invocation follow a request/response pattern or more like a channel subscription where multiple updates at different times are streamed to the client in response to the invocation request? In our example we assume the simpler request/response communication pattern and therefore will set the `flowInvocationType` to `FlowInvocationType.FLOWDYNAMIC` + +3. Invoke the flow via the API client with the `params` argument being specified as an empty array `[]` + + import { DefaultApi as CordaApi } from "@hyperledger/cactus-plugin-ledger-connector-corda"; + import { FlowInvocationType } from "@hyperledger/cactus-plugin-ledger-connector-corda"; + + const apiUrl \= "your-cactus-host.example.com"; // don't forget to specify the port if applicable + const apiClient \= new CordaApi({ basePath: apiUrl }); + + const res \= await apiClient.invokeContractV1({ + flowFullClassName: "com.example.organization.samples.application.flows.SomeCoolFlow", + flowInvocationType: FlowInvocationType.FLOWDYNAMIC, + params: \[\], + timeoutMs: 60000, + }); + + +### Invoke Contract (flow) with a single integer parameter + +Below, we’ll demonstrate invoking a simple contract with a single numeric parameter. + +**The contract source:** + +package com.example.organization.samples.application.flows; + +class SomeCoolFlow { + // constructor with a primitive type long argument + public SomeCoolFlow(long myParameterThatIsLong) { + // do something with the parameter here + } +} + +**Steps to build your request:** + +1. Find out the fully qualified class name of your contract (flow) and set this as the value for the request parameter `flowFullClassName` + +2. Decide on your flow invocation type. More details at [Invoke Contract (flow) with no parameters](#invoke-contract-flow-with-no-parameters) + +3. Find out what is the fully qualified class name of the parameter you wish to pass in. You can do this be inspecting the sources of the contract itself. If you do not have access to those sources, then the documentation of the contract should have answers or the person who authored said contract. In our case here the fully qualified class name for the number parameter is simply `long` because it is a primitive data type and as such these can be referred to in their short form, but the fully qualified version also works such as: `java.lang.Long`. When in doubt about these, you can always consult the [official java.lang.Long Java Docs](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/lang/Long.html) After having determined the above, you can construct your first `JvmObject` JSON object as follows in order to pass in the number `42` as the first and only parameter for our flow invocation: + + params: \[ + { + jvmTypeKind: JvmTypeKind.PRIMITIVE, + jvmType: { + fqClassName: "long", + }, + primitiveValue: 42, + } + \] + +4. Invoke the flow via the API client with the `params` populated as explained above: + + import { DefaultApi as CordaApi } from "@hyperledger/cactus-plugin-ledger-connector-corda"; + import { FlowInvocationType } from "@hyperledger/cactus-plugin-ledger-connector-corda"; + + // don't forget to specify the port if applicable + const apiUrl \= "your-cactus-host.example.com"; + const apiClient \= new CordaApi({ basePath: apiUrl }); + + const res \= await apiClient.invokeContractV1({ + flowFullClassName: "com.example.organization.samples.application.flows.SomeCoolFlow", + flowInvocationType: FlowInvocationType.FLOWDYNAMIC, + params: \[ + { + jvmTypeKind: JvmTypeKind.PRIMITIVE, + jvmType: { + fqClassName: "long", + }, + primitiveValue: 42, + } + \], + timeoutMs: 60000, + }); + + +### Invoke Contract (flow) with a custom class parameter + +Below, we’ll demonstrate invoking a contract with a single class instance parameter. + +**The contract sources:** + +package com.example.organization.samples.application.flows; + +// contract with a class instance parameter +class BuildSpaceshipFlow { + public BuildSpaceshipFlow(SpaceshipInfo buildSpecs) { + // build spaceship as per the specs + } +} + +package com.example.organization.samples.application.flows; + +// The type that the contract accepts as an input parameter +class SpaceshipInfo { + public SpaceshipInfo(String name, Integer seatsForHumans) { + } +} + +**Assembling and Sending your request:** + +Invoke the flow via the API client with the `params` populated as shown below. + +Key thing notice here is that we now have a class instance as a parameter for our contract (flow) invocation so we have to describe how this class instance itself will be instantiated by providing a nested array of parameters via the `jvmCtorArgs` which stands for Java Virtual Machine Constructor Arguments meaning that elements of this array will be passed in dynamically (via Reflection) to the class constructor. + +**Java Equivalent** + +cordaRpcClient.startFlowDynamic( + BuildSpaceshipFlow.class, + new SpaceshipInfo( + "The last spaceship you'll ever need.", + 10000000 + ) +); + +**Cactus Invocation JSON DLS Equivalent to the Above Java Snippet** + +import { DefaultApi as CordaApi } from "@hyperledger/cactus-plugin-ledger-connector-corda"; +import { FlowInvocationType } from "@hyperledger/cactus-plugin-ledger-connector-corda"; + +// don't forget to specify the port if applicable +const apiUrl \= "your-cactus-host.example.com"; +const apiClient \= new CordaApi({ basePath: apiUrl }); + +const res \= await apiClient.invokeContractV1({ + flowFullClassName: "com.example.organization.samples.application.flows.BuildSpaceshipFlow", + flowInvocationType: FlowInvocationType.FLOWDYNAMIC, + params: \[ + { + jvmTypeKind: JvmTypeKind.REFERENCE, + jvmType: { + fqClassName: "com.example.organization.samples.application.flows.SpaceshipInfo", + }, + + jvmCtorArgs: \[ + { + jvmTypeKind: JvmTypeKind.PRIMITIVE, + jvmType: { + fqClassName: "java.lang.String", + }, + primitiveValue: "The last spaceship you'll ever need.", + }, + { + jvmTypeKind: JvmTypeKind.PRIMITIVE, + jvmType: { + fqClassName: "java.lang.Long", + }, + primitiveValue: 10000000000, + }, + \], + } + \], + timeoutMs: 60000, +}); + +### Transaction Monitoring + +* There are two interfaces to monitor changes of vault states - reactive `watchBlocksV1` method, and low-level HTTP API calls. + +* Note: The monitoring APIs are implemented only on kotlin-server connector (`main-server`), not typescript connector! + +* For usage examples review the functional test file: `packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/monitor-transactions-v4.8.test.ts` + +* Because transactions read from corda are stored on the connector, they will be lost if connector is closed/killed before transaction were read by the clients. + +* Each client has own set of state monitors that are managed independently. After starting the monitoring, each new transaction is queued on the connector until read and explicitly cleared by `watchBlocksV1` or direct HTTP API call. + +* Client monitors can be periodically removed by the connector, if there was no action from the client for specified amount of time. + +* Client expiration delay can be configured with `cactus.sessionExpireMinutes` option. It default to 30 minutes. + +* Each transaction has own index assigned by the corda connector. Index is unique for each client monitoring session. For instance: + + * Stopping monitoring for given state will reset the transaction index counter for given client. After restart, it will report first transaction with index 0. + + * Each client can see tha same transaction with different index. + + * Index can be used to determine the transaction order for given client session. + + +#### watchBlocksV1 + +* `watchBlocksV1(options: watchBlocksV1Options): Observable` + +* Reactive (RxJS) interface to observe state changes. + +* Internally, it uses polling of low-level HTTP APIs. + +* Watching block should return each block at least once, no blocks should be missed after startMonitor has started. The only case when transaction is lost is when connector we were connected to died. + +* Transactions can be duplicated in case internal `ClearMonitorTransactionsV1` call was not successful (for instance, because of connection problems). + +* Options: + + * `stateFullClassName: string`: state to monitor. + + * `pollRate?: number`: how often poll the kotlin server for changes (default 5 seconds). + + +#### Low-level HTTP API + +* These should not be used when watchBlocks API is sufficient. + +* Consists of the following methods: + + * `startMonitorV1`: Start monitoring for specified state changes. All changes after calling this function will be stored in internal kotlin-server buffer, ready to be read by calls to `GetMonitorTransactionsV1`. Transactions occuring before the call to startMonitorV1 will not be reported. + + * `GetMonitorTransactionsV1`: Read all transactions for given state name still remaining in internal buffer. + + * `ClearMonitorTransactionsV1`: Remove transaction for given state name with specified index number from internal buffer. Should be used to acknowledge receiving specified transactions in user code, so that transactions are not reported multiple times. + + * `stopMonitorV1`: Don’t watch for transactions changes anymore, remove any transactions that were not read until now. + + +### Custom Configuration via Env Variables + +{ + "cactus": { + "threadCount": 3, + "sessionExpireMinutes": 10, + "corda": { + "node": { + "host": "localhost" + }, + "rpc": { + "port": 10006, + "username": "user1", + "password": "test" + } + } + } +} + +SPRING\_APPLICATION\_JSON\='{"cactus":{"corda":{"node": {"host": "localhost"}, "rpc":{"port": 10006, "username":"user1", "password": "test"}}}}' gradle test + +{ + "flowFullClassName" : "net.corda.samples.example.flows.ExampleFlow${"$"}Initiator", + "flowInvocationType" : "FLOW\_DYNAMIC", + "params" : \[ { + "jvmTypeKind" : "PRIMITIVE", + "jvmType" : { + "fqClassName" : "java.lang.Integer" + }, + "primitiveValue" : 42, + "jvmCtorArgs" : null + }, { + "jvmTypeKind" : "REFERENCE", + "jvmType" : { + "fqClassName" : "net.corda.core.identity.Party" + }, + "primitiveValue" : null, + "jvmCtorArgs" : \[ { + "jvmTypeKind" : "REFERENCE", + "jvmType" : { + "fqClassName" : "net.corda.core.identity.CordaX500Name" + }, + "primitiveValue" : null, + "jvmCtorArgs" : \[ { + "jvmTypeKind" : "PRIMITIVE", + "jvmType" : { + "fqClassName" : "java.lang.String" + }, + "primitiveValue" : "PartyB", + "jvmCtorArgs" : null + }, { + "jvmTypeKind" : "PRIMITIVE", + "jvmType" : { + "fqClassName" : "java.lang.String" + }, + "primitiveValue" : "New York", + "jvmCtorArgs" : null + }, { + "jvmTypeKind" : "PRIMITIVE", + "jvmType" : { + "fqClassName" : "java.lang.String" + }, + "primitiveValue" : "US", + "jvmCtorArgs" : null + } \] + }, { + "jvmTypeKind" : "REFERENCE", + "jvmType" : { + "fqClassName" : "org.hyperledger.cactus.plugin.ledger.connector.corda.server.impl.PublicKeyImpl" + }, + "primitiveValue" : null, + "jvmCtorArgs" : \[ { + "jvmTypeKind" : "PRIMITIVE", + "jvmType" : { + "fqClassName" : "java.lang.String" + }, + "primitiveValue" : "EdDSA", + "jvmCtorArgs" : null + }, { + "jvmTypeKind" : "PRIMITIVE", + "jvmType" : { + "fqClassName" : "java.lang.String" + }, + "primitiveValue" : "X.509", + "jvmCtorArgs" : null + }, { + "jvmTypeKind" : "PRIMITIVE", + "jvmType" : { + "fqClassName" : "java.lang.String" + }, + "primitiveValue" : "MCowBQYDK2VwAyEAoOv19eiCDJ7HzR9UrfwbFig7qcD1jkewKkkS4WF9kPA=", + "jvmCtorArgs" : null + } \] + } \] + } \], + "timeoutMs" : null +} + +I 16:51:01 1 Client.main - nodeDiagnosticInfo= +{ + "version" : "4.6", + "revision" : "85e387ea730d9be7d6dc2b23caba1ee18305af74", + "platformVersion" : 8, + "vendor" : "Corda Open Source", + "cordapps" : \[ { + "type" : "Workflow CorDapp", + "name" : "workflows-1.0", + "shortName" : "Example-Cordapp Flows", + "minimumPlatformVersion" : 8, + "targetPlatformVersion" : 8, + "version" : "1", + "vendor" : "Corda Open Source", + "licence" : "Apache License, Version 2.0", + "jarHash" : { + "offset" : 0, + "size" : 32, + "bytes" : "V7ssTw0etgg3nSGk1amArB+fBH8fQUyBwIFs0DhID+0=" + } + }, { + "type" : "Contract CorDapp", + "name" : "contracts-1.0", + "shortName" : "Example-Cordapp Contracts", + "minimumPlatformVersion" : 8, + "targetPlatformVersion" : 8, + "version" : "1", + "vendor" : "Corda Open Source", + "licence" : "Apache License, Version 2.0", + "jarHash" : { + "offset" : 0, + "size" : 32, + "bytes" : "Xe0eoh4+T6fsq4u0QKqkVsVDMYSWhuspHqE0wlOlyqU=" + } + } \] +} + +Building Docker Image Locally +-------------------------------------------------------------------------------------------- + +The `cccs` tag used in the below example commands is a shorthand for the full name of the container image otherwise referred to as `cactus-corda-connector-server`. + +From the project root: + +DOCKER\_BUILDKIT\=1 docker build ./packages/cactus-plugin-ledger-connector-corda/src/main-server/ \-t cccs + +Example NodeDiagnosticInfo JSON Response +------------------------------------------------------------------------------------------------------------------ + +{ + "version": "4.6", + "revision": "85e387ea730d9be7d6dc2b23caba1ee18305af74", + "platformVersion": 8, + "vendor": "Corda Open Source", + "cordapps": \[ + { + "type": "Workflow CorDapp", + "name": "workflows-1.0", + "shortName": "Obligation Flows", + "minimumPlatformVersion": 8, + "targetPlatformVersion": 8, + "version": "1", + "vendor": "Corda Open Source", + "licence": "Apache License, Version 2.0", + "jarHash": { + "bytes": "Vf9MllnrC7vrWxrlDE94OzPMZW7At1HhTETL/XjiAmc=", + "offset": 0, + "size": 32 + } + }, + { + "type": "CorDapp", + "name": "corda-confidential-identities-4.6", + "shortName": "corda-confidential-identities-4.6", + "minimumPlatformVersion": 1, + "targetPlatformVersion": 1, + "version": "Unknown", + "vendor": "Unknown", + "licence": "Unknown", + "jarHash": { + "bytes": "nqBwqHJMbLW80hmRbKEYk0eAknFiX8N40LKuGsD0bPo=", + "offset": 0, + "size": 32 + } + }, + { + "type": "Contract CorDapp", + "name": "corda-finance-contracts-4.6", + "shortName": "Corda Finance Demo", + "minimumPlatformVersion": 1, + "targetPlatformVersion": 8, + "version": "1", + "vendor": "R3", + "licence": "Open Source (Apache 2)", + "jarHash": { + "bytes": "a43Q/GJG6JKTZzq3U80P8L1DWWcB/D+Pl5uitEtAeQQ=", + "offset": 0, + "size": 32 + } + }, + { + "type": "Workflow CorDapp", + "name": "corda-finance-workflows-4.6", + "shortName": "Corda Finance Demo", + "minimumPlatformVersion": 1, + "targetPlatformVersion": 8, + "version": "1", + "vendor": "R3", + "licence": "Open Source (Apache 2)", + "jarHash": { + "bytes": "wXdD4Iy50RaWzPp7n9s1xwf4K4MB8eA1nmhPquTMvxg=", + "offset": 0, + "size": 32 + } + }, + { + "type": "Contract CorDapp", + "name": "contracts-1.0", + "shortName": "Obligation Contracts", + "minimumPlatformVersion": 8, + "targetPlatformVersion": 8, + "version": "1", + "vendor": "Corda Open Source", + "licence": "Apache License, Version 2.0", + "jarHash": { + "bytes": "grTZzN71Cpxw6rZe/U5SB6/ehl99B6VQ1+ZJEx1rixs=", + "offset": 0, + "size": 32 + } + } + \] +} + +Monitoring +------------------------------------------------------ + +### Usage Prometheus + +The prometheus exporter object is initialized in the `PluginLedgerConnectorCorda` class constructor itself, so instantiating the object of the `PluginLedgerConnectorCorda` class, gives access to the exporter object. You can also initialize the prometheus exporter object seperately and then pass it to the `IPluginLedgerConnectorCordaOptions` interface for `PluginLedgerConnectoCorda` constructor. + +`getPrometheusExporterMetricsEndpointV1` function returns the prometheus exporter metrics, currently displaying the total transaction count, which currently increments everytime the `transact()` method of the `PluginLedgerConnectorCorda` class is called. + +### Prometheus Integration + +To use Prometheus with this exporter make sure to install [Prometheus main component](https://prometheus.io/download/). Once Prometheus is setup, the corresponding scrape\_config needs to be added to the prometheus.yml + +\- job\_name: 'corda\_ledger\_connector\_exporter' + metrics\_path: api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/get-prometheus-exporter-metrics + scrape\_interval: 5s + static\_configs: + - targets: \['{host}:{port}'\] + +Here the `host:port` is where the prometheus exporter metrics are exposed. The test cases (For example, packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/deploy-cordapp-jars-to-nodes.test.ts) exposes it over `0.0.0.0` and a random port(). The random port can be found in the running logs of the test case and looks like (42379 in the below mentioned URL) `Metrics URL: http://0.0.0.0:42379/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-corda/get-prometheus-exporter-metrics` + +Once edited, you can start the prometheus service by referencing the above edited prometheus.yml file. On the prometheus graphical interface (defaulted to http://localhost:9090), choose **Graph** from the menu bar, then select the **Console** tab. From the **Insert metric at cursor** drop down, select **cactus\_corda\_total\_tx\_count** and click **execute** + +### Helper code + +#### response.type.ts + +This file contains the various responses of the metrics. + +#### data-fetcher.ts + +This file contains functions encasing the logic to process the data points + +#### metrics.ts + +This file lists all the prometheus metrics and what they are used for. + +[Previous](cactus-plugin-ledger-connector-besu.md "@hyperledger/cactus-plugin-ledger-connector-besu") [Next](cactus-plugin-ledger-connector-fabric.md "@hyperledger/cactus-plugin-ledger-connector-fabric") + +* * * diff --git a/docs/docs/cactus/packages/cactus-plugin-ledger-connector-fabric.md b/docs/docs/cactus/packages/cactus-plugin-ledger-connector-fabric.md new file mode 100644 index 0000000000..7c51350c58 --- /dev/null +++ b/docs/docs/cactus/packages/cactus-plugin-ledger-connector-fabric.md @@ -0,0 +1,540 @@ +`@hyperledger/cactus-plugin-ledger-connector-fabric` +======================================================================================================================================== + +1\. Usage +------------------------------------------------ + +This plugin provides a way to interact with Fabric networks. Using this one can perform: + +* Deploy smart contracts (chaincode). + +* Execute transactions on the ledger. + +* Invoke chaincode functions. + + +The above functionality can either be accessed by importing the plugin directly as a library (embedding) or by hosting it as a REST API through the [Cactus API server](https://www.npmjs.com/package/@hyperledger/cactus-cmd-api-server) + +We also publish the [Cactus API server as a container image](https://github.com/hyperledger/cactus/pkgs/container/cactus-cmd-api-server) to the GitHub Container Registry that you can run easily with a one liner. The API server is also embeddable in your own NodeJS project if you choose to do so. + +### 1.1. Installation + +**npm** + +npm install @hyperledger/cactus-plugin-ledger-connector-fabric + +**yarn** + +yarn add @hyperledger/cactus-plugin-ledger-connector-fabric + +### 1.2. Using as a Library + +import { + PluginLedgerConnectorFabric, + DefaultEventHandlerStrategy, +} from "@hyperledger/cactus-plugin-ledger-connector-fabric"; + +const plugin \= new PluginLedgerConnectorFabric({ + // See test cases for exact details on what parameters are needed +}); + +const req: RunTransactionRequest \= { + // See tests for specific examples on request properties +}; + +try { + const res \= await plugin.transact(req); +} catch (ex: Error) { + // Make sure to handle errors gracefully (which is dependent on your use-case) + console.error(ex); + throw ex; +} + +### 1.3. Using Via The API Client + +**Prerequisites** + +* A running Fabric ledger (network) + +* You have a running Cactus API server on `$HOST:$PORT` with the Fabric connector plugin installed on it (and the latter configured to have access to the Fabric ledger from point 1) + + +import { + PluginLedgerConnectorFabric, + DefaultApi as FabricApi, + DefaultEventHandlerStrategy, +} from "@hyperledger/cactus-plugin-ledger-connector-fabric"; + +// Step zero is to deploy your Fabric ledger and the Cactus API server +const apiUrl \= \`https://${HOST}:${PORT}\`; + +const config \= new Configuration({ basePath: apiUrl }); + +const apiClient \= new FabricApi(config); + +const req: RunTransactionRequest \= { + // See tests for specific examples on request properties +}; + +try { + const res \= await apiClient.runTransactionV1(req); +} catch (ex: Error) { + // Make sure to handle errors gracefully (which is dependent on your use-case) + console.error(ex); + throw ex; +} + +### 1.4. Signing Credentials with Hashicorp Vault + +To support signing of message with multiple identity types + +// vault server config for supporting vault identity provider +const vaultConfig:IVaultConfig \= { + endpoint : "http://localhost:8200", + transitEngineMountPath: "/transit", +} +// web-socket server config for supporting vault identity provider +const webSocketConfig:IVaultConfig \= { + server: socketServer as FabricSocketServer +} +// provide list of identity signing to be supported +const supportedIdentity:FabricSigningCredentialType\[\] \= \[FabricSigningCredentialType.VaultX509,FabricSigningCredentialType.WsX509,FabricSigningCredentialType.X509\] +const pluginOptions:IPluginLedgerConnectorFabricOptions \= { + // other options + vaultConfig : vaultConfig, + webSocketConfig : webSocketConfig, + supportedIdentity:supportedIdentity + // .. other options +} +const connector: PluginLedgerConnectorFabric \= new PluginLedgerConnectorFabric(pluginOptions); + +To enroll an identity + +await connector.enroll( + { + keychainId: "keychain-identifier-for storing-certData", + keychainRef: "cert-data-identifier", + + // require in case of vault + type: FabricSigningCredentialType.VaultX509, // FabricSigningCredentialType.X509 + vaultTransitKey: { + token: "vault-token", + keyName: "vault-key-label", + }, + // required in case of web-socket server + type: FabricSigningCredentialType.WsX509, + webSocketKey: { + signature: signature, + sessionId: sessionId, + }, + }, + { + enrollmentID: "client2", + enrollmentSecret: "pw", + mspId: "Org1MSP", + caId: "ca.org1.example.com", + }, + ); + +To Register an identity using register’s key + +const secret \= await connector.register( + { + keychainId: "keychain-id-that-store-certData-of-registrar", + keychainRef: "certData-label", + + // require in case of vault + type: FabricSigningCredentialType.VaultX509, // FabricSigningCredentialType.X509 + vaultTransitKey: { + token: testToken, + keyName: registrarKey, + }, + // required in case of web-socket server + type: FabricSigningCredentialType.WsX509, + webSocketKey: { + signature: signature, + sessionId: sessionId, + }, + }, + { + enrollmentID: "client-enrollmentID", + enrollmentSecret: "pw", + affiliation: "org1.department1", + }, + "ca.org1.example.com", // caID + ); + +To transact with fabric + +const resp \= await connector.transact{ + signingCredential: { + keychainId: keychainId, + keychainRef: "client-certData-id", + + // require in case of vault + type: FabricSigningCredentialType.VaultX509, // FabricSigningCredentialType.X509 + vaultTransitKey: { + token: testToken, + keyName: registrarKey, + }, + // required in case of web-socket server + type: FabricSigningCredentialType.WsX509, + webSocketKey: { + signature: signature, + sessionId: sessionId, + }, + }, + // .. other options +} + +To Rotate the key + +await connector.rotateKey( + { + keychainId: keychainId, + keychainRef: "client-certData-id", + type: FabricSigningCredentialType.VaultX509, // FabricSigningCredentialType.X509 + + // require in case of vault + vaultTransitKey: { + token: testToken, + keyName: registrarKey, + }, + // key rotation currently not available using web-socket server + // web-socket connection not used to manages external keys + // user should re-enroll with new pub/priv key pair + }, + { + enrollmentID: string; + enrollmentSecret: string; + caId: string; + } +) + +> Extensive documentation and examples in the [readthedocs](https://readthedocs.org/projects/hyperledger-cactus/) (WIP) + +#### 1.4.1. Identity Providers + +Identity providers allows client to manage their private more effectively and securely. Cactus Fabric Connector support multiple type of providers. Each provider differ based upon where the private are stored. On High level certificate credential are stored as + +{ + type: FabricSigningCredentialType; + credentials: { + certificate: string; + // if identity type is IdentityProvidersType.X509 + privateKey?: string; + }; + mspId: string; +} + +Currently Cactus Fabric Connector supports following Identity Providers + +* X509 : Simple and unsecured provider wherein `private` key is stored along with certificate in some `datastore`. Whenever connector require signature on fabric message, private key is brought from the `datastore` and message signed at the connector. + +* Vault-X.509 : Secure provider wherein `private` key is stored with vault’s transit transit engine and certificate in `certDatastore`. Rather then bringing the key to the connector, message digest are sent to the vault server which returns the `signature`. + +* WS-X.509 : Secure provider wherein `private` key is stored with `client` and certificate in `certDatastore`. To get the fabric messages signed, message digest is sent to the client via `webSocket` connection opened by the client in the beginning (as described above) + + +#### 1.4.2. Setting up a WS-X.509 provider + +The following packages are used to access private keys (via web-socket) stored on a clients external device (e.g., browser, mobile app, or an IoT device…). -[ws-identity](https://github.com/brioux/ws-identity): web-socket server that issues new ws-session tickets, authenticates incoming connections, and sends signature requests -[ws-identity-client](https://github.com/brioux/ws-identity-client): backend connector to send requests from fabric application to ws-identity -[ws-wallet](https://github.com/brioux/ws-wallet): external clients crypto key tool: create new key pair, request session ticket and open web-socket connection with ws-identity + +#### 1.4.3. Building the ws-identity docker image + +TBD + +### 1.5 Monitoring new blocks (WatchBlocks) + +* Use `ApiClient` to receive new blocks from a fabric ledger. + +* Type of the response can be configured. + +* Credentials must be configured using `gatewayOptions` argument (you can either send them directly in request or use wallet stored in keychain). + + +#### 1.5.1 Example + +For more detailed example check [fabric-watch-blocks-v1-endpoint.test.ts](#./src/test/typescript/integration/fabric-v2-2-x/fabric-watch-blocks-v1-endpoint.test.ts) + +// Setup +const signingCredential \= { + keychainId: uuidv4(), + keychainRef: "user2", +}; + +// Create RxJS Observable. +// This will connect to the fabric connector and start the monitoring operation. +const watchObservable \= apiClient.watchBlocksV1({ + channelName: "mychannel", // fabric channel name + gatewayOptions: { // use signing credential from keychain + identity: signingCredential.keychainRef, + wallet: { + keychain: signingCredential, + }, + }, + WatchBlocksListenerTypeV1.Full, // return full block data +}); + +// Subscribe to the observable to receive new blocks +const subscription \= watchObservable.subscribe({ + next(event) { + // Handle new event + }, + error(err) { + // Handle error from connector + }, +}); + +#### 1.5.2 Listener Type + +There are two types of listener type - original and cactus ones. + +##### Original + +Corresponds directly to `BlockType` from `fabric-common`: + +* `WatchBlocksListenerTypeV1.Filtered`, + +* `WatchBlocksListenerTypeV1.Full`, + +* `WatchBlocksListenerTypeV1.Private`, + + +##### Cactus (custom) + +Parses the data and returns custom formatted block. + +* `WatchBlocksListenerTypeV1.CactusTransactions`: Returns transactions summary. Compatible with legacy `fabric-socketio` monitoring operation. + + +2\. Architecture +-------------------------------------------------------------- + +The sequence diagrams for various endpoints are mentioned below + +### 2.1. run-transaction-endpoint + +![run-transaction-endpoint sequence diagram](../_images/run-transaction-endpoint1.png) + +The above diagram shows the sequence diagram of run-transaction-endpoint. User A (One of the many Users) interacts with the API Client which in turn, calls the API server. API server then executes transact() method which is explained in detailed in the subsequent diagram. + +![run-transaction-endpoint transact() method](../_images/run-transaction-endpoint-transact1.png) + +The above diagram shows the sequence diagram of transact() method of the PluginLedgerConnectorFabric class. The caller to this function, which in reference to the above sequence diagram is API server, sends RunTransactionRequest object as an argument to the transact() method. Based on the invocationType (FabricContractInvocationType.CALL, FabricCOntractInvocationType.SEND), corresponding responses are send back to the caller. + +![run-transaction-endpoint-enroll](../_images/run-transaction-endpoint-enroll.png) + +The above diagram shows the sequence diagram of enroll() method of the PluginLedgerConnectorFabric class. The caller to this function, which in reference to the above sequence diagram is API server, sends Signer object along with EnrollmentRequest as an argument to the enroll() method. Based on the singerType (FabricSigningCredentialType.X509, FabricSigningCredentialType.VaultX509, FabricSigningCredentialType.WsX509), corresponding identity is enrolled and stored inside keychain. + +3\. Containerization +---------------------------------------------------------------------- + +### 3.1. Building/running the container image locally + +In the Cactus project root say: + +DOCKER\_BUILDKIT\=1 docker build \-f ./packages/cactus-plugin-ledger-connector-fabric/Dockerfile . \-t cplcb + +Build with a specific version of the npm package: + +DOCKER\_BUILDKIT\=1 docker build \--build-arg NPM\_PKG\_VERSION\=0.4.1 \-f ./packages/cactus-plugin-ledger-connector-fabric/Dockerfile . \-t cplcb + +### 3.2. Running the container + +Launch container with plugin configuration as an **environment variable**: + +docker run \\ + \--rm \\ + \--publish 3000:3000 \\ + \--publish 4000:4000 \\ + \--env PLUGINS\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-fabric", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"instanceId": "some-unique-fabric-connector-instance-id", "dockerBinary": "usr/local/bin/docker","cliContainerEnv": { + "CORE\_PEER\_LOCALMSPID": "Org1MSP", + "CORE\_PEER\_ADDRESS": "peer0.org1.example.com:7051", + "CORE\_PEER\_MSPCONFIGPATH": + "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp", + "CORE\_PEER\_TLS\_ROOTCERT\_FILE": + "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt", + "ORDERER\_TLS\_ROOTCERT\_FILE": + "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" + }, + "discoveryOptions": { + "enabled": true, + "asLocalhost": true + } + }}}\]' \\ + cplcb + +Launch container with plugin configuration as a **CLI argument**: + +docker run \\ + \--rm \\ + \--publish 3000:3000 \\ + \--publish 4000:4000 \\ + cplcb \\ + ./node\_modules/.bin/cactusapi \\ + \--plugins\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-fabric", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"instanceId": "some-unique-fabric-connector-instance-id", "dockerBinary": "usr/local/bin/docker","cliContainerEnv": { + "CORE\_PEER\_LOCALMSPID": "Org1MSP", + "CORE\_PEER\_ADDRESS": "peer0.org1.example.com:7051", + "CORE\_PEER\_MSPCONFIGPATH": + "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp", + "CORE\_PEER\_TLS\_ROOTCERT\_FILE": + "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt", + "ORDERER\_TLS\_ROOTCERT\_FILE": + "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" + }, + "discoveryOptions": { + "enabled": true, + "asLocalhost": true + } + }}}\]' + +Launch container with **configuration file** mounted from host machine: + +echo '\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-fabric", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"instanceId": "some-unique-fabric-connector-instance-id", "dockerBinary": "usr/local/bin/docker","cliContainerEnv": { + "CORE\_PEER\_LOCALMSPID": "Org1MSP", + "CORE\_PEER\_ADDRESS": "peer0.org1.example.com:7051", + "CORE\_PEER\_MSPCONFIGPATH": + "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp", + "CORE\_PEER\_TLS\_ROOTCERT\_FILE": + "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt", + "ORDERER\_TLS\_ROOTCERT\_FILE": + "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" + }, + "discoveryOptions": { + "enabled": true, + "asLocalhost": true + } + }}}\]' \> cactus.json + +docker run \\ + \--rm \\ + \--publish 3000:3000 \\ + \--publish 4000:4000 \\ + \--mount type\=bind,source\="$(pwd)"/cactus.json,target\=/cactus.json \\ + cplcb \\ + ./node\_modules/.bin/cactusapi \\ + \--config-file\=/cactus.json + +### 3.3. Testing API calls with the container + +Don’t have a fabric network on hand to test with? Test or develop against our fabric All-In-One container! + +**Terminal Window 1 (Ledger)** + +docker run \--privileged \-p 0.0.0.0:8545:8545/tcp \-p 0.0.0.0:8546:8546/tcp \-p 0.0.0.0:8888:8888/tcp \-p 0.0.0.0:9001:9001/tcp \-p 0.0.0.0:9545:9545/tcp ghcr.io/hyperledger/cactus-fabric-all-in-one:v1.0.0-rc.2 + +**Terminal Window 2 (Cactus API Server)** + +docker run \\ + \--network host \\ + \--rm \\ + \--publish 3000:3000 \\ + \--publish 4000:4000 \\ + \--env PLUGINS\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-fabric", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"instanceId": "some-unique-fabric-connector-instance-id", "dockerBinary": "usr/local/bin/docker","cliContainerEnv": { + "CORE\_PEER\_LOCALMSPID": "Org1MSP", + "CORE\_PEER\_ADDRESS": "peer0.org1.example.com:7051", + "CORE\_PEER\_MSPCONFIGPATH": + "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp", + "CORE\_PEER\_TLS\_ROOTCERT\_FILE": + "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt", + "ORDERER\_TLS\_ROOTCERT\_FILE": + "/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" + }, + "discoveryOptions": { + "enabled": true, + "asLocalhost": true + } + }}}\]' \\ + cplcb + +**Terminal Window 3 (curl - replace eth accounts as needed)** + +curl \--location \--request POST 'http://127.0.0.1:4000/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/run-transaction' \\ +--header 'Content-Type: application/json' \\ +--data-raw '{ + channelName: "mychannel", + contractName: "contract-example"; + invocationType: "FabricContractInvocationType.SEND"; + methodName: "example" +}' + +The above should produce a response that looks similar to this: + +{ + "success": true, + "data": { + "transactionReceipt": { + "blockHash": "0x7c97c038a5d3bd84613fe23ed442695276d5d2df97f4e7c4f10ca06765033ffd", + "blockNumber": 1218, + "contractAddress": null, + "cumulativeGasUsed": 21000, + "from": "0x627306090abab3a6e1400e9345bc60c78a8bef57", + "gasUsed": 21000, + "logs": \[\], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "status": true, + "to": "0xf17f52151ebef6c7334fad080c5704d77216b732", + "transactionHash": "0xc7fcb46c735bdc696d500bfc70c72595a2b8c31813929e5c61d9a5aec3376d6f", + "transactionIndex": 0 + } + } +} + +4\. Prometheus Exporter +---------------------------------------------------------------------------- + +This class creates a prometheus exporter, which scraps the transactions (total transaction count) for the use cases incorporating the use of Fabric connector plugin. + +### 4.1. Usage Prometheus + +The prometheus exporter object is initialized in the `PluginLedgerConnectorFabric` class constructor itself, so instantiating the object of the `PluginLedgerConnectorFabric` class, gives access to the exporter object. You can also initialize the prometheus exporter object seperately and then pass it to the `IPluginLedgerConnectorFabricOptions` interface for `PluginLedgerConnectoFabric` constructor. + +`getPrometheusExporterMetricsEndpointV1` function returns the prometheus exporter metrics, currently displaying the total transaction count, which currently increments everytime the `transact()` method of the `PluginLedgerConnectorFabric` class is called. + +### 4.2. Prometheus Integration + +To use Prometheus with this exporter make sure to install [Prometheus main component](https://prometheus.io/download/). Once Prometheus is setup, the corresponding scrape\_config needs to be added to the prometheus.yml + +\- job\_name: 'fabric\_ledger\_connector\_exporter' + metrics\_path: api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/get-prometheus-exporter-metrics + scrape\_interval: 5s + static\_configs: + - targets: \['{host}:{port}'\] + +Here the `host:port` is where the prometheus exporter metrics are exposed. The test cases (For example, packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts) exposes it over `0.0.0.0` and a random port(). The random port can be found in the running logs of the test case and looks like (42379 in the below mentioned URL) `Metrics URL: http://0.0.0.0:42379/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-fabric/get-prometheus-exporter-metrics` + +Once edited, you can start the prometheus service by referencing the above edited prometheus.yml file. On the prometheus graphical interface (defaulted to http://localhost:9090), choose **Graph** from the menu bar, then select the **Console** tab. From the **Insert metric at cursor** drop down, select **cactus\_fabric\_total\_tx\_count** and click **execute** + +### 4.3. Helper code + +#### 4.3.1. response.type.ts + +This file contains the various responses of the metrics. + +#### 4.3.2. data-fetcher.ts + +This file contains functions encasing the logic to process the data points + +#### 4.3.3. metrics.ts + +This file lists all the prometheus metrics and what they are used for. + +5\. Contributing +-------------------------------------------------------------- + +We welcome contributions to Hyperledger Cactus in many forms, and there’s always plenty to do! + +Please review [CONTIRBUTING.md](#../../CONTRIBUTING.md) to get started. + +6\. License +---------------------------------------------------- + +This distribution is published under the Apache License Version 2.0 found in the [LICENSE](#../../LICENSE) file. + +7\. Acknowledgments +-------------------------------------------------------------------- + +[Previous](cactus-plugin-ledger-connector-corda.md "@hyperledger/cactus-plugin-ledger-connector-corda") [Next](cactus-plugin-ledger-connector-quorum.md "@hyperledger/cactus-plugin-ledger-connector-quorum") + +* * * diff --git a/docs/docs/cactus/packages/cactus-plugin-ledger-connector-quorum.md b/docs/docs/cactus/packages/cactus-plugin-ledger-connector-quorum.md new file mode 100644 index 0000000000..319fb26785 --- /dev/null +++ b/docs/docs/cactus/packages/cactus-plugin-ledger-connector-quorum.md @@ -0,0 +1,350 @@ +`@hyperledger/cactus-plugin-ledger-connector-quorum` +======================================================================================================================================= + +This plugin provides `Cactus` a way to interact with Quorum networks. Using this we can perform: + +* Deploy Smart-contracts through bytecode. + +* Build and sign transactions using different keystores. + +* Invoke smart-contract functions that we have deployed on the network. + + +Summary +------------------------------------------------ + +* [Getting Started](#getting-started) + +* [Usage](#usage) + +* [Prometheus Exporter](#prometheus-exporter) + +* [Runing the tests](#running-the-tests) + +* [Contributing](#contributing) + +* [License](#license) + +* [Acknowledgments](#acknowledgments) + + +Getting Started +---------------------------------------------------------------- + +Clone the git repository on your local machine. Follow these instructions that will get you a copy of the project up and running on your local machine for development and testing purposes. + +### Prerequisites + +In the root of the project to install the dependencies execute the command: + +npm run configure + +Usage +-------------------------------------------- + +To use this import public-api and create new **PluginLedgerConnectorQuorum**. + + const connector: PluginLedgerConnectorQuorum \= new PluginLedgerConnectorQuorum({ + instanceId: uuidV4(), + rpcApiHttpHost, + pluginRegistry: new PluginRegistry(), + }); + +You can make calls through the connector to the plugin API: + +async invokeContract(req: InvokeContractJsonObjectV1Request):Promise; +async transact(req: RunTransactionRequest): Promise; +async transactSigned(rawTransaction: string): Promise; +async transactGethKeychain(txIn: RunTransactionRequest): Promise; +async transactPrivateKey(req: RunTransactionRequest): Promise; +async transactCactusKeychainRef(req: RunTransactionRequest):Promise; +async deployContract(req: DeployContractSolidityBytecodeV1Request :Promise; +async deployContractJsonObject(req: DeployContractSolidityBytecodeJsonObjectV1Request): Promise +async invokeRawWeb3EthMethod(req: InvokeRawWeb3EthMethodV1Request): Promise; +async invokeRawWeb3EthContract(req: InvokeRawWeb3EthContractV1Request): Promise; + +Call example to deploy a contract: + +const deployOut \= await connector.deployContract({ + web3SigningCredential: { + ethAccount: firstHighNetWorthAccount, + secret: "", + type: Web3SigningCredentialType.GETHKEYCHAINPASSWORD, + }, + bytecode: ContractJson.bytecode, + gas: 1000000, +}); + +The field “type” can have the following values: + +enum Web3SigningCredentialType { + CACTUSKEYCHAINREF \= 'CACTUS\_KEYCHAIN\_REF', + GETHKEYCHAINPASSWORD \= 'GETH\_KEYCHAIN\_PASSWORD', + PRIVATEKEYHEX \= 'PRIVATE\_KEY\_HEX', + NONE \= 'NONE' +} + +> Extensive documentation and examples in the [readthedocs](https://readthedocs.org/projects/hyperledger-cactus/) (WIP) + +QuorumApiClient +---------------------------------------------------------------- + +All connector API endpoints are defined in [open-api specification](#./src/main/json/openapi.json). You can use [QuorumApiClient](#./src/main/typescript/api-client) to call remote quorum connector functions. It also contain additional utility functions to ease integration. + +### REST Functions + +See [DefaultApi](#./src/main/typescript/generated/openapi/typescript-axios/api.ts) for up-to-date listing of supported endpoints. + +* deployContractSolBytecodeJsonObjectV1 + +* deployContractSolBytecodeV1 + +* getPrometheusMetricsV1 + +* invokeContractV1 + +* invokeContractV1NoKeychain + +* invokeRawWeb3EthContractV1 + +* invokeRawWeb3EthMethodV1 + +* runTransactionV1 + + +### Asynchronous Functions (socket.io) + +* watchBlocksV1 + + +### Send Request Methods + +Both methods are deprecated, async version returns immediately while sync respond with Promise of a call results. + +* `sendAsyncRequest` + +* `sendSyncRequest` + + +#### Supported Requests + +* `web3Eth`: Calls `invokeRawWeb3EthMethodV1` + +* `web3EthContract`: Calls `invokeRawWeb3EthContractV1` + + +#### Arguments + +* The same for both async and sync methods. + +* Arguments interpretation depends on `method.type` (i.e. request type) + + +// Contract definition for web3EthContract request, ignored otherwise +contract: { + abi?: AbiItem\[\], + address?: string +}, + +// Request definition +method: { + type: "web3Eth" | "web3EthContract", + command: string // web3 method + function?: string; // contract function + params?: any\[\]; // contract parameters +} + +// web3 method arguments +args: { + { + args?: any\[\] | Record; + } +}, + +Running the tests +-------------------------------------------------------------------- + +To check that all has been installed correctly and that the pugin has no errors, there are two options to run the tests: + +* Run this command at the project’s root: + + +npm run test:plugin-ledger-connector-quorum + +### Building/running the container image locally + +In the Cactus project root say: + +DOCKER\_BUILDKIT\=1 docker build \-f ./packages/cactus-plugin-ledger-connector-quorum/Dockerfile . \-t cplcb + +Build with a specific version of the npm package: + +DOCKER\_BUILDKIT\=1 docker build \--build-arg NPM\_PKG\_VERSION\=0.4.1 \-f ./packages/cactus-plugin-ledger-connector-quorum/Dockerfile . \-t cplcb + +#### Running the container + +Launch container with plugin configuration as an **environment variable**: + +docker run \\ + \--rm \\ + \--publish 3000:3000 \\ + \--publish 4000:4000 \\ + \--env AUTHORIZATION\_PROTOCOL\='NONE' \\ + \--env AUTHORIZATION\_CONFIG\_JSON\='{}' \\ + \--env PLUGINS\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-quorum", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-quorum-connector-instance-id"}}\]' \\ + cplcb + +Launch container with plugin configuration as a **CLI argument**: + +docker run \\ + \--rm \\ + \--publish 3000:3000 \\ + \--publish 4000:4000 \\ + cplcb \\ + ./node\_modules/@hyperledger/cactus-cmd-api-server/dist/lib/main/typescript/cmd/cactus-api.js \\ + \--authorization-protocol\='NONE' \\ + \--authorization-config-json\='{}' \\ + \--plugins\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-quorum", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-quorum-connector-instance-id"}}\]' + +Launch container with **configuration file** mounted from host machine: + +echo '{"authorizationProtocol":"NONE","authorizationConfigJson":{},"plugins":\[{"packageName":"@hyperledger/cactus-plugin-ledger-connector-quorum","type":"org.hyperledger.cactus.plugin\_import\_type.LOCAL","action":"org.hyperledger.cactus.plugin\_import\_action.INSTALL","options":{"rpcApiHttpHost":"http://localhost:8545","instanceId":"some-unique-quorum-connector-instance-id"}}\]}' \> cactus.json + +docker run \\ + \--rm \\ + \--publish 3000:3000 \\ + \--publish 4000:4000 \\ + \--mount type\=bind,source\="$(pwd)"/cactus.json,target\=/cactus.json \\ + cplcb \\ + ./node\_modules/@hyperledger/cactus-cmd-api-server/dist/lib/main/typescript/cmd/cactus-api.js \\ + \--config-file\=/cactus.json + +#### Testing API calls with the container + +Don’t have a quorum network on hand to test with? Test or develop against our quorum All-In-One container! + +**Terminal Window 1 (Ledger)** + +docker run \-p 0.0.0.0:8545:8545/tcp \-p 0.0.0.0:8546:8546/tcp \-p 0.0.0.0:8888:8888/tcp \-p 0.0.0.0:9001:9001/tcp \-p 0.0.0.0:9545:9545/tcp hyperledger/cactus-quorum-all-in-one:latest + +**Terminal Window 2 (Cactus API Server)** + +docker run \\ + \--network host \\ + \--rm \\ + \--publish 3000:3000 \\ + \--publish 4000:4000 \\ + \--env PLUGINS\='\[{"packageName": "@hyperledger/cactus-plugin-ledger-connector-quorum", "type": "org.hyperledger.cactus.plugin\_import\_type.LOCAL", "action": "org.hyperledger.cactus.plugin\_import\_action.INSTALL", "options": {"rpcApiHttpHost": "http://localhost:8545", "instanceId": "some-unique-quorum-connector-instance-id"}}\]' \\ + cplcb + +**Terminal Window 3 (curl - replace eth accounts as needed)** + +curl \--location \--request POST 'http://127.0.0.1:4000/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-quorum/run-transaction' \\ +--header 'Content-Type: application/json' \\ +--data-raw '{ + "web3SigningCredential": { + "ethAccount": "627306090abaB3A6e1400e9345bC60c78a8BEf57", + "secret": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3", + "type": "PRIVATE\_KEY\_HEX" + }, + "consistencyStrategy": { + "blockConfirmations": 0, + "receiptType": "NODE\_TX\_POOL\_ACK" + }, + "transactionConfig": { + "from": "627306090abaB3A6e1400e9345bC60c78a8BEf57", + "to": "f17f52151EbEF6C7334FAD080c5704D77216b732", + "value": 1, + "gas": 10000000 + } +}' + +The above should produce a response that looks similar to this: + +{ + "success": true, + "data": { + "transactionReceipt": { + "blockHash": "0x7c97c038a5d3bd84613fe23ed442695276d5d2df97f4e7c4f10ca06765033ffd", + "blockNumber": 1218, + "contractAddress": null, + "cumulativeGasUsed": 21000, + "from": "0x627306090abab3a6e1400e9345bc60c78a8bef57", + "gasUsed": 21000, + "logs": \[\], + "logsBloom": "0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", + "status": true, + "to": "0xf17f52151ebef6c7334fad080c5704d77216b732", + "transactionHash": "0xc7fcb46c735bdc696d500bfc70c72595a2b8c31813929e5c61d9a5aec3376d6f", + "transactionIndex": 0 + } + } +} + +Prometheus Exporter +------------------------------------------------------------------------ + +This class creates a prometheus exporter, which scrapes the transactions (total transaction count) for the use cases incorporating the use of Quorum connector plugin. + +### Prometheus Exporter Usage + +The prometheus exporter object is initialized in the `PluginLedgerConnectorQuorum` class constructor itself, so instantiating the object of the `PluginLedgerConnectorQuorum` class, gives access to the exporter object. You can also initialize the prometheus exporter object seperately and then pass it to the `IPluginLedgerConnectorQuorumOptions` interface for `PluginLedgerConnectoQuorum` constructor. + +`getPrometheusMetricsV1` function returns the prometheus exporter metrics, currently displaying the total transaction count, which currently increments everytime the `transact()` method of the `PluginLedgerConnectorQuorum` class is called. + +### Prometheus Integration + +To use Prometheus with this exporter make sure to install [Prometheus main component](https://prometheus.io/download/). Once Prometheus is setup, the corresponding scrape\_config needs to be added to the prometheus.yml + +\- job\_name: 'quorum\_ledger\_connector\_exporter' + metrics\_path: api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-quorum/get-prometheus-exporter-metrics + scrape\_interval: 5s + static\_configs: + - targets: \['{host}:{port}'\] + +Here the `host:port` is where the prometheus exporter metrics are exposed. The test cases (For example, packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/deploy-contract-from-json.test.ts) exposes it over `0.0.0.0` and a random port(). The random port can be found in the running logs of the test case and looks like (42379 in the below mentioned URL) `Metrics URL: http://0.0.0.0:42379/api/v1/plugins/@hyperledger/cactus-plugin-ledger-connector-quorum/get-prometheus-exporter-metrics` + +Once edited, you can start the prometheus service by referencing the above edited prometheus.yml file. On the prometheus graphical interface (defaulted to http://localhost:9090), choose **Graph** from the menu bar, then select the **Console** tab. From the **Insert metric at cursor** drop down, select **cactus\_quorum\_total\_tx\_count** and click **execute** + +### Helper code + +#### response.type.ts + +This file contains the various responses of the metrics. + +#### data-fetcher.ts + +This file contains functions encasing the logic to process the data points + +#### metrics.ts + +This file lists all the prometheus metrics and what they are used for. + +Running the tests +------------------------------------------------------ + +To check that all has been installed correctly and that the pugin has no errors, there are two options to run the tests: + +* Run this command at the project’s root: + + +npm run test:plugin-ledger-connector-quorum + +Contributing +---------------------------------------------------------- + +We welcome contributions to Hyperledger Cactus in many forms, and there’s always plenty to do! + +Please review [CONTIRBUTING.md](#../../CONTRIBUTING.md) to get started. + +License +------------------------------------------------ + +This distribution is published under the Apache License Version 2.0 found in the [LICENSE](#../../LICENSE) file. + +Acknowledgments +---------------------------------------------------------------- + +[Previous](cactus-plugin-ledger-connector-fabric.md "@hyperledger/cactus-plugin-ledger-connector-fabric") [Next](cactus-test-api-client.md "@hyperledger/cactus-test-api-client") + +* * * diff --git a/docs/docs/cactus/packages/cactus-test-api-client.md b/docs/docs/cactus/packages/cactus-test-api-client.md new file mode 100644 index 0000000000..85ad4df824 --- /dev/null +++ b/docs/docs/cactus/packages/cactus-test-api-client.md @@ -0,0 +1,20 @@ +`@hyperledger/cactus-test-api-client` +========================================================================================================= + +This is the test package for the package that’s called `cactus-api-client` + +Usage +-------------------------------------------- + +// TODO: DEMONSTRATE API + +FAQ +---------------------------------------- + +### **What is a dedicated test package for?** + +This is a dedicated test package meaning that it verifies the integration between two packages that are somehow dependent on each other and therefore these tests cannot be added properly in the child package due to circular dependency issues and it would not be fitting to add it in the parent because the child package’s tests should not be held by the parent as a matter of principle. + +[Previous](cactus-plugin-ledger-connector-quorum.md "@hyperledger/cactus-plugin-ledger-connector-quorum") [Next](cactus-test-cmd-api-server.md "@hyperledger/cactus-test-cmd-api-server") + +* * * diff --git a/docs/docs/cactus/packages/cactus-test-cmd-api-server.md b/docs/docs/cactus/packages/cactus-test-cmd-api-server.md new file mode 100644 index 0000000000..32873de650 --- /dev/null +++ b/docs/docs/cactus/packages/cactus-test-cmd-api-server.md @@ -0,0 +1,20 @@ +`@hyperledger/cactus-test-cmd-api-server` +================================================================================================================= + +This is the test package for the package that’s called `cactus-cmd-api-server` + +Usage +-------------------------------------------- + +// TODO: DEMONSTRATE API + +FAQ +---------------------------------------- + +### **What is a dedicated test package for?** + +This is a dedicated test package meaning that it verifies the integration between two packages that are somehow dependent on each other and therefore these tests cannot be added properly in the child package due to circular dependency issues and it would not be fitting to add it in the parent because the child package’s tests should not be held by the parent as a matter of principle. + +[Previous](cactus-test-api-client.md "@hyperledger/cactus-test-api-client") [Next](cactus-test-plugin-ledger-connector-quorum.md "@hyperledger/cactus-test-plugin-ledger-connector-quorum") + +* * * diff --git a/docs/docs/cactus/packages/cactus-test-plugin-ledger-connector-quorum.md b/docs/docs/cactus/packages/cactus-test-plugin-ledger-connector-quorum.md new file mode 100644 index 0000000000..0186ecee6f --- /dev/null +++ b/docs/docs/cactus/packages/cactus-test-plugin-ledger-connector-quorum.md @@ -0,0 +1,18 @@ +`@hyperledger/cactus-test-plugin-ledger-connector-quorum` +================================================================================================================================================= + +Usage +-------------------------------------------- + +// TODO: DEMONSTRATE API + +FAQ +---------------------------------------- + +### **What is a dedicated test package for?** + +This is a dedicated test package meaning that it verifies the integration between two packages that are somehow dependent on each other and therefore these tests cannot be added properly in the child package due to circular dependency issues and it would not be fitting to add it in the parent because the child package’s tests should not be held by the parent as a matter of principle. + +[Previous](cactus-test-cmd-api-server.md "@hyperledger/cactus-test-cmd-api-server") [Next](cactus-test-tooling.md "@hyperledger/cactus-test-tooling") + +* * * diff --git a/docs/docs/cactus/packages/cactus-test-tooling.md b/docs/docs/cactus/packages/cactus-test-tooling.md new file mode 100644 index 0000000000..cfb146ffc7 --- /dev/null +++ b/docs/docs/cactus/packages/cactus-test-tooling.md @@ -0,0 +1,24 @@ +`@hyperledger/cactus-test-tooling` +=================================================================================================== + +> TODO: description + +Usage +-------------------------------------------- + +// TODO: DEMONSTRATE API + +Docker image for the ws-identity server +---------------------------------------------------------------------------------------------------------------- + +A docker image of the [ws-identity server](https://hub.docker.com/repository/docker/brioux/ws-identity) is used to test integration of WS-X.509 credential type in the fabric connector plugin. + +[ws-identity](https://github.com/brioux/ws-identity) includes A Docker file to build the image: clone the repo, install packages, build src and the image + +npm install +npm run build +docker build . \-t \[image\-name\] + +[Previous](cactus-test-plugin-ledger-connector-quorum.md "@hyperledger/cactus-test-plugin-ledger-connector-quorum") [Next](../support.md "Ledger Support for Connectors") + +* * * diff --git a/docs/docs/cactus/regulatory-and-industry-initiatives-reading-list.md b/docs/docs/cactus/regulatory-and-industry-initiatives-reading-list.md new file mode 100644 index 0000000000..9a3f0ddc20 --- /dev/null +++ b/docs/docs/cactus/regulatory-and-industry-initiatives-reading-list.md @@ -0,0 +1,59 @@ +Regulatory and Industry Initiatives Reading List +================================================ + +A non-exhaustive list of industry standards and regulations/regulatory plans that one could read through if they are trying to get a comprehensive picture of what it takes from the non-technical standpoint to interoperate existing productive systems in finance, trade and more. + +While these documents are not dealing with technological problems, even just the awareness of their existence could still add tremendous value to someone who is looking to implement some sort of integration/interoperability between different DLTs or a DLT and any pre-existing centralized system. + +MICA European crypto assets regulation (coming into force by 2023) +------------------------------------------------------------------ + +https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX%3A52020PC0593 + +Pilot Regime for DLT market infrastructure +------------------------------------------ + +https://eur-lex.europa.eu/legal-content/EN/TXT/PDF/?uri=CELEX:52020PC0594&from=EN + +Paperless trade framework (UN / UNESCAP more on APAC now but supposed to expand in EU) for bilateral cooperation +---------------------------------------------------------------------------------------------------------------- + +https://readiness.digitalizetrade.org/ + +ICC Digital Standard Initiative (Private sector) +------------------------------------------------ + +https://iccwbo.org/media-wall/news-speeches/digital-trade-standards-initiative-launches-under-the-umbrella-of-icc/ + +BAFT Digital Ledger Payment Commitment - Technical and Business Best Practices (Private sector - Banking Industry) +------------------------------------------------------------------------------------------------------------------ + +https://www.baft.org/wp-content/uploads/2021/03/baft-dlpc-technical-bps-v1-1.pdf + +https://www.baft.org/wp-content/uploads/2021/03/baft-dlpc-business-bps-v1-1.pdf + +DCSA Digital Container Shipping Association (Private sector - shipping industry) +-------------------------------------------------------------------------------- + +https://dcsa.org/dcsa-publishes-standards-for-the-bill-of-lading/ + +MSB Networked Supervision +------------------------- + +https://www.occ.gov/news-issuances/news-releases/2021/nr-occ-2021-2.html + +OCC Interpretative letter on the use of DA for payments +------------------------------------------------------- + +https://www.occ.gov/news-issuances/news-releases/2021/nr-occ-2021-2a.pdf + +Open Digital Asset Protocol from IETF (Thanks to Rafael Belchior for these) +--------------------------------------------------------------------------- + +https://datatracker.ietf.org/doc/draft-hargreaves-odap/ https://datatracker.ietf.org/doc/draft-belchior-gateway-recovery/ + +There are some more standards in section 6.2 of https://deepai.org/publication/a-survey-on-blockchain-interoperability-past-present-and-future-trends + +[Previous](whitepaper.md "Hyperledger Cactus White Paper") [Next](packages.md "Cactus Components") + +* * * diff --git a/docs/docs/cactus/support.md b/docs/docs/cactus/support.md new file mode 100644 index 0000000000..255d8e4e1a --- /dev/null +++ b/docs/docs/cactus/support.md @@ -0,0 +1,15 @@ +Ledger Support for Connectors +============================================================================================ + +This section contains the ledger supported versions for connectors in Hyperledger Cactus. + +* [Besu](support/besu.md) +* [Corda](support/corda.md) +* [Fabric](support/fabric.md) +* [Iroha](support/iroha.md) +* [Quorum](support/quorum.md) +* [xDai](support/xdai.md) + +[Previous](packages/cactus-test-tooling.md "@hyperledger/cactus-test-tooling") [Next](support/besu.md "Besu Support") + +* * * diff --git a/docs/docs/cactus/support/besu.md b/docs/docs/cactus/support/besu.md new file mode 100644 index 0000000000..a88205bc7f --- /dev/null +++ b/docs/docs/cactus/support/besu.md @@ -0,0 +1,128 @@ +Besu Support +========================================================== + +Note + +The deployContract feature is for development and test case authoring only, not recommended to be used in production environments for managing smart contracts. + +Hyperledger Cactus v0.9.0 + +Besu version + +deployContract\* + +invokeContract + +runTransaction + +Besu 21.1.6 and Orion 21.1.1 + +✅ test + +✅ test + +✅ test + +Besu 1.5.1 and Orion 1.6 + +✅ test + +✅ test + +✅ test + +Hyperledger Cactus v0.8.0 + +Besu version + +deployContract\* + +invokeContract + +runTransaction + +Besu 1.5.1 and Orion 1.6 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/invoke-contract.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts) + +Hyperledger Cactus v0.7.0 + +Besu version + +deployContract\* + +invokeContract + +runTransaction + +Besu 1.5.1 and Orion 1.6 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/invoke-contract.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts) + +Hyperledger Cactus v0.6.0 + +Besu version + +deployContract\* + +invokeContract + +runTransaction + +Besu 1.5.1 and Orion 1.6 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/invoke-contract.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts) + +Hyperledger Cactus v0.5.0 + +Besu version + +deployContract\* + +invokeContract + +runTransaction + +Besu 1.5.1 and Orion 1.6 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/invoke-contract.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts) + +Hyperledger Cactus v0.4.1 + +Besu version + +deployContract\* + +invokeContract + +runTransaction + +Besu 1.5.1 and Orion 1.6 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/invoke-contract-v2.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-besu/src/test/typescript/integration/plugin-ledger-connector-besu/deploy-contract/deploy-contract-from-json.test.ts) + + + +[Previous](../support.md "Ledger Support for Connectors") [Next](corda.md "Corda Support") + +* * * diff --git a/docs/docs/cactus/support/corda.md b/docs/docs/cactus/support/corda.md new file mode 100644 index 0000000000..1cb5cfdcae --- /dev/null +++ b/docs/docs/cactus/support/corda.md @@ -0,0 +1,136 @@ +Corda Support +============================================================ + +Note + +The deployContract feature is for development and test case authoring only, not recommended to be used in production environments for managing smart contracts. + +Hyperledger Cactus v0.9.0 + +Corda version + +deployContract\* + +invokeContract + +runTransaction + +Corda 4.8 + +✅ test + +✅ test + +✅ test + +Corda 4.7 + +✅ test + +✅ test + +✅ test + +Corda 4.5 + +✅ test + +✅ test + +✅ test + +Hyperledger Cactus v0.8.0 + +Corda version + +deployContract\* + +invokeContract + +runTransaction + +Corda 4.5 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/deploy-cordapp-jars-to-nodes.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts) + +Hyperledger Cactus v0.7.0 + +Corda version + +deployContract\* + +invokeContract + +runTransaction + +Corda 4.5 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/deploy-cordapp-jars-to-nodes.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts) + +Hyperledger Cactus v0.6.0 + +Corda version + +deployContract\* + +invokeContract + +runTransaction + +Corda 4.5 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/deploy-cordapp-jars-to-nodes.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts) + +Hyperledger Cactus v0.5.0 + +Corda version + +deployContract\* + +invokeContract + +runTransaction + +Corda 4.5 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/deploy-cordapp-jars-to-nodes.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts) + +Hyperledger Cactus v0.4.1 + +Corda version + +deployContract\* + +invokeContract + +runTransaction + +Corda 4.5 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/deploy-cordapp-jars-to-nodes.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-corda/src/test/typescript/integration/jvm-kotlin-spring-server.test.ts) + + + +[Previous](besu.md "Besu Support") [Next](fabric.md "Fabric Support") + +* * * diff --git a/docs/docs/cactus/support/fabric.md b/docs/docs/cactus/support/fabric.md new file mode 100644 index 0000000000..caa1e79f64 --- /dev/null +++ b/docs/docs/cactus/support/fabric.md @@ -0,0 +1,168 @@ +Fabric Support +============================================================== + +Note + +The deployContract feature is for development and test case authoring only, not recommended to be used in production environments for managing smart contracts. + +Hyperledger Cactus v0.9.0 + +Fabric version + +deployContract\* + +invokeContract + +runTransaction + +Fabric 2.2.0 + +✅ test + +✅ test + +✅ test + +Fabric 1.4.8 + +✅ test + +✅ test + +✅ test + +Hyperledger Cactus v0.8.0 + +Fabric version + +deployContract\* + +invokeContract + +runTransaction + +Fabric 2.2.0 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-javascript-source.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts) + +Fabric 1.4.8 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/deploy-cc-from-golang-source.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts) + +Hyperledger Cactus v0.7.0 + +Fabric version + +deployContract\* + +invokeContract + +runTransaction + +Fabric 2.2.0 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-javascript-source.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts) + +Fabric 1.4.8 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/deploy-cc-from-golang-source.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts) + +Hyperledger Cactus v0.6.0 + +Fabric version + +deployContract\* + +invokeContract + +runTransaction + +Fabric 2.2.0 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-javascript-source.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts) + +Fabric 1.4.8 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/deploy-cc-from-golang-source.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts) + +Hyperledger Cactus v0.5.0 + +Fabric version + +deployContract\* + +invokeContract + +runTransaction + +Fabric 2.2.0 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/deploy-cc-from-javascript-source.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts) + +Fabric 1.4.8 + +[✅](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/deploy-cc-from-golang-source.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts) + +Hyperledger Cactus v0.4.1 + +Fabric version + +deployContract\* + +invokeContract + +runTransaction + +Fabric 2.2.0 + +❌ + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v2-2-x/run-transaction-endpoint-v1.test.ts) + +Fabric 1.4.8 + +✅ + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-fabric/src/test/typescript/integration/fabric-v1-4-x/run-transaction-endpoint-v1.test.ts) + + + +[Previous](corda.md "Corda Support") [Next](iroha.md "Iroha Support") + +* * * diff --git a/docs/docs/cactus/support/iroha.md b/docs/docs/cactus/support/iroha.md new file mode 100644 index 0000000000..dec2132b10 --- /dev/null +++ b/docs/docs/cactus/support/iroha.md @@ -0,0 +1,22 @@ +Iroha Support +============================================================ + +Note + +The deployContract feature not yet implemented since Iroha lacks full smart contract support during the initial development stage of the Iroha connector plugin. + +Hyperledger Cactus v0.9.0 + +Iroha version + +runTransaction + +Iroha 1.2.0 and Postgres 9.5 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.9.0/packages/cactus-plugin-ledger-connector-iroha/src/test/typescript/integration/run-transaction-endpoint-v1.test.ts) + + + +[Previous](fabric.md "Fabric Support") [Next](quorum.md "Quorum Support") + +* * * diff --git a/docs/docs/cactus/support/quorum.md b/docs/docs/cactus/support/quorum.md new file mode 100644 index 0000000000..6ad23472bb --- /dev/null +++ b/docs/docs/cactus/support/quorum.md @@ -0,0 +1,168 @@ +Quorum Support +============================================================== + +Note + +The deployContract feature is for development and test case authoring only, not recommended to be used in production environments for managing smart contracts. + +Hyperledger Cactus v0.9.0 + +Quorum version + +deployContract\* + +invokeContract + +runTransaction + +Quorum 21.4.1 and Tessera 21.1.1 + +✅ test + +✅ test + +✅ test + +Quorum 2.3.0 and Tessera 0.10.0 + +✅ test + +✅ test + +✅ test + +Hyperledger Cactus v0.8.0 + +Quorum version + +deployContract\* + +invokeContract + +runTransaction + +Quorum 21.4.1 and Tessera 21.1.1 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-deploy-contract-from-json.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-invoke-contract.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-deploy-contract-from-json.test.ts) + +Quorum 2.3.0 and Tessera 0.10.0 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v2.3.0-deploy-contract-from-json.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v2.3.0-invoke-contract.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v2.3.0-deploy-contract-from-json.test.ts) + +Hyperledger Cactus v0.7.0 + +Quorum version + +deployContract\* + +invokeContract + +runTransaction + +Quorum 21.4.1 and Tessera 21.1.1 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-deploy-contract-from-json.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-invoke-contract.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-deploy-contract-from-json.test.ts) + +Quorum 2.3.0 and Tessera 0.10.0 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v2.3.0-deploy-contract-from-json.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v2.3.0-invoke-contract.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v2.3.0-deploy-contract-from-json.test.ts) + +Hyperledger Cactus v0.6.0 + +Quorum version + +deployContract\* + +invokeContract + +runTransaction + +Quorum 21.4.1 and Tessera 21.1.1 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-deploy-contract-from-json.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-invoke-contract.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v21.4.1-deploy-contract-from-json.test.ts) + +Quorum 2.3.0 and Tessera 0.10.0 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v2.3.0-deploy-contract-from-json.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v2.3.0-invoke-contract.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/v2.3.0-deploy-contract-from-json.test.ts) + +Hyperledger Cactus v0.5.0 + +Quorum version + +deployContract\* + +invokeContract + +runTransaction + +Quorum 21.4.1 and Tessera 21.1.1 + +❌ + +❌ + +❌ + +Quorum 2.3.0 and Tessera 0.10.0 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/deploy-contract-from-json.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/invoke-contract.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/deploy-contract-from-json.test.ts) + +Hyperledger Cactus v0.4.1 + +Quorum version + +deployContract\* + +invokeContract + +runTransaction + +Quorum 21.4.1 and Tessera 21.1.1 + +❌ + +❌ + +❌ + +Quorum 2.3.0 and Tessera 0.10.0 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/deploy-contract-from-json.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/invoke-contract-v2.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.4.1/packages/cactus-plugin-ledger-connector-quorum/src/test/typescript/integration/plugin-ledger-connector-quorum/deploy-contract/deploy-contract-from-json.test.ts) + + + +[Previous](iroha.md "Iroha Support") [Next](xdai.md "xDai Support") + +* * * diff --git a/docs/docs/cactus/support/xdai.md b/docs/docs/cactus/support/xdai.md new file mode 100644 index 0000000000..651db15d5b --- /dev/null +++ b/docs/docs/cactus/support/xdai.md @@ -0,0 +1,120 @@ +xDai Support +========================================================== + +Note + +The deployContract feature is for development and test case authoring only, not recommended to be used in production environments for managing smart contracts. + +Hyperledger Cactus v0.9.0 + +xDai version + +deployContract\* + +invokeContract + +runTransaction + +xDai 1.8.27 + +✅ test + +✅ test + +✅ test + +Hyperledger Cactus v0.8.0 + +xDai version + +deployContract\* + +invokeContract + +runTransaction + +xDai 1.8.27 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/deploy-contract-from-json-xdai.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/invoke-contract-xdai.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.8.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/deploy-contract-from-json-xdai.test.ts) + +Hyperledger Cactus v0.7.0 + +xDai version + +deployContract\* + +invokeContract + +runTransaction + +xDai 1.8.27 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/deploy-contract-from-json-xdai.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/invoke-contract-xdai.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.7.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/deploy-contract-from-json-xdai.test.ts) + +Hyperledger Cactus v0.6.0 + +xDai version + +deployContract\* + +invokeContract + +runTransaction + +xDai 1.8.27 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/deploy-contract-from-json-xdai.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/invoke-contract-xdai.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.6.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/deploy-contract-from-json-xdai.test.ts) + +Hyperledger Cactus v0.5.0 + +xDai version + +deployContract\* + +invokeContract + +runTransaction + +xDai 1.8.27 + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/deploy-contract-from-json-xdai.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/invoke-contract-xdai.test.ts) + +✅ [test](https://github.com/hyperledger/cactus/blob/v0.5.0/packages/cactus-plugin-ledger-connector-xdai/src/test/typescript/integration/deploy-contract-from-json-xdai.test.ts) + +Hyperledger Cactus v0.4.1 + +xDai version + +deployContract\* + +invokeContract + +runTransaction + +xDai 1.8.27 + +❌ + +❌ + +❌ + + + +[Previous](quorum.md "Quorum Support") + +* * * diff --git a/docs/docs/cactus/whitepaper.md b/docs/docs/cactus/whitepaper.md new file mode 100644 index 0000000000..4711378684 --- /dev/null +++ b/docs/docs/cactus/whitepaper.md @@ -0,0 +1,8 @@ +Hyperledger Cactus White Paper +====================================================================================== + +The white paper is presently undergoing a revision. Please visit the [repository](https://github.com/hyperledger/cacti/blob/main/whitepaper/whitepaper.md) for updates. + +[Previous](contributing.md "Contributing") [Next](regulatory-and-industry-initiatives-reading-list.md "Regulatory and Industry Initiatives Reading List") + +* * * diff --git a/docs/docs/concepts/data-sharing.md b/docs/docs/concepts/data-sharing.md new file mode 100644 index 0000000000..b4e9cf00c7 --- /dev/null +++ b/docs/docs/concepts/data-sharing.md @@ -0,0 +1,3 @@ +# Data Sharing + +This is a basic interoperability mode or use case pattern. [Here](../weaver/interoperability-modes.md#data-sharing) is a description. diff --git a/docs/docs/contact-us.md b/docs/docs/contact-us.md new file mode 100644 index 0000000000..c1d7a1926c --- /dev/null +++ b/docs/docs/contact-us.md @@ -0,0 +1,9 @@ +You can contact us or seek help through the following channels: + +- Mailing list: [cacti@lists.hyperledger.org](mailto:cacti@lists.hyperledger.org) +- Discord channels: + * Cacti users: [https://discord.com/channels/905194001349627914/908379366650703943](https://discord.com/channels/905194001349627914/908379366650703943) + * Cacti contributors: [https://discord.com/channels/905194001349627914/908379338716631050](https://discord.com/channels/905194001349627914/908379338716631050) + * Hyperledger: [https://discord.com/invite/hyperledger](https://discord.com/invite/hyperledger) + +The maintainers are [listed](https://github.com/hyperledger/cacti/blob/main/MAINTAINERS.md) in the GitHub repository. diff --git a/docs/docs/contributing/asking-a-question.md b/docs/docs/contributing/asking-a-question.md new file mode 100644 index 0000000000..7dafbaa6ec --- /dev/null +++ b/docs/docs/contributing/asking-a-question.md @@ -0,0 +1,17 @@ +# Asking a Question + +!!! tip + + * check the [FAQs](../faqs.md) to see if your question has already been asked. + * make sure you provide all relevant details. + * include information about what you have already tried. + * review [How to Ask Technical Questions to Get Quality Answers](https://opensource.com/life/16/10/how-ask-technical-questions) prior to asking your question. + +## Chat +[Hyperledger’s Discord server](https://discord.gg/hyperledger) is the place to go for real-time chat about everything from quick help to involved discussions. + +For general Hyperledger Cacti discussions, join the Discord server and visit #Cacti. + +## Mailing Lists +The Hyperledger Cacti mailing list is hosted by the Hyperledger Foundation: https://lists.hyperledger.org. + diff --git a/docs/docs/contributing/how-to-contribute.md b/docs/docs/contributing/how-to-contribute.md new file mode 100644 index 0000000000..24593aad55 --- /dev/null +++ b/docs/docs/contributing/how-to-contribute.md @@ -0,0 +1,71 @@ +# How to Contribute + +The Hyperledger Cacti repository contains [specific instructions](https://github.com/hyperledger/cacti/blob/main/CONTRIBUTING.md) for contributing to that project. + +In this section, you will find generic instructions and guidelines for contributing to any Hyperledger project. + +## Ways to Contribute + +Contributions from the development community help improve the capabilities of +Hyperledger Cacti. These contributions are the most effective way to +make a positive impact on the project. + +Ways you can contribute: + +* Bugs or issues: Report problems or defects found when working with the project (see [Reporting a Bug](./reporting-a-bug.md)) +* Core features and enhancements: Provide expanded capabilities or optimizations +* Documentation: Improve existing documentation or create new information +* Tests: Add functional, performance, or scalability tests + +Issues can be found in GitHub. Any unassigned items are probably still open. When in doubt, ask on Discord about a specific issue (see [Asking a Question](./asking-a-question.md)). We also use the #good-first-issue tag to represent issues that might be good for first timers. + +## The Commit Process + +Hyperledger Cacti is Apache 2.0 licensed and accepts contributions via GitHub pull requests. When contributing code, please follow these guidelines: + +* Fork the repository and make your changes in a feature branch +* Include unit and integration tests for any new features and updates to existing tests +* Ensure that the unit and integration tests run successfully prior to submitting the pull request. + +### Pull Request Guidelines + +A pull request can contain a single commit or multiple commits. The most +important guideline is that a single commit should map to a single fix or +enhancement. Here are some example scenarios: + +* If a pull request adds a feature but also fixes two bugs, the pull request should have three commits: one commit for the feature change and two commits for the bug fixes. +* If a PR is opened with five commits that contain changes to fix a single issue, the PR should be rebased to a single commit. +* If a PR is opened with several commits, where the first commit fixes one issue and the rest fix a separate issue, the PR should be rebased to two commits (one for each issue). + +!!! important + Your pull request should be rebased against the current master branch. Do not merge the current master branch in with your topic branch. Do not use the Update Branch button provided by GitHub on the pull request page. + +### Commit Messages + +Commit messages should follow common Git conventions, such as using the imperative mood, separate subject lines, and a line length of 72 characters. These rules are well documented in [Chris Beam's blog post](https://chris.beams.io/posts/git-commit/#seven-rules). + +### Signed-off-by + +Each commit must include a "Signed-off-by" line in the commit message (``git commit -s``). This sign-off indicates that you agree the commit satisfies the [Developer Certificate of Origin (DCO)](http://developercertificate.org/). + +### Commit Email Address + +Your commit email address must match your GitHub email address. For more information, see https://help.github.com/articles/setting-your-commit-email-address-in-git/ + +### Important GitHub Requirements + +A pull request cannot merged until it has passed these status checks: + +* The build must pass all checks +* The PR must be approved by at least two reviewers without any + outstanding requests for changes + +## Inclusive Language + +- Consider that users who will read the source code and documentation are from different background and cultures and that they have different preferences. +- Avoid potential offensive terms and, for instance, prefer "allow list and deny list" to "white list and black list". +- We believe that we all have a role to play to improve our world, and even if writing inclusive code and documentation might not look like a huge improvement, it's a first step in the right direction. +- We suggest to refer to [Microsoft bias free writing guidelines](https://learn.microsoft.com/en-us/style-guide/bias-free-communication) and [Google inclusive doc writing guide](https://developers.google.com/style/inclusive-documentation) as starting points. + +## Credits +This document is based on [Hyperledger Sawtooth's Contributing documentation](https://github.com/hyperledger/sawtooth-docs/blob/main/community/contributing.md). diff --git a/docs/docs/contributing/reporting-a-bug.md b/docs/docs/contributing/reporting-a-bug.md new file mode 100644 index 0000000000..9a1139bcbc --- /dev/null +++ b/docs/docs/contributing/reporting-a-bug.md @@ -0,0 +1,14 @@ +# Reporting a Bug + +To report a bug, submit an issue in our public [issue tracker]. + +When reporting an issue, please provide as much detail as possible about how to reproduce it. If possible, explain how to reproduce the issue. Details are very helpful. Please include the following information: + +* Operating system and version (if Mac, include the processor) +* Project version +* Environment details (virtual, physical, etc.) +* Steps to reproduce the issue +* Actual results +* Expected results + + [issue tracker]: https://github.com/hyperledger/cacti/issues diff --git a/docs/docs/contributing/requesting-a-change.md b/docs/docs/contributing/requesting-a-change.md new file mode 100644 index 0000000000..ece4ea2a19 --- /dev/null +++ b/docs/docs/contributing/requesting-a-change.md @@ -0,0 +1,157 @@ +# Requesting a Change + +Hyperledger Cacti is a powerful tool which serves a wide range of use cases. +Put yourself in our shoes – with a project of this size, it can be challenging +to maintain existing functionality while constantly adding new features at the +same time. We highly value every idea or contribution from our community, and +we kindly ask you to take the time to read the following guidelines before +submitting your change request in our public [issue tracker]. This will help us +better understand the proposed change, and how it will benefit the community. + +This guide is our best effort to explain the criteria and reasoning behind our +decisions when evaluating change requests and considering them for +implementation. + + [issue tracker]: https://github.com/hyperledger/cacti/issues + +## Before creating an issue + +Before you invest your time to fill out and submit a change request, we kindly +ask you to do some preliminary work by answering some questions to determine if +your idea is a good fit and matches the project's philosophy and tone. + +__Please find answers to the following questions before creating an issue.__ + +### It's not a bug, it's a feature + +Change requests are intended for suggesting minor adjustments, ideas for new +features, or to influence the project's direction and vision. It is important +to note that change requests are not intended for reporting bugs, as they're +missing essential information for debugging. + +If you want to report a bug, please refer to our [bug reporting guide] instead. + + [bug reporting guide]: reporting-a-bug.md + +### Source of inspiration + +If you have seen your idea implemented in similar project, make sure to collect enough information on its implementation before submitting, as this allows us to evaluate potential fit more quickly. Explain what you like and dislike about the implementation. + +### Benefit for the community + +Our [Discord server] is the best place to connect with our community. When +evaluating new ideas, it's essential to seek input from other users and consider +alternative viewpoints. This approach helps to implement new features in a way +that benefits a large number of users. + + [Discord server]: https://discord.gg/hyperledger + +## Issue template + +Now that you have taken the time to do the necessary preliminary work and ensure +that your idea meets our requirements, you are invited to create a change +request. The following guide will walk you through all necessary steps to help +you submit a comprehensive and useful issue: + +- [Title] +- [Context] optional +- [Description] +- [Related links] +- [Use cases] +- [Visuals] optional +- [Checklist] + + [Title]: #title + [Context]: #context + [Description]: #description + [Related links]: #related-links + [Use cases]: #use-cases + [Visuals]: #visuals + [Checklist]: #checklist + +### Title + +A good title is short and descriptive. It should be a one-sentence executive +summary of the idea, so the potential impact and benefit for the community can +be inferred from the title. + +### Context optional { #context } + +Before describing your idea, you can provide additional context for us to +understand what you are trying to achieve. Explain the circumstances +in which you're using Hyperledger Cacti, and what you _think_ might be +relevant. Don't write about the change request here. + +!!! success "Why we need this" + Some ideas might only benefit specific settings, environments or edge cases. With a little context, change requests can be prioritized more accurately. + +### Description + +Next, provide a detailed and clear description of your idea. Explain why your +idea is relevant to Hyperledger Cacti and must be implemented here, and not +in one of its dependencies. + +- __Explain the what, not the why__ – don't explain + [the benefits of your idea][Use cases] here, we're getting there. + Focus on describing the proposed change request as precisely as possible. + +- __Keep it short and concise__ – be brief and to the point when describing + your idea, there is no need to over-describe it. Maintainers and future + users will be grateful for having to read less. + +- __One idea at a time__ – if you have multiple ideas that don't belong +together, please open separate change requests for each of those ideas. + +- :material-run-fast: __Stretch goal__ – if you have a customization or another way to add the proposed change, you can help other users by sharing it here before we maintainers can add it to our code base. + +!!! success "Why we need this" + To understand and evaluate your proposed change, we need to have a clear understanding of your idea. By providing a detailed and precise description, you can help save you and us time spent discussing further clarification of your idea in the comments. + +### Related links + +Please provide any relevant links to issues, discussions, or documentation +sections related to your change request. If you (or someone else) already +discussed this idea with the community on our discussion board, please include +the link to the discussion as well. + +!!! success "Why we need this" + Related links help us gain a comprehensive understanding of your change request by providing additional context. Additionally, linking to previous issues and discussions allows us to quickly evaluate the feedback and input already provided by the community. + +### Use cases + +Explain how your change request would work from a user's +perspective – what's the expected impact and why does it not only benefit you, +but other users? How many of them? Furthermore, would it potentially break +existing functionality? + +!!! success "Why we need this" + Understanding the use cases and benefits of an idea is crucial in evaluating its potential impact and usefulness for the project and its users. This information helps us to understand the expected value of the idea and how it aligns with the goals of the project. + +### Visuals optional { #visuals } + +We now have a clear and detailed description of your idea, including information +on its potential use cases and relevant links for context. If you have any +visuals, such as sketches, screenshots, mockups, or external assets, you may +present them in this section. + +!!! tip + You can drag and drop the files here or include links to external assets. + +Additionally, if you have seen this change, feature, or improvement used +elsewhere, please provide an example by showcasing +it and describing how it was implemented and incorporated. + +!!! success "Why we need this" + Illustrations and visuals can help us maintainers better understand and envision your idea. Screenshots, sketches, or mockups can create an additional level of detail and clarity that text alone may not be able to convey. Also, seeing how your idea has been implemented in other projects can help us understand its potential impact and feasibility in Hyperledger Cacti, which helps us maintainers evaluate and triage change requests. + +### Checklist + +Thanks for following the change request guide and creating a high-quality +change request. This section ensures that you have read this guide and have +worked to your best knowledge to provide us with every piece of information to +review your idea for Hyperledger Cacti. + +__We'll take it from here.__ + +## Credits +This document is based on [Material for MkDocs Requesting a Change](https://github.com/squidfunk/mkdocs-material/blob/master/docs/contributing/requesting-a-change.md). diff --git a/docs/docs/faqs.md b/docs/docs/faqs.md new file mode 100644 index 0000000000..f2963a897f --- /dev/null +++ b/docs/docs/faqs.md @@ -0,0 +1,18 @@ +# Frequently Asked Questions + +## History + +### When and how was Cacti created? + +Cacti was created as the merer of two pre-existing Hyperledger projects in late 2022. See the [announcement blog post](https://www.hyperledger.org/blog/2022/11/07/introducing-hyperledger-cacti-a-multi-faceted-pluggable-interoperability-framework) for details. + +### Who is involved in maintaining Cacti? + +The project is maintained jointly by members of Accenture, Fujitsu, and IBM, with contributions from a diverse community of open-source developers and researchers. + +## Usage and Logistics + +### How do I contribute to the project? + +[Here](contributing/how-to-contribute.md) is how you can contribute to Cacti. For specific help or troubleshooting, visit the project's [Discord channels](./contact-us.md). + diff --git a/docs/docs/glossary.md b/docs/docs/glossary.md new file mode 100644 index 0000000000..011cd1daa9 --- /dev/null +++ b/docs/docs/glossary.md @@ -0,0 +1,31 @@ +**interoperability** + +: capabilities that enable a given blockchain or DLT network to share and exchange ledger state information and assets with each other, and thereby to seamlessly fulfil transactions that advance the states of multiple chains simultaneously. + +**asset exchange** + +: _to be filled in_ + +**asset transfer** + +: _to be filled in_ + +**data sharing** + +: _to be filled in_ + +**node server** + +: _to be filled in_ + +**relay** + +: _to be filled in_ + +**connector** + +: _to be filled in_ + +**driver** + +: (synonymous with "connector") diff --git a/docs/docs/guides/developers.md b/docs/docs/guides/developers.md new file mode 100644 index 0000000000..2d332cf37a --- /dev/null +++ b/docs/docs/guides/developers.md @@ -0,0 +1,3 @@ +# Developer's Guide + +We will provide more instructions and guidelines soon. For now, please refer to the [Cacti Contributions guide](../contributing/how-to-contribute.md) and the [project best practices](../references/best-practices.md). diff --git a/docs/docs/guides/operations.md b/docs/docs/guides/operations.md new file mode 100644 index 0000000000..f444606144 --- /dev/null +++ b/docs/docs/guides/operations.md @@ -0,0 +1,3 @@ +# Operator's Guide + +We will provide more instructions and guidelines soon. For now, please refer to the [Cacti Contributions guide](../contributing/how-to-contribute.md) and the [project best practices](../references/best-practices.md). diff --git a/docs/docs/guides/upgrading.md b/docs/docs/guides/upgrading.md new file mode 100644 index 0000000000..fc6e79042a --- /dev/null +++ b/docs/docs/guides/upgrading.md @@ -0,0 +1,3 @@ +# Upgrading + +We will provide more instructions and guidelines soon. For now, please refer to the [Cacti Contributions guide](../contributing/how-to-contribute.md) and the [project best practices](../references/best-practices.md). diff --git a/docs/docs/images b/docs/docs/images new file mode 120000 index 0000000000..847b03ed05 --- /dev/null +++ b/docs/docs/images @@ -0,0 +1 @@ +../../images/ \ No newline at end of file diff --git a/docs/docs/images-weaver b/docs/docs/images-weaver new file mode 120000 index 0000000000..d6b3bf143b --- /dev/null +++ b/docs/docs/images-weaver @@ -0,0 +1 @@ +../../weaver/resources/images/ \ No newline at end of file diff --git a/docs/docs/images-weaver-docs b/docs/docs/images-weaver-docs new file mode 120000 index 0000000000..ea8bec7b12 --- /dev/null +++ b/docs/docs/images-weaver-docs @@ -0,0 +1 @@ +../../weaver/docs/static \ No newline at end of file diff --git a/docs/docs/index.md b/docs/docs/index.md new file mode 100644 index 0000000000..d8d5f20abd --- /dev/null +++ b/docs/docs/index.md @@ -0,0 +1,35 @@ +# A Pluggable Interoperability Toolkit for Blockchain and DLT Networks + +![Cacti Logo Color](./images/HL_Cacti_Logo_Color.png#gh-light-mode-only){: style="height:70%;width:70%"} +![Cacti Logo Color](./images/HL_Cacti_Logo_Colorreverse.svg#gh-dark-mode-only){: style="height:70%;width:70%"} + +Cacti is a multi-faceted pluggable interoperability framework to link networks built on heterogeneous distributed ledger and blockchain technologies and to run transactions spanning multiple networks. It offers a collection of vendor-neutral and DLT-specific modules, libraries, and SDKs for popular DLTs, and templates to help you configure your networks and adapt your DApps to interoperate with other networks and their DApps for the purposes of carrying out atomic asset swaps, asset transfers, sharing ledger state, and other use cases. Cacti does not require deployment of, or dependence on, separate chains, and therefore is uniquely suited to help private (or permissioned) DLT networks be interoperable while keeping control of their governance and maintaining security and privacy. + +Cacti is the product of a [merger](https://www.hyperledger.org/blog/2022/11/07/introducing-hyperledger-cacti-a-multi-faceted-pluggable-interoperability-framework) between the pre-existing Cactus and Weaver Lab projects, bringing together two code bases with overlapping as well as complementary feature sets under a common umbrella repository. The core (and shared) design philosophy of Cacti is the enablement of interoperability in a manner that preserves the self-sovereignty of existing networks while providing consensus-driven control over cross-network interactions, does not require modifications to existing DLT stacks, and eschews reliance on third-party chains. Cacti covers the spectrum of generic interoperability modes required to fulfil cross-network transactions, namely asset exchanges, asset transfers, and ledger data sharing. + +Cacti is built on a modular architecture and supports extensions through the plugin model. It maintains certain core components that are independent of DLTs, and also packages (called _connectors_ or _drivers_) and libraries for specific DLTs. The following blockchains and DLTs are presently supported to varying extents within the repository: + +* Hyperledger Besu +* Hyperledger Fabric +* Hyperledger Indy +* Hyperledger Iroha +* Hyperledger Sawtooth +* R3 Corda +* Go-Ethereum +* Quorum +* Xdai + +Client libraries and examples are provided in the following languages: JavaScript/TypeScript, Golang, Java/Kotlin, Solidity. + +## Useful links + +* [Vision](./vision.md) +* [Architecture](./architecture.md) +* [Cactus whitepaper](https://github.com/hyperledger/cacti/blob/main/whitepaper/whitepaper.md) +* [Weaver RFCs](https://github.com/hyperledger/cacti/tree/main/weaver/rfcs) +* [Running pipelines with Cactus packages](./cactus/) +* [Running pipelines with Weaver packages](./weaver/) + +!!! note + + If you have questions not addressed by this documentation, or run into issues with any of the tutorials, please [reach out](./contact-us.md) to the Cacti maintainers (and community). diff --git a/docs/docs/references/best-practices.md b/docs/docs/references/best-practices.md new file mode 100644 index 0000000000..ec0dab879d --- /dev/null +++ b/docs/docs/references/best-practices.md @@ -0,0 +1,3 @@ +# Project Best Practices + +See the [Hyperledger Project Best Practices guidelines](https://github.com/hyperledger/toc/blob/gh-pages/guidelines/project-best-practices.md) for a comprehensive and up-to-date set of practices recommended for anyone wishing to build, maintain, or contribute to a team-based open-source project, especially one built on GitHub. diff --git a/docs/docs/references/business.md b/docs/docs/references/business.md new file mode 100644 index 0000000000..79d50a9515 --- /dev/null +++ b/docs/docs/references/business.md @@ -0,0 +1,3 @@ +# BUsiness Uses of Cacti + +Here is a list of practical real-world projects that Cacti (or portions of it) have been used in. diff --git a/docs/docs/references/events.md b/docs/docs/references/events.md new file mode 100644 index 0000000000..e0ddcfef59 --- /dev/null +++ b/docs/docs/references/events.md @@ -0,0 +1,3 @@ +# Events and Podcasts + +See list of presentations and panel discussions on the topic of interoperability generally as well as Cacti specifically. diff --git a/docs/docs/references/github.md b/docs/docs/references/github.md new file mode 100644 index 0000000000..9a5b9b76f2 --- /dev/null +++ b/docs/docs/references/github.md @@ -0,0 +1,3 @@ +# Hyperledger GitHub Contribution Guide + +See the [Hyperledger GitHub Contribution Guide](https://github.com/hyperledger/toc/blob/gh-pages/guidelines/github-contribution-guide.md) for instructions on how to use, sync, and contribute to any open-source Hyperledger project maintained on GitHub. diff --git a/docs/docs/references/publications.md b/docs/docs/references/publications.md new file mode 100644 index 0000000000..6034c64945 --- /dev/null +++ b/docs/docs/references/publications.md @@ -0,0 +1,3 @@ +# Published Articles and Research Papers + +See list below. diff --git a/docs/docs/references/specs.md b/docs/docs/references/specs.md new file mode 100644 index 0000000000..cbb84b7282 --- /dev/null +++ b/docs/docs/references/specs.md @@ -0,0 +1,10 @@ +# Technical Specifications + +The two legacy projects that Cacti is comprised of have independent sets of design and interface specifications, including examples of usage, as follows: + +- **Cactus**: See the official [Cactus whitepaper](https://github.com/hyperledger/cacti/tree/main/whitepaper/whitepaper.md) for technical designs and usage. +- **Weaver**: See the official [Weaver RFCs](https://github.com/hyperledger/cacti/tree/main/weaver/rfcs/) for technical designs and interface specifications. + +!!! note + + We will create a unified set of technical specifications for Cacti as the Cactus and Weaver modules get integrated in a deeper way following the [reference architecture](). Keep watching these pages for updates! diff --git a/docs/docs/use-cases.md b/docs/docs/use-cases.md new file mode 100644 index 0000000000..2c50ad393c --- /dev/null +++ b/docs/docs/use-cases.md @@ -0,0 +1,3 @@ +# Use Cases and Applications for Cacti + +This page is under construction. While we are working on it, you can find compelling examples and sample code [here](https://github.com/hyperledger/cacti/blob/main/whitepaper/whitepaper.md), [here](./weaver/user-stories/), [here](https://github.com/hyperledger/cacti/tree/main/examples), and [here](https://github.com/hyperledger/cacti/tree/main/weaver/samples). diff --git a/docs/docs/vision.md b/docs/docs/vision.md new file mode 100644 index 0000000000..7f2799f0fc --- /dev/null +++ b/docs/docs/vision.md @@ -0,0 +1,21 @@ +## Mission and Objectives + +Cacti aims to make the process of interoperation, interconnection, and integration of systems built on blockchain or DLT with each other (or with centralized systems) easy, controllable, trustworthy, and decentralized. It will allow networks to remain self-sovereign and evolve independently without losing the ability to link with other networks and manage digital assets across networks when required. In effect, it enables a _network-of-networks_, or a global scale decentrantralized system of networks (akin to the Internet) without forcing all networks to coalesce, or subscribe to, a single canonical chain. + +## Project Scope + +The existence of several blockchain and distributed ledger technologies of different flavors in the market as well as networks of varying scopes and sizes built on them necessitates the need for interoperability and integration, lest we end up with a fragmented ecosystem where digital assets and the workfows (often contracts) governing them remain isolated in silos. The solution to this is not to force all chains to coalesce (i.e., "*a single chain to rule them all*") but rather enable the networks to orchestrate transactions spanning their boundaries without sacrificing security, privacy, or governance autonomy (i.e., self-sovereignty). Hyperledger Cacti offers a family of protocols, modules, libraries, and SDKs, that can enable one network to be interoperable with, and carry out transactions directly with, another while eschewing the need for a central or common settlement chain. Cacti will allow networks to share ledger data, and exchange and transfer assets atomically, and manage identities, across their boundaries, as illustrated in the figure below. + + + +As a fusion of two earlier systems (Cactus and Weaver) that have similar philosophies and goals, yet offer distinct mechanisms backed by differemt design and trust assumptions, Cacti offers a spectrum of selectable and configurable features for cross-network transaction orchestrations. An example illustrated below shows how distributed applications running on Fabric and Besu ledgers respectively can carry out the same set of cross-network transactions using the **Node Server** (Cactus legacy) or through **Relays** (Weaver legacy). + + + +The present (initial) version of the Cacti code base is simply an aggregation of the legacy Cactus and Weaver code bases with their original folder structures. Until merge and integration (see further below), users should examine, test, and use them separately as follows: +- Cactus code and documentation lies within this (root) folder, excluding the `weaver` folder. See [Cactus documentation](./README-cactus.md) to test and use Cactus. +- Weaver code and documentation lies within the [weaver](./weaver/) folder. See [Weaver documentation](./weaver/README.md) to test and use Weaver. + +## Project Roadmap + +You can find the project roadmap in the [GitHub repository](https://github.com/hyperledger/cacti/blob/main/ROADMAP.md). diff --git a/docs/docs/weaver/architecture-and-design/decentralized-identity.md b/docs/docs/weaver/architecture-and-design/decentralized-identity.md new file mode 100644 index 0000000000..3fcc40badf --- /dev/null +++ b/docs/docs/weaver/architecture-and-design/decentralized-identity.md @@ -0,0 +1,162 @@ +--- +id: decentralized-identity +title: Decentralized Identity +--- + + + +Interoperation for asset or data transfers/exchanges relies on a message-passing infratructure and pan-network data processing modules, as we have seen in earlier pages. But there is yet another crucial basis these data processing modules need to satisfy our design principles of network independence and avoidance of trust parties. This is the ability of a network as a whole and of its individual members to accurately identify and authenticate another network's members. + +Further, for the networks to remain independent and interact ad hoc with each other, we cannot impose a central authority that unifies their private identity management systems. So the identity basis of interoperation must be decentralized, leading inevitably to the requirement of exchanging identity information across networks as a pre-requisite for asset and data transfers/exchanges. This is illustrated in the figure below where interoperation protocols are classified in two planes (or tiers), data and identity, with the former depending on the latter. + +![alt text](../../../images-weaver-docs/architecture-assets/identity-data-planes.jpg) + +- In the __data plane__ lies the protocols that effect the actual exchanges of data and assets. The figure above illustrates a typical data-sharing instance, where the network at the left requests a data record from the right. The latter receives the request via the two relays (not explicitly marked in this diagram) and runs an access control check through consensus in its _interop module_ before responding with the data record and supporting proof. The network at the left receives the data and proof, again via the two relays, and verifies the data using the supplied proof. __Note: since a core part of both request and proof are digital signatures of network members, the ability to identify and authenticate network members is necessary to perform these endpoint functions__. +- Here is where the __identity plane__ enters the picture, as a trust anchor for the data plane. The most general function of this plane is illustrated in the figure, where the networks get each others' identity and configuration (i.e., membership structure and network topology) information. This exchange has as its own trust basis (or dependency) a set of identity providers and verifiers. (_Note_: these identity providers and verifiers may belong to the two networks or they could be external entities.) The outcome of the exchange is a record of the other network's identity and configuration information on one's ledger, which can then be looked up in a data plane protocol instance. + +### Identity Plane: Strawman Approach + +The simplest identity plane protocol involves a direct exchange of identity information between representatives of the two networks: in other words, an API integration. But this approach suffers from the same drawbacks that API integration in the data plane would. It diminishes a blockchain network to a single trusted spokesperson, exposing that network to risk. Even if such a spokesperson could be designated, appropriately framing access control policies for potentially every other blockchain network in the world would be very challenging. This approach is therefore insecure and not scalable, and therefore ought to be treated purely as a strawman. + +### Networks as Groups of Self-Sovereign Members + +A secure and sustainable identity plane plaform can be built on the basis of _self-sovereign identity_ and _decentralized identifiers_. We recognize that: + +- Each constituent member of a blockchain network may already possess an identity from a third-party provider +- Membership within a network can be treated as a property of a sovereign organization rather than subordination to a network's governing authority +- DIDs allow members to control who they wish to share their identities with and the levels of exposure +- Network membership lists and individual members' identities can respectively be validated by different providers, thereby maintaining decentralization of infrastructure + +### Distributed Identity Management Infrastructure + +The distributed identity management infrastructure for interoperation is illustrated in the figure below. We assume the existence of one or more _Interoperation Identity Networks (IINs)_ that act as registries and credential validators for the organizations that form the memberships of blockchain networks. + +![alt text](../../../images-weaver-docs/architecture-assets/decentralized-id-mgmt-arch.jpg) + +An IIN can be built from scratch to facilitate blockchain interoperation, but it can also be an augmentation of an existing decentralized identity provider or registry. Its purpose is to maintain identity records and credentials for organizations and validate these to third parties as per the desire of the identity or credential owner. In this model, an IIN can itself be reputed or it can bring together many reputed and trusted identity providers (called _stewards_) into a shared network. As long as the members of two blockchain networks have shared trust in one or more IINs, an identity plane exchange can be effected, thereby setting the foundation for data and asset transfers. + +#### Interoperation Identity Network + +The ideal IIN architecture is illustrated in the figure below, inspired by Hyperleder Indy, whose architecture is used in our canonical (or reference) implementation. Built on a DLT itself, an Indy-based IIN can provide the combination of assurance and decentralization that a centralized registry cannot. Further, such an IIN will support the entire SSI and DID standard, maintaining credential schemas and verification keys, and issuing _verifiable credentials_ that can be used for privacy-preserving authentications. + +![alt text](../../../images-weaver-docs/architecture-assets/iin.jpg) + +An IIN is modeled as a network with a distributed shared ledger, implemented using an Indy Node Pool and running BFT consensus. The ledger is also (ideally) meant to be publicly accessible, though there is nothing preventing our protocols from working with a private IIN. + +A canonical IIN maintains the following: + +- DID records corresponding to organizations that are members of one or more blockchain networks, whose salient attributes include: + * Unique (within an IIN) identifier or _verinym_ for the identity owner + * Service endpoint for the identity owner + * Credential schemas + * Credential definitions (public keys used to authenticate signed credentials) + +Every IIN has a set of bootstrapped _trust anchors_ called _stewards_. A steward can create other trust anchors by issuing them suitable credentials. The trust anchors are the primary identity providers in our distributed identity management architecture. They can be existing reputed authorities or identity providers who are trusted to certify blockchain networks' memberships, or they can be created ad hoc by a consortium representing the members of a blockchain network. + +For one blockchain network to discover and validate another in the identity plane, it must trust one or more IINs and trust anchors who can provide that validation. We envision a shared and mutually reinforcing trust among stewards and other anchors within an IIN. An anchor could gain trust by virtue of joining a well-established IIN. Similarly, an IIN bootstrapped with well-known stewards gains trust because of the collective reputations of those stewards. + +Examples of entities that can act as stewards or trust anchors within IINs: the Sovrin Foundation (an organization dedicated to enabling open-source digital ID management, and which also maintains Indy), companies like Maersk or Walmart that have founded real-world blockchain networks, companies like IBM or R3 that maintain popular DLT platforms. + +IINs don't have to be built on Indy. Alternatives like Sidetree exist, providing similar functionality. There are also various existing DID registries that are already issuing credentials to existing organizations. To the extent possible, we would like to leverage all of this existing infrastructure and not force any network menmber to find yet another identity provider. Therefore, these existing registries or networks can be used as IINs: the only requirement is that they follow the standards for SSI and DIDs and issuing VCs. + +#### Network Membership Credentials + +Two kinds of credentials (each with a schema and a definition) are maintained on an IIN ledger: + +1. __Member list__: This contains a network name or ID and a set of DIDs of that network's members. + * This is a per-network credential whose schema and verification key must be maintained on an IIN. + * This is issued by a steward or trust anchor in an IIN and is associated with that steward's or anchor's DID. +2. __Membership__: This contains an oranization's attributes, including the set of IDs of networks to which it belongs. + * This is designed to be an extensible credential, i.e., support more attributes in the future. + * An existing membership credential (of the VC form) can be used as long as it matches the schema recorded on an IIN. + * The issuer must be a steward or trust anchor (or equivalent, if it's a non-Indy registry) in an IIN. + * This is associated with the member's DID. + +#### Identity Info: Units of Exchange + +The IIN is used to discover the membership list of a foreign network and establish the authenticity of its members. Memnbership credentials are independent of blockchain networks. + +But data plane transfers and exchanges require knowledge of in-network identities and certificates, which are issued by a network's membership manager(s) to peers and clients. These are not shared through IINs for several reasons. First, the volume of this information can be quite high and further it is subject to change based on a network's internal needs. Also, a network or its members may not wish to expose all this information to an IIN, which is designed to be publicly accessible. Therefore, it is infeasible or undesirable to shared network-specific credentials via established IINs. Instead, we will enable the _peer-to-peer_ exchange of such credentials after the membership discovery and validation procedure is complete. + +Specifically, the identity information for a network member consists of the set of certificate chains of the membership managers for that particular member (organization). These consist of one or more hierarchies of root and intermediate CA certificates. For example: + +- In Fabric, each organization uses one or more MSPs (_membership service providers_), each running one or more root and intermediate Fabric-CA servers. Any network peer belonging to an organization is issued a certificate authorized by one of these certificate chains. To authenticate a network peer or client in a data plane protocol, knowledge of these certificate chains is essential. +- In Corda, the entire network typically consists of a hierarchy of CAs, from a root to multiple _doormen_, and from each doorman to multiple nodes. Finally, the certificates used to sign transactions are issued by the node CAs. Therefore, knowledge of the root, doormen, and node CA certificates is essential for authenticating signers. + +More generally, each unit of exchange corresponding to a network member is a _Security Group_, so-called because each network member is an independent organization in its own right with a security domain. + +#### IIN Agents as Member Representatives + +Every network member needs a proxy (either an abstraction or a separate module) for communication with IINs and with the members of foreign networks in the identity plane. We use the term "IIN Agent" to refer to this proxy, and illustrate its functioning as a module within a Fabric network through the reference diagram below. + +![alt text](../../../images-weaver-docs/architecture-assets/iin-augmented-network.jpg) + +In the reference implementation, IIN Agents are built as Hyperledger Aries nodes and communicate with each other and with IIN stewards and trust anchors using the Aries protocol. (IIN stewards and trust anchors are also built as Aries nodes.) + +The list of trusted IINs is recorded on the local network's shared ledger, as illustrated in the figure (and thereby agreed through network consensus). To be able to interoperate with another network, the latter's members must have identity records maintained by sume subset of these trusted IINs and their VCs must be issued by these IINs stewards and trust anchors. + +#### Protocols + +Let us consider a scenario where _NETWORK 1_ and _NETWORK 2_ wish to interoperate, and their respective member organizations are as follows: + +- _NETWORK 1_: Org3, Org4, Org5 +- _NETWORK 2_: Org1, Org2 + +Each network discovers the other's member list and obtains and records ech member's security group to the local shared ledger. We can enumerate these as follows: + +- _NETWORK 1_ discovers and registers _NETWORK 2_:Org1 +- _NETWORK 1_ discovers and registers _NETWORK 2_:Org2 +- _NETWORK 2_ discovers and registers _NETWORK 1_:Org3 +- _NETWORK 2_ discovers and registers _NETWORK 1_:Org4 +- _NETWORK 2_ discovers and registers _NETWORK 1_:Org5 + +Each of these can be done in parallel and each discovery and registration operation is idempotent as long as the security group of a network member does not change. + +The high-level workflow for discovery and registration is illustrated below (using _NETWORK 2_ as the seeker and _NETWORK 1_ as the provider). + +![alt text](../../../images-weaver-docs/architecture-assets/protocol-identity-overview.jpg) + +(_Note_: "Network unit" is synonymous with "network member") + +Prerequisites for this process are: + +- The member list credential of _NETWORK 1_ is provided by a steward or trust anchor in a particular IIN which is also on the trust list recorded in the ledger of _NETWORK 2_. +- The membership credentials for both organizations in _NETWORK 1_ are supplied by one or more IINs that are on the trust list of _NETWORK 2_. +- Each of the 5 organizations (2 in _NETWORK 1_ and 3 in _NETWORK 2_) has an IIN Agent running on their behalf. + +Let us take the example of _NETWORK 2_ having already obtained the security group info for Org4 and Org5 in _NETWORK 1_. It is now discovering and registering _NETWORK 1_:Org3. We assume that there is a single IIN with a single Steward for validating member list as well as membership credentials for all members of both the networks. + +_Note_: we assume here for simplicity that a steward as a reputed identity provider has a mechanism to validate the bona fides of an orgganization and its membership in a given network. There are other techniques involving group signatures that could be applied to corroborate an organization's claim to network membership rather than requiring a steward to use an out-of-band security mechanism, but that is presently beyond the scope of this design. + +The discovery and registration procedure steps are as follows: + +- The IIN Agent for Org3 registers its membership to _NETWORK 1_ at the Steward in IIN: + * _NETWORK 1_:Org3 gets a DID (verinym) issued + * The Steward updates the member list credential for _NETWORK 1_ to include Org3 + * Org3 obtains a membership credential from Steward +- The IIN Agent for Org3 issues itself a self-signed VC containing its security group info +- The IIN Agent for _NETWORK 2_:Org2 (only one organization in the network needs to do this) obtains the new member list credential from Steward in IIN and validates it using the IIN ledger records +- The IIN Agent for _NETWORK 2_:Org2 discovers that Org3 is a member of _NETWORK 1_, fetches Org3's membership credential from Org3's IIN Agent, and validates it using the IIN ledger records +- The IIN agent for _NETWORK 2_:Org2 fetches the self-signed security group credential from the IIN agent of _NETWORK 1_:Org3 and validates it +- The IIN agent for _NETWORK 2_:Org2 triggers a flow among the IIN Agents of _NETWORK 2_ to collect signatures endorsing the security group info for _NETWORK 1_:Org3 fetched above + * The IIN Agent for _NETWORK 2_:Org1 gets this endorsement request, and validates both the membership credential and the security group info for _NETWORK 1_:Org3 by communicating with the Steward, the IIN ledger, and the IIN Agent for _NETWORK 1_:Org3 + * The IIN Agent for _NETWORK 2_:Org1 signs the request from Org2 containing the security group info for _NETWORK 1_:Org3 after the above check succeeds +- When the IIN agent for _NETWORK 2_:Org2 gets signatures from the IIN Agents representing each member of _NETWORK 2_, it submits the security group info for _NETWORK 1_:Org3 alon with the signatures to the _interop module_ (typically smart contract) for recording on the ledger of _NETWORK 2_ + * Now the ledger of _NETWORK 2_ contains the identities and certificates of all three members of _NETWORK 1_: Org3,Org4,Org5, and data plane interoperation may ensue. + +_Note_: the last step above (recording to the local ledger via the _interop module_) may be performed by IIN Agents of both Org1 and Org2 as they have no means of synchronizing their actions, but this recording will be idempotent and hence not cause any harm. + +The process above is illustrated with a few more details in the sequence of protocol diagrams below. + +![alt text](../../../images-weaver-docs/architecture-assets/protocol-registration-phase.jpg) + +![alt text](../../../images-weaver-docs/architecture-assets/protocol-get-info-phase.jpg) + +![alt text](../../../images-weaver-docs/architecture-assets/protocol-update-info-phase.jpg) + +### References +Bishakh Chandra Ghosh, Venkatraman Ramakrishna, Chander Govindarajan, Dushyant Behl, Dileban Karunamoorthy, Ermyas Abebe, Sandip Chakraborty, [Decentralized Cross-Network Identity Management for Blockchain Interoperation](https://arxiv.org/abs/2104.03277), _ICBC 2021_ diff --git a/docs/docs/weaver/architecture-and-design/drivers.md b/docs/docs/weaver/architecture-and-design/drivers.md new file mode 100644 index 0000000000..e98bf16a69 --- /dev/null +++ b/docs/docs/weaver/architecture-and-design/drivers.md @@ -0,0 +1,17 @@ +--- +id: drivers +title: Drivers +--- + + + +The driver is responsible for all communication between the relay and its network. In the previous sections we have thought about the driver as a component of the relay. We have done this because conceptually it makes sense to think about it like that. However, in our reference implementation we have made it a seperate process which communicates with the relay via gRPC, as shown below. There are two main reasons for this: + +1. There must exist a different driver for each network type (e.g. Fabric, Corda etc.) and therefore having the driver as a seperate process makes it easy to "plug" different drivers into the relay. +2. A possible use case of the relay is that a single relay instance may have multiple drivers (e.g. if multiple entities in the network want to run their own driver). In this case, this plugin style approach of drivers makes it possible to do without having to modify code for each configuration. + +![](../../../images-weaver-docs/architecture-assets/driver_architecture.png) diff --git a/docs/docs/weaver/architecture-and-design/overview.md b/docs/docs/weaver/architecture-and-design/overview.md new file mode 100644 index 0000000000..12c6400b73 --- /dev/null +++ b/docs/docs/weaver/architecture-and-design/overview.md @@ -0,0 +1,34 @@ +--- +id: overview +title: Overview +--- + + + +The below diagram shows a high level architecture diagram of the Weaver framework. + +![](../../../images-weaver-docs/architecture-assets/architecture_overview.png) + +## Network + +The networks in the system can be made up of various heterogenious technologies, including Hyperledger Fabric and Corda. Each network in the system needs to contain an interoperability (IOP) module that enables them to communicate with the relays. + +## Relay + +The relays act as a conduit to facilitate communication of protocols between networks (e.g. data transfer, asset exchange etc). The roles of the relays are described in more detail in [relay](./relay.md). + +# Design Decisions + +The high level design decisions that were made for the system are outlined here. + +## Synchronous vs Asynchronous message communication + +We decided to go with an asynchronous message architecture. The primary reason for this is because requests can take an arbitary amount of time to respond, it is not practical for a synchronous message to wait that long for a reply. For example, obtaining a 12 block confirmation on the Bitcoin network can take about 2 hours. + +## Message vs connection oriented communication + +We decided to go with a message oriented architecture. The primary reason for this is because it makes the system more fault tolerant. With a message oriented architecture the requester and responder don't need to be alive at the same time. For example, if the requestor crashes while the responder is processing the request, the communication is not interrupted since the responder will just send a message when it has finished processing the request. The design choice also enables the systen to be made more fault tolerant in the future by implementing message queues between components in the system. diff --git a/docs/docs/weaver/architecture-and-design/relay.md b/docs/docs/weaver/architecture-and-design/relay.md new file mode 100644 index 0000000000..b74fd13937 --- /dev/null +++ b/docs/docs/weaver/architecture-and-design/relay.md @@ -0,0 +1,29 @@ +--- +id: relay +title: Relay +--- + + + +![](../../../images-weaver-docs/architecture-assets/relay_architecture.png) + +As mentioned in the overview, relays facilitate communication of protocols between networks. To do this, they are composed of three main pieces: + +- `Relay service` - A gRPC server that listens for and handles incoming requests from other relays. For example, a remote network requesting state. +- `App service` - A gRPC server that listens for and handles requests from applications that are requesting an asset from a remote network. +- `Driver` - The driver is responsible for all communication between the relay and its network. The driver is described in more detail in [drivers](./drivers.md). + +The diagram below shows an example communication between two networks, A and B, where network A is requesting state from network B. + +![](../../../images-weaver-docs/architecture-assets/relay_flow.png) + +1. An application sends a request to their networks relay over gRPC +2. The local relay inspects the query within the request and uses the relevant information to forward the request to the correct remote relay +3. The remote relay's driver interprets the query and invokes the smart contract for the query +4. Once network B has returned a response to its relay, the relay forwards the response back to relay A +5. The application gets the response from the relay, this can either be via a push or pull mechanism +6. The application invokes a domain specific smart contract to process the response from network B diff --git a/docs/docs/weaver/architecture-and-design/weaver-dapps.md b/docs/docs/weaver/architecture-and-design/weaver-dapps.md new file mode 100644 index 0000000000..b4cc327242 --- /dev/null +++ b/docs/docs/weaver/architecture-and-design/weaver-dapps.md @@ -0,0 +1,32 @@ +--- +id: weaver-dapps +title: Weaver Dapps +--- + + + +As mentioned in the [overview](./overview.md), DLTs that integrate with Weaver must contain an interop (IOP) module to facilitate interoperation between ledgers. The interop module contains all the logic responsible for membership, verification policies and access control policies (refer to the RFCs for more information on these). Below shows the architecture of how these interop modules work with the two currently supported DLTs, Fabric and Corda. + +## Fabric + +When Fabric is the requesting network, the IOP module is used to verify the proof and then forward the state onto the application chaincode. + +![](../../../images-weaver-docs/architecture-assets/fabric_dapp_flow1.png) + +When Fabric is the responding network, the IOP module is in charge of verifying the identity of the requester, making sure the requester has access to the state they are requesting, and then finally retrieving the state from the application chaincode to send back to the requesting network. + +![](../../../images-weaver-docs/architecture-assets/fabric_dapp_flow2.png) + +Verification Policy, Access Control and Membership are modular components within the interop chaincode for seperation of concerns of the code. + +## Corda + +As can be seen from the diagrams below, the architecture for Corda is very similar to that of Fabric. The main difference is that the interop module and the application specific flows are in seperate CorDapps, instead of seperate chaincodes like in Fabric. + +![](../../../images-weaver-docs/architecture-assets/corda_dapp_flow1.png) + +![](../../../images-weaver-docs/architecture-assets/corda_dapp_flow2.png) diff --git a/docs/docs/weaver/deployment-considerations/deployment-patterns.md b/docs/docs/weaver/deployment-considerations/deployment-patterns.md new file mode 100644 index 0000000000..bfcd1610b2 --- /dev/null +++ b/docs/docs/weaver/deployment-considerations/deployment-patterns.md @@ -0,0 +1,10 @@ +--- +id: "deployment-patterns" +title: Deployment Patterns +--- + + diff --git a/docs/docs/weaver/deployment-considerations/governance-and-policies.md b/docs/docs/weaver/deployment-considerations/governance-and-policies.md new file mode 100644 index 0000000000..bc1314e27c --- /dev/null +++ b/docs/docs/weaver/deployment-considerations/governance-and-policies.md @@ -0,0 +1,10 @@ +--- +id: "governance-and-policies" +title: Governance and Policies +--- + + diff --git a/docs/docs/weaver/deployment-considerations/legal-and-regulation.md b/docs/docs/weaver/deployment-considerations/legal-and-regulation.md new file mode 100644 index 0000000000..f2ffed8875 --- /dev/null +++ b/docs/docs/weaver/deployment-considerations/legal-and-regulation.md @@ -0,0 +1,10 @@ +--- +id: legal-and-regulation +title: Legal and Regulation +--- + + diff --git a/docs/docs/weaver/design-principles.md b/docs/docs/weaver/design-principles.md new file mode 100644 index 0000000000..21b57378a5 --- /dev/null +++ b/docs/docs/weaver/design-principles.md @@ -0,0 +1,101 @@ +--- +id: design-principles +title: Design Principles +--- + + + +We list principles and considerations that guide the design of a framework for interoperability between decentralized networks, along with associated reasoning. Our present solution, though a work-in-progress, attempts to adhere to these principles. + + +### How to determine need for interoperation, and its mode and mechanics? +- Assess dependence decision (i,e., between networks) to determine goals and required assurances: + * The decision to depend on a network is a complex one, as a network is itself an affiliation of independent parties. + * There are different approaches with varying levels of complexity and assurance. + * Examine structural assurances provided by networks and their participants, and do a cost-benefit analysis to determine a suitable approach. +- The mechanics of interoperation can be derived from assumptions made in the above assessment. +- __Our assumptions and aproach__: + * Individual network participants are untrustworthy. + * The network is trustworthy in the collective. + * The internal consensus mechanism of a network protects it from Byzantine failures. + * Interoperability needs will not force structural changes or forks in a network nor constrain that network's internal evolution. + + +### Principles and Ideals for Interoperability Solution Design +Here are our guiding principles that accord with our assumptions and approach, in no particular order. + +#### Favor Technical Assurances over Social Assurances +- Technical assurances are provided by protocols and security mechanisms, including distributed consensus. +- Social assurances include governance (collectively, through a consortium, or via a hierarchy), legal rules and regulations, reputations and history of past behavior. +- The reason to favor the former is that it can provide provable guarantees that are independent of the trustworthiness of individual participants, whereas the latter can be brittle and rely on participants' compliance. + +#### Be Inclusive and Accommodate Heterogeneity +- Avoid approaches for protocol design that are specific to a particular DLT implementation or network structure. +- Specify the communication protocol in a network-neutral language. +- Design protocol units that can abstract out common features for information and assurances from diverse DLTs. + +#### Allow Networks to Retain Independence and Collective Sovereignty +- A network is treated as an independent self-governing system with the freedom of choice to interoperate with another on a need basis. +- Network members retain collective sovereignty over their internal processes as well as access control rules governing remote interoperation. +- Networks have full and collective control, via their native consensus and smart contract mechanisms, over exposure of data, assets, and transactions to other networks. + * A network acts as a unit for framing and enforcing rules controlling access to information held on its ledger(s) by a remote network. +- Similarly, networks have full and collective control, via their native consensus and smart contract mechanisms, over acceptance of data or assets and verifications of transactions occurring in, other networks. + +#### Minimize Network Coupling +- Networks/consortia must retain independence for governance and configuration + * Therefore, interoperation must require loose coupling rather than a merging or overlapping of two networks +- Loose coupling between dependent networks allows changes to counterparty networks' implementations with minimal or no impact to cross-network dependencies. +- Domain decoupling: + * Define standards for contract interfaces + * Define standards for representing data types and assets types (e.g. https://www.gs1.org/traceability) + * Define standards for identity portability +- Communication decoupling: + * Define standards for network interface/API + * Define standards for protocol behavior + * Define standards for messaging formats + +#### Do not Compromise on Privacy and Confidentiality +- By design, a permissioned network should retain its privacy, and interoperation mechanisms should not leak information outside the bounds of what access control rules allow. +- Cross-network communications should be kept private and confidential and revealed only to interested parties, applying the principle of least privilege. + +#### Minimize Trust Footprint and Avoid Centralization +- Design for decentralization across networks as within networks: + * Avoid introducing centralized services that are easy to compromise + * Assume that failure scenarios that apply to networks also hold for any service coordinating interoperability. +- Reduce trust to only what is essential (i.e. identity providers in the network). +- No trusted third-party intermediary or infrastructure (e.g., Polka Dot, Cosmos) should be relied upon for the purpose of cross network data verification or settlement. +- Reduce trust and centralization to only essential functions that cannot be completely decentralized: + * Communicate messages across networks using some networking infrastructure: + - This communication infrastructure is not trusted to maintain confidentiality or integrity of messages, and it may mount denial of service attacks. + * Identity provision and verification: + - This is necessary for permissioned networks that have private memberships governed by a _committee_ that may be centralized or distributed. + +#### Favor dependence on proofs over trust +- _This is also implied by the "No Trusted Intermediaries" principle_. +- Information transferred across networks must carry verifiable proofs. +- The receiving network must be able to specify a _verification policy_ for proofs that it can independently and collectively (i.e., through consensus) verify. + +#### Minimize Impact and Adaptation +- Enabling interoperation must not require changes to existing network protocols. +- Enabling interoperation must not impact existing network operation in any way nor require any blockchain forks. +- Adaptation in existing smart contracts and applications must be avoided unless absolutely necessary, and follow modular principles. + +#### Maximize Operational Efficiency +- Minimize payloads in cross-network protocol units. +- Strive for event-driven asynchronous messaging architectures (_this is also implied by the "Minimal Coupling" principle_). + + +### Design Guidelines for Network Architects and Developers +- Architects and application developers (both in the smart contract and services layers) must design with interoperability in mind: + * This has the advantage of minimizing or eliminating any code adaptations required for interoperability during a network's life cycle. +- Apply standards when defining assets, data and logic within network apps to maximize external consumption: + * Networks with well-defined standards-based interfaces simplifies interoperability: + - Interfaces include: contracts, data/assets, identity, APIs, protocol, messaging. +- Enables network implementation to evolve while eliminating or minimising external impact: + * Implement in a modular way: many patterns and principles exist in the field of web services. + * Decouple interoperability-related application modules as much as possible (_this guideline applies to blockchain-related modules within enterprise apps too_). + - This will make maintenance easier and also allow administrators to minimize the amount of code that needs to be deployed in higher-security enterprise zones. diff --git a/docs/docs/weaver/getting-started/enabling-weaver-network/besu.md b/docs/docs/weaver/getting-started/enabling-weaver-network/besu.md new file mode 100644 index 0000000000..81c3c4e16c --- /dev/null +++ b/docs/docs/weaver/getting-started/enabling-weaver-network/besu.md @@ -0,0 +1,11 @@ +--- +id: besu +title: Hyperledger Besu +--- + + + diff --git a/docs/docs/weaver/getting-started/enabling-weaver-network/corda.md b/docs/docs/weaver/getting-started/enabling-weaver-network/corda.md new file mode 100644 index 0000000000..41caa7afb5 --- /dev/null +++ b/docs/docs/weaver/getting-started/enabling-weaver-network/corda.md @@ -0,0 +1,637 @@ +--- +id: corda +title: Corda +--- + + + +After testing the Weaver interoperation mechanisms on [basic sample networks](../test-network/overview.md), you may be interested in finding out how you can equip an existing real network, whether in development or in production, to exercise these mechanisms. In this document, we will demonstrate how to equip a Corda network and application with Weaver components and capabilities. + +## Model + +The figure below illustrates a typical Corda network. The infrastructure consists of a set of nodes (each maintaining its share of the global state in a local vault), notaries, and CAs. On the nodes are installed one or more CorDapps, representing shared business logic across subsets of those nodes. The core of a CorDapp consists of a collection of workflows (or flows) and contracts acting on states; we layer the flows above the contracts in thebelow image just to illustrate that flows represent transaction (state update) triggers, and contract validations occur during the executions of flows. Further up in the stack lie client applications associated with CorDapps that can are used to trigger flows (and by implication, contracts). + +![alt text](../../../../images-weaver-docs/enabling-weaver/corda-network-model.png) + +Such a network equipped with Weaver components and capabilities will look like the figure below. Legacy components are marked in grey and Weaver and bridging components in green. + +![alt text](../../../../images-weaver-docs/enabling-weaver/corda-weaver-model.png) + +The relay and driver are the only additional infrastructure that need to be installed. One or more relays can be installed, as can one or more drivers. The drivers are illustrated in the client layer rather than in the bottom layer because, though they are coupled with relays, they trigger flows just like any client application does. + +Existing CorDapp flows and contracts deployed on the network's nodes remain undisturbed. All that is required is the deployment of an Interoperation CorDapp (flows and contracts) on every node that needs to offer or consume state from foreign networks. + +Client applications will need some additional code and configuration because the decisions to exercise interoperation mechanisms (relay queries for data sharing or atomic asset exchanges) are strictly part of business logic. But Weaver's Corda Interoperation Java-Kotlin SDK offers various helper functions to ease this process and keep the adaptation to a minimum, as we wil see later in this document. Finally, an _identity service_ must be offered by the network to expose its CAs' certificate chains to foreign networks, thereby laying the basis for interoperation. This service simply needs to offer a REST endpoint, and can be implemented as a standalone application or (more conveniently) as an augmentation of one or more of the existing client layer applications. + +## Procedural Overview + +A Corda network is typically created in phases, in the following sequence: + +1. **Development**: This involves writing CorDapp which consists of contracts and workflows, and client layer applications. The cordapp's deployment name/ID and its transaction API must be designed first, but subsequent development of the two layers of applications can then proceed parallelly. +2. **Pre-Configuration**: This involves creating a desired specification (as a set of configuration diles) of the network topology and the ledgers it maintains. +3. **Startup and Bootstrap**: This is the launch phase, in which the network components and applications are started and bootstrapped (i.e., configured with initial state and operating rules). + +Assuming that the reader is familiar with this procedure, we will walk through the changes required in each phase to make your network ready for interoperation using Weaver components and code templates. This will involve code addition and adaptation, deployment of additional modules, additional configuration, and creation of additional ledger state records. The requirements and effort will vary with the mode of interoperation you wish to support in your Fabric network. + +## Development Phase + +A Corda distributed application's business logic code spans three layers as illustrated in the network model: + +### CorDapp + +CorDapps (Corda Distributed Applications) are distributed applications that run on the Corda platform. The goal of a CorDapp is to allow nodes to reach agreement on updates to the ledger. They achieve this goal by defining flows that Corda node owners can invoke over RPC. + +#### For Data Sharing + +No code changes are required for Weaver enablement, because data sharing involves: + +- View packaging (and optionally, encryption) logic and access control logic in a source network, and +- View validation logic in a destination network + +This logic is standard and independent of contract, workflow, and state, particulars. It is already implemented in the Interoperation CorDapp offered by Weaver. Hence you just need to deploy that CorDapp to exercise data sharing from, or to, your application CorDapp. Your application CorDapp can be oblivious of the Interoperation CorDapp's workings and of the view request-response protocol. + +#### For Asset Exchange + +To exchange an asset using Weaver, the asset's state on the ledger must be controlled in the following ways: + +- Locked in favor of a party +- Claimed by the party to whom the asset is pledged +- Returned to the original owner if it is not claimed within a given timeframe + +In addition, the state of the asset (i.e., whether it is locked), and its current and targeted owners, must be determinable by looking at the ledger records. + +The bookkeeping logic required to maintain records of locks can be abstracted away from the particulars of a digital asset and its workflow. But as such assets and their properties (including ownership) can be, and are, encoded in an arbitrary number of ways, we cannot provide a one-size-fits all set of functions (like in the data sharing protocol) to exchange any kind of asset. Instead, we must rely on the application CorDapp managing an asset, as it knows precisely what the asset's properties are and how they can be updated and queried on the ledger. + +What Weaver offers, therefore, is the following: + +- Lock management logic implemented in the Interoperation CorDapp that treats each asset as an abstract object (an instance of generic corda's `ContractState`) and is agnostic of the assets' internals. It consumes (burns) the asset state and creates a new `HTLC` state that indicates that the asset is locked, while in claim and unlock new asset state is created (minted) with appropriate owner while consuming `HTLC` state. This logic can be exercised in by installing Interoperation CorDapp on the nodes. +- A set of template functions with sample (and extensible) code that must be added to the application CorDapp to augment the above lock management functions. + +Below, we list the template functions with sample code that you, as a developer, must use and adapt within your CorDapp. + +- **Flow to get Asset State**: For non-fungible assets, create a flow like: + ```kotlin + class RetrieveStateAndRef( + val type: String, + val id: String + ): FlowLogic> + ``` + And for fungible assets, create a flow like: + ```kotlin + class RetrieveStateAndRef( + val type: String, + val quantity: Long + ): FlowLogic> + ``` + The name of these flows can be anything, but the parameters should be same, and return type should `StateAndRef`. These flows are supposed to get the `StateAndRef` object to the asset state that has to be locked, which can be identified by `type` and `id` for non-fungible assets, and `type` and `quantity` for fungible assets. + +- **Flow to update owner in asset state**: Create a flow like: + ```kotlin + class UpdateOwnerFromPointer( + val statePointer: StaticPointer + ) : FlowLogic() + ``` + Again the name can be anything but the function parameter should be same, i.e. take a `StaticPointer` and return the `ContractState` of the asset involved in asset exchange. This flow is supposed to resolve the `StaticPointer` to actual asset, and update the owner of this asset to the caller of this flow. + +#### For Asset Transfer + +_TBD_ + +### Contracts CorDapp + +No code changes are required for Weaver enablement. For asset exchange, Weaver assumes that application CorDapp that manages assets must already have a asset creation (mint) contract command and asset deletion (burn) contract command, which can be invoked when `Issuer` party is involved in the transaction. + +## Client Layer applications + +Weaver provides an SDK to help you adapt your applications to exercise the various interoperability modes. These are called out as **SDK Helpers** in the network model illustrated earlier. Your Corda network's Client layer applications have business logic embedded in them that, broadly speaking, accept data from users and other external agents and invoke workflows from CorDapp over RPC. When you use Weaver for network interoperability, other options can be added, namely requesting and accepting data from foreign networks, and triggering locks and claims for atomic exchanges spanning two networks. Weaver's Corda Interoperation SDK offers a library to exercise these options. But this will involve modification to the application's business logic. +To use Weaver's Corda SDK, you need to create a [personal access token](https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token) with `read:packages` access in GitHub, to access Weaver packages. +You also need to add the following to your application's `build.gradle` file: +```groovy +repositories { + maven { + url https://maven.pkg.github.com/hyperledger/cacti + credentials { + username + password + } + } +} +dependencies { + implementation(group: 'org.hyperledger.cacti.weaver.sdk.corda', name: 'weaver-sdk-corda', version: "2.0.0-alpha.1") + implementation(group: 'org.hyperledger.cacti.weaver.imodule.corda', name: 'interop-contracts', version: "2.0.0-alpha.1") + implementation(group: 'org.hyperledger.cacti.weaver.imodule.corda', name: 'interop-workflows', version: "2.0.0-alpha.1") + implementation(group: 'org.hyperledger.cacti.weaver.protos', name: 'protos-java-kt', version: "2.0.0-alpha.1") +} +``` +(Or check out the [package website](https://github.com/hyperledger/cacti/packages/1856827) and select a different version.) + +#### For Identity Administration + +A Corda network needs to share its security domain (or membership) configuration, i.e., its nodes' CA certificate chains, with a foreign network with which it seeks to interoperate. Though such sharing can be implemented using several different mechanisms, ranging from manual to automated, the simplest and most modular way is to expose a REST endpoint that agents in foreign networks can reach. Further, this REST endpoint can be implemented as a standalone web application or it can be an extension of one or more of the existing client layer applications. (Multiple apps can expose the same endpoint serving the same information for redundancy.) We will demonstrate an example of this while leaving other implementation modes to the user. +Let's say a Corda network consists of two nodes called `PartyA` and `PartyB`, each running a client layer application with a web server whose URL prefixes are `http://partya.mynetwork.com:9000` and `http://partyb.mynetwork.com:9000` respectively. Each app then can expose a REST endpoint (again, as an example) `http://partya.mynetwork.com:9000/node_sec_grp` and `http://partyb.mynetwork.com:9000/node_sec_grp` respectively. +At each web server's backend, you need to implement logic to retrieve the node's ID and it's associated certificated chains. Sample code is given below for a Kotlin implementation built on `weaver-sdk-corda`. You can use this code verbatim, except for some minor changes like ``, other parameters like security domain, and list of names of nodes as appropriate for your environment: + +```kotlin +import org.hyperledger.cacti.weaver.sdk.corda.CredentialsCreator +import com.google.protobuf.util.JsonFormat + + +@RestController +@CrossOrigin +@RequestMapping("/") // The paths for HTTP requests are relative to this base path. +class Controller { + // Expose "node_sec_grp" endpoint using Rest Controller + @RequestMapping(value = ["/node_sec_grp"], method = arrayOf(RequestMethod.GET), produces = arrayOf("application/json")) + private fun GetNetworkConfig(): String { + val jsonPrinter = JsonFormat.printer().includingDefaultValueFields() + + val credentialsCreator = CredentialsCreator( + "/build/nodes", + "mynetwork", // security domain name + ["PartyA", "PartyB"], // list of nodes + "", + "" + ) + + // Generate Membership + val membership = credentialsCreator.createMembership() + return jsonPrinter.print(membership) + } +} +``` +An agent from a foreign network can query either `http://partya.mynetwork.com:9000/sec_group` or `http://partyb.mynetwork.com:9000/sec_group` and obtain the security domain (or membership) configuration of the entire network. + +#### For Data Sharing + +Consider a scenario inspired by the [global trade use case](../../user-stories/global-trade.md) where a letter of credit (L/C) management business logic is installed in the `trade-finance-network` network, supports a flow named `UploadBillOfLading`, which validates and records a bill of lading (B/L) supplied by a user via a UI. Weaver will enable such a B/L to be fetched from a different network `trade-logistics-network` by querying the function `GetBillOfLading` exposed by the chaincode `shipmentcc` installed in the `tradelogisticschannel` channel (_The trade logistics network can be built on Corda as well. The steps for Weaver-enablement will mostly be the same, with the exception of view address creation logic. Here, for demonstration purposes, we assume that that counter-party network is built on Fabric_). + +(In preparation, a suitable access control policy must be recorded on `tradelogisticschannel` in `trade-logistics-network`, and a suitable verification policy must be recorded in the vault of `trade-finance-network`. We will see how to do this in the [Startup and Bootstrap Weaver Components](#startup-and-bootstrap-weaver-components) section later.) + +You will need to insert some code in the client layer application that accepts a B/L and submits a `UploadBillOfLading` request in `trade-finance-network`. (No code changes need to be made in any application in the other network.) The logic to accept a B/L should be replaced (or you can simply add an alternative) by a call to the `InteroperableHelper.interopFlow` function offered by the [cacti-weaver-sdk-corda](https://github.com/hyperledger/cacti/packages/1856827) library. The following code sample illustrates this: + +```kt +import org.hyperledger.cacti.weaver.sdk.corda.InteroperableHelper +import com.mynetwork.flow.UploadBillOfLading + +val viewAddress = InteroperableHelper.createFabricViewAddress( + 'trade-logistics-network', // Security Domain/Group + ], // Replace with remote network's relay + 'tradelogisticschannel', // Remote network's channel + 'shipmentcc', // Remote network's cc + 'GetBillOfLading', // Remote network's cc Fun + [ ] // Replace with a value that can be used to look up the right B/L +) +try { + val response = InteroperableHelper.interopFlow( + proxy, // CordaRPCOps instance to start flows + viewAddress, + [:] // Replace with local network's relay address and port + ).fold({ + println("Error in Interop Flow: ${it.message}") + }, { + val linearId = it.toString() + val BoLString = InteroperableHelper.getExternalStatePayloadString( + proxy, + linearId + ) + val result = proxy.startFlow(::UploadBillOfLading, BoLString) + println("$result") + } +} catch (e: Exception) { + println("Error: ${e.toString()}") +} +``` + +Let us understand this code snippet better. The function `UploadBillOfLading` expects one argument, the bill of lading contents. The `InteroperableHelper.createFabricViewAddress` is used to create view address that is to passed to `InteroperableHelper.interopFlow` function. The equivalent function to create a view address for a remote Corda network is `InteroperableHelper.createCordaViewAddress`. + +The rest of the code ought to be self-explanatory. Values are hardcoded for explanation purposes. + +**Enabling TLS**: +By default, the TLS is set to false in `interopFlow`, i.e. disabled. But if you want to enable TLS, can pass additional parameters to the `interopFlow` function as follows: +```kt +val response = InteroperableHelper.interopFlow( + proxy, // CordaRPCOps instance to start flows + viewAddress, + [:], // Replace with local network's relay address and port + 'trade-finance-network', // Local network name (destination) + true, // Boolean indication TLS is enabled. + // JKS file path containing relay server TLS CA certificates + , // password used to create the JKS file +) +``` +OR +```kt +val response = InteroperableHelper.interopFlow( + proxy, // CordaRPCOps instance to start flows + viewAddress, + [:], // Replace with local network's relay address and port + 'trade-finance-network', // Local network name (destination) + true, // Boolean indication TLS is enabled. + , // colon-separated list of CA certificate file paths +) +``` + +#### For Asset exchange + +Let's take an example of asset exchange between `Alice` and `Bob`, where Bob wants to purchase an asset of type `Gold` with id `A123` from `Alice` in `BondNetwork` in exchange for `200` tokens of type `CBDC01` in `TokenNetwork`. + +`Alice` needs to select a secret text (say `s`), and hash it (say `H`) using say `SHA512`, which will be used to lock her asset in `BondNetwork`. To lock the non-fungible asset using hash `H` and timeout duration of 10 minutes, you need to add following code snippet in your application: +```kotlin +import org.hyperledger.cacti.weaver.sdk.corda.AssetManager +import org.hyperledger.cacti.weaver.sdk.corda.HashFunctions + +var hash: HashFunctions.Hash = HashFunctions.SHA512 +hash.setSerializedHashBase64(H) +val proxy = +val issuer = +val recipient = +val contractId = AssetManager.createHTLC( + proxy, + "Gold", // Type + "A123", // ID + recipient, + hash, + 10L, // Duration tmeout in secs, L denotes Long + 1, // 1 if timeout is Duration, 0 if timeout is in absolute epochs + "com.cordaSimpleApplication.flow.RetrieveStateAndRef", // full name of "Flow to get Asset State" + AssetContract.Commands.Delete(), // Contract command for Asset to Burn/Delete the state + issuer, + observers // Optional parameter for list of observers for this transaction +) +``` + +Now `Bob` will lock his tokens in `TokenNetwork`. To lock the fungible asset using same hash `H` and timeout of 5 minutes (half the timeout duration used by Alice in `BondNetwork`), add following code snippet in your application: +```kotlin +import org.hyperledger.cacti.weaver.sdk.corda.AssetManager +import org.hyperledger.cacti.weaver.sdk.corda.HashFunctions + +var hash: HashFunctions.Hash = HashFunctions.SHA512 +hash.setSerializedHashBase64(H) +val proxy = +val issuer = +val recipient = +val contractId = AssetManager.createFungibleHTLC( + proxy, + "CBDC01", // Type + "200", // Quantity + recipient, + hash, + 5L, // Duration timeout in secs, L denotes Long + 1, // 1 if timeout is Duration, 0 if timeout is in absolute epochs + "com.cordaSimpleApplication.flow.RetrieveStateAndRef", // full name of "Flow to get Asset State" + AssetContract.Commands.Delete(), // Contract command for Asset to Burn/Delete the state + issuer, + observers // Optional parameter for list of observers for this transaction +) +``` + +The above locks will return `contractId`, that has to be stored and will be used in other HTLC functions. + +To query whether the assets are locked or not in any network, use following query function: +```kotlin +val isLockedBoolean = AssetManager.isAssetLockedInHTLC( + rpc.proxy, + contractId +) +``` + +Now to claim the asset using the secret text (pre-image of hash) `s`, add following code snippet: +```kotlin +var hash: HashFunctions.Hash = HashFunctions.SHA512() +hash.setPreimage(s) +val issuer = +val proxu = +val res = AssetManager.claimAssetInHTLC( + proxy, + contractId, // ContractId obtained during lock + hash, + AssetContract.Commands.Issue(), // Contract command for issuing/minting asset + "com.cordaSimpleApplication.flow.UpdateAssetOwnerFromPointer", // full name of flow to update owner in asset state + issuer, + observers // Optional parameter for list of observers for this transaction +) +// return value is boolean indicating success or failure of claim +``` +The above function can be adapted to both `BondNetwork` and `TokenNetwork`. + +If the asset has to be unlocked, use following code snippet: +```kotlin +val issuer = +val proxu = +val res = AssetManager.reclaimAssetInHTLC( + rpc.proxy, + contractId, // ContractId obtained during lock + AssetContract.Commands.Issue(), // Contract command for issuing/minting asset + issuer, + observers // Optional parameter for list of observers for this transaction +) +// return value is boolean indicating success or failure of claim +``` + +#### For Asset Transfer + +_TBD_ + +## Pre-Configuration Phase + +No changes are required in your network's pre-configuration process for Weaver enablement. + +Typically, pre-configuration involves: + +* Generating node folders for each participating node in the network, which contains CorDapps, certificates, persistence db, etc sub directories. Using Gradle task `net.corda.plugins.Cordform` or `net.corda.plugins.Dockerform`, the folders get created under the directory `build/nodes` (this path is used in above sample code for Identity Service). + +* The RPC address, username and password specified in above task will be used to create an instance of `CordaRPCOps`, which is the first argument for most `weaver-sdk-corda` static functions as we saw in previous section. For example, one of them is `InteroperableHelper.interopFlow`: +```kotlin +val response = InteroperableHelper.interopFlow( + proxy, // CordaRPCOps instance to start flows + viewAddress, + [:], // Replace with local network's relay address and port +) +``` +Also, the Corda Driver (which we will setup in the following sections) needs a specific RPC user to be created, so make sure to add that in the Gradle task above, and note the credentials. + +* Sample `net.corda.plugins.Dockerform` task: +```groovy +task prepareDockerNodes(type: net.corda.plugins.Dockerform, dependsOn: ['jar']) { + def HOST_ADDRESS = "0.0.0.0" + nodeDefaults { + projectCordapp { + deploy = false + } + } + node { + name "O=Notary,L=London,C=GB" + notary = [validating : true] + p2pPort 10004 + rpcSettings { + address("$HOST_ADDRESS:10003") + adminAddress("$HOST_ADDRESS:10005") + } + cordapps.clear() + } + node { + name "O=PartyA,L=London,C=GB" + p2pPort 10007 + rpcSettings { + address("$HOST_ADDRESS:10003") + adminAddress("$HOST_ADDRESS:10005") + } + rpcUsers = [ + [ user: "user1", "password": "test", "permissions": ["ALL"]], + [ user: "driverUser1", "password": "test", "permissions": ["ALL"]]] // <-- Driver RPC User + } + node { + name "O=PartyB,L=London,C=GB" + p2pPort 10009 + rpcSettings { + address("$HOST_ADDRESS:10003") + adminAddress("$HOST_ADDRESS:10005") + } + rpcUsers = [ + [ user: "user1", "password": "test", "permissions": ["ALL"]], + [ user: "driverUser1", "password": "test", "permissions": ["ALL"]]] // <-- Driver RPC User + } +} +``` + +## Startup and Bootstrap Phase + +To launch a network using containerized components, you will typically use a Docker Compose or Kubernetes configuration file. No modifications are needed to the node's configurations. Sample instructions are given below for networks launched using Docker Compose; we leave it to the reader to adapt these to their custom launch processes. + +### For Asset Exchange + +The asset exchange mode currently requires only the Interoperation CorDapp module from Weaver. Relays and drivers are not necessary. In the future, we expect to make the asset exchange protocol moe automated using these components; the instructions here will be updated appropriately. + +### Install Interoperation CorDapp on Nodes + +After bootstrapping the nodes folder, copy the following two CorDapps in `build/nodes/PartyA/cordapps` and `build/nodes/PartyB/cordapps` folders (`PartyA` and `PartyB` node names are for example only): + +- [org.hyperledger.cacti.weaver.imodule.corda.interop-contracts](https://github.com/hyperledger/cacti/packages/1856825) +- [org.hyperledger.cacti.weaver.imodule.corda.interop-workflows](https://github.com/hyperledger/cacti/packages/1856826) + +| Notes | +|:------| +| You can follow any installation process for this CorDapp, but make sure it is installed on all the nodes that maintain the states involved in cross-network operations in their vaults. | + +### For Data Sharing or Asset Transfer + +Both the data sharing and asset transfer modes require the Interoperation CorDapp, relays, and drivers, to be deployed. + +#### Install Interoperation CorDapp on Nodes + +After bootstrapping the nodes folder, copy the following two CorDapps in `build/nodes/PartyA/cordapps` and `build/nodes/PartyB/cordapps` folders (`PartyA` and `PartyB` node names are for example only): + +- [org.hyperledger.cacti.weaver.imodule.corda.interop-contracts](https://github.com/hyperledger/cacti/packages/1856825) +- [org.hyperledger.cacti.weaver.imodule.corda.interop-workflows](https://github.com/hyperledger/cacti/packages/1856826) + +| Notes | +|:------| +| You can follow any installation process for this CorDapp, but make sure it is installed on all the nodes that maintain the states involved in cross-network operations in their vaults. | + +#### Launch Relay + +You need to run one or more relays for network-to-network communication. Here we provide instructions to run one relay running in a Docker container, which is sufficient for data sharing. (Later, we will provide instructions to run multiple relays, which will be useful from a failover perspective.) + +Weaver provides a [pre-built image](https://github.com/hyperledger/cacti/pkgs/container/cacti-weaver-relay-server) for the relay. Before launching a container, you just need to customize its configuration for your Fabric network, which you can do by simply creating a folder (let's call it `relay_config`) and configuring the following files in it: + +- `.env`: This sets suitable environment variables within the relay container. Copy the `.env.template` file [from the repository](https://github.com/hyperledger/cacti/blob/main/weaver/core/relay/.env.template) and customize it for your purposes, as indicated in the below sample: + ``` + PATH_TO_CONFIG=./config.toml + RELAY_NAME=<"name" in config.toml> + RELAY_PORT= + EXTERNAL_NETWORK= + DOCKER_IMAGE_NAME=ghcr.io/hyperledger/cacti-weaver-relay-server + DOCKER_TAG=2.0.0-alpha.1 + ``` + - The `PATH_TO_CONFIG` variable should point to the properties file typically named `config.toml` (you can name this whatever you wish). See further below for instructions to write this file. + - The `RELAY_NAME` variable specifies a unique name for this relay. It should match what's specified in the `config.toml` (more on that below). + - The `RELAY_PORT` variable specifies the port this relay server will listen on. It should match what's specified in the `config.toml` (more on that below). + - The `EXTERNAL_NETWORK` variable should be set to the [name](https://docs.docker.com/compose/networking/) of your Fabric network. + - The `DOCKER_*` variables are used to specify the image on which the container will be built. Make sure you set `DOCKER_TAG` to the latest version you see on [GitHub](https://github.com/hyperledger/cacti/pkgs/container/cacti-weaver-relay-server). + + For more details, see the [Relay Docker README](https://github.com/hyperledger/cacti/blob/main/weaver/core/relay/relay-docker.md) ("Relay Server Image" and "Running With Docker Compose" sections). + +- `config.toml`: This is the file specified in the `PATH_TO_CONFIG` variable in the `.env`. It specifies properties of this relay and the driver(s) it supports. A sample is given below: + ```toml + name= + port= + host="0.0.0.0" + db_path="db//requests" + remote_db_path="db//remote_request" + + # FOR TLS + cert_path="credentials/fabric_cert.pem" + key_path="credentials/fabric_key" + tls= + + [networks] + [networks.] + network="" + + [relays] + [relays.] + hostname="" + port="" + + [drivers] + [drivers.] + hostname="" + port="" + ``` + - `` should be a unique ID representing this relay; e.g., `my_network_relay`. It should match the `RELAY_NAME` value in `.env`. + - `` is the port number the relay server will listen on. It should match the `RELAY_PORT` value in `.env`. + - `db_path` and `remote_db_path` are used internally by the relay to store data. Replace `` with the same value set for the `name` parameter. (These can point to any filesystem paths in the relay's container.) + - If you set `tls` to `true`, the relay will enforce TLS communication. The `cert_path` and `key_path` should point to a Fabric TLS certificate and key respectively, such as those created using the `cryptogen` tool. + - `` is a unique identifier for your local network. You can set it to whatever value you wish. + - `` refers to the driver used by this relay to respond to requests. This also refers to one of the drivers's specifications in the `drivers` section further below. In this code snippet, we have defined one driver. (The names in lines 14 and 22 must match.) In lines 23 and 24 respectively, you should specify the hostname and port for the driver (whose configuration we will handle later). + - The `relays` section specifies all foreign relays this relay can connect to. The `` value should be a unique ID for a given foreign relay, and this value will be used by your Layer-2 applications when constructing view addresses for data sharing requests. In lines 18 and 19, you should specify the hostname and port for the foreign relay. + - **Enabling TLS**: + - You can make your relay accept TLS connections by specifying a TLS certificate file path and private key file path in `cert_path` and `key_path` respectively, and set `tls` to `true`. + - To communicate with a foreign relay using TLS, specify that relay's TLS CA certificate path in `tlsca_cert_path` (currently only one certificate can be configured) and set `tls` to `true` by extending that relay's section as follows (*Note*: this CA certificate should match the one specified in the `cert_path` property in the foreign relay's `config.toml` file): + ```toml + [relays] + [relays.] + hostname="" + port="" + tls= + tlsca_cert_path="" + ``` + - To communicate with a driver using TLS, specify the driver's TLS CA certificate in `tlsca_cert_path` (currently only one certificate can be configured) and set `tls` to `true` by extending that driver's section as follows (*Note*: this CA certificate must match the certificate used by the driver using the `DRIVER_TLS_CERT_PATH` property in its `.env` configuration file, which we will examine later): + ```toml + [drivers] + [drivers.] + hostname="" + port="" + tls= + tlsca_cert_path="" + ``` + + | Notes | + |:------| + | You can specify more than one foreign relay instance in the `relays` section. | + | You can specify more than one driver instance in the `drivers` section. | + +- `docker-compose.yaml`: This specifies the properties of the relay container. You can use the [file in the repository](https://github.com/hyperledger/cacti/blob/main/weaver/core/relay/docker-compose.yaml) verbatim. + +To start the relay server, navigate to the folder containing the above files and run the following: +```bash +docker-compose up -d relay-server +``` + +#### Launch Driver + +You need to run one or more drivers through which your relay can interact with your Corda network. Here we provide instructions to run one Corda driver running in a Docker container, which is sufficient for data sharing. (Later, we will provide instructions to run multiple drivers, which will be useful both from a failover perspective and to interact with different subsets of your Corda network.) + +Weaver provides a [pre-built image](https://github.com/hyperledger/cacti/pkgs/container/cacti-weaver-driver-corda) for the Corda driver. Before launching a container, you just need to customize the container configuration for your Corda network, which you can do by simply configuring the following: + +- `.env`: This sets suitable environment variables within the driver container. Copy the `.env.docker.template` file [from the repository](https://github.com/hyperledger/cacti/blob/main/weaver/core/drivers/corda-driver/.env.docker.template) and customize it for your purposes, as indicated in the below sample: + ``` + NETWORK_NAME= + DRIVER_PORT= + DRIVER_RPC_USERNAME= + DRIVER_RPC_PASSWORD= + EXTERNAL_NETWORK= + DOCKER_IMAGE_NAME=ghcr.io/hyperledger/cacti-weaver-driver-corda + DOCKER_TAG=2.0.0-alpha.1 + RELAY_TLS= + RELAY_TLSCA_TRUST_STORE= + RELAY_TLSCA_TRUST_STORE_PASSWORD= + RELAY_TLSCA_CERT_PATHS= + DRIVER_TLS= + DRIVER_TLS_CERT_PATH= + DRIVER_TLS_KEY_PATH= + ``` + - `NETWORK_NAME` is only used as suffix for container and has no other significance. + - `DRIVER_PORT` variable should be set to the port this driver will listen on. + - `DRIVER_RPC_USERNAME` variable should be set to rpc user created [above](#pre-configuration) for the driver. + - `DRIVER_RPC_PASSWORD` variable should be set to password of above rpc user. + - `EXTERNAL_NETWORK` variable should be set to the [name](https://docs.docker.com/compose/networking/) of your Corda network. + - **Enabling TLS**: + - You can make your driver accept TLS connections by specifying `DRIVER_TLS` as `true` and specifying a TLS certificate file path and private key file path in `DRIVER_TLS_CERT_PATH` and `DRIVER_TLS_KEY_PATH` respectively. The same certificate should be specified in this driver's definition in the `drivers` section in the `config.toml` file of your relay in the `tlsca_cert_path` property (see the earlier section on relay configuration). + - To communicate with your network' relay using TLS (i.e., if the relay is TLS-enabled), specify that relay's TLS CA certificate path in `RELAY_TLSCA_CERT_PATH` (currently only one certificate can be configured) and set `RELAY_TLS` to `true`. This CA certificate should match the one specified in the `cert_path` property in the relay's `config.toml` file (see the earlier section on relay configuration): + - You can point to the folder in your host system containing the certificate and key using the `TLS_CREDENTIALS_DIR` variable. (This folder will be synced to the `/corda-driver/credentials` folder in the Fabric Driver container as specified in the [docker-compose file](https://github.com/hyperledger/cacti/blob/main/weaver/core/drivers/fabric-driver/docker-compose.yml).) Make sure you point to the right certificate and key file paths within the container using the `DRIVER_TLS_CERT_PATH`, `DRIVER_TLS_KEY_PATH`, and `RELAY_TLSCA_CERT_PATH` variables. + +- `docker-compose.yaml`: This specifies the properties of the driver container. You can use the [file in the repository](https://github.com/hyperledger/cacti/blob/main/weaver/core/drivers/corda-driver/docker-compose.yml) verbatim. + +To start the driver, navigate to the folder containing the above files and run the following: +```bash +docker-compose up -d +``` + +#### Vault Initialization + +To prepare your network for interoperation with a foreign network, you need to record the following to your vault using the [Corda SDK](https://github.com/hyperledger/cacti/packages/1856827) (`org.hyperledger.cacti.weaver.sdk.corda.weaver-sdk-corda`): + +- **Access control policies**: + Let's take the example of the request made from `trade-finance-network` to `trade-logistics-network` for a B/L earlier in this document. `trade-logistics-network` can have a policy of the following form permitting access to the `GetBillOfLading` function from a client representing the `PartyA` node in `trade-finance-network` as follows: + ```json + { + "securityDomain":"trade-finance-network", + "rules": + [ + { + "principal":"", + "principalType":"certificate", + "resource":"exporternode:10003;carriernode:10003#com.mynetwork.flow.GetBillOfLading:*", + "read":true + } + ] + } + ``` + In this sample, a single rule is specified for requests coming from `trade-finance-network`: it states that a workflow call to `com.mynetwork.flow.GetBillOfLading` made to `exporter` and `carrier` nodes of remote Corda network is permitted for a requestor whose certificate is specified in the `principal` attribute. The `*` at the end indicates that any arguments passed to the function will pass the access control check. The `exporternode:10003` and `carriernode:10003` are of form `:`, for `exporter` and `carrier` nodes respectively in the remote Corda network. + + You need to record this policy rule on your Corda network's vault by invoking either the `AccessControlPolicyManager.createAccessControlPolicyState` function or the `AccessControlPolicyManager.updateAccessControlPolicyState` function on the `weaver-sdk-corda`; use the former if you are recording a set of rules for the given `securityDomain` for the first time and the latter to overwrite a set of rules recorded earlier. The above JSON needs to be converted to protobuf object of `org.hyperledger.cacti.weaver.protos.common.access_control.AccessControl.AccessControlPolicy`, using google's protobuf library, and the object is the second argument of above functions (first being the instance of CordaRPCOps). + +- **Verification policies**: + Taking the same example as above, an example of a verification policy for a B/L requested by the `trade-finance-network` from the `trade-logistics-network` is as follows: + ```json + { + "securityDomain":"trade-logistics-network", + "identifiers": + [ + { + "pattern":"tradelogisticschannel:shipmentcc:GetBillOfLading:*", + "policy": + { + "type":"Signature", + "criteria": + [ + "ExporterMSP", + "CarrierMSP" + ] + } + } + ] + } + ``` + In this sample, a single verification policy rule is specified for data views coming from `trade-logistics-network`: it states that the data returned by the `GetBillOfLading` query made to the `shipmentcc` chaincode on the `tradelogisticschannel` channel requires as proof two signatures, one from a peer in the organization whose MSP ID is `ExporterMSP` and another from a peer in the organization whose MSP ID is `CarrierMSP`. + + | Notes | + |:------| + | If the remote network is built on Corda, the resource specified in the access control policy can be used here as the `pattern`, with different node names specified in the `criteria`. | + + You need to record this policy rule on your Corda network's vault by invoking Corda sdk's function `VerificationPolicyManager.createVerificationPolicyState(proxy, verificationPolicyProto)`, where `proxy` is an instance of `CordaRPCOps` as described in previous sections, and `verificationPolicyProto` is an object of protobuf `org.hyperledger.cacti.weaver.protos.common.verification_policy.VerificationPolicyOuterClass.VerificationPolicy`. You can examine the full proto structure [here](https://github.com/hyperledger/cacti/blob/main/weaver/common/protos/common/verification_policy.proto). (_Google's protobuf library can be used to convert above JSON to protobuf object._) + + | Notes | + |:------| + | For any cross-network data request, make sure an access control policy is recorded in the _source network_ (`trade-logistics-network` in the above example) and a corresponding verification policy is recorded in the _destination network_ (`trade-finance-network` in the above example) before any relay request is triggered. | + +- **Foreign network security domain (membership) configuration**: + Run the following procedure (pseudocode) to record security domain configuration for every foreign network you wish your Corda network to interoperate with (you will need to collect the identity service URLs for all the foreign networks first): + ``` + for each foreign network: + send an HTTP GET request to the network's identity service (using 'curl' or 'wget' from a shell script or equivalent programming language APIs). + convert the response string to protobuf object of 'org.hyperledger.cacti.weaver.protos.common.membership.MembershipOuterClass.Membership'. + invoke 'MembershipManager.createMembershipState(proxy, membershipProto)' or 'MembershipManager.updateMembershipState(proxy, membershipProto)' on Corda sdk. + ``` + As in the above two cases, use `createMembershipState` to record a confiuration for the first time for a given `securityDomain` and `updateMembershipState` to overwrite a configuration. + + | Notes | + |:------| + | Security domain configurations (organization lists and their certificate chains) for any Fabric/Corda network are subject to change, so you should run the above procedure periodically in a loop. | + +Your Corda network is now up and running with the necessary Weaver components, and your network's vault is bootstrapped with the initial configuration necessary for cross-network interactions! diff --git a/docs/docs/weaver/getting-started/enabling-weaver-network/fabric.md b/docs/docs/weaver/getting-started/enabling-weaver-network/fabric.md new file mode 100644 index 0000000000..81c0543f4b --- /dev/null +++ b/docs/docs/weaver/getting-started/enabling-weaver-network/fabric.md @@ -0,0 +1,865 @@ +--- +id: fabric +title: Hyperledger Fabric +--- + + + +After testing the Weaver interoperation mechanisms on [basic sample networks](../test-network/overview.md), you may be interested in finding out how you can equip an existing real network, whether in development or in production, to exercise these mechanisms. In this document, we will demonstrate how to equip a Fabric network and application with Weaver components and capabilities. + +## Model + +The figure below illustrates a typical Fabric network. The infrastructure consists of a set of peers, ordering service nodes, and CAs that perform the roles of MSPs; each serves a given _organization_ which is one of the constituent units of the network. On the peers are installed one or more smart contracts (_chaincode_), representing shared business logic across the different organizations. Further up lie the so-called Layer-2 (or client) applications that consist of organization-specific business logic and invoke the smart contracts using APIs exposed by the Fabric SDK and with wallet credentials issued by their respective organizations' CAs. + +![alt text](../../../../images-weaver-docs/enabling-weaver/fabric-network-model.png) + +Such a network equipped with Weaver components and capabilities will look like the figure below. Legacy components are marked in grey and Weaver and bridging components in green. + +![alt text](../../../../images-weaver-docs/enabling-weaver/fabric-weaver-model.png) + +The relay and driver are the only additional infrastructure that need to be installed. One or more relays can be installed, as can one or more drivers. The drivers are illustrated in Layer-2 rather than in the bottom layer because, though they are coupled with relays, they exercise contracts using the Fabric SDK and organization-issued credentials just like any Layer-2 application does. + +Existing chaincode deployed on the network's channels remain undisturbed. All that is required in the smart contracts layer is the deployment of the Fabric Interoperation Chaincode on every channel that needs to offer or consume state from foreign networks. + +Layer-2, or client, applications will need some additional code and configuration because the decisions to exercise interoperation mechanisms (relay queries for data sharing or atomic asset exchanges) are strictly part of business logic. But Weaver's Fabric Interoperation Node SDK offers various helper functions to ease this process and keep the adaptation to a minimum, as we wil see later in this document. Finally, an _identity service_ must be offered by the network to expose its CAs' certificate chains to foreign networks, thereby laying the basis for interoperation. This service simply needs to offer a REST endpoint, and can be implemented as a standalone application or (more conveniently) as an augmentation of one or more of the existing Layer-2 applications. + +## Procedural Overview + +A Hyperledger Fabric network is typically created in phases, in the following sequence: + +1. **Development**: This involves writing chaincode and Layer-2 applications. The chaincode's deployment name/ID and its transaction API must be designed first, but subsequent development of the two layers of applications can then proceed parallelly. +2. **Pre-Configuration**: This involves creating a desired specification (as a set of configuration diles) of the network topology and the ledgers it maintains. +3. **Startup and Bootstrap**: This is the launch phase, in which the network components and applications are started and bootstrapped (i.e., configured with initial state and operating rules). + +Assuming that the reader is familiar with this procedure, we will walk through the changes required in each phase to make your network ready for interoperation using Weaver components and code templates. This will involve code addition and adaptation, deployment of additional modules, additional configuration, and creation of additional ledger state records. The requirements and effort will vary with the mode of interoperation you wish to support in your Fabric network. + +## Development Phase + +A Fabric distributed application's business logic code spans two layers as illustrated in the network model. + +### Chaincode + +These are smart contracts embodied in code, managing business workflow state and digital assets. + +#### For Data Sharing + +No code changes are required for Weaver enablement, because data sharing involves: + +- View packaging (and optionally, encryption) logic and access control logic in a source network, and +- View validation logic in a destination network + +This logic is standard and independent of smart contract, asset, and state, particulars. It is already implemented in the Fabric Interoperation Chaincode offered by Weaver. Hence you just need to deploy that chaincode to exercise data sharing from, or to, your application chaincode. Your application chaincode can be oblivious of the Fabric Interoperation Chaincode's workings and of the view request-response protocol. + +#### For Asset Exchange + +To exchange an asset using Weaver, the asset's state on the ledger must be controlled in the following ways: + +- Locked in favor of a party +- Claimed by the party to whom the asset is pledged +- Returned to the original owner if it is not claimed within a given timeframe + +In addition, the state of the asset (i.e., whether it is locked), and its current and targeted owners, must be determinable by looking at the ledger records. + +The bookkeeping logic required to maintain records of locks can be abstracted away from the particulars of a digital asset and its workflow. But as such assets and their properties (including ownership) can be, and are, encoded in an arbitrary number of ways, we cannot provide a one-size-fits all set of functions (like in the data sharing protocol) to exchange any kind of asset. Instead, we must rely on the application contract (chaincode) managing an asset, as it knows precisely what the asset's properties are and how they can be updated and queried on the ledger (channel). + +What Weaver offers, therefore, is the following: + +- Lock management (bookkeeping) logic implemented in the Fabric Interoperation Chaincode that treats each asset as an abstract object and is agnostic of the assets' internals. This logic can be exercised in one of two ways: + - Importing the [`assetexchange`](https://pkg.go.dev/github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/libs/assetexchange/v2) library from the Fabric Interoperation Chaincode into your application chaincode, or + - Invoking them within the Fabric Interoperation Chaincode using a [chaincode-to-chaincode call](https://pkg.go.dev/github.com/hyperledger/fabric-chaincode-go/shim#ChaincodeStub.InvokeChaincode). +- A set of template functions with sample (and extensible) code that must be added to the application chaincode to exercise the above lock management functions. + +Below, we list the template functions with sample code that you, as a developer, must use and adapt within your chaincode, in either mode (library import or chaincode invocations). + +| Notes | +|:------| +| The instructions here apply only to chaincode implemented in Go, because Weaver presently offers only a Go version of the Fabric Interoperation Chaincode. | + +- _Using the [`assetexchange`](https://pkg.go.dev/github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/libs/assetexchange/v2) Library_: This method doesn't require the [`Fabric Interoperation Chaincode`](https://pkg.go.dev/github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/contracts/interop/v2) to be installed. In your smart contract's `go.mod`, add the following in the `require` section (the sample below uses the current versions for dependency packages; update them to the latest versions offered by Cacti): + ```go + require( + ... + github.com/hyperledger/cacti/weaver/common/protos-go/v2 v2.0.0-alpha.1 + github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/libs/assetexchange/v2 v2.0.0-alpha.1 + ... + ) + ``` + The following functions need to be added to your chaincode, and the smart contract class/type used below is called `SmartContract` (_Note_: the function signature, i.e. the name, arguments, and return values, need to be exactly what is given in the below samples; you can have additional code to manage asset state as per need): + 1. **LockAsset** + ```go + import ( + ... + "github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/libs/assetexchange/v2" + ) + func (s *SmartContract) LockAsset(ctx contractapi.TransactionContextInterface, assetExchangeAgreementSerializedProto64 string, lockInfoSerializedProto64 string) (string, error) { + // Add some safety checks before calling LockAsset from library + // Caller of this chaincode is supposed to be the Locker and the owner of the asset being locked. + contractId, err := assetexchange.LockAsset(ctx, "", assetExchangeAgreementSerializedProto64, lockInfoSerializedProto64) + if err != nil { + return "", logThenErrorf(err.Error()) + } + // Post proccessing of asset after LockAsset called like change status of the asset so that it can't be spent. + ... + return contractId, nil + } + ``` + Here `assetExchangeAgreementSerializedProto64` is a serialized protobuf in Base64 encoded string of `AssetExchangeAgreement` protobuf structure, and can be used to extract details like asset id, type of asset and recipient. Check the structure definition [here](https://github.com/hyperledger/cacti/blob/main/weaver/rfcs/formats/assets/exchange.md#representing-two-party-asset-exchange-agreements). + Similarly `lockInfoSerializedProto64` is a serialized protobuf in Base64 encoded string of `AssetLock` protobuf structure. Check the structure definition [here](https://github.com/hyperledger/cacti/blob/main/weaver/rfcs/formats/assets/exchange.md#representing-locks-on-assets). + 2. **LockFungibleAsset** + ```go + func (s *SmartContract) LockFungibleAsset(ctx contractapi.TransactionContextInterface, fungibleAssetExchangeAgreementSerializedProto64 string, lockInfoSerializedProto64 string) (string, error) { + // Add some safety checks before calling LockFungibleAsset from library + // Caller of this chaincode is supposed to be the Locker and the owner of the asset being locked. + contractId, err := assetexchange.LockFungibleAsset(ctx, "", fungibleAssetExchangeAgreementSerializedProto64, lockInfoSerializedProto64) + if err != nil { + return "", logThenErrorf(err.Error()) + } + // Post proccessing of asset after LockFungibleAsset called like reduce the amount of tokens owned by the locker, or mark it locked so that it can't be spent. + ... + return contractId, nil + } + ``` + Here `fungibleAssetExchangeAgreementSerializedProto64` is a serialized protobuf in Base64 encoded string of `FungibleAssetExchangeAgreement` protobuf structure, and can be used to extract details like asset quantity, type of asset and recipient. Check the structure definition [here](https://github.com/hyperledger/cacti/blob/main/weaver/rfcs/formats/assets/exchange.md#representing-two-party-asset-exchange-agreements). + 3. **IsAssetLockedQueryUsingContractId** + ```go + func (s *SmartContract) IsAssetLockedQueryUsingContractId(ctx contractapi.TransactionContextInterface, contractId string) (bool, error) { + return assetexchange.IsAssetLockedQueryUsingContractId(ctx, contractId) + } + ``` + 4. **ClaimAssetUsingContractId** + ```go + func (s *SmartContract) ClaimAssetUsingContractId(ctx contractapi.TransactionContextInterface, contractId, claimInfoSerializedProto64 string) (bool, error) { + // Note recipient will be the caller for this function + claimed := false + err := assetexchange.ClaimAssetUsingContractId(ctx, contractId, claimInfoSerializedProto64) + if err != nil { + return false, logThenErrorf(err.Error()) + } + claimed = true + // After the above function call, update the owner of the asset with recipeint/caller + ... + return claimed, nil + } + ``` + 5. **UnlockAssetUsingContractId** + ```go + func (s *SmartContract) UnlockAssetUsingContractId(ctx contractapi.TransactionContextInterface, contractId string) (bool, error) { + unlocked := false + err := assetexchange.UnlockAssetUsingContractId(ctx, contractId) + if err != nil { + return false, logThenErrorf(err.Error()) + } + unlocked = true + ... + return true, nil + } + ``` + + In addition, you should add the following extra utility functions to enable client applications to query and discover asset state: + ```go + func (s *SmartContract) GetHTLCHashByContractId(ctx contractapi.TransactionContextInterface, contractId string) (string, error) { + return assetexchange.GetHTLCHashByContractId(ctx, contractId) + } + func (s *SmartContract) GetHTLCHashPreImageByContractId(ctx contractapi.TransactionContextInterface, contractId string) (string, error) { + return assetexchange.GetHTLCHashPreImageByContractId(ctx, contractId) + } + ``` + + There is an alternative API to implement asset exchange using this library, which doesn't involve contract IDs. For details, see the [Asset Exchange Library README](https://github.com/hyperledger/cacti/blob/main/weaver/core/network/fabric-interop-cc/libs/assetexchange/README.md#without-contractid). + +- _Using the [`Fabric Interoperation Chaincode`](https://pkg.go.dev/github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/contracts/interop/v2)_: This method requires the Fabric Interoperation Chaincode to be installed on all peers of the channel, using a special chaincode ID (e.g., `interop`, which is what we will use later in this document). Your application chaincode needs to implement the interface `github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/interfaces/asset-mgmt/v2`. + In your smart contract's `go.mod`, add the following in the `require` section (update the version to the latest Cacti version): + ```go + require( + ... + github.com/hyperledger/cacti/weaver/common/protos-go/v2 v2.0.0-alpha.1 + github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/interfaces/asset-mgmt/v2 v2.0.0-alpha.1 + ... + ) + ``` + In the SmartContract class definition file, add the following code: + ```go + import ( + ... + am "github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/interfaces/asset-mgmt/v2" + ) + type SmartContract struct { + contractapi.Contract + amc am.AssetManagementContract + } + ``` + The following functions need to be added to your chaincode (_Note_: the function signature, i.e. the name, arguments, and return values, need to be exactly what is given in the below samples; you can have additional code to manage asset state as per need): + 1. **LockAsset** + ```go + func (s *SmartContract) LockAsset(ctx contractapi.TransactionContextInterface, assetExchangeAgreementSerializedProto64 string, lockInfoSerializedProto64 string) (string, error) { + // Add some safety checks before calling LockAsset from library + // Caller of this chaincode is supposed to be the Locker and the owner of the asset being locked. + contractId, err := s.amc.LockAsset(ctx, "", assetExchangeAgreementSerializedProto64, lockInfoSerializedProto64) + if err != nil { + return "", logThenErrorf(err.Error()) + } + // Post proccessing of asset after LockAsset called like change status of the asset so that it can't be spent. + ... + return contractId, nil + } + ``` + Here `assetExchangeAgreementSerializedProto64` is a serialized protobuf in Base64 encoded string of `AssetExchangeAgreement` protobuf structure, and can be used to extract details like asset id, type of asset and recipient. Check the structure definition [here](https://github.com/hyperledger/cacti/blob/main/weaver/rfcs/formats/assets/exchange.md#representing-two-party-asset-exchange-agreements). + Similarly `lockInfoSerializedProto64` is a serialized protobuf in Base64 encoded string of `AssetLock` protobuf structure. Check the structure definition [here](https://github.com/hyperledger/cacti/blob/main/weaver/rfcs/formats/assets/exchange.md#representing-locks-on-assets). + 2. **LockFungibleAsset** + ```go + func (s *SmartContract) LockFungibleAsset(ctx contractapi.TransactionContextInterface, fungibleAssetExchangeAgreementSerializedProto64 string, lockInfoSerializedProto64 string) (string, error) { + // Add some safety checks before calling LockFungibleAsset from library + // Caller of this chaincode is supposed to be the Locker and the owner of the asset being locked. + contractId, err := s.amc.LockFungibleAsset(ctx, "", fungibleAssetExchangeAgreementSerializedProto64, lockInfoSerializedProto64) + if err != nil { + return "", logThenErrorf(err.Error()) + } + // Post proccessing of asset after LockFungibleAsset called like reduce the amount of tokens owned by the locker, or mark it locked so that it can't be spent. + ... + return contractId, nil + } + ``` + Here `fungibleAssetExchangeAgreementSerializedProto64` is a serialized protobuf in Base64 encoded string of `FungibleAssetExchangeAgreement` protobuf structure, and can be used to extract details like asset quantity, type of asset and recipient. Check the structure definition [here](https://github.com/hyperledger/cacti/blob/main/weaver/rfcs/formats/assets/exchange.md#representing-two-party-asset-exchange-agreements). + 3. **IsAssetLockedQueryUsingContractId** + ```go + func (s *SmartContract) IsAssetLockedQueryUsingContractId(ctx contractapi.TransactionContextInterface, contractId string) (bool, error) { + return s.amc.IsAssetLockedQueryUsingContractId(ctx, contractId) + } + ``` + 4. **ClaimAssetUsingContractId** + ```go + func (s *SmartContract) ClaimAssetUsingContractId(ctx contractapi.TransactionContextInterface, contractId, claimInfoSerializedProto64 string) (bool, error) { + // Note recipient will be the caller for this function + claimed := false + err := s.amc.ClaimAssetUsingContractId(ctx, contractId, claimInfoSerializedProto64) + if err != nil { + return false, logThenErrorf(err.Error()) + } + claimed = true + // After the above function call, update the owner of the asset with recipeint/caller + ... + return claimed, nil + } + ``` + 5. **UnlockAssetUsingContractId** + ```go + func (s *SmartContract) UnlockAssetUsingContractId(ctx contractapi.TransactionContextInterface, contractId string) (bool, error) { + unlocked := false + err := s.amc.UnlockAssetUsingContractId(ctx, contractId) + if err != nil { + return false, logThenErrorf(err.Error()) + } + unlocked = true + ... + return true, nil + } + ``` + In addition, you should add the following extra utility functions to enable client applications to query and discover asset state: + ```go + func (s *SmartContract) GetHTLCHashByContractId(ctx contractapi.TransactionContextInterface, contractId string) (string, error) { + return s.amc.GetHTLCHashByContractId(ctx, contractId) + } + func (s *SmartContract) GetHTLCHashPreImageByContractId(ctx contractapi.TransactionContextInterface, contractId string) (string, error) { + return s.amc.GetHTLCHashPreImageByContractId(ctx, contractId) + } + ``` + +#### For Asset Transfer + +_TBD_ + +### Client (or Layer-2) Applications + +Weaver provides an SDK to help you adapt your applications to exercise the various interoperability modes. These are called out as **Interoperation Helpers** in the network model illustrated earlier. Your Fabric network's Layer-2 applications have business logic embedded in them that, broadly speaking, accept data from users and other external agents and invoke smart contracts using library functions and APIs offered by the Fabric SDK. When you use Weaver for network interoperability, other options can be added, namely requesting and accepting data from foreign networks, and triggering locks and claims for atomic exchanges spanning two networks. Weaver's Fabric Interoperation SDK (currently implemented both in Node.js and Golang) offers a library to exercise these options, supplementing the Fabric SDK. But this will involve modification to the application's business logic. + +| Notes | +|:------| +| The instructions here apply to applications implemented in Node.js (JavaScript and TypeScript), using the Weaver Node SDK for Fabric. We will add instructions later for Go applications using the Weaver Go SDK for Fabric. | + +To import and use the Weaver SDK, you need to add the following dependency to the `dependencies` section of your Node.js application's `package.json` file: +```json +"@hyperledger/cacti-weaver-sdk-fabric": "latest", +``` +(Instead of `latest`, you can select a particular version from the [package website](https://github.com/hyperledger/cacti/pkgs/npm/cacti-weaver-sdk-fabric).) + +Before you run `npm install` to fetch the dependencies, make sure you create a [personal access token](https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token) with `read:packages` access in GitHub. Create an `.npmrc` file in the same folder as the `package.json` with the following contents: + +``` +@hyperledger:registry=https://npm.pkg.github.com/hyperledger +//npm.pkg.github.com/:_authToken= +``` +Replace `` in this file with the token you created in GitHub. + +First, you must incorporate some code for Weaver's network administration, specifically identity management. Then, using the given sample code and examples, you can adapt your applications for each interoperability mode. + +#### For Identity Administration + +A Fabric network channel must share its security domain (or membership) configuration, i.e., its organizations' CA certificate chains, with a foreign network with which it seeks to interoperate. Each organization must run an IIN Agent for this purpose. The set of IIN Agents, a.k.a. the _local membership_ must be recorded in the ledger before those agents can be operational. In your Fabric network application suite, one or more applications will exist for network administration; the following code snippet should be added in at least one of those applications to record local membership as a prerequisite for interoperability: + ```typescript + import { MembershipManager } from '@hyperledger/cacti-weaver-sdk-fabric' + + const gateway = + + try { + const response = await MembershipManager.createLocalMembership( + gateway, + members, // list of all organization MSPIDs that are part of the channel + securityDomain, // name of the local network's security domain + channelName, // Channel Name + contractName // Fabric Interoperation Chaincode installation ID on the channel + ) + } catch (e) { + // On error try updating local membership + const response = await MembershipManager.updateLocalMembership(gateway, members, securityDomain, channelName, contractName) + } + ``` + + - `` should be replaced with standard (boilerplate) code to get a handle to your network's gateway. This requires a special wallet identity, namely one with a `network-admin` attribute indicating that the caller is a trusted network administrator who is authorized to record local memberships on the `channelName` channel. + - `members` must consist of the list of organizational MSP IDs for the `channelName` channel. + +#### For Data Sharing + +Consider a scenario inspired by the [global trade use case](../../user-stories/global-trade.md) where a letter of credit (L/C) management business logic (chaincode `letterofcreditcc`) installed in the `tradefinancechannel` channel in the `trade-finance-network` network supports a transaction `RecordBillOfLading`, which validates and records a bill of lading (B/L) supplied by a user via a UI. Weaver will enable such a B/L to be fetched from a different network `trade-logistics-network` by querying the function `GetBillOfLading` exposed by the chaincode `shipmentcc` installed in the `tradelogisticschannel` channel. + +(In preparation, a suitable access control policy must be recorded on `tradelogisticschannel` in `trade-logistics-network`, and a suitable verification policy must be recorded on `tradefinancechannel` in `trade-finance-network`. We will see how to do this in the "Startup and Boostrap" section later.) + +You will need to insert some code in the Layer-2 application that accepts a B/L and submits a `RecordBillOfLading` transaction in `trade-finance-network`. (No code changes need to be made in any application in the other network.) The logic to accept a B/L should be replaced (or you can simply add an alternative) by a call to the `interopFlow` function offered by the [cacti-weaver-sdk-fabric](https://github.com/hyperledger/cacti/pkgs/npm/cacti-weaver-sdk-fabric) library (there's an [equivalent library in Golang](https://github.com/hyperledger/cacti/releases/tag/weaver%2Fsdks%2Ffabric%2Fgo-sdk%2Fv2.0.0-alpha.1) too). The following code sample illustrates this (the Golang equivalent is left to the reader): +```js +const ihelper = require('@hyperledger/cacti-weaver-sdk-fabric').InteroperableHelper; +const interopcc = ; // Use Fabric SDK functions: (new Gateway()).getNetwork(...).getContract() +const keyCert = await ihelper.getKeyAndCertForRemoteRequestbyUserName(, ); // Read key and certificate for from wallet (get handle using Fabric SDK Wallets API) +// Collect view addresses for relay requests in the context of an interop flow +interopJSONs.push({ + NetworkID: 'trade-logistics-network', + RemoteEndpoint: ], // Replace with remote network's relay address and port + ChannelID: 'tradelogisticschannel', + ChaincodeID: 'shipmentcc', + ChaincodeFunc: 'GetBillOfLading', + ccArgs: [ ], // Replace with a value that can be used to look up the right B/L + Sign: true +}); +const indices = [ 1 ]; +// Trigger an end-to-end interoperation (data sharing) protocol +// Send a request to a foreign network via your relay, receive the response and submit a transaction to a local chaincode +const flowResponse = await ihelper.interopFlow( + interopcc, + 'trade-finance-network', + { + channel: 'tradefinancechannel', + contractName: 'letterofcreditcc', + ccFunc: 'RecordBillOfLading', + ccArgs: [ , '' ] + }, + , // Replace with this Layer-2 application's organization's MSP ID + [:], // Replace with local network's relay address and port + indices, + interopJSONs, + keyCert, + , // List of orgs to submit transaction to local i.e. trade logistics network + false, // Boolean flag to indicate whether return without submit transaction to local i.e. trade logistics network + false, // Boolean flag indicating no TLS communication with relay + [], // Keep it empty when TLS is disabled + , // Boolean flag to indicate whether to use to end-to-end encryption +); +// List of errors to check for +if (!flowResponse.views || flowResponse.views.length === 0 || !flowResponse.result || flowResponse.views.length !== argIndices.length) { + throw ; +} +``` +Let us understand this code snippet better. The structure in lines 20-25 specifies the local chaincode transaction that is to be triggered after remote data (view) has been requested and obtained via relays. The function `RecordBillOfLading` expects two arguments as specified in line 24: the first is the common shipment reference that is used by the letter of credit in `trade-finance-network` and the bill of lading in `trade-logistics-network`, and the second is the bill of lading contents. When the `interopFlow` function is called, this argument is left blank because it is supposed to be filled with contents obtained from a view request. The array list `indices`, which is passed as an argument to `interopFlow` therefore contains the index value `1` (line 14), indicating which argument ought to be substituted with view data. The `interopJSONs` array correspondingly contains a list of view addresses that are to be supplied to the relay. The `` if set to `true` will enable end-to-end confidentiality, i.e. payload will be encrypted from `trade-finance-network`'s Weaver chaincode, and will be decrypted in SDK (i.e. Layer-2 client application) at `trade-logistics-network`, but relays and drivers in between will not be able to see the payload. By default this flag is set to `false`. + +| Notes | +|:------| +| A local chaincode invocation may require multiple view requests to different networks, which is why `indices` and `interopJSONs` are arrays; they therefore must have the same lengths. | + +The rest of the code ought to be self-explanatory. Values are hardcoded for explanation purposes, but you can refactor the above code by reading view addresses corresponding to chaincode invocations from a configuration file. + +**Enabling TLS**: +By default, the TLS is set to false in `interopFlow`, i.e. disabled. But if you want to enable TLS, can pass additional parameters to the `interopFlow` function as follows: +```TypeScript +const flowResponse = await ihelper.interopFlow( + interopcc, + 'trade-finance-network', + { + channel: 'tradefinancechannel', + contractName: 'letterofcreditcc', + ccFunc: 'RecordBillOfLading', + ccArgs: [ , '' ] + }, + , // Replace with this Layer-2 application's organization's MSP ID + [:], // Replace with local network's relay address and port + indices, + interopJSONs, + keyCert, + , // List of orgs to submit transaction to in trade logistics network + false, // Boolean flag to indicate whether return without submit transaction to local i.e. trade logistics network + true, // Boolean indication TLS is enabled. + , // list of CA certificate file paths +); +``` + +#### For Asset Exchange + +Let's take an example of asset exchange between `Alice` and `Bob`, where Bob wants to purchase an asset of type `Gold` with id `A123` from `Alice` in `BondNetwork` in exchange for `200` tokens of type `CBDC01` in `TokenNetwork`. + +`Alice` needs to select a secret text (say `s`), and hash it (say `H`) using say `SHA512`, which will be used to lock her asset in `BondNetwork`. At the place in your application where an asset exchange is to be initiated, you need to add code to enable Alice to lock the non-fungible asset using hash `H` and timeout duration of 10 minutes: +```typescript +import { AssetManager, HashFunctions } from '@hyperledger/cacti-weaver-sdk-fabric' + +const hash = HashFunctions.SHA512(); // Create Hash instance of one of the supported Hash Algorithm +hash.setSerializedHashBase64(H); // Set the Hash +const timeout = Math.floor(Date.now()/1000) + 10 * 60; + +const bondContract = ; + +const result = await AssetManager.createHTLC( + bondContract, + "Gold", // Asset ID + "A123", // Asset Type + bobCertificate, // Certificate of Bob in Bond Network + hash, // Hash generated by Alice using her secret s + timeout, // Timeout in epoch for 10 mins from current time + null // Optional callback function to be called after the asset is locked +); +let bondContractId = result.result; // Unique ID for this asset exchange contract in BondNetwork +``` + +| Notes | +|:------| +| Note that 'Alice' and 'Bob' and the asset specifics can be parameterized in the above code, which can be reused for arbitrary asset exchange scenarios in your business workflow. The above code is only meant to be a sample. | + +Now `Bob` will lock his tokens in `TokenNetwork`. To lock the fungible asset using same hash `H` and timeout of 5 minutes (half the timeout duration used by Alice in `BondNetwork`), add the following code snippet in your application: +```typescript +const hash = HashFunctions.SHA512(); // Create Hash instance of one of the supported Hash Algorithm +hash.setSerializedHashBase64(H); // Set the Hash +const timeout = Math.floor(Date.now()/1000) + 5 * 60; + +const tokenContract = ; +const result = await AssetManager.createFungibleHTLC( + tokenContract, + "CBDC01", // Token ID + 200, // Token Quantity + aliceCertificate, // Certificate of Alice in Token Network + hash, // Hash H used by Alice in Bond Network + timeout, // Timeout in epoch for 5 mins from current time + null // Optional callback function to be called after the asset is locked +) +const tokenContractId = result.result // Unique ID for this asset exchange contract in TokenNetwork +``` + +Wherever the lock status of the asset is required in your application, you should insert a query function call as follows: +```typescript +const contract = ; +// Below contractId is the ID obtained during lock +const isLocked = AssetManager.isAssetLockedInHTLCqueryUsingContractId(contract, contractId) +``` + +Wherever a participant (either 'Alice' or 'Bob' in this example) needs to claim a locked asset using the secret text (pre-image of hash) `s` in your application, insert the following code snippet (*Note*: typically one would insert this in event callback functions or in functions that are polling the ledger to monitor whether the asset is locked in favor of a given recipient): +```typescript +const hash = HashFunctions.SHA512(); // Create Hash instance of one of the supported Hash Algorithm +hash.setPreimage(s) // Set Pre-Image s +const contract = ; +const claimSuccess = await AssetManager.claimAssetInHTLCusingContractId( + contract, + contractId, // contractId obtained during lock + hash +) +// return value claimSuccess is boolean indicating success or failure of claim +``` + +Wherever the asset must be unlocked in your application (typically, an event callback function triggered upon the expiration of the time lock), insert the following code snippet: +```typescript +const contract = ; +const reclaimSuccess = await AssetManager.reclaimAssetInHTLCusingContractId( + contract, + contractId // contractId obtained during lock +) +// return value 'reclaimSuccess' is a boolean indicating success or failure of reclaim +``` + +#### For Asset Transfer + +_TBD_ + +## Pre-Configuration Phase + +Typically, pre-configuration in a Fabric network involves generating (after creating the channel specifications and policies): + +- _Channel artifacts_: orderer genesis block, channel transaction, and anchor peer configurations from a `configtx.yaml` file (using Fabric's `configtxgen` tool) +- _Crypto artifacts_: keys and certificates for CAs, peers, orderers, and clients from a `crypto-config.yaml` file (using Fabric's `cryptogen` tool) +- _Connection profiles_: one for every network organization, which will be used by the organization's Layer-2 applications to connect to the network's peers and CAs + +No changes are required in this process to support any of the three interoperation modes using Weaver. The connection profiles generated above will be used by certain Weaver modules, as we will see later. The only additional step required is to generate special wallet identities for the following: + +- Network administrator: one or more identities containing the `network-admin` attribute; only a user/application possessing this identity may record special (privileged) information regarding memberships and policies on the channel. +- Fabric Driver: one or more identities (for each deployed driver) containing the `relay` attribute; only a relay-driver combination possessing this identity may run data sharing-related operations on the deployed Fabric Interoperation Chaincode. +- IIN Agent: one or more identities (for each deployed agent) containing the `iin-agent` attribute: only an agent may submit foreign network membership records to the Fabric Interoperation Chaincode. + +Later we will see how the components possessing these identities are deployed. + +## Startup and Bootstrap Phase + +After writing application code and creating the network configuration files, the components of a Fabric network (peers, CAs, and ordering service) are launched. In this section, we will list the additional tasks you, as a Fabric network administrator, must perform to make your network ready to interoperate. + +To launch a network using containerized components, you will typically use a Docker Compose or Kubernetes configuration file. No modifications are needed to the peers', orderers', and CAs' configurations. Sample instructions are given below for networks launched using Docker Compose; we leave it to the reader to adapt these to their custom launch processes. + +### For Asset Exchange + +The asset exchange mode currently requires only the Fabric Interoperation Chaincode module from Weaver. Relays, drivers, and IIN agents, are not necessary. In the future, we expect to make the asset exchange protocol moe automated using these components; the instructions here will be updated appropriately. + +#### Install the Fabric Interoperation Chaincode + +Install the Fabric Interoperation Chaincode in the relevant channel(s), i.e., those that run chaincodes that will be involved in asset exchanges. This is a Go module that can be fetched from `github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/contracts/interop`. Following that, you an install it using the appropriate Fabric process: in Fabric v2, you will need to package, install, approve, and commit this module on the selected channels in your network. + +### For Data Sharing or Asset Transfer + +Both the data sharing and asset transfer modes require the Fabric Interoperation Chaincode, relays, drivers, and IIN agents, to be deployed. + +#### Install the Fabric Interoperation Chaincode + +Install the Fabric Interoperation Chaincode in the relevant channel(s), i.e., those that run chaincodess that will be involved in data sharing (and asset transfers, which require multiple data shares). This is a Go module that can be fetched from `github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/contracts/interop`. Following that, you an install it using the appropriate Fabric process: in Fabric v2, you will need to package, install, approve, and commit this module on the selected channels in your network. + +#### Launch Relay + +You need to run one or more relays for network-to-network communication. Here we provide instructions to run one relay running in a Docker container, which is sufficient for data sharing. (Later, we will provide instructions to run multiple relays, which will be useful from a failover perspective.) + +Weaver provides a [pre-built image](https://github.com/hyperledger/cacti/pkgs/container/cacti-weaver-relay-server) for the relay. Before launching a container, you just need to customize its configuration for your Fabric network, which you can do by simply creating a folder (let's call it `relay_config`) and configuring the following files in it: + +- `.env`: This sets suitable environment variables within the relay container. Copy the `.env.template` file [from the repository](https://github.com/hyperledger/cacti/blob/main/weaver/core/relay/.env.template) and customize it for your purposes, as indicated in the below sample: + ``` + PATH_TO_CONFIG=./config.toml + RELAY_NAME=<"name" in config.toml> + RELAY_PORT= + EXTERNAL_NETWORK= + DOCKER_IMAGE_NAME=ghcr.io/hyperledger/cacti-weaver-relay-server + DOCKER_TAG=2.0.0-alpha.1 + ``` + - The `PATH_TO_CONFIG` variable should point to the properties file typically named `config.toml` (you can name this whatever you wish). See further below for instructions to write this file. + - The `RELAY_NAME` variable specifies a unique name for this relay. It should match what's specified in the `config.toml` (more on that below). + - The `RELAY_PORT` variable specifies the port this relay server will listen on. It should match what's specified in the `config.toml` (more on that below). + - The `EXTERNAL_NETWORK` variable should be set to the [name](https://docs.docker.com/compose/networking/) of your Fabric network. + - The `DOCKER_*` variables are used to specify the image on which the container will be built. Make sure you set `DOCKER_TAG` to the latest version you see on [GitHub](ility/pkgs/container/weaver-relay-server). + + For more details, see the [Relay Docker README](https://github.com/hyperledger/cacti/blob/main/weaver/core/relay/relay-docker.md) ("Relay Server Image" and "Running With Docker Compose" sections). + +- `config.toml`: This is the file specified in the `PATH_TO_CONFIG` variable in the `.env`. It specifies properties of this relay and the driver(s) it supports. A sample is given below: + ```toml + name= + port= + host="0.0.0.0" + db_path="db//requests" + remote_db_path="db//remote_request" + + # FOR TLS + cert_path="credentials/fabric_cert.pem" + key_path="credentials/fabric_key" + tls= + + [networks] + [networks.] + network="" + + [relays] + [relays.] + hostname="" + port="" + + [drivers] + [drivers.] + hostname="" + port="" + ``` + - `` should be a unique ID representing this relay; e.g., `my_network_relay`. It should match the `RELAY_NAME` value in `.env`. + - `` is the port number the relay server will listen on. It should match the `RELAY_PORT` value in `.env`. + - `db_path` and `remote_db_path` are used internally by the relay to store data. Replace `` with the same value set for the `name` parameter. (These can point to any filesystem paths in the relay's container.) + - If you set `tls` to `true`, the relay will enforce TLS communication. The `cert_path` and `key_path` should point to a Fabric TLS certificate and key respectively, such as those created using the `cryptogen` tool. + - `` is a unique identifier for your local network. You can set it to whatever value you wish. + - `` refers to the driver used by this relay to respond to requests. This also refers to one of the drivers's specifications in the `drivers` section further below. In this code snippet, we have defined one driver. (The names in lines 14 and 22 must match.) In lines 23 and 24 respectively, you should specify the hostname and port for the driver (whose configuration we will handle later). + - The `relays` section specifies all foreign relays this relay can connect to. The `` value should be a unique ID for a given foreign relay, and this value will be used by your Layer-2 applications when constructing view addresses for data sharing requests. In lines 18 and 19, you should specify the hostname and port for the foreign relay. + - **Enabling TLS**: + - You can make your relay accept TLS connections by specifying a TLS certificate file path and private key file path in `cert_path` and `key_path` respectively, and set `tls` to `true`. + - To communicate with a foreign relay using TLS, specify that relay's TLS CA certificate path in `tlsca_cert_path` (currently only one certificate can be configured) and set `tls` to `true` by extending that relay's section as follows (*Note*: this CA certificate should match the one specified in the `cert_path` property in the foreign relay's `config.toml` file): + ```toml + [relays] + [relays.] + hostname="" + port="" + tls= + tlsca_cert_path="" + ``` + - To communicate with a driver using TLS, specify the driver's TLS CA certificate in `tlsca_cert_path` (currently only one certificate can be configured) and set `tls` to `true` by extending that driver's section as follows (*Note*: this CA certificate must match the certificate used by the driver using the `DRIVER_TLS_CERT_PATH` property in its `.env` configuration file, which we will examine later): + ```toml + [drivers] + [drivers.] + hostname="" + port="" + tls= + tlsca_cert_path="" + ``` + + | Notes | + |:------| + | You can specify more than one foreign relay instance in the `relays` section. | + | You can specify more than one driver instance in the `drivers` section. | + +- `docker-compose.yaml`: This specifies the properties of the relay container. You can use the [file in the repository](https://github.com/hyperledger/cacti/blob/main/weaver/core/relay/docker-compose.yaml) verbatim. + +To start the relay server, navigate to the folder containing the above files and run the following: +```bash +docker-compose up -d relay-server +``` + +#### Launch Driver + +You need to run one or more drivers through which your relay can interact with your Fabric network. Here we provide instructions to run one Fabric driver running in a Docker container, which is sufficient for data sharing. (Later, we will provide instructions to run multiple drivers, which will be useful both from a failover perspective and to interact with different subsets of your Fabric network, like private data collections.) + +Weaver provides a [pre-built image](https://github.com/hyperledger/cacti/pkgs/container/cacti-weaver-driver-fabric) for the Fabric driver. Before launching a container, you just need to customize its configuration for your Fabric network, which you can do by simply creating a folder (let's call it `driver_config`) and configuring the following files in it: + +- `.env`: This sets suitable environment variables within the driver container. Copy the `.env.docker.template` file [from the repository](https://github.com/hyperledger/cacti/blob/main/weaver/core/drivers/fabric-driver/.env.docker.template) and customize it for your purposes, as indicated in the below sample: + ``` + CONNECTION_PROFILE= + DRIVER_CONFIG=./config.json + RELAY_ENDPOINT=: + NETWORK_NAME= + DRIVER_PORT= + INTEROP_CHAINCODE= + EXTERNAL_NETWORK= + TLS_CREDENTIALS_DIR= + DOCKER_IMAGE_NAME=ghcr.io/hyperledger/cacti-weaver-driver-fabric + DOCKER_TAG=2.0.0-alpha.1 + DRIVER_TLS= + DRIVER_TLS_CERT_PATH=path_to_tls_cert_pem_for_driver + DRIVER_TLS_KEY_PATH=path_to_tls_key_pem_for_driver + RELAY_TLS= + RELAY_TLSCA_CERT_PATH=path_to_tls_ca_cert_pem_for_relay + ``` + - `` should point to the path of a connection profile you generated in the "Pre-Configuration" section. A Fabric driver obtains client credentials from one of the organizations in your network, so pick an organization and point to the right connection profile. + - The `DRIVER_CONFIG` variable should point to the `config.json` (you can name this whatever you wish) specified below. + - `` should be set to the hostname of the relay server machine and `` should match the `port` value in the relay's `config.toml` (see above). + - The `NETWORK_NAME` variable should be a unique ID referring to the Fabric network. It will be used to distinguish container names and wallet paths. (This setting is relevant in situations where a driver is used to query multiple network channels.) + - The `DRIVER_PORT` variable should be set to the port this driver will listen on. + - The `INTEROP_CHAINCODE` variable should be set to the ID of the Fabric Interop Chaincode installed on your Fabric network channel. + - The `EXTERNAL_NETWORK` variable should be set to the [name](https://docs.docker.com/compose/networking/) of your Fabric network. + - **Enabling TLS**: + - You can make your driver accept TLS connections by specifying `DRIVER_TLS` as `true` and specifying a TLS certificate file path and private key file path in `DRIVER_TLS_CERT_PATH` and `DRIVER_TLS_KEY_PATH` respectively. The same certificate should be specified in this driver's definition in the `drivers` section in the `config.toml` file of your relay in the `tlsca_cert_path` property (see the earlier section on relay configuration). + - To communicate with your network' relay using TLS (i.e., if the relay is TLS-enabled), specify that relay's TLS CA certificate path in `RELAY_TLSCA_CERT_PATH` (currently only one certificate can be configured) and set `RELAY_TLS` to `true`. This CA certificate should match the one specified in the `cert_path` property in the relay's `config.toml` file (see the earlier section on relay configuration): + - You can point to the folder in your host system containing the certificate and key using the `TLS_CREDENTIALS_DIR` variable. (This folder will be synced to the `/fabric-driver/credentials` folder in the Fabric Driver container as specified in the [docker-compose file](https://github.com/hyperledger/cacti/blob/main/weaver/core/drivers/fabric-driver/docker-compose.yml).) Make sure you point to the right certificate and key file paths within the container using the `DRIVER_TLS_CERT_PATH`, `DRIVER_TLS_KEY_PATH`, and `RELAY_TLSCA_CERT_PATH` variables. + +- `config.json`: This contains settings used to connect to a CA of a Fabric network organization and enroll a client. A sample is given below: + ```json + { + "admin":{ + "name":"admin", + "secret":"adminpw" + }, + "relay": { + "name":"relay", + "affiliation":"", + "role": "client", + "attrs": [{ "name": "relay", "value": "true", "ecert": true }] + }, + "mspId":"", + "caUrl":"" + } + ``` + - As in the `.env` configuration, you should pick an organization for the driver to associate with. The `admin` section specifies the registrar name and password (this should be familiar to any Fabric network administrator) used to enroll clients. Default values of `admin` and `adminpw` are specified above as examples, which you should replace with the right values configured in your network organization's CA. + - `` should be what's specified in your organization's Fabric CA server configuration. The default is `org1.department1`, but you should look up the appropriate value from the CA server's configuration file. + - `` should be set to the (or an) MSP ID of the selected organization. + - `` should be set to the CA server's endpoint. If you launched your CA server as a container from a docker-compose file, this should be set to the container's service name. + + | Notes | + |:------| + | If your connection profile already contains specifications for a CA server, you can leave the `` value as a blank. | + +- `docker-compose.yaml`: This specifies the properties of the driver container. You can use the [file in the repository](https://github.com/hyperledger/cacti/blob/main/weaver/core/drivers/fabric-driver/docker-compose.yml) verbatim. + +To start the driver, navigate to the folder containing the above files and run the following: +```bash +docker-compose up -d +``` + +#### Launch IIN Agents + +You need to run one IIN Agent for each organization in the Fabric network channel you are enabling Weaver in. This agent runs a protocol with other organizations' agents and with targeted foreign networks' agents to sync and record foreign networks' memberships to the channel ledger. + +Weaver provides a [pre-built image](https://github.com/hyperledger/cacti/pkgs/container/cacti-weaver-iin-agent) for the IIN Agent. Before launching a container, you just need to customize its configuration for your Fabric network organization, which you can do by simply creating a folder (let's call it `iin_agent_config_`) and configuring the following files in it: + +- `config.json`: This contains settings used to connect to a Fabric network organization and its CA (part of the organization's MSP). A sample is given below: + ``` + { + "admin":{ + "name":"admin", + "secret":"adminpw" + }, + "agent": { + "name":"iin-agent", + "affiliation":"", + "role": "client", + "attrs": [{ "name": "iin-agent", "value": "true", "ecert": true }] + }, + "mspId":"", + "ordererMspIds": [], + "ccpPath": "", + "walletPath": "", + "caUrl": "", + "local": "false" + } + ``` + +- `dnsconfig.json`: This specifies the list of known IIN agents of your network (i.e., belonging to other organizations) and of foreign networks. A sample DNS configuration file is given below: + ``` + { + "": { + "": { + "endpoint": "", + "tls": , + "tlsCACertPath": "" + }, + "": { + "endpoint": "", + "tls": , + "tlsCACertPath": "" + } + }, + "": { + "": { + "endpoint": "", + "tls": , + "tlsCACertPath": "" + }, + "": { + "endpoint": "", + "tls": , + "tlsCACertPath": "" + } + } + } + ``` + - Each security domain (i.e., unique ledger, like a Fabric channel) scopes a set of JSON objects, each containing specifications of an IIN Agent. The key (`` for example) in each is the IIN Agent's name, which can be the organization's MSP ID (for a Fabric network). The value is another JSON object, containing an `endpoint` with a hostname and port for the agent. + - **Enabling TLS**: To communicate with a given IIN Agent using TLS (i.e., if that agent is TLS-enabled), specify `tls` as `true` and that agent's TLS CA certificate path in `tlsCACertPath` (currently only one certificate can be configured) within the JSON object corresponding to that agent. This CA certificate should match the one specified in that IIN Agent's `.env` file, whose configuration we will specify later. + +- `security-domain-config.json`: This config file contains list of security domain defined for the network and its members, i.e. it can be list of organizations or channel name. Sample security domain configuration file: + ``` + { + "": "", + "": [ + "", + "" + ] + } + ``` + +- `.env`: This sets suitable environment variables within the driver container. Copy the `.env.template` file [from the repository](https://github.com/hyperledger/cacti/blob/main/weaver/core/identity-management/iin-agent/.env.docker.template) and customize it for your purposes, as indicated in the below sample: + ``` + IIN_AGENT_PORT= + IIN_AGENT_TLS= + IIN_AGENT_TLS_CERT_PATH= + IIN_AGENT_TLS_KEY_PATH= + MEMBER_ID= + SECURITY_DOMAIN=network1 + DLT_TYPE=fabric + CONFIG_PATH=./config.json + DNS_CONFIG_PATH=./dnsconfig.json + SECURITY_DOMAIN_CONFIG_PATH=./security-domain-config.json + WEAVER_CONTRACT_ID= + SYNC_PERIOD= + AUTO_SYNC= + TLS_CREDENTIALS_DIR= + DOCKER_IMAGE_NAME=ghcr.io/hyperledger/cacti-weaver-iin-agent + DOCKER_TAG= + EXTERNAL_NETWORK= + ``` + - `IIN_AGENT_ENDPOINT`: The endpoint at which IIN Agent server should listen. E.g.: `0.0.0.0:9500` + - `IIN_AGENT_TLS`: Set this to `true` to enable TLS on IIN Agent server + - `IIN_AGENT_TLS_CERT_PATH`: Path to TLS certificate if TLS is enabled + - `IIN_AGENT_TLS_KEY_PATH`: Path to TLS key if TLS is enabled + - `MEMBER_ID`: Member Id for this IIN Agent. For fabric network, it should be the Organization's MSP ID + - `SECURITY_DOMAIN`: Security domain to which this IIN Agent belongs + - `DLT_TYPE`: To indicate the type of DLT for which this IIN Agent is running. E.g. `fabric` + - `CONFIG_PATH`: Path to ledger specific config file (explained in next subsection) + - `DNS_CONFIG_PATH`: Path to DNS config file explained in previous sub sections + - `SECURITY_DOMAIN_CONFIG_PATH`: Path to security domain config file explained in previous sub sections + - `WEAVER_CONTRACT_ID`: Contract ID for DLT specific Weaver interoperation module installed on network + - `SYNC_PERIOD`: Period at which auto synchronization of memberships from other security domains should happen + - `AUTO_SYNC`: Set this to `true` to enable auto synchronization of memberships from other security domains + - `DOCKER_TAG`: Set this to the desired version of the Weaver IIN Agent [docker image](https://github.com/hyperledger/cacti/pkgs/container/cacti-weaver-iin-agent) + - `EXTERNAL_NETWORK`: Set to the network [name](https://docs.docker.com/compose/networking/) of your Fabric network. + - **Enabling TLS**: + - Make your IIN Agent accept TLS connections by specifying `IIN_AGENT_TLS` as `true` and specifying a TLS certificate file path and private key file path in `IIN_AGENT_TLS_CERT_PATH` and `IIN_AGENT_TLS_KEY_PATH` respectively. The same certificate should be specified in this agent's JSON object in another agent's `dnsconfig.json` file under the appropriate security domain and IIN Agent ID scope. + - You can point to the folder in your host system containing the certificate and key using the `TLS_CREDENTIALS_DIR` variable. (This folder will be synced to the `/opt/iinagent/credentials` folder in the IIN Agent container as specified in the [docker-compose file](https://github.com/hyperledger/cacti/blob/main/weaver/core/identity-management/iin-agent/docker-compose.yml).) Make sure you point to the right certificate and key file paths within the container using the `IIN_AGENT_TLS_CERT_PATH` and `IIN_AGENT_TLS_KEY_PATH` variables respectively. + +- `docker-compose.yaml`: This specifies the properties of the IIN agent container. You can use the [file in the repository](https://github.com/hyperledger/cacti/blob/main/weaver/core/identity-management/iin-agent/docker-compose.yml) verbatim. + +Now to start the IIN agent, navigate to the folder containing the above files and run the following: +```bash +docker-compose up -d +``` + +Repeat the above steps to launch an IIN Agent for every other organization on your channnel, i.e., create similar configuration files in an organization-specific folder. Make sure you: + +- Update the organization names in every relevant location in the `config.json`. +- Update `IIN_AGENT_ENDPOINT` and `MEMBER_ID` in the `.env`. + + +#### Ledger Initialization + +To prepare your network for interoperation with a foreign network, you need to record the following to your network channel through the Fabric Interoperation Chaincode: + +- **Access control policies**: + Let's take the example of the request made from `trade-finance-network` to `trade-logistics-network` for a B/L earlier in this document. `trade-logistics-network` can have a policy of the following form permitting access to the `GetBillOfLading` function from a client belonging to the `Exporter` organization in `trade-finance-network` as follows: + ```json + { + "securityDomain":"trade-finance-network", + "rules": + [ + { + "principal":"ExporterMSP", + "principalType":"ca", + "resource":"tradelogisticschannel:shipmentcc:GetBillOfLading:*", + "read":true + } + ] + } + ``` + In this sample, a single rule is specified for requests coming from `trade-finance-network`: it states that a `GetBillOfLading` query made to the `shipmentcc` contract installed on the `tradelogisticschannel` channel is permitted for a requestor possessing credentials certified by an MSP with the `ExporterMSP` identity. The `*` at the end indicates that any arguments passed to the function will pass the access control check. + + You need to record this policy rule on your Fabric network's channel by invoking either the `CreateAccessControlPolicy` function or the `UpdateAccessControlPolicy` function on the Fabric Interoperation Chaincode that is already installed on that channel; use the former if you are recording a set of rules for the given `securityDomain` for the first time and the latter to overwrite a set of rules recorded earlier. In either case, the chaincode function will take a single argument, which is the policy in the form of a JSON string (make sure you escape the double quotes before sending the request to avoid parsing errors). You can do this in one of two ways: (1) writing a small piece of code in Layer-2 that invokes the contract using the Fabric SDK Gateway API, or (2) running a `peer chaincode invoke` command from within a Docker container built on the `hyperledger/fabric-tools` image. Either approach should be familiar to a Fabric practitioner. + +- **Verification policies**: + Taking the same example as above, an example of a verification policy for a B/L requested by the `trade-finance-network` from the `trade-logistics-network` is as follows: + ```json + { + "securityDomain":"trade-logistics-network", + "identifiers": + [ + { + "pattern":"tradelogisticschannel:shipmentcc:GetBillOfLading:*", + "policy": + { + "type":"Signature", + "criteria": + [ + "ExporterMSP", + "CarrierMSP" + ] + } + } + ] + } + ``` + In this sample, a single verification policy rule is specified for data views coming from `trade-logistics-network`: it states that the data returned by the `GetBillOfLading` query made to the `shipmentcc` chaincode on the `tradelogisticschannel` channel requires as proof two signatures, one from a peer in the organization whose MSP ID is `ExporterMSP` and another from a peer in the organization whose MSP ID is `CarrierMSP`. + + You need to record this policy rule on your Fabric network's channel by invoking either the `CreateVerificationPolicy` function or the `UpdateVerificationPolicy` function on the Fabric Interoperation Chaincode that is already installed on that channel; use the former if you are recording a set of rules for the given `securityDomain` for the first time and the latter to overwrite a set of rules recorded earlier. In either case, the chaincode function will take a single argument, which is the policy in the form of a JSON string (make sure you escape the double quotes before sending the request to avoid parsing errors). As with the access control policy, you can do this in one of two ways: (1) writing a small piece of code in Layer-2 that invokes the contract using the Fabric SDK Gateway API, or (2) running a `peer chaincode invoke` command from within a Docker container built on the `hyperledger/fabric-tools` image. Either approach should be familiar to a Fabric practitioner. + + | Notes | + |:------| + | For any cross-network data request, make sure an access control policy is recorded in the _source network_ (`trade-logistics-network` in the above example) and a corresponding verification policy is recorded in the _destination network_ (`trade-finance-network` in the above example) before any relay request is triggered. | + +- **Local network security domain (membership) configuration**: + Recall the code snippet added to your application in the "Identity Administration" section. Exercise that code snippet, exposed either through a function API or an HTTP endpoint, to record the initial local membership for the relevant network channels. + +Your Fabric network is now up and running with the necessary Weaver components, and your network's channel's ledger is bootstrapped with the initial configuration necessary for cross-network interactions! diff --git a/docs/docs/weaver/getting-started/enabling-weaver-network/overview.md b/docs/docs/weaver/getting-started/enabling-weaver-network/overview.md new file mode 100644 index 0000000000..08473b624a --- /dev/null +++ b/docs/docs/weaver/getting-started/enabling-weaver-network/overview.md @@ -0,0 +1,19 @@ +--- +id: overview +title: Enabling Cacti Weaver in Existing DLT Applications Overview +sidebar_label: Overview +pagination_label: Enabling Cacti Weaver in Existing DLT Applications +pagination_prev: external/getting-started/interop/overview +--- + + + +If you have an existing DLT network and application suite built on any of the following platforms, follow the appropriate link below to understand how to adapt it to use Cacti-Weaver capabilities for cross-network interactions. + +* [Hyperledger Fabric](./fabric.md) +* [R3 Corda](./corda.md) +* [Hyperledger Besu](./besu.md) diff --git a/docs/docs/weaver/getting-started/guide.md b/docs/docs/weaver/getting-started/guide.md new file mode 100644 index 0000000000..81fab08518 --- /dev/null +++ b/docs/docs/weaver/getting-started/guide.md @@ -0,0 +1,34 @@ +--- +id: guide +title: Using Weaver +--- + + + +The easiest way to understand how Weaver works is to run it at a small scale: + +- First, [launch a set of basic test networks](./test-network/overview.md) built on Fabric, Corda and Besu. These networks offer the most basic capabilities of their DLT platforms and run toy applications (contracts and Layer-2) that can easily be tracked and debugged. You can launch these networks in one of several different ways: building Weaver components and dependencies locally or importing pre-built ones from Github packages, running core components in the host or in Docker containers. The choice depends on whether you just want to get these networks up and running or if you wish to customize the setup by modifying source code and configurations. +- Once the test networks are launched, you can test two distinct kinds of interoperation modes: + * [Data sharing](./interop/data-sharing.md): all combinations of Fabric and Corda networks supported + * [Asset exchange](./interop/asset-exchange/overview.md): all pairs of network types from {Fabric, Corda, Besu} are supported + * [Asset transfer](./interop/asset-transfer.md): all combinations of Fabric and Corda networks supported +- (To bring down the test networks, go back to the "Setup" pages and follow instructions in the respective "Teardown" sections.) +- After you run these tests and get a flavor of how the system and protocols work, you will be ready to move on to "real" networks, enhancing them with interoperation capabilities by incorporating Weaver into them. Check out the guidelines and templates for [Fabric](./enabling-weaver-network/fabric.md), [Corda](./enabling-weaver-network/corda.md), and [Besu](./enabling-weaver-network/besu.md) networks. + +If you wish to go further and understand Weaver specifics, dig into the code, or contribute to the open-source project, check out the [project repository](https://github.com/hyperledger/cacti/weaver). For specific information about individual Weaver components, see: + +- [Relay](https://github.com/hyperledger/cacti/blob/main/weaver/core/relay/README.md) module +- [Fabric](https://github.com/hyperledger/cacti/blob/main/weaver/core/drivers/fabric-driver/readme.md) and [Corda](https://github.com/hyperledger/cacti/blob/main/weaver/core/drivers/corda-driver/README.md) drivers +- [Fabric Interoperation Chaincode](https://github.com/hyperledger/cacti/blob/main/weaver/core/network/fabric-interop-cc/README.md), [Interoperation CorDapp](https://github.com/hyperledger/cacti/blob/main/weaver/core/network/corda-interop-app/README.md), and [Besu Interoperation Contract](https://github.com/hyperledger/cacti/blob/main/weaver/core/network/besu/README.md) +- Common [protobufs](https://github.com/hyperledger/cacti/tree/main/weaver/common/protos): compiled in [JavaScript](https://github.com/hyperledger/cacti/blob/main/weaver/common/protos-js/README.md), [Golang](https://github.com/hyperledger/cacti/blob/main/weaver/common/protos-go/README.md), [Java](https://github.com/hyperledger/cacti/blob/main/weaver/common/protos-java-kt/README.md), [Rust](https://github.com/hyperledger/cacti/blob/main/weaver/common/protos-rs/README.md) and [Solidity](https://github.com/hyperledger/cacti/blob/main/weaver/common/protos-sol/README.md) +- Fabric Interoperation SDKs in [Node.js](https://github.com/hyperledger/cacti/blob/main/weaver/sdks/fabric/interoperation-node-sdk/README.md) and [Golang](https://github.com/hyperledger/cacti/blob/main/weaver/sdks/fabric/go-sdk/readme.md) +- Corda Interoperation SDK in [Kotlin/Java](https://github.com/hyperledger/cacti/blob/main/weaver/sdks/corda/README.md) +- Besu Interoperation SDK in [Node.js](https://github.com/hyperledger/cacti/blob/main/weaver/sdks/besu/interoperation-node-sdk/README.md) +- Sample [Fabric](https://github.com/hyperledger/cacti/tree/main/weaver/samples/fabric) and [Corda](https://github.com/hyperledger/cacti/tree/main/weaver/samples/corda) applications for experimentation and testing +- [Fabric](https://github.com/hyperledger/cacti/blob/main/weaver/tests/network-setups/fabric/dev/README.md), [Corda](https://github.com/hyperledger/cacti/blob/main/weaver/tests/network-setups/corda/README.md), and [Besu](https://github.com/hyperledger/cacti/blob/main/weaver/tests/network-setups/besu/README.md) test network setups + +The Weaver [RFCs](https://github.com/hyperledger/cacti/blob/main/weaver/rfcs/README.md) contain detailed specifications of the models, data structures, protocols, and message formats. diff --git a/docs/docs/weaver/getting-started/interop/asset-exchange/besu-besu.md b/docs/docs/weaver/getting-started/interop/asset-exchange/besu-besu.md new file mode 100644 index 0000000000..0000224ead --- /dev/null +++ b/docs/docs/weaver/getting-started/interop/asset-exchange/besu-besu.md @@ -0,0 +1,144 @@ +--- +id: besu-besu +title: "Asset Exchange: Besu with Besu" +sidebar_label: Besu with Besu +pagination_label: Besu with Besu +pagination_prev: external/getting-started/interop/asset-exchange/overview +--- + +We divide this page into two sections, if you used default configuration in ledger initialization step, then go to section [AliceERC721 with BobERC20](#aliceerc721-with-boberc20), otherwise if you used hybrid tokens in `network`, then go to section [AliceERC1155 with BobERC20](#aliceerc1155-with-boberc20) + +| Notes | +|:------| +| The hash used in following steps can be replaced by any valid `SHA256` hash. | + +## AliceERC721 with BobERC20 + +One Besu network transfers an non-fungible `AliceERC721` token with id `0` from Alice to Bob in exchange for a transfer of `10 BobERC20` tokens from Bob to Alice in the other network. We will use account `1` for Alice and account `2` for Bob in both networks. + +Run the following steps: + +1. Navigate to the `weaver/samples/besu/besu-cli` folder in your clone of the Cacti repository. +2. Run the following to verify the status of the assets owned by `alice` and `bob` in the two networks: + ```bash + ./bin/besu-cli asset get-balance --network=network1 --account=1 + ./bin/besu-cli asset get-balance --network=network1 --account=2 + ./bin/besu-cli asset get-balance --network=network2 --account=1 + ./bin/besu-cli asset get-balance --network=network2 --account=2 + ``` +3. Generate Secret-Hash Pair using following command (prints hash in base64): + ``` + ./bin/besu-cli hash --hash_fn=SHA256 secrettext + ``` +4. Run the following to trigger `alice` locking `AliceERC721` token with id `0` for `bob` in `network1` for 1 hour + ```bash + ./bin/besu-cli asset lock --network=network1 --sender_account=1 --recipient_account=2 --token_id=0 --asset_type=ERC721 --timeout=3600 --hash_base64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs= + ``` + Value set to `hash_base64` argument corresponds to what was generated in Step 3. Note the `contract-id` printed as output in above command. The output line containing `contract-id` (text in base64 after `Lock contract ID:`) would like this: + ```bash + Lock contract ID: 48f59da2ac632117bf79b4aa986f5ece8a2439dc143d576965c17bc8275b0925 + ``` +5. Run the following to verify `alice`'s lock, replacing `` with actual `contract-id`: + ```bash + ./bin/besu-cli asset is-locked --network=network1 --lock_contract_id= + ``` +6. Run the following to trigger `bob` locking `10` units of `BobERC20` tokens for `alice` in `network2` for 30 mins: + ```bash + ./bin/besu-cli asset lock --network=network2 --sender_account=2 --recipient_account=1 --amount=10 --timeout=1800 --hash_base64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs= + ``` + Note the `contract-id` again for this lock printed as output in above command. Let's refer it `` for this demonstration. +7. Run the following to verify `bob`'s lock: + ```bash + ./bin/besu-cli asset is-locked --network=network2 --lock_contract_id= + ``` +8. Run the following to trigger `alice`'s claim for `10` units of `BobERC20` tokens locked by `bob` in `network2`: + ```bash + ./bin/besu-cli asset claim --network=network2 --recipient_account=1 --preimage=secrettext --lock_contract_id= + ``` +9. Run the following to trigger `bob`'s claim for `AliceERC721` NFT with id `0` locked by `alice` in `network1`: + ```bash + ./bin/besu-cli asset claim --network=network1 --recipient_account=2 --preimage=secrettext --token_id=0 --lock_contract_id= + ``` + +The above steps complete a successful asset exchange between two Besu networks. +In addition to the above commands, following commands can be run if specified timeout has expired and the locked asset remains unclaimed. + +- If `alice` wants to unlock the asset, run the following to trigger `alice`'s re-claim for `AliceERC721` NFT with id `0` locked in `network1`: + ```bash + ./bin/besu-cli asset unlock --network=network1 --lock_contract_id= --sender_account=1 --token_id=0 + ``` + +- If `bob` wants to unlock the token asset, run the following to trigger `bob`'s re-claim for `10 BobERC20` tokens locked in `network2`: + ```bash + ./bin/besu-cli asset unlock --network=network2 --lock_contract_id= --sender_account=2 + ``` + +## AliceERC1155 with BobERC20 + +One Besu network transfers an non-fungible `5 AliceERC1155` tokens with id `0` from Alice to Bob in exchange for a transfer of `50 BobERC20` tokens from Bob to Alice in the other network. We will use account `1` for Alice and account `2` for Bob in both networks. + +Run the following steps: + +1. Navigate to the `weaver/samples/besu/besu-cli` folder in your clone of the Cacti repository. +2. Run the following to verify the status of the assets owned by `alice` and `bob` in the two networks: + ```bash + ./bin/besu-cli asset get-balance --network=network1 --account=1 + ./bin/besu-cli asset get-balance --network=network1 --account=2 + ./bin/besu-cli asset get-balance --network=network2 --account=1 + ./bin/besu-cli asset get-balance --network=network2 --account=2 + ``` +3. Generate Secret-Hash Pair using following command (prints hash in base64): + ``` + ./bin/besu-cli hash --hash_fn=SHA256 secrettext + ``` +4. Run the following to trigger `alice` locking `5 AliceERC1155` token with id `0` for `bob` in `network1` for 1 hour + ```bash + ./bin/besu-cli asset lock --network=network1 --sender_account=1 --recipient_account=2 --amount=5 --token_id=0 --asset_type=ERC1155 --timeout=3600 --hash_base64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs= + ``` + Value set to `hash_base64` argument corresponds to what was generated in Step 3. Note the `contract-id` printed as output in above command. The output line containing `contract-id` (text in base64 after `Lock contract ID:`) would like this: + ```bash + Lock contract ID: 48f59da2ac632117bf79b4aa986f5ece8a2439dc143d576965c17bc8275b0925 + ``` +5. Run the following to verify `alice`'s lock, replacing `` with actual `contract-id`: + ```bash + ./bin/besu-cli asset is-locked --network=network1 --lock_contract_id= + ``` +6. Run the following to trigger `bob` locking `50` units of `BobERC20` tokens for `alice` in `network2`: + ```bash + ./bin/besu-cli asset lock --network=network2 --sender_account=2 --recipient_account=1 --amount=50 --timeout=3600 --hash_base64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs= + ``` + Note the `contract-id` again for this lock printed as output in above command. Let's refer it `` for this demonstration. +7. Run the following to verify `bob`'s lock: + ```bash + ./bin/besu-cli asset is-locked --network=network2 --lock_contract_id= + ``` +8. Run the following to trigger `alice`'s claim for `50` units of `BobERC20` tokens locked by `bob` in `network2`: + ```bash + ./bin/besu-cli asset claim --network=network2 --recipient_account=1 --preimage=secrettext --lock_contract_id= + ``` +9. Run the following to trigger `bob`'s claim for `5 AliceERC1155` tokens with id `0` locked by `alice` in `network1`: + ```bash + ./bin/besu-cli asset claim --network=network1 --recipient_account=2 --preimage=secrettext --token_id=0 --lock_contract_id= + ``` + +The above steps complete a successful asset exchange between two Besu networks. +In addition to the above commands, following commands can be run if specified timeout has expired and the locked asset remains unclaimed. + +- If `alice` wants to unlock the asset, run the following to trigger `alice`'s re-claim for `5 AliceERC1155` tokens with id `0` locked in `network1`: + ```bash + ./bin/besu-cli asset unlock --network=network1 --lock_contract_id= --sender_account=1 --token_id=0 + ``` + +- If `bob` wants to unlock the token asset, run the following to trigger `bob`'s re-claim for `50 BobERC20` tokens locked in `network2`: + ```bash + ./bin/besu-cli asset unlock --network=network2 --lock_contract_id= --sender_account=2 + ``` + +Run the following to verify the status of the assets owned by `alice` and `bob` in the two networks: +```bash +./bin/besu-cli asset get-balance --network=network1 --account=1 +./bin/besu-cli asset get-balance --network=network1 --account=2 +./bin/besu-cli asset get-balance --network=network2 --account=1 +./bin/besu-cli asset get-balance --network=network2 --account=2 +``` + diff --git a/docs/docs/weaver/getting-started/interop/asset-exchange/corda-besu.md b/docs/docs/weaver/getting-started/interop/asset-exchange/corda-besu.md new file mode 100644 index 0000000000..00daa3dc5b --- /dev/null +++ b/docs/docs/weaver/getting-started/interop/asset-exchange/corda-besu.md @@ -0,0 +1,79 @@ +--- +id: corda-besu +title: "Asset Exchange: Corda with Besu" +sidebar_label: Corda with Besu +pagination_label: Corda with Besu +pagination_prev: external/getting-started/interop/asset-exchange/overview +--- + +We will demonstrate asset exchange of an `AliceERC721` NFT in Besu `network1` with `10` tokens on `Corda_Network`. +For Besu commands, run from `weaver/weaver/samples/besu/besu-cli` folder, and for Corda commands, run from `samples/corda/corda-simple-application` folder, in your clone of the Cacti repository. Here `Alice` with account `1` and `Bob` with account `2` in Besu `network1` correspond to `PartyA` (`CORDA_PORT=10006`) and `PartyB` (`CORDA_PORT=10009`) in `Corda_Network` respectively. Following are the step-by-step asset exchange process: + +1. From corda client, generate secret-hash pair using following command (prints hash in base64): + ``` + ./clients/build/install/clients/bin/clients utils hash --hash-fn=SHA256 -s secrettext + ``` +2. Run the following to verify the status of the tokens owned by `PartyA` and `PartyB` in the `Corda_Network` and `Corda_Network2`: + ```bash + ./scripts/getAssetStatus.sh 2 + ``` +3. Run the following in `besu-cli`, to verify the status of the assets owned by `Alice` and `Bob` in the Besu networks: + ```bash + ./bin/besu-cli asset get-balance --network=network1 --account=1 + ./bin/besu-cli asset get-balance --network=network1 --account=2 + ``` +4. Complete the asset exchange using following steps: + - Run the following to trigger `alice` locking `AliceERC721` token with id `0` for `bob` in `network1` for 1 hour + ```bash + ./bin/besu-cli asset lock --network=network1 --sender_account=1 --recipient_account=2 --token_id=0 --asset_type=ERC721 --timeout=3600 --hash_base64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs= + ``` + Note the `contract-id` printed as output in above command. The output line containing `contract-id` (text in base64 after `Lock contract ID:`) would like this: + ```bash + Lock contract ID: 48f59da2ac632117bf79b4aa986f5ece8a2439dc143d576965c17bc8275b0925 + ``` + - Run the following to verify `alice`'s lock, replacing `` with actual `contract-id`: + ```bash + ./bin/besu-cli asset is-locked --network=network1 --lock_contract_id= + ``` + - Run the following to trigger `PartyB` locking `50` units of token type `t1` for `PartyA` in `Corda_Network` for 30 mins: + ```bash + CORDA_PORT=10009 ./clients/build/install/clients/bin/clients lock-asset --fungible --hashBase64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs= --timeout=1800 --recipient="O=PartyA,L=London,C=GB" --param=t1:50 + ``` + Note the `contract-id` displayed after successful execution of the command, will be used in next steps. The output containing `contract-id` would like this: + ```bash + HTLC Lock State created with contract ID Right(b=10448674_80d2bee7-5a5d-45df-b14e-60bac4ba1bf3). + ``` + `contract-id` is the alphanumeric text (with underscore and hyphens) after `b=` within parenthesis. Let's refer it `` for this demonstration. + - Run the following to verify `PartyB`'s lock (can be verified by both parties): + ```bash + CORDA_PORT=10006 ./clients/build/install/clients/bin/clients is-asset-locked --contract-id= + ``` + - Run the following to trigger `PartyA`'s claim for `50` units of token type `t1` locked by `PartyB` in `Corda_Network`: + ```bash + CORDA_PORT=10006 ./clients/build/install/clients/bin/clients claim-asset --secret=secrettext --contract-id= + ``` + `PartyB` can see its node's logs to get the revealed hash preimage, and use it to claim in the Besu network. + - Run the following to trigger `bob`'s claim for `AliceERC721` NFT with id `0` locked by `alice` in `network1`: + ```bash + ./bin/besu-cli asset claim --network=network1 --recipient_account=2 --preimage=secrettext --token_id=0 --lock_contract_id= + ``` + + The above steps complete a successful asset exchange between two Besu networks. + In addition to the above commands, following commands can be run if specified timeout has expired and the locked asset remains unclaimed. + - If `alice` wants to unlock the asset, run the following to trigger `alice`'s re-claim for `AliceERC721` NFT with id `0` locked in `network1`: + ```bash + ./bin/besu-cli asset unlock --network=network1 --lock_contract_id= --sender_account=1 --token_id=0 + ``` + - If `PartyB` wants to unlock the token asset, run the following to trigger unlock for `t1:50` locked in `Corda_Network`: + ```bash + CORDA_PORT=10009 ./clients/build/install/clients/bin/clients unlock-asset --contract-id= + ``` +5. Run the following to verify the status of the tokens owned by `PartyA` and `PartyB` in the `Corda_Network` and `Corda_Network2`: + ```bash + ./scripts/getAssetStatus.sh 2 + ``` +6. Run the following in `besu-cli`, to verify the status of the assets owned by `Alice` and `Bob` in the Besu networks: + ```bash + ./bin/besu-cli asset get-balance --network=network1 --account=1 + ./bin/besu-cli asset get-balance --network=network1 --account=2 + ``` diff --git a/docs/docs/weaver/getting-started/interop/asset-exchange/corda-corda.md b/docs/docs/weaver/getting-started/interop/asset-exchange/corda-corda.md new file mode 100644 index 0000000000..f4e5b5f6a3 --- /dev/null +++ b/docs/docs/weaver/getting-started/interop/asset-exchange/corda-corda.md @@ -0,0 +1,71 @@ +--- +id: corda-corda +title: "Asset Exchange: Corda with Corda" +sidebar_label: Corda with Corda +pagination_label: Corda with Corda +pagination_prev: external/getting-started/interop/asset-exchange/overview +--- + +We will demonstrate asset exchange of a tokens in `Corda_Network` with tokens on `Corda_Network2`. Here `PartyA` (`CORDA_PORT=10006`) and `PartyB` (`CORDA_PORT=10009`) in `Corda_Network` correspond to `PartyA` (`CORDA_PORT=30006`) and `PartyB` (`CORDA_PORT=30009`) in `Corda_Network2` respectively. Following are the step-by-step asset exchange process: + +| Notes | +|:------| +| The hash used in following steps can be replaced by any valid `SHA256` hash. | + +- Navigate to the `weaver/samples/corda/corda-simple-application` folder in your clone of the Cacti repository. +- Run the following to verify the status of the tokens owned by `PartyA` and `PartyB` in the `Corda_Network` and `Corda_Network2`: + ```bash + ./scripts/getAssetStatus.sh 2 + ``` +- Generate Secret-Hash Pair using following command (prints hash in base64): + ``` + ./clients/build/install/clients/bin/clients utils hash --hash-fn=SHA256 -s secrettext + ``` +- Run the following to trigger `PartyA` locking `30` units of token type `t1` for `PartyB` in `Corda_Network` for 60 mins: + ```bash + CORDA_PORT=10006 ./clients/build/install/clients/bin/clients lock-asset --fungible --hashBase64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs= --timeout=3600 --recipient="O=PartyB,L=London,C=GB" --param=t1:30 + ``` + Note the `contract-id` displayed after successful execution of the command, will be used in next steps. The output containing `contract-id` would like this: + ```bash + HTLC Lock State created with contract ID Right(b=10448674_80d2bee7-5a5d-45df-b14e-60bac4ba1bf3). + ``` + `contract-id` is the alphanumeric text (with underscore and hyphens) after `b=` within parenthesis. Let's denote it ``. +- Run the following to verify `PartyA`'s lock (can be verified by both parties): + ```bash + CORDA_PORT=10009 ./clients/build/install/clients/bin/clients is-asset-locked --contract-id= + ``` +- Run the following to trigger `PartyB` locking `50` units of token type `t2` for `PartyA` in `Corda_Network2` for 30 mins: + ```bash + CORDA_PORT=30009 ./clients/build/install/clients/bin/clients lock-asset --fungible --hashBase64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs= --timeout=1800 --recipient="O=PartyA,L=London,C=GB" --param=t2:50 + ``` + Note the `contract-id` displayed after successful execution of the command, will be used in next steps. Let's denote it ``. +- Run the following to verify `PartyB`'s lock (can be verified by both parties): + ```bash + CORDA_PORT=30006 ./clients/build/install/clients/bin/clients is-asset-locked --contract-id= + ``` +- Run the following to trigger `PartyA`'s claim for `50` units of token type `t2` locked by `PartyB` in `Corda_Network2`: + ```bash + CORDA_PORT=30006 ./clients/build/install/clients/bin/clients claim-asset --secret=secrettext --contract-id= + ``` + `PartyB` can see its node's logs to get the revealed hash preimage, and use it to claim the bond in the Fabric network. +- Run the following to trigger `PartyB`'s claim for `30` units of token type `t1` locked by `PartyA` in `Corda_Network`: + ```bash + CORDA_PORT=10009 ./clients/build/install/clients/bin/clients claim-asset --secret=secrettext --contract-id= + ``` +- Run the following to verify the status of the tokens owned by `PartyA` and `PartyB` in the `Corda_Network` and `Corda_Network2`: + ```bash + ./scripts/getAssetStatus.sh 2 + ``` + + +The above steps complete a successful asset exchange between two Corda networks. +In addition to the above commands, following commands can be run if specified timeout has expired and the locked asset remains unclaimed. + +- If `PartyA` wants to unlock the token `t1:30` asset, run the following to trigger `PartyA`'s re-claim in `Corda_Network`: + ```bash + CORDA_PORT=10006 ./clients/build/install/clients/bin/clients unlock-asset --contract-id= + ``` +- If `PartyB` wants to unlock the token `t2:50` asset, run the following to trigger `PartyB`'s re-claim in `Corda_Network2`: + ```bash + CORDA_PORT=30009 ./clients/build/install/clients/bin/clients unlock-asset --contract-id= + ``` diff --git a/docs/docs/weaver/getting-started/interop/asset-exchange/fabric-besu.md b/docs/docs/weaver/getting-started/interop/asset-exchange/fabric-besu.md new file mode 100644 index 0000000000..1694643df7 --- /dev/null +++ b/docs/docs/weaver/getting-started/interop/asset-exchange/fabric-besu.md @@ -0,0 +1,79 @@ +--- +id: fabric-besu +title: "Asset Exchange: Fabric with Besu" +sidebar_label: Fabric with Besu +pagination_label: Fabric with Besu +pagination_prev: external/getting-started/interop/asset-exchange/overview +--- + +We will demonstrate asset exchange of a bond in Fabric `network1` with `10 BobERC20` tokens on Besu `network2`. +For Fabric commands, run from `weaver/samples/fabric/fabric-cli` folder, and for Besu commands, run from `weaver/samples/besu/besu-cli` folder, in your clone of the Cacti repository. Here `Alice` and `Bob` in Fabric `network1` correspond to account `1` and account `2` in Besu `network2` respectively. Following are the step-by-step asset exchange process: + +| Notes | +|:------| +| The hash used in following steps can be replaced by any valid `SHA256` hash. | + +- From `fabric-cli`, generate secret-hash pair using following command (prints hash in base64): + ``` + ./bin/fabric-cli hash --hash_fn=SHA256 secrettext + ``` +- Run the following to verify the status of the bond assets owned by `alice` and `bob` in the Fabric network `network1` from `weaver/samples/fabric/fabric-cli` folder: + ```bash + ./scripts/getAssetStatus.sh + ``` +- Run the following in `besu-cli`, to verify the status of the assets owned by `Alice` and `Bob` in the Besu network `network2`: + ```bash + ./bin/besu-cli asset get-balance --network=network2 --account=1 + ./bin/besu-cli asset get-balance --network=network2 --account=2 + ``` +- Run the following to trigger `alice` locking `bond01:a03` for `bob` in `network1` for 60 mins: + ```bash + ./bin/fabric-cli asset exchange lock --timeout-duration=3600 --locker=alice --recipient=bob --hashBase64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs= --target-network=network1 --param=bond01:a03 + ``` +- Run the following to verify `alice`'s lock: + ```bash + ./bin/fabric-cli asset exchange is-locked --locker=alice --recipient=bob --target-network=network1 --param=bond01:a03 + ``` +- Run the following to trigger `bob` locking `10` units of `BobERC20` tokens for `alice` in `network2` for 30 mins: + ```bash + ./bin/besu-cli asset lock --network=network2 --sender_account=2 --recipient_account=1 --amount=10 --timeout=1800 --hash_base64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs= + ``` + Note the `contract-id` printed as output in above command. The output line containing `contract-id` (text in base64 after `Lock contract ID:`) would like this: + ```bash + Lock contract ID: 48f59da2ac632117bf79b4aa986f5ece8a2439dc143d576965c17bc8275b0925 + ``` + Let's refer it `` for this demonstration. + +- Run the following to verify `bob`'s lock: + ```bash + ./bin/besu-cli asset is-locked --network=network2 --lock_contract_id= + ``` +- Run the following to trigger `alice`'s claim for `10` units of `BobERC20` tokens locked by `bob` in `network2`: + ```bash + ./bin/besu-cli asset claim --network=network2 --recipient_account=1 --preimage=secrettext --lock_contract_id= + ``` +- Run the following to trigger `bob`'s claim for `bond01:a03` locked by `alice` in `network1`: + ```bash + ./bin/fabric-cli asset exchange claim --recipient=bob --locker=alice --target-network=network1 --param=bond01:a03 --secret=secrettext + ``` +- Run the following to verify the status of the bond assets owned by `alice` and `bob` in the Fabric network `network1` from `weaver/samples/fabric/fabric-cli` folder: + ```bash + ./scripts/getAssetStatus.sh + ``` +- Run the following in `besu-cli`, to verify the status of the assets owned by `Alice` and `Bob` in the Besu network `network2`: + ```bash + ./bin/besu-cli asset get-balance --network=network2 --account=1 + ./bin/besu-cli asset get-balance --network=network2 --account=2 + ``` + +The above steps complete a successful asset exchange between Fabric and Corda networks. +In addition to the above commands, following commands can be run if specified timeout has expired and the locked asset remains unclaimed. + +- If `alice` wants to unlock the bond asset, run the following to trigger `alice`'s re-claim for `bond01:a03` locked in `network1`: + ```bash + ./bin/fabric-cli asset exchange unlock --locker=alice --recipient=bob --target-network=network1 --param=bond01:a03 + ``` +- If `bob` wants to unlock the token asset, run the following to trigger `bob`'s re-claim for `50 BobERC20` tokens locked in `network2`: + ```bash + ./bin/besu-cli asset unlock --network=network2 --lock_contract_id= --sender_account=2 + ``` diff --git a/docs/docs/weaver/getting-started/interop/asset-exchange/fabric-corda.md b/docs/docs/weaver/getting-started/interop/asset-exchange/fabric-corda.md new file mode 100644 index 0000000000..5a76e173a4 --- /dev/null +++ b/docs/docs/weaver/getting-started/interop/asset-exchange/fabric-corda.md @@ -0,0 +1,77 @@ +--- +id: fabric-corda +title: "Asset Exchange: Fabric with Corda" +sidebar_label: Fabric with Corda +pagination_label: Fabric with Corda +pagination_prev: external/getting-started/interop/asset-exchange/overview +--- + +We will demonstrate asset exchange of a bond in Fabric `network1` with tokens on `Corda_Network`. +For Fabric commands, run from `weaver/samples/fabric/fabric-cli` folder, and for Corda commands, run from `weaver/samples/corda/corda-simple-application` folder, in your clone of the Cacti repository. Here `Alice` and `Bob` in Fabric `network1` correspond to `PartyA` (`CORDA_PORT=10006`) and `PartyB` (`CORDA_PORT=10009`) in `Corda_Network` respectively. Following are the step-by-step asset exchange process: + +| Notes | +|:------| +| The hash used in following steps can be replaced by any valid `SHA256` hash. | + +- Run the following to verify the status of the bond assets owned by `alice` and `bob` in the Fabric network `network1` from `weaver/samples/fabric/fabric-cli` folder: + ```bash + ./scripts/getAssetStatus.sh + ``` +- Run the following to verify the status of the assets owned by `PartyA` and `PartyB` in the `Corda_Network` from `weaver/samples/corda/corda-simple-application` folder: + ```bash + ./scripts/getAssetStatus.sh + ``` +- Generate Secret-Hash Pair using following command (prints hash in base64): + ``` + ./bin/fabric-cli hash --hash_fn=SHA256 secrettext + ``` +- Run the following to trigger `alice` locking `bond01:a03` for `bob` in `network1` for 60 mins: + ```bash + ./bin/fabric-cli asset exchange lock --timeout-duration=3600 --locker=alice --recipient=bob --hashBase64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs= --target-network=network1 --param=bond01:a03 + ``` +- Run the following to verify `alice`'s lock: + ```bash + ./bin/fabric-cli asset exchange is-locked --locker=alice --recipient=bob --target-network=network1 --param=bond01:a03 + ``` +- Run the following to trigger `PartyB` locking `50` units of token type `t1` for `PartyA` in `Corda_Network` for 30 mins: + ```bash + CORDA_PORT=10009 ./clients/build/install/clients/bin/clients lock-asset --fungible --hashBase64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs= --timeout=1800 --recipient="O=PartyA,L=London,C=GB" --param=t1:50 + ``` + Note the `contract-id` displayed after successful execution of the command, will be used in next steps. The output containing `contract-id` would like this: + ```bash + HTLC Lock State created with contract ID Right(b=10448674_80d2bee7-5a5d-45df-b14e-60bac4ba1bf3). + ``` + `contract-id` is the alphanumeric text (with underscore and hyphens) after `b=` within parenthesis. +- Run the following to verify `PartyB`'s lock (can be verified by both parties): + ```bash + CORDA_PORT=10006 ./clients/build/install/clients/bin/clients is-asset-locked --contract-id= + ``` +- Run the following to trigger `PartyA`'s claim for `50` units of token type `t1` locked by `PartyB` in `Corda_Network`: + ```bash + CORDA_PORT=10006 ./clients/build/install/clients/bin/clients claim-asset --secret=secrettext --contract-id= + ``` + `PartyB` can see its node's logs to get the revealed hash preimage, and use it to claim the bond in the Fabric network. +- Run the following to trigger `bob`'s claim for `bond01:a03` locked by `alice` in `network1`: + ```bash + ./bin/fabric-cli asset exchange claim --recipient=bob --locker=alice --target-network=network1 --param=bond01:a03 --secret=secrettext + ``` +- Run the following to verify the status of the bond assets owned by `alice` and `bob` in the Fabric network `network1` from `weaver/samples/fabric/fabric-cli` folder: + ```bash + ./scripts/getAssetStatus.sh + ``` +- Run the following to verify the status of the assets owned by `PartyA` and `PartyB` in the `Corda_Network` from `weaver/samples/corda/corda-simple-application` folder: + ```bash + ./scripts/getAssetStatus.sh + ``` + +The above steps complete a successful asset exchange between Fabric and Corda networks. +In addition to the above commands, following commands can be run if specified timeout has expired and the locked asset remains unclaimed. + +- If `alice` wants to unlock the bond asset, run the following to trigger `alice`'s re-claim for `bond01:a03` locked in `network1`: + ```bash + ./bin/fabric-cli asset exchange unlock --locker=alice --recipient=bob --target-network=network1 --param=bond01:a03 + ``` +- If `PartyB` wants to unlock the token asset, run the following to trigger unlock for `t1:50` locked in `Corda_Network`: + ```bash + CORDA_PORT=10009 ./clients/build/install/clients/bin/clients unlock-asset --contract-id= + ``` diff --git a/docs/docs/weaver/getting-started/interop/asset-exchange/fabric-fabric.md b/docs/docs/weaver/getting-started/interop/asset-exchange/fabric-fabric.md new file mode 100644 index 0000000000..72c0822fd2 --- /dev/null +++ b/docs/docs/weaver/getting-started/interop/asset-exchange/fabric-fabric.md @@ -0,0 +1,81 @@ +--- +id: fabric-fabric +title: "Asset Exchange: Fabric with Fabric" +sidebar_label: Fabric with Fabric +pagination_label: Fabric with Fabric +pagination_prev: external/getting-started/interop/asset-exchange/overview +--- + +One Fabric network transfers a bond from Alice to Bob in exchange for a transfer of tokens from Bob to Alice in the other network +Ensure that one of the following chaincodes have been deployed in both networks: + +* `simpleasset` +* `simpleassetandinterop` +* `simpleassettransfer` + +Run the following steps: + +| Notes | +|:------| +| The hash used in following steps can be replaced by any valid `SHA256` hash. | + +1. Navigate to the `weaver/samples/fabric/fabric-cli` (for the Node.js version) or the `weaver/samples/fabric/go-cli` (for the Golang version) folder in your clone of the Cacti repository. +2. Run the following to verify the status of the assets owned by `alice` and `bob` in the two networks: + ```bash + ./scripts/getAssetStatus.sh 2 + ``` +3. Complete the asset exchange in either of the two different ways: + * Using a single command: + - Run the following to trigger exchange of bond `bond01:a03` owned by `alice` in `network1` with `100` units of tokens `token1` owned by `bob` in `network2`: + ```bash + ./bin/fabric-cli asset exchange-all --network1=network1 --network2=network2 --secret=secrettext --timeout-duration=100 alice:bond01:a03:bob:token1:100 + ``` + - To verify that `bob` now owns a bond in exchange for `alice` owning some tokens, run the following: + ```bash + ./scripts/getAssetStatus.sh 2 + ``` + * Using step-by-step commands: + - Generate Secret-Hash Pair using following command (prints hash in base64): + ``` + ./bin/fabric-cli hash --hash_fn=SHA256 secrettext + ``` + - Run the following to trigger `alice` locking `bond01:a03` for `bob` in `network1` + ```bash + ./bin/fabric-cli asset exchange lock --timeout-duration=3600 --locker=alice --recipient=bob --hashBase64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs= --target-network=network1 --param=bond01:a03 + ``` + - Run the following to verify `alice`'s lock: + ```bash + ./bin/fabric-cli asset exchange is-locked --locker=alice --recipient=bob --target-network=network1 --param=bond01:a03 + ``` + - Run the following to trigger `bob` locking `100` units of `token1` for `alice` in `network2`: + ```bash + ./bin/fabric-cli asset exchange lock --fungible --timeout-duration=1800 --locker=bob --recipient=alice --hashBase64=ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs= --target-network=network2 --param=token1:100 + ``` + Note the `contract-id` printed as output in above command. The output line containing `contract-id` (text in base64 after `Contract Id:`) would like this: + ```bash + ℹ Fungible Asset Locked with Contract Id: E0JZq8Z+eS//2Bt4WU0pU210MvNgDC2hdUT1RgszOq0=, preimage: null, hashvalue: ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs= + ``` + - Run the following to verify `bob`'s lock: + ```bash + ./bin/fabric-cli asset exchange is-locked --fungible --locker=bob --recipient=alice --target-network=network2 --contract-id= + ``` + - Run the following to trigger `alice`'s claim for `100` units of `token1` locked by `bob` in `network2`: + ```bash + ./bin/fabric-cli asset exchange claim --fungible --recipient=alice --target-network=network2 --contract-id= --secret= + ``` + - Run the following to trigger `bob`'s claim for `bond01:a03` locked by `alice` in `network1`: + ```bash + ./bin/fabric-cli asset exchange claim --recipient=bob --locker=alice --target-network=network1 --param=bond01:a03 --secret= + ``` + + The above steps complete a successful asset exchange between two Fabric networks. + In addition to the above commands, following commands can be run if specified timeout has expired and the locked asset remains unclaimed. + + - If `alice` wants to unlock the bond asset, run the following to trigger `alice`'s re-claim for `bond01:a03` locked in `network1`: + ```bash + ./bin/fabric-cli asset exchange unlock --locker=alice --recipient=bob --target-network=network1 --param=bond01:a03 + ``` + - If `bob` wants to unlock the token asset, run the following to trigger `bob`'s re-claim for `token1:100` locked in `network2`: + ```bash + ./bin/fabric-cli asset exchange unlock --fungible --locker=bob --target-network=network2 --contract-id= + ``` diff --git a/docs/docs/weaver/getting-started/interop/asset-exchange/overview.md b/docs/docs/weaver/getting-started/interop/asset-exchange/overview.md new file mode 100644 index 0000000000..5b21b53b1c --- /dev/null +++ b/docs/docs/weaver/getting-started/interop/asset-exchange/overview.md @@ -0,0 +1,24 @@ +--- +id: overview +title: Asset Exchange +sidebar_label: Overview +pagination_label: Asset Exchange +pagination_prev: external/getting-started/interop/overview +--- + + + +This document lists sample ways in which you can exercise the asset-exchange interoperation protocol on the test network [launched earlier](external/getting-started/test-network/overview.md). + +For this scenario, you only need the networks to be running with the appropriate contracts deployed and the ledgers bootstrapped. You do not need to run relays, drivers and IIN agents. You can run the following combinations of exchanges (_other combinations of DLTs will be supported soon_). + +* [Fabric with Fabric](./fabric-fabric.md) +* [Fabric with Corda](./fabric-corda.md) +* [Fabric with Besu](./fabric-besu.md) +* [Corda with Corda](./corda-corda.md) +* [Corda with Besu](./corda-besu.md) +* [Besu with Besu](./besu-besu.md) diff --git a/docs/docs/weaver/getting-started/interop/asset-transfer.md b/docs/docs/weaver/getting-started/interop/asset-transfer.md new file mode 100644 index 0000000000..750e52833c --- /dev/null +++ b/docs/docs/weaver/getting-started/interop/asset-transfer.md @@ -0,0 +1,310 @@ +--- +id: asset-transfer +title: Asset Transfer +pagination_prev: external/getting-started/interop/overview +pagination_next: external/getting-started/enabling-weaver-network/overview +--- + + + +This document lists sample ways in which you can exercise the asset-transfer interoperation protocol on the test network [launched earlier](external/getting-started/test-network/overview.md). + +Once the networks, relays, and drivers have been launched, and the ledgers bootstrapped, you can trigger the following interoperation flows corresponding to distinct asset-sharing combinations _other combinations of DLTs will be supported soon_): + +## 1. Fabric with Fabric + +One Fabric network transfers either a bond or some tokens owned by Alice to Bob in the other network + +Assuming that the `simpleassettransfer` chaincode has been deployed in both networks, run the following steps by navigating to the `samples/fabric/fabric-cli` folder (_the Go CLI doesn't support asset transfer yet_). + +### Transfer or recover a bond (non-fungible) asset + +1. Verify that `alice` owns bonds with ids `a03` and `a04` as follows: + ```bash + ./bin/fabric-cli chaincode query --user=alice mychannel simpleassettransfer ReadAsset '["bond01","a03"]' --local-network=network1 + ./bin/fabric-cli chaincode query --user=alice mychannel simpleassettransfer ReadAsset '["bond01","a04"]' --local-network=network1 + ``` + You should see a JSON structure corresponding to the bond being logged on the console in each case. +2. Get `alice` in `network1` to pledge bond `a03` to `bob` in `network2` as follows (with a 1 hour timeout): + ```bash + ./bin/fabric-cli asset transfer pledge --source-network=network1 --dest-network=network2 --recipient=bob --expiry-secs=3600 --type=bond --ref=a03 --data-file=src/data/assetsForTransfer.json + ``` + You should see a message containing the unique ID of this pledge on the console as `Asset pledged with ID ` (`` is a hexadecimal string). +3. Get `bob` in `network2` to claim this bond asset as follows: + ```bash + ./bin/fabric-cli asset transfer claim --source-network=network1 --dest-network=network2 --user=bob --owner=alice --type='bond.fabric' --pledge-id= --param=bond01:a03 + ``` +4. Verify that `alice` in `network1` does not own this asset as follows: + ```bash + ./bin/fabric-cli chaincode query --user=alice mychannel simpleassettransfer ReadAsset '["bond01","a03"]' --local-network=network1 + ``` + You should see an error message like `Error: the asset a03 does not exist`. +5. Verify that `bob` in `network2` now owns this asset as follows: + ```bash + ./bin/fabric-cli chaincode query --user=bob mychannel simpleassettransfer ReadAsset '["bond01","a03"]' --local-network=network2 + ``` +6. Now get `alice` in `network1` to pledge bond `a04` to `bob` in `network2` as follows (with a 1 minute timeout): + ```bash + ./bin/fabric-cli asset transfer pledge --source-network=network1 --dest-network=network2 --recipient=bob --expiry-secs=60 --type=bond --ref=a04 --data-file=src/data/assetsForTransfer.json + ``` + Wait for a minute as follows: + ```bash + sleep 60 + ``` + You should see a message containing the unique ID of this pledge on the console as `Asset pledged with ID ` (`` is a hexadecimal string). +7. Now get `bob` in `network2` to claim this bond asset as follows: + ```bash + ./bin/fabric-cli asset transfer claim --source-network=network1 --dest-network=network2 --user=bob --owner=alice --type='bond.fabric' --pledge-id= --param=bond01:a04 + ``` + This should fail as the pledge has already expired. +8. Now get `alice` in `network1` to reclaim the asset as follows: + ```bash + ./bin/fabric-cli asset transfer reclaim --source-network=network1 --user=alice --type='bond.fabric' --pledge-id= --param=bond01:a04 + ``` +9. Verify that `alice` in `network1` owns this asset as follows: + ```bash + ./bin/fabric-cli chaincode query --user=alice mychannel simpleassettransfer ReadAsset '["bond01","a04"]' --local-network=network1 + ``` +10. Verify that `bob` in `network2` does not own this asset as follows: + ```bash + ./bin/fabric-cli chaincode query --user=bob mychannel simpleassettransfer ReadAsset '["bond01","a04"]' --local-network=network2 + ``` + You should see an error message like `Error: the asset a04 does not exist`. + +### Transfer or recover token (fungible) assets + +1. Verify that `alice` in `network1` owns `10000` tokens as follows: + ```bash + ./scripts/getTokenBalance.sh network1 alice + ``` +2. Verify that `bob` in `network2` owns no tokens as follows: + ```bash + ./scripts/getTokenBalance.sh network2 bob + ``` + You should see an error message like `Error: owner does not have a wallet`. +3. Get `alice` in `network1` to pledge 50 tokens to `bob` in `network2` as follows (with a 1 hour timeout): + ```bash + ./bin/fabric-cli asset transfer pledge --source-network=network1 --dest-network=network2 --recipient=bob --expiry-secs=3600 --type=token --units=50 --owner=alice --data-file=src/data/tokensForTransfer.json + ``` + You should see a message containing the unique ID of this pledge on the console as `Asset pledged with ID ` (`` is a hexadecimal string). +4. Get `bob` in `network2` to claim these tokens as follows (replace `` with the above hexadecimal value): + ```bash + ./bin/fabric-cli asset transfer claim --source-network=network1 --dest-network=network2 --user=bob --owner=alice --type='token.fabric' --pledge-id= --param=token1:50 + ``` +5. Verify that `alice` in `network1` owns `9950` tokens (after losing `50`) as follows: + ```bash + ./scripts/getTokenBalance.sh network1 alice + ``` +6. Verify that `bob` in `network2` now owns `50` tokens as follows: + ```bash + ./scripts/getTokenBalance.sh network2 bob + ``` +7. Now get `alice` in `network1` to pledge 100 tokens to `bob` in `network2` as follows (with a 1 minute timeout): + ```bash + ./bin/fabric-cli asset transfer pledge --source-network=network1 --dest-network=network2 --recipient=bob --expiry-secs=60 --type=token --units=100 --owner=alice --data-file=src/data/tokensForTransfer.json + ``` + Wait for a minute as follows: + ```bash + sleep 60 + ``` + You should see a message containing the unique ID of this pledge on the console as `Asset pledged with ID ` (`` is a hexadecimal string). +8. Now get `bob` in `network2` to claim these tokens as follows (replace `` with the above hexadecimal value): + ```bash + ./bin/fabric-cli asset transfer claim --source-network=network1 --dest-network=network2 --user=bob --owner=alice --type='token.fabric' --pledge-id= --param=token1:100 + ``` + This should fail as the pledge has already expired. +9. Now get `alice` in `network1` to reclaim these tokens as follows: + ```bash + ./bin/fabric-cli asset transfer reclaim --source-network=network1 --user=alice --type='token.fabric' --pledge-id= --param=token1:100 + ``` +10. Verify that `alice` in `network1` still owns `9950` tokens (after losing `50`) as follows: + ```bash + ./scripts/getTokenBalance.sh network1 alice + ``` +11. Verify that `bob` in `network2` still owns only `50` tokens as follows: + ```bash + ./scripts/getTokenBalance.sh network2 bob + ``` + +## 2. Corda with Corda +One Corda network transfers either a bond or some tokens owned by the party `PartyA` (`CORDA_PORT=10006`) to the party `PartyA` (`CORDA_PORT=30006`) in the other network. + +### Transfer or recover token (fungible) assets +Assume that the CorDapp `cordaSimpleApplication` has been deployed in both networks. + +- Navigate to the `weaver/samples/corda/corda-simple-application` folder in your clone of the Cacti repository. +- Add `5` tokens of type `t1` to `PartyA` in `Corda_Network`: + ```bash + NETWORK_NAME='Corda_Network' CORDA_PORT=10006 ./clients/build/install/clients/bin/clients issue-asset-state 5 t1 + ``` + (check token balance for `PartyA` by running the command `CORDA_PORT=10006 ./clients/build/install/clients/bin/clients get-asset-states-by-type t1`) + +- Let `PartyA` pledge these tokens in `Corda_Network` to be transferred to `PartyA` of `Corda_Network2` (pledge burns the tokens in the source/exporting network): + ```bash + NETWORK_NAME='Corda_Network' CORDA_PORT=10006 ./clients/build/install/clients/bin/clients transfer pledge-asset --fungible --timeout="3600" --import-network-id='Corda_Network2' --recipient='O=PartyA, L=London, C=GB' --param='t1:5' + ``` + Note the `pledge-id` displayed after successful execution of the command, which will be used in next steps. Let's denote it `` which is a hexadecimal string (pledge details can be cross checked using the commands `CORDA_PORT=10006 ./clients/build/install/clients/bin/clients transfer is-asset-pledged -pid ` and `CORDA_PORT=10006 ./clients/build/install/clients/bin/clients transfer get-pledge-state -pid `). + +- Check the token asset balance for `PartyA` in `Corda_Network` by running the below command, and the output should not include the asset `t1:5` issued earlier. + ```bash + CORDA_PORT=10006 ./clients/build/install/clients/bin/clients get-asset-states-by-type t1 + ``` +- Let `PartyA` claim in `Corda_Network2` the tokens which are pledged in the Corda network `Corda_Network` by replacing `` with the above hexadecimal value (claim issues the tokens in the destination/importing network): + ```bash + NETWORK_NAME='Corda_Network2' CORDA_PORT=30006 ./clients/build/install/clients/bin/clients transfer claim-remote-asset --pledge-id='' --locker='O=PartyA, L=London, C=GB' --transfer-category='token.corda' --export-network-id='Corda_Network' --param='t1:5' --import-relay-address='localhost:9082' + ``` + (the `linear-id`, which is displayed after successful execution of the above command, can be used to check the newly issued tokens for `PartyA` in `Corda_Network2` by running `CORDA_PORT=30006 ./clients/build/install/clients/bin/clients get-state-using-linear-id `; or simply check the token balance for `PartyA` by running the command `CORDA_PORT=30006 ./clients/build/install/clients/bin/clients get-asset-states-by-type t1` which should output `5` tokens of type `t1`) + +The above steps complete a successful asset transfer from the Corda network `Corda_Network` to the Corda network `Corda_Network2`. In addition to the above commands, following is an extra option. + +- Let `PartyA` in `Corda_Network` try re-claim the token `t1:5` asset, which will succeed only if the asset was not claimed by `PartyA` in `Corda_Network2` and the pledge has expired: + ```bash + NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients transfer reclaim-pledged-asset --pledge-id= --export-relay-address='localhost:9081' --transfer-category='token.corda' --import-network-id='Corda_Network2' --param='t1:5' + ``` + +### Transfer or recover bond (non-fungible) assets +Assume that the CorDapp `cordaSimpleApplication` has been deployed in both networks. + +- Navigate to the `weaver/samples/corda/corda-simple-application` folder in your clone of the Cacti repository. +- Add a bond asset with id `a10` and type `bond01` to `PartyA` in `Corda_Network`: + ```bash + NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients bond issue-asset 'a10' 'bond01' + ``` + (check token balance for `PartyA` by running the command `CORDA_PORT=10006 ./clients/build/install/clients/bin/clients bond get-assets-by-type 'bond01'`) + +- Let `PartyA` pledge these tokens in `Corda_Network` to be transferred to `PartyA` of `Corda_Network2` (pledge burns the tokens in the source/exporting network): + ```bash + NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients transfer pledge-asset --timeout="3600" --import-network-id='Corda_Network2' --recipient='O=PartyA, L=London, C=GB' --param='bond01:a10' + ``` + Note the `pledge-id` displayed after successful execution of the command, which will be used in next steps. Let's denote it `` which is a hexadecimal string (pledge details can be cross checked using the commands `CORDA_PORT=10006 ./clients/build/install/clients/bin/clients transfer is-asset-pledged -pid ` and `CORDA_PORT=10006 ./clients/build/install/clients/bin/clients transfer get-pledge-state -pid `). + +- Check the bond asset balance for `PartyA` in `Corda_Network` by running the below command, and the output should not include the asset `bond01:a10` issued earlier. + ```bash + CORDA_PORT=10006 ./clients/build/install/clients/bin/clients bond get-assets-by-type 'bond01'` + ``` +- Let `PartyA` in `Corda_Network2` claim the bond asset which is pledged in the Corda network `Corda_Network` by replacing `` with the above hexadecimal value (claim issues the bond asset in the destination/importing network): + ```bash + NETWORK_NAME=Corda_Network2 CORDA_PORT=30006 ./clients/build/install/clients/bin/clients transfer claim-remote-asset --pledge-id='' --locker='O=PartyA, L=London, C=GB' --transfer-category='bond.corda' --export-network-id='Corda_Network' --param='bond01:a10' --import-relay-address='localhost:9082' + ``` + (the `linear-id`, which is displayed after successful execution of the above command, can be used to check the newly issued bond asset for `PartyA` in `Corda_Network2` by running `CORDA_PORT=30006 ./clients/build/install/clients/bin/clients bond get-asset-by-linear-id `; or simply check the bond asset balance for `PartyA` by running the command `CORDA_PORT=30006 ./clients/build/install/clients/bin/clients bond get-assets-by-type 'bond01'` which should output asset with id `a10` and type `bond01`) + +The above steps complete a successful asset transfer from the Corda network `Corda_Network` to the Corda network `Corda_Network2`. In addition to the above commands, following is an extra option. + +- Let `PartyA` in `Corda_Network` try re-claim the bond asset `bond01:a10`, which will succeed only if the asset was not claimed by `PartyA` and the pledge has expired: + ```bash + NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients transfer reclaim-pledged-asset --pledge-id= --export-relay-address='localhost:9081' --transfer-category='bond.corda' --import-network-id='Corda_Network2' --param='bond01:a10' + ``` + +## 3. Fabric with Corda +A Fabric network transfers some tokens owned by `Alice` to `PartyA` (`CORDA_PORT=10006`) in a Corda network. + +### Transfer or recover token (fungible) assets + +Assuming that the `simpleassettransfer` chaincode has been deployed in Fabric network `network1`, run the following steps related to Fabric by navigating to the `samples/fabric/fabric-cli` folder (_the Go CLI doesn't support asset transfer yet_). + +Similarly, assuming that the CorDapp `cordaSimpleApplication` has been deployed in the Corda network `Corda_Network`, run the following steps related to Corda by navigating to the `samples/corda/corda-simple-application` folder. + +- Verify that `alice` in `network1` owns `10000` tokens as follows: + ```bash + ./scripts/getTokenBalance.sh network1 alice + ``` + +- Get `alice` in `network1` to pledge 50 tokens to `PartyA` in `Corda_Network` as follows (with a 1 hour timeout): + ```bash + ./bin/fabric-cli asset transfer pledge --source-network='network1' --dest-network='Corda_Network' --recipient='O=PartyA, L=London, C=GB' --expiry-secs=3600 --type='token' --units=50 --owner=alice --data-file=src/data/tokensForTransfer.json + ``` + You should see a message containing the unique ID of this pledge on the console as `Asset pledged with ID ` (`` is a hexadecimal string). + +- Verify that `alice` in `network1` owns `9950` tokens (after losing `50`) as follows: + ```bash + ./scripts/getTokenBalance.sh network1 alice + ``` + +- Let `PartyA` claim in `Corda_Network` the tokens which are pledged in the Fabric network `network1` by replacing `` with the above hexadecimal value (claim issues the tokens in the destination/importing network): + ```bash + NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients transfer claim-remote-asset --pledge-id='' --locker='alice' --transfer-category='token.fabric' --export-network-id='network1' --param='token1:50' --import-relay-address='localhost:9081' + ``` + (the `linear-id`, which is displayed after successful execution of the above command, can be used to check the newly issued tokens for `PartyA` in `Corda_Network` by running `CORDA_PORT=10006 ./clients/build/install/clients/bin/clients get-state-using-linear-id `; or simply check the token balance for `PartyA` by running the command `CORDA_PORT=10006 ./clients/build/install/clients/bin/clients get-asset-states-by-type token1` which should output `50` tokens of type `token1`) + +The above steps complete a successful asset transfer from the Fabric network `network1` to the Corda network `Corda_Network`. Below demostrates re-claim of the tokens pledged in the Fabric network after the pledge expiry. + +- Now get `alice` in `network1` to pledge 100 tokens to `PartyA` in `Corda_Network` as follows (with a 1 minute timeout): + ```bash + ./bin/fabric-cli asset transfer pledge --source-network='network1' --dest-network='Corda_Network' --recipient='O=PartyA, L=London, C=GB' --expiry-secs=60 --type=token --units=100 --owner=alice --data-file=src/data/tokensForTransfer.json + ``` + You should see a message containing the unique ID of this pledge on the console as `Asset pledged with ID ` (`` is a hexadecimal string). + + Wait for a minute as follows: + ```bash + sleep 60 + ``` + +- Let `PartyA` in `Corda_Network` claim the tokens which are pledged in the Fabric network `network1` by replacing `` with the above hexadecimal value (claim issues the tokens in the destination/importing network): + ```bash + NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients transfer claim-remote-asset --pledge-id='' --locker='alice' --transfer-category='token.fabric' --export-network-id='network1' --param='token1:100' --import-relay-address='localhost:9080' + ``` + This should fail as the pledge has already expired. + + (check the token balance for `PartyA` by running the command `CORDA_PORT=10006 ./clients/build/install/clients/bin/clients get-asset-states-by-type token1` which should still show `50` tokens of type `token1` but not `150`) + +- Now get `alice` in `network1` to reclaim these tokens as follows: + ```bash + ./bin/fabric-cli asset transfer reclaim --source-network='network1' --user='alice' --type='token.corda' --pledge-id= --param=token1:100 + ``` + +- Verify that `alice` in `network1` still owns `9950` tokens (after losing `50`) as follows: + ```bash + ./scripts/getTokenBalance.sh network1 alice + ``` + +## 4. Corda with Fabric +A Corda network transfers some tokens owned by `PartyA` (`CORDA_PORT=10006`) to `Alice` in a Fabric network. + +### Transfer or recover token (fungible) assets + +Assuming that the CorDapp `cordaSimpleApplication` has been deployed in the Corda network `Corda_Network`, run the following steps related to Corda by navigating to the `samples/corda/corda-simple-application` folder. + +Similarly, assume that the `simpleassettransfer` chaincode has been deployed in Fabric network `network1`, run the following steps related to Fabric by navigating to the `samples/fabric/fabric-cli` folder (_the Go CLI doesn't support asset transfer yet_). + +- Add `5` tokens of type `token1` to `PartyA` in `Corda_Network`: + ```bash + CORDA_PORT=10006 ./clients/build/install/clients/bin/clients issue-asset-state 5 token1 + ``` + (check token balance for `PartyA` by running the command `CORDA_PORT=10006 ./clients/build/install/clients/bin/clients get-asset-states-by-type token1`) + +- Let `PartyA` pledge (with a 1 hour timeout) these tokens in `Corda_Network` to be transferred to `Alice` of Fabric network `network1` (pledge burns the tokens in the source/exporting network): + ```bash + CORDA_PORT=10006 ./clients/build/install/clients/bin/clients transfer pledge-asset --fungible --timeout="3600" --import-network-id='network1' --recipient='alice' --param='token1:5' + ``` + Note the `pledge-id` displayed after successful execution of the command, which will be used in next steps. Let's denote it `` which is a hexadecimal string (pledge details can be cross checked using the commands `CORDA_PORT=10006 ./clients/build/install/clients/bin/clients transfer is-asset-pledged -pid ` and `CORDA_PORT=10006 ./clients/build/install/clients/bin/clients transfer get-pledge-state -pid `). + +- Check the token asset balance for `PartyA` in `Corda_Network` by running the below command, and the output should not include the asset `token1:5` issued earlier. + ``` + CORDA_PORT=10006 ./clients/build/install/clients/bin/clients get-asset-states-by-type token1` + ``` + +- Verify that `alice` in `network1` owns `10000` tokens as follows: + ```bash + ./scripts/getTokenBalance.sh network1 alice + ``` + +- Get `alice` in `network` to claim these tokens as follows (replace `` with the above hexadecimal value): + ```bash + ./bin/fabric-cli asset transfer claim --source-network='Corda_Network' --dest-network=network1 --user='alice' --owner='O=PartyA, L=London, C=GB' --type='token.corda' --pledge-id= --param=token1:5 + ``` + +- Verify that `alice` in `network` now owns `1050` tokens as follows: + ```bash + ./scripts/getTokenBalance.sh network1 alice + ``` + +The above steps complete a successful asset transfer from the Corda network `Corda_Network` to the Fabric network `network1`. In addition to the above commands, following is an extra option. + +- Let `PartyA` in `Corda_Network` try re-claim the token `token1:5` asset, which will succeed only if the asset was not claimed by `alice` in Fabric network and the pledge has expired (replace `` with the above hexadecimal value): + ```bash + NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients transfer reclaim-pledged-asset --pledge-id= --export-relay-address='localhost:9081' --transfer-category='token.fabric' --import-network-id='network1' --param='token1:5' + ``` diff --git a/docs/docs/weaver/getting-started/interop/data-sharing.md b/docs/docs/weaver/getting-started/interop/data-sharing.md new file mode 100644 index 0000000000..b7dc1f65f2 --- /dev/null +++ b/docs/docs/weaver/getting-started/interop/data-sharing.md @@ -0,0 +1,312 @@ +--- +id: data-sharing +title: Data Sharing +pagination_prev: external/getting-started/interop/overview +pagination_next: external/getting-started/enabling-weaver-network/overview +--- + + + +This document lists sample ways in which you can exercise the data-sharing interoperation protocol on the test network [launched earlier](external/getting-started/test-network/overview.md). + +Once the networks, relays, and drivers have been launched, and the ledgers bootstrapped, you can trigger four different interoperation flows corresponding to distinct data-sharing combinations as follows: + +1. **Corda to Corda**: Either Corda network requests state and proof from another Corda network +2. **Corda to Fabric**: The Corda network requests state and proof from either Fabric network +3. **Fabric to Corda**: Either Fabric network requests state and proof from the Corda network +4. **Fabric to Fabric**: One Fabric network requests state and proof from another Fabric network + +We assume that one of the following chaincodes have been deployed in either Fabric network you are testing with: + +* `simplestate` +* `simplestatewithacl` + +## Corda to Corda + +To test the scenario where `Corda_Network` requests the value of the state (key) `H` from `Corda_Network2` and writes the value to a key `H` in its local state, do the following: + +- (_Make sure the following are running_: `Corda_Network`, relay, and driver; `Corda_Network2`, relay, and driver) +- Navigate to the `weaver/samples/corda/corda-simple-application` folder in your clone of the Cacti repository. +- Run the following: + * If Relays and Drivers are deployed in the host machine: + - Without TLS: + ```bash + NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients request-state --wkey=H localhost:9081 localhost:9082/Corda_Network2/localhost:30006#com.cordaSimpleApplication.flow.GetStateByKey:H + ``` + - With TLS: + ```bash + RELAY_TLS=true RELAY_TLSCA_CERT_PATHS=../../../core/relay/credentials/fabric_ca_cert.pem NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients request-state --wkey=H localhost:9081 localhost:9082/Corda_Network2/localhost:30006#com.cordaSimpleApplication.flow.GetStateByKey:H + ``` + * If Relays and Drivers are deployed in Docker containers: + - Without TLS: + ```bash + NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients request-state --wkey=H localhost:9081 relay-corda2:9082/Corda_Network2/corda_network2_partya_1:10003#com.cordaSimpleApplication.flow.GetStateByKey:H + ``` + - With TLS: + ```bash + RELAY_TLS=true RELAY_TLSCA_CERT_PATHS=../../../core/relay/credentials/docker/ca-cert.pem NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients request-state --wkey=H localhost:9081 relay-corda2:9082/Corda_Network2/corda_network2_partya_1:10003#com.cordaSimpleApplication.flow.GetStateByKey:H + ``` + +- Query the value of the requested state using key `H` in `Corda_Network` by running the following command: + ```bash + NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients get-state H + ``` + +To test the scenario where `Corda_Network2` requests the value of the state (key) `C` from `Corda_Network` and writes the value to a key `C` in its local state, do the following: + +- (_Make sure the following are running_: `Corda_Network`, relay, and driver; `Corda_Network2`, relay, and driver) +- Navigate to the `weaver/samples/corda/corda-simple-application` folder in your clone of the Cacti repository. +- Run the following: + * If Relays and Drivers are deployed in the host machine: + - Without TLS: + ```bash + NETWORK_NAME=Corda_Network2 CORDA_PORT=30006 ./clients/build/install/clients/bin/clients request-state --wkey=C localhost:9082 localhost:9081/Corda_Network/localhost:10006#com.cordaSimpleApplication.flow.GetStateByKey:C + ``` + - With TLS: + ```bash + RELAY_TLS=true RELAY_TLSCA_CERT_PATHS=../../../core/relay/credentials/fabric_ca_cert.pem NETWORK_NAME=Corda_Network2 CORDA_PORT=30006 ./clients/build/install/clients/bin/clients request-state --wkey=C localhost:9082 localhost:9081/Corda_Network/localhost:10006#com.cordaSimpleApplication.flow.GetStateByKey:C + ``` + * If Relays and Drivers are deployed in Docker containers: + - Without TLS: + ```bash + NETWORK_NAME=Corda_Network2 CORDA_PORT=30006 ./clients/build/install/clients/bin/clients request-state --wkey=C localhost:9082 relay-corda:9081/Corda_Network/corda_partya_1:10003#com.cordaSimpleApplication.flow.GetStateByKey:C + ``` + - With TLS: + ```bash + RELAY_TLS=true RELAY_TLSCA_CERT_PATHS=../../../core/relay/credentials/docker/ca-cert.pem NETWORK_NAME=Corda_Network2 CORDA_PORT=30006 ./clients/build/install/clients/bin/clients request-state --wkey=C localhost:9082 relay-corda:9081/Corda_Network/corda_partya_1:10003#com.cordaSimpleApplication.flow.GetStateByKey:C + ``` + +- Query the value of the requested state, using the key `C` in `Corda_Network` by running the following command: + ```bash + NETWORK_NAME=Corda_Network2 CORDA_PORT=30006 ./clients/build/install/clients/bin/clients get-state C + ``` + +## Corda to Fabric + +To test the scenario where `Corda_Network` requests the value of the state (key) `a` from `network1` and writes the value to a key `a` in its local state, do the following: + +- (_Make sure the following are running_: Corda network, relay, and driver; Fabric `network1`, relay, and driver) +- Navigate to the `weaver/samples/corda/corda-simple-application` folder in your clone of the Cacti repository. +- Run the following: + * If Relays and Drivers are deployed in the host machine: + - Without TLS: + ```bash + NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients request-state --wkey=a localhost:9081 localhost:9080/network1/mychannel:simplestate:Read:a + ``` + - With TLS: + ```bash + RELAY_TLS=true RELAY_TLSCA_CERT_PATHS=../../../core/relay/credentials/fabric_ca_cert.pem NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients request-state --wkey=a localhost:9081 localhost:9080/network1/mychannel:simplestate:Read:a + ``` + * If Relays and Drivers are deployed in Docker containers: + - Without TLS: + ```bash + NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients request-state --wkey=a localhost:9081 relay-network1:9080/network1/mychannel:simplestate:Read:a + ``` + - With TLS: + ```bash + RELAY_TLS=true RELAY_TLSCA_CERT_PATHS=../../../core/relay/credentials/docker/ca-cert.pem NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients request-state --wkey=a localhost:9081 relay-network1:9080/network1/mychannel:simplestate:Read:a + ``` + +- Query the value of the requested state (key) `a` in `Corda_Network` using the following: + ```bash + NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients get-state a + ``` + +To test the scenario where `Corda_Network` requests the value of the state (key) `Arcturus` from `network2` and writes the value to a key `Arcturus` in its local state, do the following: + +- (_Make sure the following are running_: Corda network, relay, and driver; Fabric `network2`, relay, and driver) +- Navigate to the `weaver/samples/corda/corda-simple-application` folder in your clone of the Cacti repository. +- Run the following: + * If Relays and Drivers are deployed in the host machine: + - Without TLS: + ```bash + NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients request-state --wkey=Arcturus localhost:9081 localhost:9083/network2/mychannel:simplestate:Read:Arcturus + ``` + - With TLS: + ```bash + RELAY_TLS=true RELAY_TLSCA_CERT_PATHS=../../../core/relay/credentials/fabric_ca_cert.pem NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients request-state --wkey=Arcturus localhost:9081 localhost:9083/network2/mychannel:simplestate:Read:Arcturus + ``` + * If Relays and Drivers are deployed in Docker containers: + - Without TLS: + ```bash + NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients request-state --wkey=Arcturus localhost:9081 relay-network2:9083/network2/mychannel:simplestate:Read:Arcturus + ``` + - With TLS: + ```bash + RELAY_TLS=true RELAY_TLSCA_CERT_PATHS=../../../core/relay/credentials/docker/ca-cert.pem NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients request-state --wkey=Arcturus localhost:9081 relay-network2:9083/network2/mychannel:simplestate:Read:Arcturus + ``` + +- Query the value of the requested state (key) `Arcturus` in `Corda_Network` using the following: + ```bash + NETWORK_NAME=Corda_Network CORDA_PORT=10006 ./clients/build/install/clients/bin/clients get-state Arcturus + ``` + +| Notes | +|:------| +| You can test the above data transfer scenario with `Corda_Network2` instead of `Corda_Network` by changing the following in the `request-state` or `get-state` command:
  • Network name environment variable:
    • `NETWORK_NAME=Corda_Network` to `NETWORK_NAME=Corda_Network2`
  • Corda node's RPC endpoint port environment variable:
    • `CORDA_PORT=10006` to `CORDA_PORT=30006`
  • Local relay address
    • `localhost:9081` to `localhost:9082` (host deployment of relays and drivers)
    • `relay-corda2:9081` to `relay-corda2:9082` (Docker container deployment of relays and drivers)
| + +## Fabric to Corda + +To test the scenario where `network1` requests the value of the state (key) `H` from `Corda_Network` and writes the value to a key `H` in its local state, do the following: + +- (_Make sure the following are running_: Corda network, relay, and driver; Fabric `network1`, relay, and driver) +- Navigate to the `weaver/samples/fabric/fabric-cli` (for the Node.js version) or the `weaver/samples/fabric/go-cli` (for the Golang version) folder in your clone of the Cacti repository. +- (Make sure you have configured `fabric-cli` as per earlier instructions) +- Edit `chaincode.json`: in the `simplestate:Create:args` attribute, replace the argument `"a"` with `"H"` (this specifies the key to which the data from the remote view is to be written into); i.e.,: + ```json + "args": ["a", ""] + ``` + with + ```json + "args": ["H", ""] + ``` +- Run the following: + * If Relays and Drivers are deployed in the host machine: + - Without TLS: + ```bash + ./bin/fabric-cli interop --local-network=network1 --sign=true --requesting-org=Org1MSP localhost:9081/Corda_Network/localhost:10006#com.cordaSimpleApplication.flow.GetStateByKey:H --debug=true + ``` + - With TLS: + ```bash + ./bin/fabric-cli interop --local-network=network1 --sign=true --requesting-org=Org1MSP --relay-tls=true --relay-tls-ca-files=../../../core/relay/credentials/fabric_ca_cert.pem localhost:9081/Corda_Network/localhost:10006#com.cordaSimpleApplication.flow.GetStateByKey:H --debug=true + ``` + * If Relays and Drivers are deployed in Docker containers: + - Without TLS: + ```bash + ./bin/fabric-cli interop --local-network=network1 --sign=true --requesting-org=Org1MSP relay-corda:9081/Corda_Network/corda_partya_1:10003#com.cordaSimpleApplication.flow.GetStateByKey:H --debug=true + ``` + - With TLS: + ```bash + ./bin/fabric-cli interop --local-network=network1 --sign=true --requesting-org=Org1MSP --relay-tls=true --relay-tls-ca-files=../../../core/relay/credentials/docker/ca-cert.pem relay-corda:9081/Corda_Network/corda_partya_1:10003#com.cordaSimpleApplication.flow.GetStateByKey:H --debug=true + ``` + +- Query the value of the requested state (key) `H` in `network1` using the following: + ```bash + ./bin/fabric-cli chaincode query mychannel simplestate read '["H"]' --local-network=network1 + ``` + +To test the scenario where `network2` requests the value of the state (key) `H` from `Corda_Network` and writes the value to a key `H` in its local state, do the following: + +- (_Make sure the following are running_: Corda network, relay, and driver; Fabric `network2`, relay, and driver) +- Navigate to the `weaver/samples/fabric/fabric-cli` (for the Node.js version) or the `weaver/samples/fabric/go-cli` (for the Golang version) folder in your clone of the Cacti repository. +- (Make sure you have configured `fabric-cli` as per earlier instructions) +- Edit `chaincode.json`: in the `simplestate:Create:args` attribute, replace the argument `"a"` with `"H"` (this specifies the key to which the data from the remote view is to be written into); i.e.,: + ```json + "args": ["a", ""] + ``` + with + ```json + "args": ["H", ""] + ``` +- Run the following: + * If Relays and Drivers are deployed in the host machine: + - Without TLS: + ```bash + ./bin/fabric-cli interop --local-network=network2 --sign=true --requesting-org=Org1MSP localhost:9081/Corda_Network/localhost:10006#com.cordaSimpleApplication.flow.GetStateByKey:H --debug=true + ``` + - With TLS: + ```bash + ./bin/fabric-cli interop --local-network=network2 --sign=true --requesting-org=Org1MSP --relay-tls=true --relay-tls-ca-files=../../../core/relay/credentials/fabric_ca_cert.pem localhost:9081/Corda_Network/localhost:10006#com.cordaSimpleApplication.flow.GetStateByKey:H --debug=true + ``` + * If Relays and Drivers are deployed in Docker containers: + - Without TLS: + ```bash + ./bin/fabric-cli interop --local-network=network2 --sign=true --requesting-org=Org1MSP relay-corda:9081/Corda_Network/corda_partya_1:10003#com.cordaSimpleApplication.flow.GetStateByKey:H --debug=true + ``` + - With TLS: + ```bash + ./bin/fabric-cli interop --local-network=network2 --sign=true --requesting-org=Org1MSP --relay-tls=true --relay-tls-ca-files=../../../core/relay/credentials/docker/ca-cert.pem relay-corda:9081/Corda_Network/corda_partya_1:10003#com.cordaSimpleApplication.flow.GetStateByKey:H --debug=true + ``` + +- Query the value of the requested state (key) `H` in `network2` using the following: + ```bash + ./bin/fabric-cli chaincode query mychannel simplestate read '["H"]' --local-network=network2 + ``` + +| Notes | +|:------| +| You can test the above data transfer scenario with `Corda_Network2` instead of `Corda_Network` by changing the following in the view address (last parameter in the `interop` command):
  • Local relay address (prefix):
    • `localhost:9081` to `localhost:9082` (host deployment of relays and drivers)
    • `relay-corda2:9081` to `relay-corda2:9082` (Docker container deployment of relays and drivers)
  • Network name:
    • `Corda_Network` to `Corda_Network2`
  • Corda node's RPC endpoint:
    • `localhost:10006` to `localhost:30006` (host deployment of relays and drivers)
    • `corda_partya_1:10003` to `corda_network2_partya_1:10003` (Docker container deployment of relays and drivers)
| + +## Fabric to Fabric + +To test the scenario where `network1` requests the value of the state (key) `Arcturus` from `network2` and writes the value to a key `Arcturus` in its local state, do the following: + +- (_Make sure the following are running_: Fabric `network1`, relay, and driver; Fabric `network2`, relay, and driver) +- Navigate to the `weaver/samples/fabric/fabric-cli` (for the Node.js version) or the `weaver/samples/fabric/go-cli` (for the Golang version) folder in your clone of the Cacti repository. +- (Make sure you have configured `fabric-cli` as per earlier instructions) +- Edit `chaincode.json`: in the `simplestate:Create:args` attribute, replace the argument `"a"` with `"Arcturus"` (this specifies the key to which the data from the remote view is to be written into); i.e.,: + ```json + "args": ["a", ""] + ``` + with + ```json + "args": ["Arcturus", ""] + ``` +- Run the following: + * If Relays and Drivers are deployed in the host machine: + - Without TLS: + ```bash + ./bin/fabric-cli interop --local-network=network1 --requesting-org=Org1MSP localhost:9083/network2/mychannel:simplestate:Read:Arcturus + ``` + - With TLS: + ```bash + ./bin/fabric-cli interop --local-network=network1 --requesting-org=Org1MSP --relay-tls=true --relay-tls-ca-files=../../../core/relay/credentials/fabric_ca_cert.pem localhost:9083/network2/mychannel:simplestate:Read:Arcturus + ``` + * If Relays and Drivers are deployed in Docker containers: + - Without TLS: + ```bash + ./bin/fabric-cli interop --local-network=network1 --requesting-org=Org1MSP relay-network2:9083/network2/mychannel:simplestate:Read:Arcturus + ``` + - With TLS: + ```bash + ./bin/fabric-cli interop --local-network=network1 --requesting-org=Org1MSP --relay-tls=true --relay-tls-ca-files=../../../core/relay/credentials/docker/ca-cert.pem relay-network2:9083/network2/mychannel:simplestate:Read:Arcturus + ``` + +| Notes | +|:------| +| If you wish to enable end-to-end confidentiality for this data sharing session, add the `--e2e-confidentiality=true` switch to any of the above commands. For example: `./bin/fabric-cli interop --local-network=network1 --requesting-org=Org1MSP --e2e-confidentiality=true localhost:9083/network2/mychannel:simplestate:Read:Arcturus` | + +- Query the value of the requested state (key) `Arcturus` in `network1` using the following: + ```bash + ./bin/fabric-cli chaincode query mychannel simplestate read '["Arcturus"]' --local-network=network1 + ``` + +To test the scenario where `network2` requests the value of the state (key) `a` from `network1` and writes the value to a key `a` in its local state, do the following: + +- (_Make sure the following are running_: Fabric `network1`, relay, and driver; Fabric `network2`, relay, and driver) +- Navigate to the `weaver/samples/fabric/fabric-cli` (for the Node.js version) or the `weaver/samples/fabric/go-cli` (for the Golang version) folder in your clone of the Cacti repository. +- (Make sure you have configured `fabric-cli` as per earlier instructions) +- (There is no need to edit `chaincode.json` to change the key as the default argument `"a"` is what we intend to use in this data sharing use scenario.) +- Run the following: + * If Relays and Drivers are deployed in the host machine: + - Without TLS: + ```bash + ./bin/fabric-cli interop --local-network=network2 --requesting-org=Org1MSP localhost:9080/network1/mychannel:simplestate:Read:a + ``` + - With TLS: + ```bash + ./bin/fabric-cli interop --local-network=network2 --requesting-org=Org1MSP --relay-tls=true --relay-tls-ca-files=../../../core/relay/credentials/fabric_ca_cert.pem localhost:9080/network1/mychannel:simplestate:Read:a + ``` + * If Relays and Drivers are deployed in Docker containers: + - Without TLS: + ```bash + ./bin/fabric-cli interop --local-network=network2 --requesting-org=Org1MSP relay-network1:9080/network1/mychannel:simplestate:Read:a + ``` + - With TLS: + ```bash + ./bin/fabric-cli interop --local-network=network2 --requesting-org=Org1MSP --relay-tls=true --relay-tls-ca-files=../../../core/relay/credentials/docker/ca-cert.pem relay-network1:9080/network1/mychannel:simplestate:Read:a:173 + ``` + +| Notes | +|:------| +| If you wish to enable end-to-end confidentiality for this data sharing session, add the `--e2e-confidentiality=true` switch to any of the above commands. For example: `./bin/fabric-cli interop --local-network=network2 --requesting-org=Org1MSP --e2e-confidentiality=true localhost:9080/network1/mychannel:simplestate:Read:a` | + +- Query the value of the requested state (key) `a` in `network2` using the following: + ```bash + ./bin/fabric-cli chaincode query mychannel simplestate read '["a"]' --local-network=network2 + ``` + diff --git a/docs/docs/weaver/getting-started/interop/overview.md b/docs/docs/weaver/getting-started/interop/overview.md new file mode 100644 index 0000000000..a4305282ff --- /dev/null +++ b/docs/docs/weaver/getting-started/interop/overview.md @@ -0,0 +1,19 @@ +--- +id: overview +title: Testing Interoperation Modes Overview +sidebar_label: Overview +pagination_label: Testing Interoperation Modes +pagination_prev: external/getting-started/test-network/ledger-initialization +--- + + + +To test any of the interoperability modes supported by Weaver in test networks that have already been launched and bootstrapped, follow the appropriate link below. + +* [Data Sharing](./data-sharing.md) +* [Asset Exchange](./asset-exchange/overview.md) +* [Asset Transfer](./asset-transfer.md) diff --git a/docs/docs/weaver/getting-started/test-network/advanced-configuration.md b/docs/docs/weaver/getting-started/test-network/advanced-configuration.md new file mode 100644 index 0000000000..7034cd37c8 --- /dev/null +++ b/docs/docs/weaver/getting-started/test-network/advanced-configuration.md @@ -0,0 +1,127 @@ +--- +id: advanced-configuration +title: Advanced Configuration +--- + + + +You can configure the different components of the test network to use non-default parameter values for various settings (such as host names or port numbers). Here is a list of configurations you can tweak, classified by the DLT type. + +## Corda + +### Relay + +To run the relay on a different port from the default (`9081`), do the following: + +- Navigate to the `weaver/core/relay` folder in your clone of the Cacti repository. +- Update the `port` field in `config/Corda_Relay.toml`. +- To ensure that the relay of `network1` can communicate with this relay, update the `port` field in the `relays.Corda_Relay` section in `config/Fabric_Relay.toml` with the same value. +- To ensure that the relay of `network2` can communicate with this relay, update the `port` field in the `relays.Corda_Relay` section in `config/Fabric_Relay2.toml` with the same value. +- (You can update host names in similar locations, by adjusting the `hostname` field.) +- When you attempt a Fabric to Corda interoperation flow, use the new host name or port (instead of `localhost:9081`). + +### Driver + +To run the driver on a different port from the default (`9099`), do the following: + +- Navigate to the `weaver/core/drivers/corda-driver` folder in your clone of the Cacti repository. +- Set the environment variable `DRIVER_PORT` appropriately while running the executable as follows: + ```bash + DRIVER_PORT= ./build/install/corda-driver/bin/corda-driver + ``` + +To ensure that the relay can connect to this driver: + +- Navigate to the `weaver/core/relay` folder in your clone of the Cacti repository. +- Update the `port` field in the `drivers.Corda` section in `config/Corda_Relay.toml` with the same value. + +### Network + +| Notes | +|:------| +| In our sample setup, all the Corda nodes must be running on the same machine (`localhost` or some other) for seamless communication. | + +To change the ports the Corda nodes are listening on, do the following: + +- Navigate to the `weaver/tests/network-setups/corda` folder in your clone of the Cacti repository. +- Update the exposed ports in `docker-compose.yml` (defaults are `10003` for the `notary` container and `10006` for the `partya` container). +- Navigate to the `weaver/samples/corda/corda-simple-application` folder in your clone of the Cacti repository. +- Update the `CORDA_HOST` (default is `localhost`) and `CORDA_PORT` (default is `10006`) environment variables on your host machine to reflect the above update, or run the client bootstrapping script as follows: + ```bash + CORDA_HOST= CORDA_PORT= make initialise-vault + ``` +- When you attempt a Fabric to Corda interoperation flow, use the new host name and port values as in the following example (`network1` requesting `Corda_Network`): + ```bash + ./bin/fabric-cli interop --local-network=network1 --requesting-org=org1.network1.com localhost:9081/Corda_Network/:#com.cordaSimpleApplication.flow.GetStateByKey:H` + ``` + +### Client Application + +The config files used to initialise the network's verification policies, access control policies, and security group info, contain the address (host name and port) of the Corda node. + +To update the address of the Corda node, do the following: + +- Navigate to the `weaver/samples/corda/corda-simple-application` folder in your clone of the Cacti repository. +- Edit the `rules --> resource` field in line 7 in `clients/src/main/resources/config/FabricNetworkAccessControlPolicy.json` by replacing `localhost:10006` with `:` as specified in the previous section. + +## Fabric + +### Relay + +To run the relay on a different port from the default (`9080` for `network1` and `9083` for `network2`), do the following: + +- Navigate to the `weaver/core/relay` folder in your clone of the Cacti repository. +- Update the `port` field in `config/Fabric_Relay.toml` (for `network1`) or `config/Fabric_Relay2.toml` (for `network2`). +- To ensure Fabric-Fabric relay communication, update the foreign relay port in the `port` field in the `relays.Fabric_Relay` section in either of the above files. +- To ensure that the Corda network's relay can communicate with this relay, update the `port` field in the `relays.Fabric_Relay` section in `config/Corda_Relay.toml`. +- (You can update host names in similar locations, by adjusting the `hostname` field.) +- When you attempt a Fabric to Fabric or Corda to Fabric interoperation flow, use the new host name or port (instead of `localhost:9081` or `localhost:9083`). +- Navigate to the `weaver/core/drivers/fabric-driver` folder in your clone of the Cacti repository. +- Update the `RELAY_ENDPOINT` variable in `.env` or specify `RELAY_ENDPOINT=:` in the command line while running the driver using `npm run dev`. +- Navigate to the `weaver/samples/fabric/fabric-cli` folder in your clone of the Cacti repository. +- Update the `relayEndpoint` variables appropriately. + +### Driver + +The `fabric-driver` configuration can be controlled by environment variables either set in `.env` in the `weaver/core/drivers/fabric-driver` folder (or a copy if you created one) in your clone of the Cacti repository or passed in the command line when you run `npm run dev` to start the driver. The relevant variables you can control when you make any change to the setup are: + +- `CONNECTION_PROFILE`: this is the path to the connection profile. If you make changes to the network or use a different one, create a new connection profile and point to it using this variable. +- `RELAY_ENDPOINT`: this is the endpoint of the relay (hostname and port), and you can adjust it as described in the previous section; this is where the relay will be listening for incoming requests and from where the relay will channel foreign requests as well. +- `DRIVER_ENDPOINT`: this is the hostname and port the driver itself will bind to, and you can change it from the default (`localhost:9090` for `network1` and `localhost:9095` for `network2`) as per your need + +### Fabric CLI + +You can adjust settings for `fabric-cli` in the `.env` and `config.json` (in the `weaver/samples/fabric/fabric-cli` folder in your clone of the Cacti repository) as described earlier. + +Important environment variables (in `.env`) are: + +- `DEFAULT_CHANNEL`: this is the name of the channel the CLI will interact with. If you build a new channel or network, update the channel name here. +- `DEFAULT_CHAINCODE`: this is the name of the interoperaton chaincode the CLI will submit transactions and queries to for policy and security group bootstrapping. If you wish to test with a modified interoperation chaincode with a different name, update this value. +- `MEMBER_CREDENTIAL_FOLDER`: as described earlier, this is an absolute path that points to policies and security group info associated with foreign networks. You can adjust this info for the existing three networks or add credentials for another network you wish to test interoperation flows with. +- `LOCAL`: this is a boolean, indicating whether the network to connect to is running on (and as) `localhost` +- `DEFAULT_APPLICATION_CHAINCODE`: this is the name of the application chaincode which maintains information that can be shared (with proof) with other networks upon request using interoperation. You may write and deploy your own chaincode and use its name here instead of the default `simplestate`. +- `CONFIG_PATH`: this points to the JSON file containing the configurations of all the Fabric networks that need to be configured using the `fabric-cli`. + +The `config.json` (which can have a different name as long as you add the right reference to `.env` and configure `fabric-cli` suitably) has the following structure (it can have any number of networks specified): + +``` +{ + "network1": { + "connProfilePath": "", + "relayEndpoint": "" + }, + "network2": { + "connProfilePath": "", + "relayEndpoint": "" + } +} + +``` + +- `connProfilePath`: absolute path of the network's connection profile +- `relayEndpoint`: hostname and port of the particular network's relay (make sure you sync this with any changes made to that relay's configuration) + diff --git a/docs/docs/weaver/getting-started/test-network/ledger-initialization.md b/docs/docs/weaver/getting-started/test-network/ledger-initialization.md new file mode 100644 index 0000000000..f6c6fd3b3e --- /dev/null +++ b/docs/docs/weaver/getting-started/test-network/ledger-initialization.md @@ -0,0 +1,358 @@ +--- +id: ledger-initialization +title: Ledger Initialization +pagination_prev: external/getting-started/test-network/overview +pagination_next: external/getting-started/interop/overview +--- + + + +Once the two Fabric networks and the Corda network are up and running along with their associated relays and drivers, we must initialize states in those networks to prepare them for interoperation. For the Fabric networks, this involves recording state in the channel ledgers, and for the Corda network, in the nodes' vaults. The configuration and bootstrapping takes different form depending on what [interoperability mode](../../interoperability-modes.md) you wish to test. + +## Preparation for Data Sharing + +Follow the below instructions to prepare your networks for data sharing tests. + +### Initializing the Fabric Networks + +We use the Fabric CLI (`fabric-cli`) built earlier (in `weaver/samples/fabric/fabric-cli` for the Node.js version and `weaver/samples/fabric/go-cli` for the Golang version) for this purpose. + +#### Configuring the Fabric CLI + +During bootstrap, the ledgers in both `network1` and `network2` must be populated with the following information scoped by the interoperation chaincode: + +- Access control policies governing requests from foreign networks +- Security group info for foreign networks (i.e., identities of network units and their membership providers' certificate chains) +- Verification policies for proofs supplied by foreign networks + +Knowledge of foreign networks that must be configured in this stage is as follows: + +- `network1` has policies and security group info for `network2` and `Corda_Network` +- `network2` has policies and security group info for `network1` and `Corda_Network` + +(_`Corda_Network` will be launched later._) +The ledgers must also be populated with sample key-value pairs for testing interoperation flows, scoped by the sample application chaincode. + +Prepare `fabric-cli` for configuration suitably as follows. + +- Navigate to the `weaver/samples/fabric/fabric-cli` (for the Node.js version) or the `weaver/samples/fabric/go-cli` (for the Golang version) folder. +- Create a `config.json` file by copying the `config.template.json` and setting (or adding or removing) suitable values: + * For each network, the relay port and connection profile paths are specified using the keys `relayPort` and `connProfilePath` respectively. + - Replace `` with the absolute path location of the `weaver` folder within your Cacti repository clone. + - Otherwise, leave the default values unchanged. +- Create a `chaincode.json` file by copying the `chaincode.json.template` and leaving the default values unchanged. This file specified the arguments of the transaction to be locally invoked after fetching a remote view. +- Create a `.env` file by copying `.env.template` and setting the following parameter values: + * If Relays and Drivers are deployed in the host machine: + ``` + MEMBER_CREDENTIAL_FOLDER=/samples/fabric/fabric-cli/src/data/credentials + DEFAULT_APPLICATION_CHAINCODE= + DEFAULT_APPLICATION_FUNC= + CONFIG_PATH=./config.json + CHAINCODE_PATH=./chaincode.json + ``` + * If Relays and Drivers are deployed in the Docker containers: + ``` + MEMBER_CREDENTIAL_FOLDER=/samples/fabric/fabric-cli/src/data/credentials_docker + DEFAULT_APPLICATION_CHAINCODE= + DEFAULT_APPLICATION_FUNC= + CONFIG_PATH=./config.json + CHAINCODE_PATH=./chaincode.json + ``` + * In each case, replace `` with the absolute path location of the `weaver` folder within your Cacti repository clone and `` with the name of the deployed chaincode, either `simplestate` or `simplestatewithacl`. + * If `simplestate` is deployed, set `` to `Create`, and if `simplestatewithacl` if deployed, set `` to `CreateFromRemote`. + * Leave the default values unchanged for the other parameters. +- Run the following command: + ```bash + ./bin/fabric-cli env set-file ./.env + ``` +| Notes | +|:------| +| If the `CONFIG_PATH` environment variable is omitted from `.env`, then you must also run:
```./bin/fabric-cli config set-file ./config.json``` | + +#### Bootstrapping Network and Application State + +Finally, to prepare both `network1` and `network2` for interoperation, run: + +```bash +./bin/fabric-cli configure all network1 network2 +``` + +If Fabric networks were launched with 2 organizations, run: +```bash +./bin/fabric-cli configure all network1 network2 --num-orgs=2 +``` + +Instead, if you launched only one of the two Fabric networks, run the following after replacing `` with either `network1` or `network2`, and `<1/2>` with number of organizations in the network: +```bash +./bin/fabric-cli configure all --num-orgs=<1/2> +``` + +**Wait for at least 5 minutes before moving on to the next step (testing interoperability modes) to allow the networks' IIN Agents to sync their respective memberships (which occur after every 5 minutes by default).** + +**Optionally**, fabric-cli can be used to trigger sync manually by running following command: +```bash +./bin/fabric-cli configure membership --local-network=network1 --target-network=network2 --iin-agent-endpoint=localhost:9500 +``` +This command syncs `network2`'s membership (target-network) in `network1` (local-network) using IIN Agent of `Org1MSP` as initiator. Similarly `network1`'s membership can be synced to `network2`'s ledger by running: +```bash +./bin/fabric-cli configure membership --local-network=network2 --target-network=network1 --iin-agent-endpoint=localhost:9501 +``` +Wait for 20-30 seconds after above commands to allow IIN Agents to finish the sync. + +### Initializing the Corda Networks + +Once the Corda networks are launched, the client applications (built earlier) needs to be exercised to generate network (ledger) state in preparation to test interoperation flows. + +#### Bootstrapping Networks and Application States +Just as we did for either Fabric network, the Corda network ledger (or _vault_ on each node) must be initialized with access control policies, verification policies, and security group information for the two Fabric networks. Further, sample key-value pairs need to be recorded so we can later share them with a Fabric network via an interoperation flow. + +Bootstrap the Corda networks and application states as follows (_the following instructions will initialize either or both Corda networks, depending on which of those are up and running_): + +- Navigate to the `weaver/samples/corda/corda-simple-application` folder. +- Run the following: + * If Relays and Drivers are deployed in the host machine: + ```bash + make initialise-vault + ``` + * If Relays and Drivers are deployed in the Docker containers: + ```bash + make initialise-vault-docker + ``` +(Add a note about ignoring errors if only one of the two networks was launched, as the init command tries to initialize both networks.) + +### Next Steps + +The test networks are now configured and their ledgers are initialized. You can now run the [data sharing flows](../interop/data-sharing.md). + + +## Preparation for Asset Exchange + +Follow the below instructions to prepare your networks for asset exchange tests. + +### Initializing the Fabric Networks + +We use the Fabric CLI (`fabric-cli`) built earlier (in `weaver/samples/fabric/fabric-cli` for the Node.js version and `weaver/samples/fabric/go-cli` for the Golang version) for this purpose. + +#### Configuring the Fabric CLI + +The ledgers must be populated with sample key-value pairs for testing interoperation flows, scoped by the sample application chaincode. + +Prepare `fabric-cli` for configuration suitably as follows. + +- Navigate to the `weaver/samples/fabric/fabric-cli` (for the Node.js version) or the `weaver/samples/fabric/go-cli` (for the Golang version) folder. +- Create a `config.json` file by copying the `config.template.json` and setting (or adding or removing) suitable values: + * For each network, the relay port and connection profile paths are specified using the keys `relayPort` and `connProfilePath` respectively. + - Replace `` with the absolute path location of the `weaver` folder within your Cacti repository clone. + - Set the `chaincode` attribute in each network to the deployed chaincode name (`simpleasset` or `simpleassetandinterop` or `simpleassettransfer`). + - Otherwise, leave the default values unchanged. +- Create a `.env` file by copying `.env.template` and setting following parameter values: + * If Relays and Drivers are deployed in the host machine: + ``` + MEMBER_CREDENTIAL_FOLDER=/samples/fabric/fabric-cli/src/data/credentials + CONFIG_PATH=./config.json + ``` + * If Relays and Drivers are deployed in the Docker containers: + ``` + MEMBER_CREDENTIAL_FOLDER=/samples/fabric/fabric-cli/src/data/credentials_docker + CONFIG_PATH=./config.json + ``` + * In each case, replace `` with the absolute path location of the `weaver` folder within your Cacti repository clone. + * Leave the default values unchanged for the other parameters. +- Run the following command: + ```bash + ./bin/fabric-cli env set-file ./.env + ``` +| Notes | +|:------| +| If the `CONFIG_PATH` environment variable is omitted from `.env`, then you must also run:
```./bin/fabric-cli config set-file ./config.json``` | + +#### Bootstrapping Network and Application State + +Finally, to prepare both `network1` and `network2` for interoperation, run: + +```bash +./scripts/initAsset.sh +``` + +### Initializing the Corda Networks + +Corda Network needs to be initialized with assets for asset-exchange to be performed: +Bootstrap the Corda network and application states as follows: + +- Navigate to the `weaver/samples/corda/corda-simple-application` folder. +- Run the following: + - For `cordaSimpleApplication` app, run: + ``` + ./scripts/initAsset.sh + ``` + +### Initializing the Besu Networks + +Let's assume that `network1` can either manage NFT `AliceERC721` or Hybrid `AliceERC1155` tokens, while `network2` manages fungible `BobERC20` tokens. Here we use account `1` for Alice and account `2` for Bob in both neworks. To prepare Besu networks for asset exchange, navigate to the `weaver/samples/besu/besu-cli` and then follow the steps in next subsections. + +#### Configuring the Besu-CLI + +Create a `config.json` file by copying the `config.template.json`, keep the default values for managing `AliceERC721` tokens in `network1` and `BobERC20` tokens in `network2`. +If you want to change the token type used in the `network1` to Hybrid `AliceERC1155` tokens, in `config.json` update `tokenContract` field with value `"../simpleasset/build/contracts/AliceERC1155.json".` + +#### Bootstrapping Network and Application State + +Finally, to prepare both `network1` and `network2` for interoperation, run: + +* If you wish to test the default exchange (ERC-20 tokens for ERC-721 tokens), run:: + ```bash + ./scripts/initAsset.sh + ``` + This will issue `100 BobERC20` tokens to each account in `network2` and `AliceERC721` token with id `0` to `Alice` and id `1` to `Bob` in `network1`. +* Instead, if you wish to test Alice's exchange of ERC-1155 tokens for Bob's ERC-20 tokens, run: + ```bash + ./scripts/initAsset.sh hybrid + ``` + This will issue `100 BobERC20` tokens to each account in `network2` and `100 AliceERC1155` tokens with id `0` to `Alice` and id `1` to `Bob` in `network1`. + + +### Next Steps + +The test networks are now configured and their ledgers are initialized. You can now run the [asset exchange flows](../interop/asset-exchange/overview.md). + +## Preparation for Asset Transfer + +Follow the below instructions to prepare your networks for asset transfer tests. + +### Initializing the Fabric Networks + +We use the Fabric CLI (`fabric-cli`) built earlier (in `weaver/samples/fabric/fabric-cli` for the Node.js version and `weaver/samples/fabric/go-cli` for the Golang version) for this purpose. + +#### Configuring the Fabric CLI + +During bootstrap, the ledgers in both `network1` and `network2` must be populated with the following information scoped by the interoperation chaincode: + +- Access control policies governing requests from foreign networks +- Security group info for foreign networks (i.e., identities of network units and their membership providers' certificate chains) +- Verification policies for proofs supplied by foreign networks + +Knowledge of foreign networks that must be configured in this stage is as follows: + +- `network1` has policies and security group info for `network2` and `Corda_Network` +- `network2` has policies and security group info for `network1` and `Corda_Network` + +(_The Corda sample application doesn't support asset transfer yet, but there is no harm in including it above._) +The ledgers must also be populated with sample key-value pairs for testing interoperation flows, scoped by the sample application chaincode. + +Prepare `fabric-cli` for configuration suitably as follows. + +- Navigate to the `weaver/samples/fabric/fabric-cli` folder (_the Go CLI doesn't support asset transfer yet_). +- Create a `config.json` file by copying the `config.template.json` and setting (or adding or removing) suitable values: + * For each network, the relay port and connection profile paths are specified using the keys `relayPort` and `connProfilePath` respectively. + - Replace `` with the absolute path location of the `weaver` folder within your Cacti repository clone. + - Set the `chaincode` attribute in each network to `simpleassettransfer`. + - Set the `aclPolicyPrincipalType` attribute in `network2` to `ca`. + - Otherwise, leave the default values unchanged. +- Create `remote-network-config.json` file by copying `remote-network-config.json.template`. Use default values if relays and drivers are deployed in the host machine; else if they are deployed in Docker, update as follows: + * Update value for `relayEndpoint` for `network1` as `relay-network1:9080`. + * Update value for `relayEndpoint` for `network2` as `relay-network2:9083`. + * Update value for `relayEndpoint` for `Corda_Network` as `relay-corda:9081`. + * Update value for `relayEndpoint` for `Corda_Network2` as `relay-corda2:9082`. + * Update value for `partyEndPoint` for `Corda_Network` as `corda_partya_1:10003`. + * Update value for `partyEndPoint` for `Corda_Network2` as `corda_network2_partya_1:10003`. +- Create `chaincode.json` file by copying `chaincode.json.template`. Keep the default values unchanged. +- Create a `.env` file by copying `.env.template` and setting the following parameter values: + * If Relays and Drivers are deployed in the host machine: + ``` + MEMBER_CREDENTIAL_FOLDER=/samples/fabric/fabric-cli/src/data/credentials + DEFAULT_APPLICATION_CHAINCODE=simpleassettransfer + CONFIG_PATH=./config.json + REMOTE_CONFIG_PATH=./remote-network-config.json + CHAINCODE_PATH=./chaincode.json + ``` + * If Relays and Drivers are deployed in the Docker containers: + ``` + MEMBER_CREDENTIAL_FOLDER=/samples/fabric/fabric-cli/src/data/credentials_docker + DEFAULT_APPLICATION_CHAINCODE=simpleassettransfer + CONFIG_PATH=./config.json + REMOTE_CONFIG_PATH=./remote-network-config.json + CHAINCODE_PATH=./chaincode.json + ``` + * In each case, replace `` with the absolute path location of the `weaver` folder within your Cacti repository clone. + * Leave the default values unchanged for the other parameters. +- Run the following command: + ``` + ./bin/fabric-cli env set-file ./.env + ``` +| Notes | +|:------| +| If the `CONFIG_PATH` environment variable is omitted from `.env`, then you must also run:
```./bin/fabric-cli config set-file ./config.json``` | + +#### Bootstrapping Network and Application State + +Create appropriate access control and verification policies for `network1` and `network2` by running: + +```bash +./bin/fabric-cli configure create all --local-network=network1 +./bin/fabric-cli configure create all --local-network=network2 +``` + +Load access control and verification policies onto the ledgers of `network1` and `network2` by running (replace `<1/2>` with number of organizations in the network): + +```bash +./bin/fabric-cli configure network --local-network=network1 --num-orgs=<1/2> +./bin/fabric-cli configure network --local-network=network2 --num-orgs=<1/2> +``` + +**Wait for at least 5 minutes before moving on to the next step (testing interoperability modes) to allow the networks' IIN Agents to sync their respective memberships (which occur after every 5 minutes by default).** + +**Optionally**, fabric-cli can be used to trigger sync manually by running following command: +```bash +./bin/fabric-cli configure membership --local-network=network1 --target-network=network2 --iin-agent-endpoint=localhost:9500 +``` +This command syncs `network2`'s membership (target-network) in `network1` (local-network) using IIN Agent of `Org1MSP` as initiator. Similarly `network1`'s membership can be synced to `network2`'s ledger by running: +```bash +./bin/fabric-cli configure membership --local-network=network2 --target-network=network1 --iin-agent-endpoint=localhost:9501 +``` +Wait for 20-30 seconds after above commands to allow IIN Agents to finish the sync. + +Initialize bond and token asset states and ownerships on the `network1` ledger by running the following (this step will also create a user `alice` in `network1` and a user `bob` in `network2`): + +```bash +./scripts/initAssetsForTransfer.sh +``` + +### Initializing the Corda Networks + +Once the Corda networks (`Corda_Network` and `Corda_Network2`) are launched, the client applications (built earlier) needs to be exercised to generate ledger state in both exporting/source and importing/destination networks in preparation to test asset transfer interoperation flows. + +#### Bootstrapping Networks and Application States +The Corda network ledger (or _vault_ on each node) must be initialized with access control policies, verification policies, and security group information for the other networks (two Fabric networks and other Corda network). + +Bootstrap the Corda networks and application states as follows (_the following instructions will initialize either or both Corda networks, depending on which of those are up and running_): + +- Navigate to the `weaver/samples/corda/corda-simple-application` folder. +- Run the following: + ```bash + cp clients/src/main/resources/config/remote-network-config.json.template clients/src/main/resources/config/remote-network-config.json + ``` + Use default values in `remote-network-config.json` if relays and drivers are deployed in the host machine; else if they are deployed in Docker, update as follows: + * Update value for `relayEndpoint` for `network1` as `relay-network1:9080`. + * Update value for `relayEndpoint` for `network2` as `relay-network2:9083`. + * Update value for `relayEndpoint` for `Corda_Network` as `relay-corda:9081`. + * Update value for `relayEndpoint` for `Corda_Network2` as `relay-corda2:9082`. + * Update value for `partyEndPoint` for `Corda_Network` as `corda_partya_1:10003`. + * Update value for `partyEndPoint` for `Corda_Network2` as `corda_network2_partya_1:10003`. +- Run the following: + * If Relays and Drivers are deployed in the host machine: + ```bash + make initialise-vault-asset-transfer + ``` + * If Relays and Drivers are deployed in the Docker containers: + ```bash + make initialise-vault-asset-transfer-docker + ``` + +### Next Steps + +The test networks are now configured and their ledgers are initialized. You can now run the [asset transfer flows](../interop/asset-transfer.md). + diff --git a/docs/docs/weaver/getting-started/test-network/overview.md b/docs/docs/weaver/getting-started/test-network/overview.md new file mode 100644 index 0000000000..719f194103 --- /dev/null +++ b/docs/docs/weaver/getting-started/test-network/overview.md @@ -0,0 +1,42 @@ +--- +id: overview +title: Component Overview +--- + + + +Weaver offers a basic test network launching capability, both to demonstrate interoperation modes and to serve as a testbed for development and prototyping. Different modes (or scenarios) require different sets of components, but collectively you will need to run the following: + +- [Fabric testnet](https://github.com/hyperledger/cacti/tree/main/weaver/tests/network-setups/fabric/dev) - A pair of basic Fabric networks for testing interop flows +- [Corda testnet](https://github.com/hyperledger/cacti/tree/main/weaver/tests/network-setups/corda) - A pair of basic Corda networks for testing interop flows +- [Besu testnet](https://github.com/hyperledger/cacti/tree/main/weaver/tests/network-setups/besu) - A pair of basic Besu networks for testing interop flows +- [Relay](https://github.com/hyperledger/cacti/tree/main/weaver/core/relay) - The server module and protocol for cross-DLT interoperability. An instance of this is needed for every Fabric and Corda network +- [Fabric driver](https://github.com/hyperledger/cacti/tree/main/weaver/core/drivers/fabric-driver) - Driver used by the Fabric networks relay to communicate with the Fabric testnet +- [Corda driver](https://github.com/hyperledger/cacti/tree/main/weaver/core/drivers/corda-driver) - Driver used by the Corda networks relay to communicate with the Corda testnet +- [Fabric Interop chaincode](https://github.com/hyperledger/cacti/tree/main/weaver/core/network/fabric-interop-cc) - The Fabric interoperability contracts handle the dual process of servicing requests for views from external networks, and verifying requested views for integrity +- [Corda interop app](https://github.com/hyperledger/cacti/tree/main/weaver/core/network/corda-interop-app) CorDapp used to handle interop duties between the relay and the application +- [Besu interop contract](https://github.com/hyperledger/cacti/tree/main/weaver/core/network/besu/contracts/interop) Solidity smart contract(s) used to handle interop duties for a Besu network +- [Fabric client](https://github.com/hyperledger/cacti/tree/main/weaver/samples/fabric/fabric-cli) - Fabric client used to trigger interop flows initiated from the Fabric side and to manage Fabric state +- [Corda client app](https://github.com/hyperledger/cacti/tree/main/weaver/samples/corda/corda-simple-application) - CorDapp and client used to trigger interop flows initiated from the Corda side and to manage Corda state +- [Besu sample application](https://github.com/hyperledger/cacti/tree/main/weaver/samples/besu/simpleasset) - A sample application for asset exchange across two besu networks using HTLC +- [Besu client app](https://github.com/hyperledger/cacti/tree/main/weaver/samples/besu/besu-cli) - Besu client used to interact with the contracts deployed on the Besu testnet + +You can launch these components in one of several different ways: + +* **Setup with Locally Built Weaver Components**: + - [Deployed on Host Machine](./setup-local.md): Build the above components purely from your local clone of the Weaver code repository. If you wish to experiment with source code modifications, this is the right option to choose. + - [Deployed in Docker containers](./setup-local-docker.md): This is similar to the above option, except with relays and drivers launched in Docker containers rather than in the host. +* **Setup with Imported Weaver Components**: + - [Deployed on Host Machine](./setup-packages.md): Import pre-built Weaver components from GitHub Packages instead of building them locally. If you wish to see how Weaver works using pre-tested components and without, choose this option. + - [Deployed in Docker containers](./setup-packages-docker.md): This is similar to the above option, except with relays and drivers launched in Docker containers rather than in the host. + +After setting up and launching the components, you must initialize the network by following steps in [Ledger Initialization](./ledger-initialization.md). +Then you can test the following interoperation modes: + +- [Data Sharing](../interop/data-sharing.md) among Fabric and Corda networks +- [Asset Exchange](../interop/asset-exchange/overview.md) among Fabric, Corda, and Besu networks +- [Asset Transfer](../interop/asset-transfer.md) between Fabric networks diff --git a/docs/docs/weaver/getting-started/test-network/setup-local-docker.md b/docs/docs/weaver/getting-started/test-network/setup-local-docker.md new file mode 100644 index 0000000000..72e5e6b88f --- /dev/null +++ b/docs/docs/weaver/getting-started/test-network/setup-local-docker.md @@ -0,0 +1,561 @@ +--- +id: setup-local-docker +title: Setup with Locally Built Dockerized Weaver Components +pagination_prev: external/getting-started/test-network/overview +pagination_next: external/getting-started/test-network/ledger-initialization +--- + + + +In this document, we detail the steps using which you can bring up networks using the default configuration settings and by fetching pre-built Weaver interoperation modules, SDK libraries, and relay docker image, drivers docker images from GitHub Package repositories. To customize these settings (e.g., hostnames, ports), refer to the [Advanced Configuration page](./advanced-configuration.md). + +| Notes | +|:------| +| All components are run within Docker containers, except client applications. | + +Follow the instructions below to build and run components followed by interoperation flows. These instructions have been tested on Ubuntu Linux (bash shell) and Mac OS. In general, they should work on any system and shell as long as the various dependencies have been installed and configured. + +## Prerequisites + +### Software +Before starting, make sure you have the following software installed on your host machine: + +- Curl: _install using package manager, like `apt` on Debian/Ubuntu Linux_ +- Git: [sample instructions](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) +- Docker: [sample instructions](https://docs.docker.com/engine/install/) (Latest version) +- Docker-Compose: [sample instructions](https://docs.docker.com/compose/install/) (Version 1.28.2 or higher, but lower than version V2) +- Golang: [sample instructions](https://golang.org/dl/) (Version 1.16 or higher) +- Java (JDK and JRE): [sample instructions](https://openjdk.java.net/install/) (Version 8) +- Node.js and NPM: [sample instructions](https://nodejs.org/en/download/package-manager/) (Version 16 Supported) +- Yarn: [sample instructions](https://classic.yarnpkg.com/en/docs/install/) +- Protoc (Protobuf compiler): _Golang should already be installed and configured._ + * Default method: Run the following with `sudo` if necessary. This will install both the protobuf compiler and the Go code generator plugins. + ``` + apt-get install protobuf-compiler + go install google.golang.org/protobuf/cmd/protoc-gen-go + go install google.golang.org/grpc/cmd/protoc-gen-go-grpc + ``` + * If the above method installs an older version of `protoc` (check using `protoc --version`), say below 3.12.x, you should download pre-compiled binaries instead. (With an older version, you may see errors while attempting to launch and setup the Fabric networks). + ``` + sudo apt-get remove protobuf-compiler + curl -LO https://github.com/protocolbuffers/protobuf/releases/download/v3.15.6/protoc-3.15.6-linux-x86_64.zip + sudo apt-get install unzip + unzip protoc-3.15.6-linux-x86_64.zip -d + export PATH="$PATH:/bin" + go install google.golang.org/protobuf/cmd/protoc-gen-go + go install google.golang.org/grpc/cmd/protoc-gen-go-grpc + ``` + | Notes | + |:------| + | The latest version at present is `3.15.6`, but you should check the above link to find the most current version before running the above steps. | + +### Credentials +Make sure you have an SSH or GPG key registered in https://github.com to allow seamless cloning of repositories (at present, various setup scripts clone repositories using the `https://` prefix but this may change to `git@` in the future). + +## Getting the Code and Documentation + +Clone the [cacti](https://github.com/hyperledger/cacti) repository. The code to get a basic test network up and running and test data-sharing interoperation flows lies in the subfolder `weaver/tests/network-setups`, which should be your starting point, though the setups will rely on other parts of the repository, as you will find out in the instructions given on this page. + +## Common Structures + +The `weaver/common/protos` folder contains structure definitions in the protobuf format that are used by all the different components. The various `weaver/common/protos-*` folders are meant to contain compiled protobufs (in different languages). + +To compile the protobufs for JavaScript, do the following: + +- Navigate to the `weaver/common/protos-js` folder. +- Run the following command: + ```bash + make build + ``` + +To compile the protobufs for Golang, do the following: + +- Navigate to the `weaver/common/protos-go` folder. +- Run the following command: + ```bash + make build + ``` + +To compile the protobufs for Java and Kotlin, do the following: + +- Navigate to the `weaver/common/protos-java-kt` folder. +- Run the following command: + ```bash + make build + ``` + +To compile the protobufs for Solidity, do the following: + +- Navigate to the `weaver/common/protos-sol` folder. +- Run the following command: + ```bash + make build + ``` + +To compile the protobufs for Rust, do the following: + +- Navigate to the `weaver/common/protos-rs` folder. +- Run the following command: + ```bash + make build + ``` + +## Securing Components + +| Notes | +|:------| +| The relays and drivers corresponding to the different test networks you will encounter below can be run with or without TLS enabled. But the default files used in the demonstrations assume that either all relays and drivers are TLS-enabled or none are. Therefore, you should determine at the outset whether or not you wish to run the entire set of components in TLS-enabled mode, and select appropriate commands in the provided instructions. | + +## Hyperledger Fabric Components + +Using the sequence of instructions below, you can start two separate Fabric networks, each with a single channel and application contract (chaincode). You can also start an interoperation contract, a relay and a _driver_ acting on behalf of each network. You can build a Fabric CLI tool with which you can initialize both networks' ledgers with access control policies, foreign networks' security groups (i.e., membership providers' certificate chains), and some sample key-value pairs that can be shared during subsequent interoperation flows. + +### Fabric Interoperation Node SDK + +A client-layer library (companion to `hyperledger/fabric-sdk-node`) is defined in the `weaver/sdks/fabric/interoperation-node-sdk` folder. This contains functions for Fabric Gateway-based applications to exercise interoperation capabilities via relays and also several utility/helper functions. The Fabric-CLI tool, which we will use later, depends on this library. + +To build the library, do the following: + +- Navigate to the `weaver/sdks/fabric/interoperation-node-sdk` folder. +- Run the following command: + ```bash + make build-local + ``` + +### Fabric Network + +The code for this lies in the `weaver/tests/network-setups/fabric/` folder. + +This folder contains code to create and launch networks `network1` and `network2` of identical specifications: + +- Network: 1 peer, 1 peer CA, 1 ordering service node, 1 ordering service CA +- Single channel named `mychannel` +- One of the following contracts deployed on `mychannel`, the choice depending on the [interoperability mode](../../interoperability-modes.md) you wish to test: + * `simplestate` ([Data Sharing](../interop/data-sharing.md)): supports simple transactions (`Create`, `Read`, `Update`, `Delete`) involving storage and lookup of pairs. + * `simplestatewithacl` ([Data Sharing](../interop/data-sharing.md)): identical to `simplestate` but with extra security features to ensure that the Weaver infrastructure cannot be bypassed by a malicious client of the network. + * `simpleasset` ([Asset Exchange](../interop/asset-exchange/overview.md)): supports creation, modification, transfer, and deletion, as well as locking, unlocking, and claiming, of simple bonds and tokens (examples of non-fungible and fungible assets respectively). + * `simpleassetandinterop` ([Asset Exchange](../interop/asset-exchange/overview.md)): identical to `simpleasset` but where the locking, unlocking, and claiming logic is imported as a library in the chaincode rather than available in the common Fabric Interoperation Chaincode (a Weaver component). + * `simpleassettransfer` ([Asset Exchange](../interop/asset-exchange/overview.md) or [Asset Transfer](../interop/asset-transfer.md)): augmentation of `simpleasset` with asset pledging, claiming, and reclaiming features for cross-network transfers. + +| Notes | +|:------| +| For new users, we recommend testing the Data Sharing feature first with the `simplestate` contract. To test the other modes, you can simply [tear down](#tear-down-the-setup) the Fabric networks and restart them with the appropriate chaincodes installed. | + +Follow the instructions below to build and launch the networks: + +- Navigate to the `weaver/tests/network-setups/fabric/dev` folder. +- To spin up both network1 and network2 with the interoperation chaincode and the default `simplestate` chaincode installed, run: + ```bash + make start-interop-local + ``` +- _To launch the networks with a different application chaincode from the above list, run_: + ```bash + make start-interop-local CHAINCODE_NAME= + ``` +- _To launch the networks with 2 organizations, each with a peer (this will enable more variation and experimentation, which you can attempt after testing interoperation protocols across basic network configurations), run_: + ```bash + make start-interop-local PROFILE="2-nodes" + ``` + +| Notes | +|:------| +| If you do not wish to test Fabric-Fabric interoperation, you can choose to launch only one of the two networks along with its interoperation chaincode. For `network1`, run `make start-interop-network1-local`, and for `network2`, run `make start-interop-network2-local` | +| If you wish to enable end-to-end confidentiality by default in the interoperation modules that are deployed during network launch, set the environment variable `E2E_CONFIDENTIALITY` to `true` in the command line as follows: `E2E_CONFIDENTIALITY=true make start-interop-local` | + +For more information, refer to the associated [README](https://github.com/hyperledger/cacti/tree/main/weaver/tests/network-setups/fabric/dev). + +**Troubleshooting Tips**: + +- If you see any errors during the launches, re-check the prerequisites (software installations and credentials). Ensure your network connection is working. As a safe bet, you can retry after cleanup: kill and remove all Docker containers and associated volumes. +- If `protoc` or `protoc-gen-go` throws an error, reinstall `protoc` and `protoc-gen-go` using suggestions made in the Prerequisites section above. + +### Fabric Relay + +The relay is a module acting on behalf of a network, enabling interoperation flows with other networks by communicating with their relays. +The code for this lies in the `weaver/core/relay` folder. Navigate to the `weaver/core/relay` folder. + +#### Building Relay Image + +To build the docker image for relay, run: +```bash +make build-server-local +``` + +#### Deployment + +* The `docker-compose.yaml` in this folder is minimally configured with default values. To modify it for use with the Fabric testnets, run: + ```bash + make convert-compose-method2 + ``` +* The `.env.n1` and `.env.n1.tls` files in the `docker/testnet-envs` directory contain environment variables used by the `network1` relay at startup and runtime. Edit either of these files (depending on whether you wish to start the relay with or without TLS), and update the following value: + ``` + DOCKER_IMAGE_NAME=cacti-weaver-relay-server + ``` +* Repeat the above step for `.env.n2` or `.env.n2.tls` in `docker/testnet-envs` directory, which contain environment variables for the `network2` relay. +* To deploy the relay server for `network1` without TLS, run: + ```bash + make start-server COMPOSE_ARG='--env-file docker/testnet-envs/.env.n1' + ``` + Instead, to deploy the relay server with TLS, run: + ```bash + make start-server COMPOSE_ARG='--env-file docker/testnet-envs/.env.n1.tls' + ``` +* To deploy the relay server for `network2` without TLS, run: + ```bash + make start-server COMPOSE_ARG='--env-file docker/testnet-envs/.env.n2' + ``` + Instead, to deploy the relay server with TLS, run: + ```bash + make start-server COMPOSE_ARG='--env-file docker/testnet-envs/.env.n2.tls' + ``` +* After launching the relay(s), you can revert the `docker-compose.yaml` changes by running: + ```bash + make convert-compose-method1 + ``` + +For more information, see the [relay-docker README](https://github.com/hyperledger/cacti/tree/main/weaver/core/relay/relay-docker.md). + +### Fabric Driver + +A driver is a DLT-specific plugin invoked by the relay while channelling external data queries to the local peer network and collecting a response with proofs. The Fabric driver is built as a Fabric client application on the `fabric-network` NPM package. +The code for this lies in the `weaver/core/drivers/fabric-driver` folder. Navigate to the `weaver/core/drivers/fabric-driver` folder. + +#### Building + +To build the fabric-driver image, run: +```bash +make build-image-local +``` + +#### Deployment + +Use the following steps to run Fabric drivers in Docker containers: + +* The `.env.n1` and `.env.n1.tls` files in the `docker-testnet-envs` directory contain environment variables used by the `network1` driver at startup and runtime. Edit either of these files (depending on whether you wish to start the relay with or without TLS) as follows: + - Replace `` with the absolute path of the `weaver` folder within your Cacti repository clone. + - Update the following value: + ``` + DOCKER_IMAGE_NAME=cacti-weaver-driver-fabric + ``` +* Repeat the above steps for `.env.n2` or `.env.n2.tls` in `docker-testnet-envs` directory, which contain environment variables for the `network2` driver. +* To deploy the Fabric driver for `network1` without TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet-envs/.env.n1' NETWORK_NAME=$(grep NETWORK_NAME docker-testnet-envs/.env.n1 | cut -d '=' -f 2) + ``` + Instead, to deploy the driver with TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet-envs/.env.n1.tls' NETWORK_NAME=$(grep NETWORK_NAME docker-testnet-envs/.env.n1.tls | cut -d '=' -f 2) + ``` +* To deploy the Fabric driver for `network2` without TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet-envs/.env.n2' NETWORK_NAME=$(grep NETWORK_NAME docker-testnet-envs/.env.n2 | cut -d '=' -f 2) + ``` + Instead, to deploy the driver with TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet-envs/.env.n2.tls' NETWORK_NAME=$(grep NETWORK_NAME docker-testnet-envs/.env.n2.tls | cut -d '=' -f 2) + ``` + +### Fabric IIN Agent + +IIN Agent is a client of a member of a DLT network or security domain with special permissions to update security domain identities and configurations on the ledger via the network's interoperation module. The code for this lies in the `weaver/core/identity-management/iin-agent` folder. Navigate to the `weaver/core/identity-management/iin-agent` folder. + +#### Building + +To build the IIN Agent image, run: +```bash +make build-image-local +``` + +#### Deployment + +Use the following steps to run Fabric IIN Agents in Docker containers: +* The `.env.n1.org1` and `.env.n1.org1.tls` files in the `docker-testnet/envs` directory contain environment variables used by the iin-agent of `org1` of `network1` at startup and runtime. Edit either of these files (depending on whether you wish to start the relay with or without TLS) as follows: + - Replace `` with the absolute path of the `weaver` folder within your Cacti repository clone. + - Update the following value: + ``` + DOCKER_IMAGE_NAME=cacti-weaver-iin-agent + ``` + - If Fabric network was started with 1 org, and IIN Agents are to be started with TLS enabled, update the `DNS_CONFIG_PATH` variable as: + ``` + DNS_CONFIG_PATH=./docker-testnet/configs/dnsconfig-tls.json + ``` + - If Fabric network was started with 2 orgs, and IIN Agents are to be started without TLS, update the `DNS_CONFIG_PATH` variable as + ``` + DNS_CONFIG_PATH=./docker-testnet/configs/dnsconfig-2-nodes.json + ``` + - If Fabric network was started with 2 orgs and IIN Agents are to be started with TLS enabled, update the `DNS_CONFIG_PATH` variable as: + ``` + DNS_CONFIG_PATH=./docker-testnet/configs/dnsconfig-tls-2-nodes.json + ``` +* Repeat the above steps for all other environment variable files (depending upon whether tls is enabled) in `docker-testnet/envs` directory. +* To deploy the Fabric IIN Agent for `org1` of `network1` without TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet/envs/.env.n1.org1' DLT_SPECIFIC_DIR=$(grep DLT_SPECIFIC_DIR docker-testnet/envs/.env.n1.org1 | cut -d '=' -f 2) + ``` + Instead, to deploy the IIN Agent with TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet/envs/.env.n1.org1.tls' DLT_SPECIFIC_DIR=$(grep DLT_SPECIFIC_DIR docker-testnet/envs/.env.n1.org1.tls | cut -d '=' -f 2) + ``` +* To deploy the Fabric IIN Agent for `org2` of `network1` without TLS (_only required if Fabric network was started with 2 orgs_), run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet/envs/.env.n1.org2' DLT_SPECIFIC_DIR=$(grep DLT_SPECIFIC_DIR docker-testnet/envs/.env.n1.org2 | cut -d '=' -f 2) + ``` + Instead, to deploy the IIN Agent with TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet/envs/.env.n1.org2.tls' DLT_SPECIFIC_DIR=$(grep DLT_SPECIFIC_DIR docker-testnet/envs/.env.n1.org2.tls | cut -d '=' -f 2) + ``` +* To deploy the Fabric IIN Agent for `org1` of `network2` without TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet/envs/.env.n2.org1' DLT_SPECIFIC_DIR=$(grep DLT_SPECIFIC_DIR docker-testnet/envs/.env.n2.org1 | cut -d '=' -f 2) + ``` + Instead, to deploy the IIN Agent with TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet/envs/.env.n2.org1.tls' DLT_SPECIFIC_DIR=$(grep DLT_SPECIFIC_DIR docker-testnet/envs/.env.n2.org1.tls | cut -d '=' -f 2) + ``` +* To deploy the Fabric IIN Agent for `org2` of `network2` without TLS (_only required if Fabric network was started with 2 orgs_), run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet/envs/.env.n2.org2' DLT_SPECIFIC_DIR=$(grep DLT_SPECIFIC_DIR docker-testnet/envs/.env.n2.org2 | cut -d '=' -f 2) + ``` + Instead, to deploy the IIN Agent with TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet/envs/.env.n2.org2.tls' DLT_SPECIFIC_DIR=$(grep DLT_SPECIFIC_DIR docker-testnet/envs/.env.n2.org2.tls | cut -d '=' -f 2) + ``` + +### Fabric Client (Application) + +The CLI is used to interact with a Fabric network, configure it and run chaincode transactions to record data on the channel ledger or query data. It is also used to interact with remote networks through the relay in order to trigger an interoperation flow for data request and acceptance. + +The `fabric-cli` Node.js source code is located in the `weaver/samples/fabric/fabric-cli` folder and the Golang source code in the `weaver/samples/fabric/go-cli` folder. + +#### Prerequisites + +If you are using a Linux system, make sure that lib64 is installed. + +| Notes | +|:------| +| For the Node.js version of the `fabric-cli`, the setup and running instructions below were tested with all Node.js versions from v11.14.0 to v14.17.3. | + +#### Installation + +You can install `fabric-cli` as follows (for both the Node.js and Golang versions): + +- Navigate to the `weaver/samples/fabric/fabric-cli` folder (for the Node.js version) or the `weaver/samples/fabric/go-cli` (for the Golang version) folder. +- Run the following to install dependencies (for the Node.js version) or the executable (for the Golang version): + ```bash + make build-local + ``` +- Use the `fabric-cli` executable in the `bin` folder for [subsequent actions](./ledger-initialization.md). + +## Corda Components + +Using the sequence of instructions below, you can start a Corda network and run an application CorDapp on it. You can also run an interoperation CorDapp, a relay and a _driver_ acting on behalf of the network. You can initialize the network's vault with access control policies, foreign networks' security groups (i.e., membership providers' certificate chains), and some sample state values that can be shared during subsequent interoperation flows. + +### Interoperation CorDapp + +The interoperation CorDapp is deployed to run as part of any Corda application flow that involves cross-network interoperation. + +Build the interoperation CorDapp as follows: + +- Navigate to the `weaver/core/network/corda-interop-app` folder. +- Run the following to create the JAR files on which other Corda network components will depend on: + ```bash + make build-local + ``` + +### Corda Interoperation SDK + +A client-layer library is defined in the `weaver/sdks/corda` folder. This contains functions for Corda based client applications to exercise interoperation capabilities via relays and also several utility/helper functions. The Corda Client tool, which we will use later, depends on this library. + +To build the library, do the following: + +- Navigate to the `weaver/sdks/corda` folder. +- Run the following command (_make sure there is no github.properties file present in the directory_): + ```bash + make build + ``` + +### Corda Simple Application and Client (Application) + +This is a simple CorDapp that maintains a state of type `SimpleState`, which is a set of key-value pairs (of strings). +The code for this lies in the `weaver/samples/corda/corda-simple-application` folder. + +Build the `corda-simple-application` CorDapp as follows: + +- Navigate to the `weaver/samples/corda/corda-simple-application` folder. +- Run the following: + ```bash + make build-local + ``` + + +### Corda Network + +The Corda networks' code lies in the `weaver/tests/network-setups/corda` folder. You can launch two separate Corda networks, namely `Corda_Network` and `Corda_Network2`. Each network runs the `weaver/samples/corda/corda-simple-application` CorDapp by default, which maintains a state named `SimpleState` containing a set of key-value pairs (of strings). + +Follow the instructions below to build and launch both networks: + +- Navigate to the `weaver/tests/network-setups/corda` folder. +- To spin up the Corda networks with the Interoperation CorDapps: + - Each consisting of 1 node and a notary (for data-transfer), run: + ```bash + make start-local + ``` + - Each consisting of 2 nodes and a notary (for asset-exchange/transfer), run: + ```bash + make start-local PROFILE="2-nodes" + ``` + - Each consisting of 3 nodes and a notary (for asset-exchange/transfer), run: + ```bash + make start-local PROFILE="3-nodes" + ``` + +| Notes | +|:------| +| If you do not wish to test Corda-Corda interoperation, you can choose to launch only one of the two networks along with its interoperation CorDapp. For `Corda_Network`, run `make start-network1-local`, and for `Corda_Network2`, run `make start-network2-local`. | + +You should see the following message in the terminal: +``` +Waiting for network node services to start +``` +The Corda nodes and notary may take a while (several minutes on memory-constrained systems) to start. If they start up successfully, you should something like the following for each network, though the number of node entries will depend on the profile you used to start the network with (replace `` with `Corda_Network` or `Corda_Network2`): +```bash +PartyA node services started for network +PartyB node services started for network +PartyC node services started for network +Notary node services started for network +``` + +### Corda Relay + +Navigate to the `weaver/core/relay` folder. Refer [here](#building-relay-image) to build the relay image if not already built. Now run a relay for `Corda_Network` and/or `Corda_Network2` in Docker container as follows: + +* The `docker-compose.yaml` in this folder is minimally configured with default values. To modify it for use with the Fabric testnets, run: + ```bash + make convert-compose-method2 + ``` +* The `.env.corda` and `.env.corda.tls` files in the `docker/testnet-envs` directory contain environment variables used by the `Corda_Network` relay at startup and runtime. Edit either of these files (depending on whether you wish to start the relay with or without TLS), and update the following value: + ``` + DOCKER_IMAGE_NAME=weaver-relay-server + ``` +* Repeat the above step for `.env.corda2` or `.env.corda2.tls` in `docker/testnet-envs` directory, which contain environment variables for the `Corda_Network2` relay. +* To deploy the relay server for `Corda_Network` without TLS, run: + ```bash + make start-server COMPOSE_ARG='--env-file docker/testnet-envs/.env.corda' + ``` + Instead, to deploy the relay server with TLS, run: + ```bash + make start-server COMPOSE_ARG='--env-file docker/testnet-envs/.env.corda.tls' + ``` +* To deploy the relay server for `Corda_Network2` without TLS, run: + ```bash + make start-server COMPOSE_ARG='--env-file docker/testnet-envs/.env.corda2' + ``` + Instead, to deploy the relay server with TLS, run: + ```bash + make start-server COMPOSE_ARG='--env-file docker/testnet-envs/.env.corda2.tls' + ``` +* After launching the relay(s), you can revert the `docker-compose.yaml` changes by running: + ```bash + make convert-compose-method1 + ``` + +### Corda Driver + +Navigate to the `weaver/core/drivers/corda-driver` folder. + +#### Building + +To build the corda driver docker image, run: +```bash +make image-local +``` + +#### Deployment + +Use the following steps to run Corda drivers in Docker containers: + +* The `.env.corda` and `.env.corda.tls` files in the `docker-testnet-envs` directory contain environment variables used by the `Corda_Network` driver at startup and runtime. Edit either of these files (depending on whether you wish to start the relay with or without TLS) to update the following value: + ``` + DOCKER_IMAGE_NAME=cacti-weaver-driver-corda + ``` +* Repeat the above steps for `.env.corda2` or `.env.corda2.tls` in `docker-testnet-envs` directory, which contain environment variables for the `Corda_Network2` driver. +- To deploy the Corda driver for `Corda_Network` without TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet-envs/.env.corda' + ``` + Instead, to deploy the driver with TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet-envs/.env.corda.tls' + ``` + If the driver starts successfully, it should log the following message when you run `docker logs driver-corda-Corda_Network`: + ``` + Corda driver gRPC server started. Listening on port 9099 + ``` +- To deploy the Corda driver for `Corda_Network2` without TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet-envs/.env.corda2' + ``` + Instead, to deploy the driver with TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet-envs/.env.corda2.tls' + ``` + If the driver starts successfully, it should log the following message when you run `docker logs driver-corda-Corda_Network2`: + ``` + Corda driver gRPC server started. Listening on port 9098 + ``` + + +## Tear Down the Setup + +Bring down the various components as follows (_Navigate to the `weaver` folder of your clone of the Cacti repository_): + +### Relay +To bring down the relays (for all 3 networks), run: +```bash +cd core/relay +make convert-compose-method2 +make stop COMPOSE_ARG='--env-file .env.n1' +make stop COMPOSE_ARG='--env-file .env.n2' +make stop COMPOSE_ARG='--env-file .env.corda' +make stop COMPOSE_ARG='--env-file .env.corda2' +make convert-compose-method1 +cd - +``` + +### Fabric Driver +To bring down the fabric drivers (for both networks), run: +```bash +cd core/drivers/fabric-driver +make stop COMPOSE_ARG='--env-file .env.n1' +make stop COMPOSE_ARG='--env-file .env.n2' +cd - +``` + +### Corda Driver +To bring down the corda driver, run: +```bash +cd core/drivers/corda-driver +make stop COMPOSE_ARG='--env-file docker-testnet-envs/.env.corda' +make stop COMPOSE_ARG='--env-file docker-testnet-envs/.env.corda2' +cd - +``` + +### Corda Network +To bring down the Corda network: +```bash +cd tests/network-setups/corda +make clean +cd - +``` + +### Fabric Network +To bring down both of the Fabric networks along with weaver components: +```bash +cd tests/network-setups/fabric/dev +make clean +cd - +``` diff --git a/docs/docs/weaver/getting-started/test-network/setup-local.md b/docs/docs/weaver/getting-started/test-network/setup-local.md new file mode 100644 index 0000000000..90cdd46b72 --- /dev/null +++ b/docs/docs/weaver/getting-started/test-network/setup-local.md @@ -0,0 +1,923 @@ +--- +id: setup-local +title: Setup with Locally Built Weaver Components +pagination_prev: external/getting-started/test-network/overview +pagination_next: external/getting-started/test-network/ledger-initialization +--- + + + +In this document, we detail the steps using which you can bring up networks using the default configuration settings and by building Weaver interoperation modules, SDK libraries, and relay drivers locally from your Cacti clone. To customize these settings (e.g., hostnames, ports), refer to the [Advanced Configuration page](./advanced-configuration.md). + +| Notes | +|:------| +| The default configuration is for a development setup, therefore all components are run on `localhost`, many within Docker containers. | + +Follow the instructions below to build and run components followed by interoperation flows. These instructions have been tested on Ubuntu Linux (bash shell) and Mac OS. In general, they should work on any system and shell as long as the various dependenices have been installed and configured. + +## Prerequisites + +### Software +Before starting, make sure you have the following software installed on your host machine: + +- OpenSSL: _install using package manager, like `apt` on Debian/Ubuntu Linux (specifically packages `openssl` and `libssl-dev`)_ +- Curl: _install using package manager, like `apt` on Debian/Ubuntu Linux_ +- Git: [sample instructions](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) +- Docker: [sample instructions](https://docs.docker.com/engine/install/) (Latest version) +- Docker-Compose: [sample instructions](https://docs.docker.com/compose/install/) (Version 1.28.2 or higher, but lower than version V2) +- Golang: [sample instructions](https://golang.org/dl/) (Version 1.16 or higher) +- Java (JDK and JRE): [sample instructions](https://openjdk.java.net/install/) (Version 8) +- Node.js and NPM: [sample instructions](https://nodejs.org/en/download/package-manager/) (Version 16 Supported) +- Yarn: [sample instructions](https://classic.yarnpkg.com/en/docs/install/) +- Rust: [sample instructions](https://www.rust-lang.org/tools/install) +- Protoc (Protobuf compiler): _Golang should already be installed and configured._ + * Default method: Run the following with `sudo` if necessary. This will install both the protobuf compiler and the Go code generator plugins. + ``` + apt-get install protobuf-compiler + go install google.golang.org/protobuf/cmd/protoc-gen-go + go install google.golang.org/grpc/cmd/protoc-gen-go-grpc + ``` + * If the above method installs an older version of `protoc` (check using `protoc --version`), say below 3.12.x, you should download pre-compiled binaries instead. (With an older version, you may see errors while attempting to launch and setup the Fabric networks). + ``` + sudo apt-get remove protobuf-compiler + curl -LO https://github.com/protocolbuffers/protobuf/releases/download/v3.15.6/protoc-3.15.6-linux-x86_64.zip + sudo apt-get install unzip + unzip protoc-3.15.6-linux-x86_64.zip -d + export PATH="$PATH:/bin" + go install google.golang.org/protobuf/cmd/protoc-gen-go + go install google.golang.org/grpc/cmd/protoc-gen-go-grpc + ``` + | Notes | + |:------| + | The latest version at present is `3.15.6`, but you should check the above link to find the most current version before running the above steps. | + +### Credentials +Make sure you have an SSH or GPG key registered in https://github.com to allow seamless cloning of repositories (at present, various setup scripts clone repositories using the `https://` prefix but this may change to `git@` in the future). + +## Getting the Code and Documentation + +Clone the [cacti](https://github.com/hyperledger/cacti) repository. The code to get a basic test network up and running and test data-sharing interoperation flows lies in the subfolder `weaver/tests/network-setups`, which should be your starting point, though the setups will rely on other parts of the repository, as you will find out in the instructions given on this page. + +## Common Structures + +The `weaver/common/protos` folder contains structure definitions in the protobuf format that are used by all the different components. The various `weaver/common/protos-*` folders are meant to contain compiled protobufs (in different languages). + +To compile the protobufs for JavaScript, do the following: + +- Navigate to the `weaver/common/protos-js` folder. +- Run the following command: + ```bash + make build + ``` + +To compile the protobufs for Golang, do the following: + +- Navigate to the `weaver/common/protos-go` folder. +- Run the following command: + ```bash + make build + ``` + +To compile the protobufs for Java and Kotlin, do the following: + +- Navigate to the `weaver/common/protos-java-kt` folder. +- Run the following command: + ```bash + make build + ``` + +To compile the protobufs for Solidity, do the following: + +- Navigate to the `weaver/common/protos-sol` folder. +- Run the following command: + ```bash + make build + ``` + +To compile the protobufs for Rust, do the following: + +- Navigate to the `weaver/common/protos-rs` folder. +- Run the following command: + ```bash + make build + ``` + +## Securing Components + +| Notes | +|:------| +| The relays and drivers corresponding to the different test networks you will encounter below can be run with or without TLS enabled. But the default files used in the demonstrations assume that either all relays and drivers are TLS-enabled or none are. Therefore, you should determine at the outset whether or not you wish to run the entire set of components in TLS-enabled mode, and select appropriate commands in the provided instructions. | + +## Hyperledger Fabric Components + +Using the sequence of instructions below, you can start two separate Fabric networks, each with a single channel and application contract (chaincode). You can also start an interoperation contract, a relay, and a _driver_ acting on behalf of each network. You can build a Fabric CLI tool with which you can initialize both networks' ledgers with access control policies, foreign networks' security groups (i.e., membership providers' certificate chains), and some sample key-value pairs that can be shared during subsequent interoperation flows. + +### Fabric Interoperation Node SDK + +A client-layer library (companion to `hyperledger/fabric-sdk-node`) is defined in the `weaver/sdks/fabric/interoperation-node-sdk` folder. This contains functions for Fabric Gateway-based applications to exercise interoperation capabilities via relays and also several utility/helper functions. The Fabric-CLI tool, which we will use later, depends on this library. + +To build the library, do the following: + +- Navigate to the `weaver/sdks/fabric/interoperation-node-sdk` folder. +- Run the following command: + ```bash + make build-local + ``` + +### Fabric Network + +The code for this lies in the `weaver/tests/network-setups` folder. + +This folder contains code to create and launch networks `network1` and `network2` of identical specifications: + +- Network: 1 peer, 1 peer CA, 1 ordering service node, 1 ordering service CA +- Single channel named `mychannel` +- One of the following contracts deployed on `mychannel`, the choice depending on the [interoperability mode](../../interoperability-modes.md) you wish to test: + * `simplestate` ([Data Sharing](../interop/data-sharing.md)): supports simple transactions (`Create`, `Read`, `Update`, `Delete`) involving storage and lookup of pairs. + * `simplestatewithacl` ([Data Sharing](../interop/data-sharing.md)): identical to `simplestate` but with extra security features to ensure that the Weaver infrastructure cannot be bypassed by a malicious client of the network. + * `simpleasset` ([Asset Exchange](../interop/asset-exchange/overview.md)): supports creation, modification, transfer, and deletion, as well as locking, unlocking, and claiming, of simple bonds and tokens (examples of non-fungible and fungible assets respectively). + * `simpleassetandinterop` ([Asset Exchange](../interop/asset-exchange/overview.md)): identical to `simpleasset` but where the locking, unlocking, and claiming logic is imported as a library in the chaincode rather than available in the common Fabric Interoperation Chaincode (a Weaver component). + * `simpleassettransfer` ([Asset Exchange](../interop/asset-exchange/overview.md) or [Asset Transfer](../interop/asset-transfer.md)): augmentation of `simpleasset` with asset pledging, claiming, and reclaiming features for cross-network transfers. + +| Notes | +|:------| +| For new users, we recommend testing the Data Sharing feature first with the `simplestate` contract. To test the other modes, you can simply [tear down](#tear-down-the-setup) the Fabric networks and restart them with the appropriate chaincodes installed. | + +Follow the instructions below to build and launch the networks: + +- Navigate to the `weaver/tests/network-setups/fabric/dev` folder. +- To spin up both network1 and network2 with the interoperation chaincode and the default `simplestate` chaincode installed, run: + ```bash + make start-interop-local + ``` +- _To launch the networks with a different application chaincode from the above list, run_: + ```bash + make start-interop-local CHAINCODE_NAME= + ``` +- _To launch the networks with 2 organizations, each with a peer (this will enable more variation and experimentation, which you can attempt after testing interoperation protocols across basic network configurations), run_: + ```bash + make start-interop-local PROFILE="2-nodes" + ``` + +| Notes | +|:------| +| If you do not wish to test Fabric-Fabric interoperation, you can choose to launch only one of the two networks along with its interoperation chaincode. For `network1`, run `make start-interop-network1-local`, and for `network2`, run `make start-interop-network2-local` | +| If you wish to enable end-to-end confidentiality by default in the interoperation modules that are deployed during network launch, set the environment variable `E2E_CONFIDENTIALITY` to `true` in the command line as follows: `E2E_CONFIDENTIALITY=true make start-interop-local` | + +For more information, refer to the associated [README](https://github.com/hyperledger/cacti/tree/main/weaver/tests/network-setups/fabric/dev). + +**Troubleshooting Tips**: + +- If you see any errors during the launches, re-check the prerequisites (software installations and credentials). Ensure your network connection is working. As a safe bet, you can retry after cleanup: kill and remove all Docker containers and associated volumes. +- If `protoc` or `protoc-gen-go` throws an error, reinstall `protoc` and `protoc-gen-go` using suggestions made in the Prerequisites section above. + +### Fabric Client (fabric-cli) + +The CLI is used to interact with a Fabric network, configure it and run chaincode transactions to record data on the channel ledger or query data. It is also used to interact with remote networks through the relay to trigger an interoperation flow for data request and acceptance. + +The `fabric-cli` Node.js source code is located in the `weaver/samples/fabric/fabric-cli` folder and the Golang source code in the `weaver/samples/fabric/go-cli` folder. + +#### Prerequisites + +If you are using a Linux system, make sure that lib64 is installed. + +| Notes | +|:------| +| For the Node.js version of the `fabric-cli`, the setup and running instructions below were tested with all Node.js versions from v11.14.0 to v14.17.3. | + +#### Installation + +You can install `fabric-cli` as follows (for both the Node.js and Golang versions): + +- Navigate to the `weaver/samples/fabric/fabric-cli` folder (for the Node.js version) or the `weaver/samples/fabric/go-cli` (for the Golang version) folder. +- Run the following to install dependencies (for the Node.js version) or the executable (for the Golang version): + ```bash + make build-local + ``` +- Use the `fabric-cli` executable in the `bin` folder for [subsequent actions](./ledger-initialization.md). + +### Fabric Relay + +The relay is a module acting on behalf of a network, enabling interoperation flows with other networks by communicating with their relays. +The code for this lies in the `weaver/core/relay` folder. + +#### Building + +_Prerequisite_: make sure Rust is already installed and that the `cargo` executable is in your system path (after installation of Rust, this should be available in `$HOME/.cargo/bin`); you can also ensure this by running `source "$HOME/.cargo/env"`. + +Build the generic (i.e., common to all DLTs) relay module as follows: + +- Navigate to the `weaver/core/relay` folder. +- Run the following: + ```bash + make + ``` +- If you observe errors during the above compilation, update certain packages (on which the Weaver Relay is dependent) to their latest versions and recompile as follows: + ```bash + make update-pkgs + make + ``` + +#### Deployment + +An instance or a relay can be run using a suitable configuration file. Samples are available in the `weaver/core/relay/config` folder. + +Run a relay for `network1` as follows: + +- Navigate to the `weaver/core/relay` folder. +- To launch the server without TLS, leave the configuration file `config/Fabric_Relay.toml` in its default state. Otherwise, edit it to set TLS flags for this relay and the other relays and drivers it will connect to in this demonstration as follows: + ```toml + . + . + cert_path="credentials/fabric_cert.pem" + key_path="credentials/fabric_key" + tls=true + . + . + [relays] + [relays.Corda_Relay] + hostname="localhost" + port="9081" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + [relays.Corda_Relay2] + hostname="localhost" + port="9082" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + [relays.Fabric_Relay2] + hostname="localhost" + port="9083" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + . + . + [drivers] + [drivers.Fabric] + hostname="localhost" + port="9090" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + . + . + ``` +- To launch the server, simply run the following: + ```bash + RELAY_CONFIG=config/Fabric_Relay.toml cargo run --bin server + ``` + +Run a relay for `network2` as follows (_do this only if you have launched both Fabric networks `network1` and `network2` and wish to test interoperation between them_) + +- Navigate to the `weaver/core/relay` folder. +- To launch the server without TLS, leave the configuration file `config/Fabric_Relay2.toml` in its default state. Otherwise, edit it to set TLS flags for this relay and the other relays and drivers it will connect to in this demonstration as follows: + ```toml + . + . + cert_path="credentials/fabric_cert.pem" + key_path="credentials/fabric_key" + tls=true + . + . + [relays] + [relays.Corda_Relay] + hostname="localhost" + port="9081" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + [relays.Corda_Relay2] + hostname="localhost" + port="9082" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + [relays.Fabric_Relay] + hostname="localhost" + port="9080" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + . + . + [drivers] + [drivers.Fabric] + hostname="localhost" + port="9095" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + . + . + ``` +- To launch the server, simply run the following: + ```bash + RELAY_CONFIG=config/Fabric_Relay2.toml cargo run --bin server + ``` + +For more information, see the [relay README](https://github.com/hyperledger/cacti/tree/main/weaver/core/relay). + + +### Fabric Driver + +A driver is a DLT-specific plugin invoked by the relay while conveying external data queries to the local peer network and collecting a response with proofs. The Fabric driver is built as a Fabric client application on the `fabric-network` NPM package. +The code for this lies in the `weaver/core/drivers/fabric-driver` folder. + +#### Configuring + +In the `weaver/core/drivers/fabric-driver` folder, copy `.env.template` to `.env` and update `CONNECTION_PROFILE` to point to the connection profile of the Fabric network (e.g. `/tests/network-setups/fabric/shared/network1/peerOrganizations/org1.network1.com/connection-org1.json`) + +Configure `fabric-driver` for `network1` as follows: + +- Navigate to the `weaver/core/drivers/fabric-driver` folder. +- Create a `.env` file by copying `.env.template` and setting suitable parameter values: + * The `CONNECTION_PROFILE` should point to the absolute path of the connection profile for `network1`. + - For this exercise, specify the path `/tests/network-setups/fabric/shared/network1/peerOrganizations/org1.network1.com/connection-org1.json` (_you must specify the full absolute path here_). + - `` here is the absolute path of the `weaver` folder within your Cacti repository clone. + * If you wish to start the driver without TLS, set the following parameter values: + ``` + RELAY_TLS=false + RELAY_TLSCA_CERT_PATH= + DRIVER_TLS=false + DRIVER_TLS_CERT_PATH= + DRIVER_TLS_KEY_PATH= + ``` + Otherwise, if you wish to start the driver with TLS enabled, set the following parameter values (replace `` with the absolute path of the `weaver` folder within your Cacti repository clone): + ``` + RELAY_TLS=true + RELAY_TLSCA_CERT_PATH=/core/relay/credentials/fabric_ca_cert.pem + DRIVER_TLS=true + DRIVER_TLS_CERT_PATH=/core/relay/credentials/fabric_cert.pem + DRIVER_TLS_KEY_PATH=/core/relay/credentials/fabric_key + ``` + * Leave the default values unchanged for the other parameters. The relay and driver endpoints as well as the network name are already specified in the template. + +#### Building + +Build the Fabric driver module as follows: + +- Navigate to the `weaver/core/drivers/fabric-driver` folder. +- Run the following: + ```bash + make build-local + ``` + +#### Running + +Run a Fabric driver for `network1` as follows: + +- Navigate to the `weaver/core/drivers/fabric-driver` folder. +- Run the following: + ```bash + npm run dev + ``` + +Run a Fabric driver for `network2` as follows (_do this only if you wish to test interoperation between the two Fabric networks `network1` and `network2`_) + +- Navigate to the `weaver/core/drivers/fabric-driver` folder. +- Run the following (replace `` with the absolute path of the `weaver` folder within your Cacti repository clone): + ```bash + CONNECTION_PROFILE=/tests/network-setups/fabric/shared/network2/peerOrganizations/org1.network2.com/connection-org1.json NETWORK_NAME=network2 RELAY_ENDPOINT=localhost:9083 DRIVER_ENDPOINT=localhost:9095 npm run dev + ``` + +| Notes | +|:------| +| The variables we specified earlier in the `.env` for `network1` are now passed in the command line. Alternatively, you can make a copy of the `fabric-driver` folder with a different name and create a separate `.env` file within it that contains links to the connection profile, relay, and driver for `network2`. | + + +### Fabric IIN Agent + +IIN Agent is a client of a member of a DLT network or security domain with special permissions to update security domain identities and configurations on the ledger via the network's interoperation module. The code for this lies in the `weaver/core/identity-management/iin-agent` folder. Navigate to the `weaver/core/identity-management/iin-agent` folder. + +#### Building + +To build the IIN Agent, run: +```bash +make build-local +``` + +#### Configuration + +Ledger config file specifies ledger specific IIN Agent details such as identity and which network and organization to connect to. + +1. To create config file for `Org1MSP`'s Fabric IIN Agent of `network1`, follow the steps: + * Create copy of template config file for Fabric IIN Agent: `src/fabric-ledger/config.json.template`, say to location `src/fabric-ledger/config-n1-org1.json`. + * Replace `` with `/tests/network-setups/fabric/shared/network1/peerOrganizations/org1.network1.com/connection-org1.json`, where `` should be substituted with the absolute path of the `weaver` folder within your Cacti repository clone. + * Set `mspId` as `Org1MSP`. + * Set `agent.affiliation` as `org1.department1`. +2. To create config file for `Org2MSP`'s Fabric IIN Agent of `network1`, repeat `Step 1` with different name for config file, say `src/fabric-ledger/config-n1-org2.json`, and replace `org1` with `org2` and `Org1MSP` with `Org2MSP`. +3. To create config file for `Org1MSP`'s Fabric IIN Agent of `network2`, repeat `Step 1` with different name for config file, say `src/fabric-ledger/config-n2-org1.json`, and replace `network1` with `network2`. +4. To create config file for `Org2MSP`'s Fabric IIN Agent of `network2`, repeat `Step 1` with different name for config file, say `src/fabric-ledger/config-n2-org2.json`, and replace `network1` with `network2`, `org1` with `org2` and `Org1MSP` with `Org2MSP`. + +#### Security Domain Configuration + +Security Domain config file specifies the scope of security domain, which can be a channel in Fabric networks or list of nodes. File `docker-testnet/configs/security-domain-config.json` can be used for Weaver testnets. + +#### DNS Configuration + +To allow an IIN Agent's to be able to discover other IIN Agents, a config file for DNS is required. Create one `dnsconfig.json` by creating a copy of template `dnsconfig.json.template`, and replace the values with: + +* If Fabric networks are started with 1 org, and IIN Agent are to be started without TLS, use following values: +```json +{ + "network1": { + "Org1MSP": { + "endpoint": "localhost:9500", + "tls": false, + "tlsCACertPath": "" + } + }, + "network2": { + "Org1MSP": { + "endpoint": "localhost:9501", + "tls": false, + "tlsCACertPath": "" + } + } +} +``` + +* If Fabric networks are started with 1 org, and IIN Agent are to be started with TLS, use following values: +```json +{ + "network1": { + "Org1MSP": { + "endpoint": "localhost:9500", + "tls": true, + "tlsCACertPath": "../../relay/credentials/fabric_ca_cert.pem" + } + }, + "network2": { + "Org1MSP": { + "endpoint": "localhost:9501", + "tls": true, + "tlsCACertPath": "../../relay/credentials/fabric_ca_cert.pem" + } + } +} +``` + +* If Fabric networks are started with 2 orgs, and IIN Agent are to be started without TLS, use following values: +```json +{ + "network1": { + "Org1MSP": { + "endpoint": "localhost:9500", + "tls": false, + "tlsCACertPath": "" + }, + "Org2MSP": { + "endpoint": "localhost:9510", + "tls": false, + "tlsCACertPath": "" + } + }, + "network2": { + "Org1MSP": { + "endpoint": "localhost:9501", + "tls": false, + "tlsCACertPath": "" + }, + "Org2MSP": { + "endpoint": "localhost:9511", + "tls": false, + "tlsCACertPath": "" + } + } +} +``` + +* If Fabric networks are started with 2 orgs, and IIN Agent are to be started with TLS, use following values: +```json +{ + "network1": { + "Org1MSP": { + "endpoint": "localhost:9500", + "tls": true, + "tlsCACertPath": "../../relay/credentials/fabric_ca_cert.pem" + }, + "Org2MSP": { + "endpoint": "localhost:9510", + "tls": true, + "tlsCACertPath": "../../relay/credentials/fabric_ca_cert.pem" + } + }, + "network2": { + "Org1MSP": { + "endpoint": "localhost:9501", + "tls": true, + "tlsCACertPath": "../../relay/credentials/fabric_ca_cert.pem" + }, + "Org2MSP": { + "endpoint": "localhost:9511", + "tls": true, + "tlsCACertPath": "../../relay/credentials/fabric_ca_cert.pem" + } + } +} +``` + +#### Environment Variables + +To configure environment variables for `Org1MSP`'s Fabric IIN Agent of `network1`, follow the steps: + +1. Create a copy of `.env.template` as `.env`, and update following values based on previous configuration file paths: +``` +IIN_AGENT_ENDPOINT=localhost:9500 +MEMBER_ID=Org1MSP +SECURITY_DOMAIN=network1 +DLT_TYPE=fabric +CONFIG_PATH=./src/fabric-ledger/config-n1-org1.json +DNS_CONFIG_PATH=./dnsconfig.json +SECURITY_DOMAIN_CONFIG_PATH=./docker-testnet/configs/security-domain-config.json +WEAVER_CONTRACT_ID=interop +AUTO_SYNC=true +``` +2. If IIN Agent has to be started with TLS enabled, also update following values: +``` +IIN_AGENT_TLS=true +IIN_AGENT_TLS_CERT_PATH=../../relay/credentials/fabric_cert.pem +IIN_AGENT_TLS_KEY_PATH=../../relay/credentials/fabric_key +``` + +#### Deployment + +Use the following steps to run Fabric IIN Agents in host machine: + +* To start IIN Agent for `Org1MSP` of `network1`, run: +```bash +npm run dev +``` +* To start IIN Agent for `Org2MSP` of `network1` (_only required if Fabric network was started with 2 orgs_), run: +```bash +IIN_AGENT_ENDPOINT=localhost:9510 MEMBER_ID=Org2MSP CONFIG_PATH=./src/fabric-ledger/config-n1-org2.json npm run dev +``` +* To start IIN Agent for `Org1MSP` of `network2`, run: +```bash +IIN_AGENT_ENDPOINT=localhost:9501 SECURITY_DOMAIN=network2 CONFIG_PATH=./src/fabric-ledger/config-n2-org1.json npm run dev +``` +* To start IIN Agent for `Org2MSP` of `network2` (_only required if Fabric network was started with 2 orgs_), run: +```bash +IIN_AGENT_ENDPOINT=localhost:9511 MEMBER_ID=Org2MSP SECURITY_DOMAIN=network2 CONFIG_PATH=./src/fabric-ledger/config-n2-org2.json npm run dev +``` + +| Notes | +|:------| +| The variables we specified earlier in the `.env` for `network1` are now passed in the command line. Alternatively, you can make a copy of the `fabric-driver` folder with a different name and create a separate `.env` file within it that contains links to the connection profile, relay, and driver for `network2`. | + +## Corda Components + +Using the sequence of instructions below, you can start a Corda network and run an application CorDapp on it. You can also run an interoperation CorDapp, a relay and a _driver_ acting on behalf of the network. You can initialize the network's vault with access control policies, foreign networks' security groups (i.e., membership providers' certificate chains), and some sample state values that can be shared during subsequent interoperation flows. + +### Interoperation CorDapp + +The interoperation CorDapp is deployed to run as part of any Corda application flow that involves cross-network interoperation. + +Build the interoperation CorDapp as follows: + +- Navigate to the `weaver/core/network/corda-interop-app` folder. +- Run the following to create the JAR files on which other Corda network components will depend on: + ```bash + make build-local + ``` + +### Corda Interoperation SDK + +A client-layer library is defined in the `weaver/sdks/corda` folder. This contains functions for Corda based client applications to exercise interoperation capabilities via relays and also several utility/helper functions. The Corda Client tool, which we will use later, depends on this library. + +To build the library, do the following: + +- Navigate to the `weaver/sdks/corda` folder. +- Run the following command (_make sure there is no github.properties file present in the directory_): + ```bash + make build + ``` + +### Corda Simple Application and Client (Application) + +This is a simple CorDapp that maintains a state of type `SimpleState`, which is a set of key-value pairs (of strings). +The code for this lies in the `weaver/samples/corda/corda-simple-application` folder. + +Build the `corda-simple-application` CorDapp as follows: + +- Navigate to the `weaver/samples/corda/corda-simple-application` folder. +- Run the following: + ```bash + make build-local + ``` + +### Corda Network + +The Corda networks' code lies in the `weaver/tests/network-setups/corda` folder. You can launch two separate Corda networks, namely `Corda_Network` and `Corda_Network2`. Each network runs the `weaver/samples/corda/corda-simple-application` CorDapp by default, which maintains a state named `SimpleState` containing a set of key-value pairs (of strings). + +Follow the instructions below to build and launch both networks: + +- Navigate to the `weaver/tests/network-setups/corda` folder. +- To spin up the Corda networks with the Interoperation CorDapps: + - Each consisting of 1 node and a notary (for data-transfer), run: + ```bash + make start-local + ``` + - Each consisting of 2 nodes and a notary (for asset-exchange/transfer), run: + ```bash + make start-local PROFILE="2-nodes" + ``` + - Each consisting of 3 nodes and a notary (for asset-exchange/transfer), run: + ```bash + make start-local PROFILE="3-nodes" + ``` + +| Notes | +|:------| +| If you do not wish to test Corda-Corda interoperation, you can choose to launch only one of the two networks along with its interoperation CorDapp. For `Corda_Network`, run `make start-network1-local`, and for `Corda_Network2`, run `make start-network2-local`. | + +You should see the following message in the terminal: +``` +Waiting for network node services to start +``` +The Corda nodes and notary may take a while (several minutes on memory-constrained systems) to start. If they start up successfully, you should something like the following for each network, though the number of node entries will depend on the profile you used to start the network with (replace `` with `Corda_Network` or `Corda_Network2`): +```bash +PartyA node services started for network +PartyB node services started for network +PartyC node services started for network +Notary node services started for network +``` + +### Corda Relay + +The relay was built earlier, so you just need to use a different configuration file to start a relay for the Corda network. + +Run a relay for `Corda_Network` as follows: + +- Navigate to the `weaver/core/relay` folder. +- (Make sure you've already built the relay by running `make`.) +- To launch the server without TLS, leave the configuration file `config/Corda_Relay.toml` in its default state. Otherwise, edit it to set TLS flags for this relay and the other relays and drivers it will connect to in this demonstration as follows: + ```toml + . + . + cert_path="credentials/fabric_cert.pem" + key_path="credentials/fabric_key" + tls=true + . + . + [relays] + [relays.Fabric_Relay] + hostname="localhost" + port="9080" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + [relays.Fabric_Relay2] + hostname="localhost" + port="9083" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + [relays.Corda_Relay2] + hostname="localhost" + port="9082" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + . + . + [drivers] + [drivers.Corda] + hostname="localhost" + port="9099" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + . + . + ``` +- To launch the server, simply run the following: + ```bash + RELAY_CONFIG=config/Corda_Relay.toml cargo run --bin server + ``` + + If the relay starts up successfully, the following will be logged on your terminal: + + ``` + Relay Name: "Corda_Relay" + RelayServer listening on [::1]:9081 + ``` + +Run a relay for `Corda_Network2` as follows (_do this only if you have launched both Corda networks `Corda_Network` and `Corda_Network2` and wish to test interoperation between them_) + +- Navigate to the `weaver/core/relay` folder. +- To launch the server without TLS, leave the configuration file `config/Corda_Relay2.toml` in its default state. Otherwise, edit it to set TLS flags for this relay and the other relays and drivers it will connect to in this demonstration as follows: + ```toml + . + . + cert_path="credentials/fabric_cert.pem" + key_path="credentials/fabric_key" + tls=true + . + . + [relays] + [relays.Fabric_Relay] + hostname="localhost" + port="9080" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + [relays.Fabric_Relay2] + hostname="localhost" + port="9083" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + [relays.Corda_Relay] + hostname="localhost" + port="9081" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + . + . + [drivers] + [drivers.Corda] + hostname="localhost" + port="9098" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + . + . + ``` +- To launch the server, simply run the following: + ```bash + RELAY_CONFIG=config/Corda_Relay2.toml cargo run --bin server + ``` + + If the relay starts up successfully, the following will be logged on your terminal: + + ``` + Relay Name: "Corda2_Relay" + RelayServer listening on [::1]:9082 + ``` + +### Corda Driver + +The code for this lies in the `weaver/core/drivers/corda-driver` folder. + +#### Building Corda Driver + +Build the Corda driver module as follows: + +- Navigate to the `weaver/core/drivers/corda-driver` folder. +- Run the following: + ```bash + make build-local + ``` + +#### Configuring + +Configure the drivers as follows (you can skip this if you wish to run the drivers without TLS): + +- Navigate to the `weaver/core/drivers/corda-driver` folder and create a `.env` file. +- To run the drivers without TLS, set the following default values: + ``` + RELAY_TLS=false + RELAY_TLSCA_TRUST_STORE= + RELAY_TLSCA_TRUST_STORE_PASSWORD= + RELAY_TLSCA_CERT_PATHS= + ``` +- To run the drivers with TLS, set the following values (replace `` with the absolute path of the `weaver` folder within your Cacti repository clone): + ``` + RELAY_TLS=true + RELAY_TLSCA_TRUST_STORE=/core/relay/credentials/fabric_trust_store.jks + RELAY_TLSCA_TRUST_STORE_PASSWORD=trelay + RELAY_TLSCA_CERT_PATHS=/core/relay/credentials/fabric_ca_cert.pem + ``` + +#### Running + +Run a Corda driver as follows: + +- Navigate to the `weaver/core/drivers/corda-driver` folder. +- Run the following to start Corda driver for `Corda_Network`: + ```bash + ./build/install/driver-corda/bin/driver-corda + ``` + If the driver starts successfully, it should log the following message on your terminal: + ``` + Corda driver gRPC server started. Listening on port 9099 + ``` +- Run the following to start Corda driver for `Corda_Network2`: + ```bash + DRIVER_PORT=9098 ./build/install/corda-driver/bin/corda-driver + ``` + If the driver starts successfully, it should log the following message on your terminal: + ``` + Corda driver gRPC server started. Listening on port 9098 + ``` + +## Hyperledger Besu Components + +Using the sequence of instructions below, you can start two separate Besu networks, each with 4 validator nodes, and EthSigner and application contract. You can also install an interoperation contract in the network. You can build a Besu CLI tool with which you can initialize both networks' ledgers. + +### Prerequisites + +- Java (JDK and JRE): [sample instructions](https://openjdk.java.net/install/) (Version 11) + You need to run Besu instructions in a separate environment (separate terminal or machine) than Corda, as Corda requires Java 8. You can also use `update-alternatives` to switch between java versions. +- tmux: `sudo apt install tmux` +- Besu: + * Download and unpack the latest https://github.com/hyperledger/besu/releases/latest. You will find it in the link of the form: https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/x.y.z/besu-x.y.z.zip with x.y.z replaced with the version number. For instance, run the following command after updating version number accordingly. + ``` + wget https://hyperledger.jfrog.io/artifactory/besu-binaries/besu/21.7.0/besu-21.7.0.zip + ``` + * Add the path to `besu-x.y.z/bin` to your system PATH +- EthSigner: + * Download and unpack the latest from https://cloudsmith.io/~consensys/repos/ethsigner/packages/?q=tag%3Alatest (Requires Java 11 or later) + * Add the path to `ethsigner-x.y.z/bin` to your system PATH + +### Besu Interoperation Node SDK + +A client-layer library is defined in the `weaver/sdks/besu/interoperation-node-sdk` folder. This contains functions for Besu web3JS based applications to exercise interoperation capabilities via several utility/helper functions. The Besu-CLI tool, which we will use later, depends on this library. + +To build the library, do the following: + +- Navigate to the `weaver/sdks/besu/interoperation-node-sdk` folder. +- Run the following command: + ```bash + make build-local + ``` + +### Besu Network + +The code for this lies in the `weaver/tests/network-setups/besu` folder. + +This folder contains code to create and launch networks `Network1` and `Network2` of identical specifications: + +- Network: 4 validator nodes, 1 EthSigner node. +- `Network1` uses `8545` port for EthSigner while `Network2` uses `9544` port for EthSigner. + +Follow the instructions below to build and launch the networks: + +- Navigate to the `weaver/tests/network-setups/besu` folder. +- To spin up both Network1 and Network2, run: + ```bash + make start + ``` + +| Notes | +|:------| +| If you do not wish to test Besu-Besu interoperation, you can choose to launch only one of the two networks. For `Network1`, run `make start-network1`, and for `Network2`, run `make start-network2` | + +For more information, refer to the associated [README](https://github.com/hyperledger/cacti/tree/main/weaver/tests/network-setups/besu). + +### Contracts + +- `AssetExchangeContract` must be deployed which is present in `weaver/core/network/besu/contracts/interop/manageAssetAny.sol`. This contract is deployed along with application contract. +- Application contract `simpleasset`, located in `weaver/samples/besu/simpleasset` directory (for [Asset Exchange](../interop/asset-exchange/overview.md)), which supports creation, modification, transfer, and deletion, as well as locking, unlocking, and claiming, of simple `AliceERC20` and `BobERC20` tokens (examples of fungible assets), or `AliceERC721` and `BobERC721` tokens (example of non-fungible assets), or `AliceERC1155` and `BobERC1155` tokens (example of hybrid assets). + +To deploy `simpleasset` with `AssetExchangeContract` on both Besu networks, navigate to the `weaver/samples/besu/simpleasset` folder, and run: +```bash +make deploy-contracts +``` + +| Notes | +|:------| +| If you chose to launch only one of the two networks, then for `Network1`, run `make deploy-contract-network1`, and for `Network2`, run `deploy-contract-network2` | + +### Besu Client (besu-cli) + +The CLI is used to interact with a Besu network, configure it and run contract transactions to record data on the ledger or query data. + +The `besu-cli` Node.js source code is located in the `weaver/samples/besu/besu-cli` folder. + +#### Prerequisites + +If you are using a Linux system, make sure that lib64 is installed. + +| Notes | +|:------| +| For the Node.js version of the `besu-cli`, the setup and running instructions below were tested with all Node.js versions from v11.14.0 to v14.17.3. | + +#### Installation + +You can install `besu-cli` as follows: + +- Navigate to the `weaver/samples/besu/besu-cli` folder. +- Run the following to install dependencies: + ```bash + make build-local + ``` +- Use the `besu-cli` executable in the `bin` folder for [subsequent actions](./ledger-initialization.md). + +## Tear Down the Setup + +Bring down the test network's components as follows: + +- Simply terminate the various relays and drivers, which are running in the foreground in different terminals +- To bring down the running Corda network: + * Navigate to the `weaver/tests/network-setups/corda` folder. + * Run the following: + ```bash + make clean + ``` +- To bring down all the running Fabric networks: + * Navigate to the `weaver/tests/network-setups/fabric/dev` folder. + * Run the following: + ```bash + make clean + ``` +- To bring down all the running Besu networks: + * Navigate to the `weaver/tests/network-setups/besu` folder. + * Run the following: + ```bash + make clean + ``` diff --git a/docs/docs/weaver/getting-started/test-network/setup-packages-docker.md b/docs/docs/weaver/getting-started/test-network/setup-packages-docker.md new file mode 100644 index 0000000000..e7a8bb955f --- /dev/null +++ b/docs/docs/weaver/getting-started/test-network/setup-packages-docker.md @@ -0,0 +1,407 @@ +--- +id: setup-packages-docker +title: Setup with Imported Dockerized Weaver Components +pagination_prev: external/getting-started/test-network/overview +pagination_next: external/getting-started/test-network/ledger-initialization +--- + + + + In this document, we detail the steps using which you can bring up networks using the default configuration settings and by fetching pre-built Weaver interoperation modules, SDK libraries, and relay docker image, drivers docker images from GitHub Package repositories. To customize these settings (e.g., hostnames, ports), refer to the [Advanced Configuration page](./advanced-configuration.md). + +| Notes | +|:------| +| All components are run within Docker containers, except client applications. | + + Follow the instructions below to build and run components followed by interoperation flows. These instructions have been tested on Ubuntu Linux (bash shell) and Mac OS. In general, they should work on any system and shell as long as the various dependencies have been installed and configured. + +## Prerequisites + +### Software +Before starting, make sure you have the following software installed on your host machine: + +- Curl: _install using package manager, like `apt` on Debian/Ubuntu Linux_ +- Git: [sample instructions](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) +- Docker: [sample instructions](https://docs.docker.com/engine/install/) (Latest version) +- Docker-Compose: [sample instructions](https://docs.docker.com/compose/install/) (Version 1.28.2 or higher, but lower than version V2) +- Golang: [sample instructions](https://golang.org/dl/) (Version 1.16 or higher) +- Java (JDK and JRE): [sample instructions](https://openjdk.java.net/install/) (Version 8) +- Node.js and NPM: [sample instructions](https://nodejs.org/en/download/package-manager/) (Version 11 to Version 16 Supported) +- Yarn: [sample instructions](https://classic.yarnpkg.com/en/docs/install/) + +### Credentials +Make sure you have an SSH or GPG key registered in https://github.com to allow seamless cloning of repositories (at present, various setup scripts clone repositories using the `https://` prefix but this may change to `git@` in the future). + +#### Package Access Token: +Create a personal access token with `read:packages` access in GitHub in order to use modules published in GitHub packages. Refer [Creating a Personal Access Token](https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token) for help. + +Run `docker login ghcr.io`, and provide GitHub email id as username and personal access token created above as password. This will allow Docker to fetch images of `relay`, `fabric-driver` and `corda-driver` from `hyperledger/cacti`. + +## Getting the Code and Documentation + +Clone the [cacti](https://github.com/hyperledger/cacti) repository. The code to get a basic test network up and running and test data-sharing interoperation flows lies in the subfolder `weaver/tests/network-setups`, which should be your starting point, though the setups will rely on other parts of the repository, as you will find out in the instructions given on this page. + +## Securing Components + +| Notes | +|:------| +| The relays and drivers corresponding to the different test networks you will encounter below can be run with or without TLS enabled. But the default files used in the demonstrations assume that either all relays and drivers are TLS-enabled or none are. Therefore, you should determine at the outset whether or not you wish to run the entire set of components in TLS-enabled mode, and select appropriate commands in the provided instructions. | + +## Hyperledger Fabric Components + +Using the sequence of instructions below, you can start two separate Fabric networks, each with a single channel and application contract (chaincode). You can also start an interoperation contract, a relay and a _driver_ acting on behalf of each network. You can build a Fabric CLI tool with which you can initialize both networks' ledgers with access control policies, foreign networks' security groups (i.e., membership providers' certificate chains), and some sample key-value pairs that can be shared during subsequent interoperation flows. + +### Fabric Network + +The code for this lies in the `weaver/tests/network-setups` folder. + +This folder contains code to create and launch networks `network1` and `network2` of identical specifications: + +- Network: 1 peer, 1 peer CA, 1 ordering service node, 1 ordering service CA +- Single channel named `mychannel` +- One of the following contracts deployed on `mychannel`, the choice depending on the [interoperability mode](../../interoperability-modes.md) you wish to test: + * `simplestate` ([Data Sharing](../interop/data-sharing.md)): supports simple transactions (`Create`, `Read`, `Update`, `Delete`) involving storage and lookup of pairs. + * `simplestatewithacl` ([Data Sharing](../interop/data-sharing.md)): identical to `simplestate` but with extra security features to ensure that the Weaver infrastructure cannot be bypassed by a malicious client of the network. + * `simpleasset` ([Asset Exchange](../interop/asset-exchange/overview.md)): supports creation, modification, transfer, and deletion, as well as locking, unlocking, and claiming, of simple bonds and tokens (examples of non-fungible and fungible assets respectively). + * `simpleassetandinterop` ([Asset Exchange](../interop/asset-exchange/overview.md)): identical to `simpleasset` but where the locking, unlocking, and claiming logic is imported as a library in the chaincode rather than available in the common Fabric Interoperation Chaincode (a Weaver component). + * `simpleassettransfer` ([Asset Exchange](../interop/asset-exchange/overview.md) or [Asset Transfer](../interop/asset-transfer.md)): augmentation of `simpleasset` with asset pledging, claiming, and reclaiming features for cross-network transfers. + +| Notes | +|:------| +| For new users, we recommend testing the Data Sharing feature first with the `simplestate` contract. To test the other modes, you can simply [tear down](#tear-down-the-setup) the Fabric networks and restart them with the appropriate chaincodes installed. | + +Follow the instructions below to build and launch the networks: + +- Navigate to the `weaver/tests/network-setups/fabric/dev` folder. +- To spin up both network1 and network2 with the interoperation chaincode and the default `simplestate` chaincode installed, run: + ```bash + make start-interop + ``` +- _To launch the networks with a different application chaincode from the above list, run_: + ```bash + make start-interop CHAINCODE_NAME= + ``` +- _To launch the networks with 2 organizations, each with a peer (this will enable more variation and experimentation, which you can attempt after testing interoperation protocols across basic network configurations), run_: + ```bash + make start-interop-local PROFILE="2-nodes" + ``` + +| Notes | +|:------| +| If you do not wish to test Fabric-Fabric interoperation, you can choose to launch only one of the two networks along with its interoperation chaincode. For `network1`, run `make start-interop-network1`, and for `network2`, run `make start-interop-network2` | +| If you wish to enable end-to-end confidentiality by default in the interoperation modules that are deployed during network launch, set the environment variable `E2E_CONFIDENTIALITY` to `true` in the command line as follows: `E2E_CONFIDENTIALITY=true make start-interop` | + +For more information, refer to the associated [README](https://github.com/hyperledger/cacti/tree/main/weaver/tests/network-setups/fabric/dev). + +**Troubleshooting Tips**: + +- If you see any errors during the launches, re-check the prerequisites (software installations and credentials). Ensure your network connection is working. As a safe bet, you can retry after cleanup: kill and remove all Docker containers and associated volumes. + +### Fabric Relay + +The relay is a module acting on behalf of a network, enabling interoperation flows with other networks by communicating with their relays. +The code for this lies in the `weaver/core/relay` folder. + +Navigate to the `weaver/core/relay` folder and run a relay as follows: + +* The `docker-compose.yaml` in this folder is minimally configured with default values. To modify it for use with the Fabric testnets, run: + ```bash + make convert-compose-method2 + ``` +* (The `.env.n1` and `.env.n1.tls` files in the `docker/testnet-envs` directory contain environment variables used by the `network1` relay at startup and runtime.) +* (The `.env.n2` and `.env.n2.tls` files in the `docker/testnet-envs` directory contain environment variables used by the `network2` relay at startup and runtime.) +* To deploy the relay server for `network1` without TLS, run: + ```bash + make start-server COMPOSE_ARG='--env-file docker/testnet-envs/.env.n1' + ``` + Instead, to deploy the relay server with TLS, run: + ```bash + make start-server COMPOSE_ARG='--env-file docker/testnet-envs/.env.n1.tls' + ``` +* To deploy the relay server for `network2` without TLS, run: + ```bash + make start-server COMPOSE_ARG='--env-file docker/testnet-envs/.env.n2' + ``` + Instead, to deploy the relay server with TLS, run: + ```bash + make start-server COMPOSE_ARG='--env-file docker/testnet-envs/.env.n2.tls' + ``` +* After launching the relay(s), you can revert the `docker-compose.yaml` changes by running: + ```bash + make convert-compose-method1 + ``` + +For more information, see the [relay-docker README](https://github.com/hyperledger/cacti/tree/main/weaver/core/relay/relay-docker.md). + +### Fabric Driver + +A driver is a DLT-specific plugin invoked by the relay while channelling external data queries to the local peer network and collecting a response with proofs. The Fabric driver is built as a Fabric client application on the `fabric-network` NPM package. +The code for this lies in the `weaver/core/drivers/fabric-driver` folder. + +Use the following steps to run Fabric drivers in Docker containers: + +- Navigate to the `weaver/core/drivers/fabric-driver` folder. + * The `.env.n1` and `.env.n1.tls` files in the `docker-testnet-envs` directory contain environment variables used by the `network1` driver at startup and runtime. Edit either of these files (depending on whether you wish to start the relay with or without TLS) as follows: + - Replace `` with the absolute path of the `weaver` folder within your Cacti repository clone. + * Repeat the above step for `.env.n2` or `.env.n2.tls` in `docker-testnet-envs` directory, which contain environment variables for the `network2` driver. + * To deploy the Fabric driver for `network1` without TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet-envs/.env.n1' NETWORK_NAME=$(grep NETWORK_NAME docker-testnet-envs/.env.n1 | cut -d '=' -f 2) + ``` + Instead, to deploy the driver with TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet-envs/.env.n1.tls' NETWORK_NAME=$(grep NETWORK_NAME docker-testnet-envs/.env.n1.tls | cut -d '=' -f 2) + ``` + * To deploy the Fabric driver for `network2` without TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet-envs/.env.n2' NETWORK_NAME=$(grep NETWORK_NAME docker-testnet-envs/.env.n2 | cut -d '=' -f 2) + ``` + Instead, to deploy the driver with TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet-envs/.env.n2.tls' NETWORK_NAME=$(grep NETWORK_NAME docker-testnet-envs/.env.n2.tls | cut -d '=' -f 2) + ``` + +### Fabric IIN Agent + +IIN Agent is a client of a member of a DLT network or security domain with special permissions to update security domain identities and configurations on the ledger via the network's interoperation module. The code for this lies in the `weaver/core/identity-management/iin-agent` folder. Navigate to the `weaver/core/identity-management/iin-agent` folder. + +#### Deployment + +Use the following steps to run Fabric IIN Agents in Docker containers: +* The `.env.n1.org1` and `.env.n1.org1.tls` files in the `docker-testnet/envs` directory contain environment variables used by the iin-agent of `org1` of `network1` at startup and runtime. Edit either of these files (depending on whether you wish to start the relay with or without TLS) as follows: + - Replace `` with the absolute path of the `weaver` folder within your Cacti repository clone. + - If Fabric network was started with 1 org, and IIN Agents are to be started with TLS enabled, update the `DNS_CONFIG_PATH` variable as: + ``` + DNS_CONFIG_PATH=./docker-testnet/configs/dnsconfig-tls.json + ``` + - If Fabric network was started with 2 orgs, and IIN Agents are to be started without TLS, update the `DNS_CONFIG_PATH` variable as + ``` + DNS_CONFIG_PATH=./docker-testnet/configs/dnsconfig-2-nodes.json + ``` + - If Fabric network was started with 2 orgs and IIN Agents are to be started with TLS enabled, update the `DNS_CONFIG_PATH` variable as: + ``` + DNS_CONFIG_PATH=./docker-testnet/configs/dnsconfig-tls-2-nodes.json + ``` +* Repeat the above steps for all other environment variable files (depending upon whether tls is enabled) in `docker-testnet/envs` directory. +* To deploy the Fabric IIN Agent for `org1` of `network1` without TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet/envs/.env.n1.org1' DLT_SPECIFIC_DIR=$(grep DLT_SPECIFIC_DIR docker-testnet/envs/.env.n1.org1 | cut -d '=' -f 2) + ``` + Instead, to deploy the IIN Agent with TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet/envs/.env.n1.org1.tls' DLT_SPECIFIC_DIR=$(grep DLT_SPECIFIC_DIR docker-testnet/envs/.env.n1.org1.tls | cut -d '=' -f 2) + ``` +* To deploy the Fabric IIN Agent for `org2` of `network1` without TLS (_only required if Fabric network was started with 2 orgs_), run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet/envs/.env.n1.org2' DLT_SPECIFIC_DIR=$(grep DLT_SPECIFIC_DIR docker-testnet/envs/.env.n1.org2 | cut -d '=' -f 2) + ``` + Instead, to deploy the IIN Agent with TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet/envs/.env.n1.org2.tls' DLT_SPECIFIC_DIR=$(grep DLT_SPECIFIC_DIR docker-testnet/envs/.env.n1.org2.tls | cut -d '=' -f 2) + ``` +* To deploy the Fabric IIN Agent for `org1` of `network2` without TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet/envs/.env.n2.org1' DLT_SPECIFIC_DIR=$(grep DLT_SPECIFIC_DIR docker-testnet/envs/.env.n2.org1 | cut -d '=' -f 2) + ``` + Instead, to deploy the IIN Agent with TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet/envs/.env.n2.org1.tls' DLT_SPECIFIC_DIR=$(grep DLT_SPECIFIC_DIR docker-testnet/envs/.env.n2.org1.tls | cut -d '=' -f 2) + ``` +* To deploy the Fabric IIN Agent for `org2` of `network2` without TLS (_only required if Fabric network was started with 2 orgs_), run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet/envs/.env.n2.org2' DLT_SPECIFIC_DIR=$(grep DLT_SPECIFIC_DIR docker-testnet/envs/.env.n2.org2 | cut -d '=' -f 2) + ``` + Instead, to deploy the IIN Agent with TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet/envs/.env.n2.org2.tls' DLT_SPECIFIC_DIR=$(grep DLT_SPECIFIC_DIR docker-testnet/envs/.env.n2.org2.tls | cut -d '=' -f 2) + ``` + + +### Fabric Client (Application) + +The CLI is used to interact with a Fabric network, configure it and run chaincode transactions to record data on the channel ledger or query data. It is also used to interact with remote networks through the relay in order to trigger an interoperation flow for data request and acceptance. + +The `fabric-cli` Node.js source code is located in the `weaver/samples/fabric/fabric-cli` folder and the Golang source code in the `weaver/samples/fabric/go-cli` folder. + +#### Prerequisites + +If you are using a Linux system, make sure that lib64 is installed. + +| Notes | +|:------| +| For the Node.js version of the `fabric-cli`, the setup and running instructions below were tested with all Node.js versions from v11.14.0 to v14.17.3. | + +#### Installation + +You can install `fabric-cli` as follows (for both the Node.js and Golang versions): + +- Navigate to the `weaver/samples/fabric/fabric-cli` folder (for the Node.js version) or the `weaver/samples/fabric/go-cli` folder. +- Create `.npmrc` from template `.npmrc.template`, by replacing `` with yours created [above](#package-access-token).. +- Run the following to install dependencies (for the Node.js version) or the executable (for the Golang version): + ```bash + make build + ``` +- Use the `fabric-cli` executable in the `bin` folder for [subsequent actions](./ledger-initialization.md). + +## Corda Components + +Using the sequence of instructions below, you can start a Corda network and run an application CorDapp on it. You can also run an interoperation CorDapp, a relay and a _driver_ acting on behalf of the network. You can initialize the network's vault with access control policies, foreign networks' security groups (i.e., membership providers' certificate chains), and some sample state values that can be shared during subsequent interoperation flows. + +### Corda Network + +The Corda networks' code lies in the `weaver/tests/network-setups/corda` folder. You can launch two separate Corda networks, namely `Corda_Network` and `Corda_Network2`. Each network runs the `weaver/samples/corda/corda-simple-application` CorDapp by default, which maintains a state named `SimpleState` containing a set of key-value pairs (of strings). + +The following steps will, in addition to launching the network, build the CorDapp and a Corda client in `weaver/samples/corda/corda-simple-application/client`. + +#### Running with Interoperation CorDapp from GitHub Packages + +Follow the instructions below to build and launch the network: + +- Navigate to the `weaver/tests/network-setups/corda` folder. +- Create copy of `github.properties.template` as `github.properties`. +- Replace `` with your GitHub email, and `` with the access token created [above](#package-access-token). +- To spin up the Corda networks with the Interoperation CorDapps: + - Each consisting of 1 node and a notary (for data-transfer), run: + ```bash + make start + ``` + - Each consisting of 2 nodes and a notary (for asset-exchange/transfer), run: + ```bash + make start PROFILE="2-nodes" + ``` + - Each consisting of 3 nodes and a notary (for asset-exchange/transfer), run: + ```bash + make start PROFILE="3-nodes" + ``` + +You should see the following message in the terminal: +``` +Waiting for network node services to start +``` +The Corda nodes and notary may take a while (several minutes on memory-constrained systems) to start. If they start up successfully, you should something like the following for each network, though the number of node entries will depend on the profile you used to start the network with (replace `` with `Corda_Network` or `Corda_Network2`): +```bash +PartyA node services started for network +PartyB node services started for network +PartyC node services started for network +Notary node services started for network +``` + +### Corda Relay + +Navigate to the `weaver/core/relay` folder and run a relay for `Corda_Network` and/or `Corda_Network2` in Docker container as follows: + +* The `docker-compose.yaml` in this folder is minimally configured with default values. To modify it for use with the Fabric testnets, run: + ```bash + make convert-compose-method2 + ``` +* (The `.env.corda` and `.env.corda.tls` files in the `docker/testnet-envs` directory contain environment variables used by the `Corda_Network` relay at startup and runtime.) + +* (The `.env.corda2` and `.env.corda2.tls` files in the `docker/testnet-envs` directory contain environment variables used by the `Corda_Network2` relay at startup and runtime.) + +* To deploy the relay server for `Corda_Network` without TLS, run: + ```bash + make start-server COMPOSE_ARG='--env-file docker/testnet-envs/.env.corda' + ``` + Instead, to deploy the relay server with TLS, run: + ```bash + make start-server COMPOSE_ARG='--env-file docker/testnet-envs/.env.corda.tls' + ``` +* To deploy the relay server for `Corda_Network2` without TLS, run: + ```bash + make start-server COMPOSE_ARG='--env-file docker/testnet-envs/.env.corda2' + ``` + Instead, to deploy the relay server with TLS, run: + ```bash + make start-server COMPOSE_ARG='--env-file docker/testnet-envs/.env.corda2.tls' + ``` +* After launching the relay(s), you can revert the `docker-compose.yaml` changes by running: + ```bash + make convert-compose-method1 + ``` + +### Corda Driver + +Use the following steps to run Corda drivers in Docker containers: + +- Navigate to the `weaver/core/drivers/corda-driver` folder. +- (The `.env.corda` and `.env.corda.tls` files in the `docker-testnet-envs` contain environment variables used by the `Corda_Network` driver at startup and runtime.) +- (The `.env.corda2` and `.env.corda2.tls` files in the `docker-testnet-envs` contain environment variables used by the `Corda_Network2` driver at startup and runtime.) +- To deploy the Corda driver for `Corda_Network` without TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet-envs/.env.corda' + ``` + Instead, to deploy the driver with TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet-envs/.env.corda.tls' + ``` + If the driver starts successfully, it should log the following message when you run `docker logs corda-driver-Corda_Network`: + ``` + Corda driver gRPC server started. Listening on port 9099 + ``` +- To deploy the Corda driver for `Corda_Network2` without TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet-envs/.env.corda2' + ``` + Instead, to deploy the driver with TLS, run: + ```bash + make deploy COMPOSE_ARG='--env-file docker-testnet-envs/.env.corda2.tls' + ``` + If the driver starts successfully, it should log the following message when you run `docker logs corda-driver-Corda_Network2`: + ``` + Corda driver gRPC server started. Listening on port 9098 + ``` + +## Tear Down the Setup + +Bring down the various components as follows (_Navigate to the `weaver` folder of your clone of the Cacti repository_): + +### Relay +To bring down the relays (for all 3 networks), run: +```bash +cd core/relay +make convert-compose-method2 +make stop COMPOSE_ARG='--env-file docker/testnet-envs/.env.n1' +make stop COMPOSE_ARG='--env-file docker/testnet-envs/.env.n2' +make stop COMPOSE_ARG='--env-file docker/testnet-envs/.env.corda' +make stop COMPOSE_ARG='--env-file docker/testnet-envs/.env.corda2' +make convert-compose-method1 +cd - +``` + +### Fabric Driver +To bring down the fabric drivers (for both networks), run: +```bash +cd core/drivers/fabric-driver +make stop COMPOSE_ARG='--env-file docker-testnet-envs/.env.n1' +make stop COMPOSE_ARG='--env-file docker-testnet-envs/.env.n2' +cd - +``` + +### Corda Driver +To bring down the corda driver, run: +```bash +cd core/drivers/corda-driver +make stop COMPOSE_ARG='--env-file docker-testnet-envs/.env.corda' +make stop COMPOSE_ARG='--env-file docker-testnet-envs/.env.corda2' +cd - +``` + +### Corda Network +To bring down the Corda network: +```bash +cd tests/network-setups/corda +make clean +cd - +``` + +### Fabric Network +To bring down both of the Fabric networks along with weaver components: +```bash +cd tests/network-setups/fabric/dev +make clean +cd - +``` diff --git a/docs/docs/weaver/getting-started/test-network/setup-packages.md b/docs/docs/weaver/getting-started/test-network/setup-packages.md new file mode 100644 index 0000000000..38bdf5307f --- /dev/null +++ b/docs/docs/weaver/getting-started/test-network/setup-packages.md @@ -0,0 +1,728 @@ +--- +id: setup-packages +title: Setup with Imported Weaver Components +pagination_prev: external/getting-started/test-network/overview +pagination_next: external/getting-started/test-network/ledger-initialization +--- + + + +In this document, we detail the steps using which you can bring up networks using the default configuration settings and by fetching pre-built Weaver interoperation modules, SDK libraries, and relay drivers from GitHub Package repositories. To customize these settings (e.g., hostnames, ports), refer to the [Advanced Configuration page](./advanced-configuration.md). + +| Notes | +|:------| +| The default configuration is for a development setup, therefore all components are run on `localhost`, many within Docker containers. | + +Follow the instructions below to build and run components followed by interoperation flows. These instructions have been tested on Ubuntu Linux (bash shell) and Mac OS. In general, they should work on any system and shell as long as the various dependencies have been installed and configured. + +## Prerequisites + +### Software +Before starting, make sure you have the following software installed on your host machine: + +- Curl: _install using package manager, like `apt` on Debian/Ubuntu Linux_ +- Git: [sample instructions](https://git-scm.com/book/en/v2/Getting-Started-Installing-Git) +- Docker: [sample instructions](https://docs.docker.com/engine/install/) (Latest version) +- Docker-Compose: [sample instructions](https://docs.docker.com/compose/install/) (Version 1.28.2 or higher, but lower than version V2) +- Golang: [sample instructions](https://golang.org/dl/) (Version 1.16 or higher) +- Java (JDK and JRE): [sample instructions](https://openjdk.java.net/install/) (Version 8) +- Node.js and NPM: [sample instructions](https://nodejs.org/en/download/package-manager/) (Version 16 Supported) +- Yarn: [sample instructions](https://classic.yarnpkg.com/en/docs/install/) +- Rust: [sample instructions](https://www.rust-lang.org/tools/install) + * To avoid errors during Weaver Relay compilation, update certain packages (on which the Weaver Relay is dependent) to their latest versions as follows: + ``` + cargo update -p nom + cargo update -p lexical-core + ``` + +### Credentials +Make sure you have an SSH or GPG key registered in https://github.com to allow seamless cloning of repositories (at present, various setup scripts clone repositories using the `https://` prefix but this may change to `git@` in the future). + +Create a personal access token with `read:packages` access in GitHub in order to use modules published in GitHub packages. Refer [Creating a Personal Access Token](https://docs.github.com/en/github/authenticating-to-github/keeping-your-account-and-data-secure/creating-a-personal-access-token) for help. + +## Getting the Code and Documentation + +Clone the [cacti](https://github.com/hyperledger/cacti) repository. The code to get a basic test network up and running and test data-sharing interoperation flows lies in the subfolder `weaver/tests/network-setups`, which should be your starting point, though the setups will rely on other parts of the repository, as you will find out in the instructions given on this page. + +## Securing Components + +| Notes | +|:------| +| The relays and drivers corresponding to the different test networks you will encounter below can be run with or without TLS enabled. But the default files used in the demonstrations assume that either all relays and drivers are TLS-enabled or none are. Therefore, you should determine at the outset whether or not you wish to run the entire set of components in TLS-enabled mode, and select appropriate commands in the provided instructions. | + +## Hyperledger Fabric Components + +Using the sequence of instructions below, you can start two separate Fabric networks, each with a single channel and application contract (chaincode). You can also start an interoperation contract, a relay, and a _driver_ acting on behalf of each network. You can build a Fabric CLI tool with which you can initialize both networks' ledgers with access control policies, foreign networks' security groups (i.e., membership providers' certificate chains), and some sample key-value pairs that can be shared during subsequent interoperation flows. + +### Fabric Network + +The code for this lies in the `weaver/tests/network-setups` folder. + +This folder contains code to create and launch networks `network1` and `network2` of identical specifications: + +- Network: 1 peer, 1 peer CA, 1 ordering service node, 1 ordering service CA +- Single channel named `mychannel` +- One of the following contracts deployed on `mychannel`, the choice depending on the [interoperability mode](../../interoperability-modes.md) you wish to test: + * `simplestate` ([Data Sharing](../interop/data-sharing.md)): supports simple transactions (`Create`, `Read`, `Update`, `Delete`) involving storage and lookup of pairs. + * `simplestatewithacl` ([Data Sharing](../interop/data-sharing.md)): identical to `simplestate` but with extra security features to ensure that the Weaver infrastructure cannot be bypassed by a malicious client of the network. + * `simpleasset` ([Asset Exchange](../interop/asset-exchange/overview.md)): supports creation, modification, transfer, and deletion, as well as locking, unlocking, and claiming, of simple bonds and tokens (examples of non-fungible and fungible assets respectively). + * `simpleassetandinterop` ([Asset Exchange](../interop/asset-exchange/overview.md)): identical to `simpleasset` but where the locking, unlocking, and claiming logic is imported as a library in the chaincode rather than available in the common Fabric Interoperation Chaincode (a Weaver component). + * `simpleassettransfer` ([Asset Exchange](../interop/asset-exchange/overview.md) or [Asset Transfer](../interop/asset-transfer.md)): augmentation of `simpleasset` with asset pledging, claiming, and reclaiming features for cross-network transfers. + +| Notes | +|:------| +| For new users, we recommend testing the Data Sharing feature first with the `simplestate` contract. To test the other modes, you can simply [tear down](#tear-down-the-setup) the Fabric networks and restart them with the appropriate chaincodes installed. | + +Follow the instructions below to build and launch the networks: + +- Navigate to the `weaver/tests/network-setups/fabric/dev` folder. +- To spin up both network1 and network2 with the interoperation chaincode and the default `simplestate` chaincode installed, run: + ```bash + make start-interop + ``` +- _To launch the networks with a different application chaincode from the above list, run_: + ```bash + make start-interop CHAINCODE_NAME= + ``` +- _To launch the networks with 2 organizations, each with a peer (this will enable more variation and experimentation, which you can attempt after testing interoperation protocols across basic network configurations), run_: + ```bash + make start-interop-local PROFILE="2-nodes" + ``` + +| Notes | +|:------| +| If you do not wish to test Fabric-Fabric interoperation, you can choose to launch only one of the two networks along with its interoperation chaincode. For `network1`, run `make start-interop-network1`, and for `network2`, run `make start-interop-network2` | +| If you wish to enable end-to-end confidentiality by default in the interoperation modules that are deployed during network launch, set the environment variable `E2E_CONFIDENTIALITY` to `true` in the command line as follows: `E2E_CONFIDENTIALITY=true make start-interop` | + +For more information, refer to the associated [README](https://github.com/hyperledger/cacti/tree/main/weaver/tests/network-setups/fabric/dev). + +**Troubleshooting Tips**: + +- If you see any errors during the launches, re-check the prerequisites (software installations and credentials). Ensure your network connection is working. As a safe bet, you can retry after cleanup: kill and remove all Docker containers and associated volumes. + +### Fabric Client (fabric-cli) + +The CLI is used to interact with a Fabric network, configure it and run chaincode transactions to record data on the channel ledger or query data. It is also used to interact with remote networks through the relay to trigger an interoperation flow for data request and acceptance. + +The `fabric-cli` Node.js source code is located in the `weaver/samples/fabric/fabric-cli` folder and the Golang source code in the `weaver/samples/fabric/go-cli` folder. + +#### Prerequisites + +If you are using a Linux system, make sure that lib64 is installed. + +| Notes | +|:------| +| For the Node.js version of the `fabric-cli`, the setup and running instructions below were tested with all Node.js versions from v11.14.0 to v14.17.3. | + +#### Installation + +You can install `fabric-cli` as follows (for both the Node.js and Golang versions): + +- Navigate to the `weaver/samples/fabric/fabric-cli` folder (for the Node.js version) or the `weaver/samples/fabric/go-cli` (for the Golang version) folder. +- Create `.npmrc` from template `.npmrc.template`, by replacing `` with yours created [above](#package-access-token).. +- Run the following to install dependencies (for the Node.js version) or the executable (for the Golang version): + ```bash + make build + ``` +- Use the `fabric-cli` executable in the `bin` folder for [subsequent actions](./ledger-initialization.md). + +### Fabric Relay + +The relay is a module acting on behalf of a network, enabling interoperation flows with other networks by communicating with their relays. +The code for this lies in the `weaver/core/relay` folder. + +#### Building + +_Prerequisite_: make sure Rust is already installed and that the `cargo` executable is in your system path (after installation of Rust, this should be available in `$HOME/.cargo/bin`); you can also ensure this by running `source "$HOME/.cargo/env"`. + +Build the generic (i.e., common to all DLTs) relay module as follows: + +- Navigate to the `weaver/core/relay` folder. +- Run the following: + ```bash + make + ``` +- If you observe errors during the above compilation, update certain packages (on which the Weaver Relay is dependent) to their latest versions and recompile as follows: + ```bash + make update-pkgs + make + ``` + +#### Deployment + +An instance or a relay can be run using a suitable configuration file. Samples are available in the `weaver/core/relay/config` folder. + +Run a relay for `network1` as follows: + +- Navigate to the `weaver/core/relay` folder. +- To launch the server without TLS, leave the configuration file `config/Fabric_Relay.toml` in its default state. Otherwise, edit it to set TLS flags for this relay and the other relays and drivers it will connect to in this demonstration as follows: + ```toml + . + . + cert_path="credentials/fabric_cert.pem" + key_path="credentials/fabric_key" + tls=true + . + . + [relays] + [relays.Corda_Relay] + hostname="localhost" + port="9081" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + [relays.Corda_Relay2] + hostname="localhost" + port="9082" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + [relays.Fabric_Relay2] + hostname="localhost" + port="9083" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + . + . + [drivers] + [drivers.Fabric] + hostname="localhost" + port="9090" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + . + . + ``` +- To launch the server, simply run the following: + ```bash + RELAY_CONFIG=config/Fabric_Relay.toml cargo run --bin server + ``` + +Run a relay for `network2` as follows (_do this only if you have launched both Fabric networks `network1` and `network2` and wish to test interoperation between them_) + +- Navigate to the `weaver/core/relay` folder. +- To launch the server without TLS, leave the configuration file `config/Fabric_Relay2.toml` in its default state. Otherwise, edit it to set TLS flags for this relay and the other relays and drivers it will connect to in this demonstration as follows: + ```toml + . + . + cert_path="credentials/fabric_cert.pem" + key_path="credentials/fabric_key" + tls=true + . + . + [relays] + [relays.Corda_Relay] + hostname="localhost" + port="9081" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + [relays.Corda_Relay2] + hostname="localhost" + port="9082" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + [relays.Fabric_Relay] + hostname="localhost" + port="9080" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + . + . + [drivers] + [drivers.Fabric] + hostname="localhost" + port="9095" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + . + . + ``` +- To launch the server, simply run the following: + ```bash + RELAY_CONFIG=config/Fabric_Relay2.toml cargo run --bin server + ``` + +For more information, see the [relay README](https://github.com/hyperledger/cacti/tree/main/weaver/core/relay). + + +### Fabric Driver + +A driver is a DLT-specific plugin invoked by the relay while conveying external data queries to the local peer network and collecting a response with proofs. The Fabric driver is built as a Fabric client application on the `fabric-network` NPM package. +The code for this lies in the `weaver/core/drivers/fabric-driver` folder. + +#### Configuring + +In the `weaver/core/drivers/fabric-driver` folder, copy `.env.template` to `.env` and update `CONNECTION_PROFILE` to point to the connection profile of the Fabric network (e.g. `/tests/network-setups/fabric/shared/network1/peerOrganizations/org1.network1.com/connection-org1.json`) + +Configure `fabric-driver` for `network1` as follows: + +- Navigate to the `weaver/core/drivers/fabric-driver` folder. +- Create a `.env` file by copying `.env.template` and setting suitable parameter values: + * The `CONNECTION_PROFILE` should point to the absolute path of the connection profile for `network1`. + - For this exercise, specify the path `/tests/network-setups/fabric/shared/network1/peerOrganizations/org1.network1.com/connection-org1.json` (_you must specify the full absolute path here_). + - `` here is the absolute path of the `weaver` folder within your Cacti repository clone. + * If you wish to start the driver without TLS, set the following parameter values: + ``` + RELAY_TLS=false + RELAY_TLSCA_CERT_PATH= + DRIVER_TLS=false + DRIVER_TLS_CERT_PATH= + DRIVER_TLS_KEY_PATH= + ``` + Otherwise, if you wish to start the driver with TLS enabled, set the following parameter values (replace `` with the absolute path of the `weaver` folder within your Cacti repository clone): + ``` + RELAY_TLS=true + RELAY_TLSCA_CERT_PATH=/core/relay/credentials/fabric_ca_cert.pem + DRIVER_TLS=true + DRIVER_TLS_CERT_PATH=/core/relay/credentials/fabric_cert.pem + DRIVER_TLS_KEY_PATH=/core/relay/credentials/fabric_key + ``` + * Leave the default values unchanged for the other parameters. The relay and driver endpoints as well as the network name are already specified. + +#### Building + +Build the Fabric driver module as follows: + +- Navigate to the `weaver/core/drivers/fabric-driver` folder. +- Create `.npmrc` from template `.npmrc.template`, by replacing `` with yours created above. +- Run the following: + ```bash + make build + ``` + +#### Running + +Run a Fabric driver for `network1` as follows: + +- Navigate to the `weaver/core/drivers/fabric-driver` folder. +- Run the following: + ```bash + npm run dev + ``` + +Run a Fabric driver for `network2` as follows (_do this only if you wish to test interoperation between the two Fabric networks `network1` and `network2`_) + +- Navigate to the `weaver/core/drivers/fabric-driver` folder. +- Run the following: + ```bash + CONNECTION_PROFILE=/tests/network-setups/fabric/shared/network2/peerOrganizations/org1.network2.com/connection-org1.json NETWORK_NAME=network2 RELAY_ENDPOINT=localhost:9083 DRIVER_ENDPOINT=localhost:9095 npm run dev + ``` + +| Notes | +|:------| +| The variables we specified earlier in the `.env` for `network1` are now passed in the command line. Alternatively, you can make a copy of the `fabric-driver` folder with a different name and create a separate `.env` file within it that contains links to the connection profile, relay, and driver for `network2`. | + + +### Fabric IIN Agent + +IIN Agent is a client of a member of a DLT network or security domain with special permissions to update security domain identities and configurations on the ledger via the network's interoperation module. The code for this lies in the `weaver/core/identity-management/iin-agent` folder. Navigate to the `weaver/core/identity-management/iin-agent` folder. + +#### Building + +Build the IIN Agent as follows: + +- Navigate to the `weaver/core/drivers/fabric-driver` folder. +- Create `.npmrc` from template `.npmrc.template`, by replacing `` with yours created above. +- Run the following: + ```bash + make build + ``` + +#### Configuration + +Ledger config file specifies ledger specific IIN Agent details such as identity and which network and organization to connect to. + +1. To create config file for `Org1MSP`'s Fabric IIN Agent of `network1`, follow the steps: + * Create copy of template config file for Fabric IIN Agent: `src/fabric-ledger/config.json.template`, say to location `src/fabric-ledger/config-n1-org1.json`. + * Replace `` with `/tests/network-setups/fabric/shared/network1/peerOrganizations/org1.network1.com/connection-org1.json`, where replace `` with the absolute path of the `weaver` folder within your Cacti repository clone. + * Set `mspId` as `Org1MSP`. + * Set `agent.affiliation` as `org1.department1`. + +2. To create config file for `Org2MSP`'s Fabric IIN Agent of `network1`, repeat `Step 1` with different name for config file, say `src/fabric-ledger/config-n1-org2.json`, and replace `org1` with `org2` and `Org1MSP` with `Org2MSP`. +3. To create config file for `Org1MSP`'s Fabric IIN Agent of `network2`, repeat `Step 1` with different name for config file, say `src/fabric-ledger/config-n2-org1.json`, and replace `network1` with `network2`. +4. To create config file for `Org2MSP`'s Fabric IIN Agent of `network2`, repeat `Step 1` with different name for config file, say `src/fabric-ledger/config-n2-org2.json`, and replace `network1` with `network2`, `org1` with `org2` and `Org1MSP` with `Org2MSP`. + +#### Security Domain Configuration + +Security Domain config file specifies the scope of security domain, which can be a channel in Fabric networks or list of nodes. File `docker-testnet/configs/security-domain-config.json` can be used for Weaver testnets. + +#### DNS Configuration + +To allow an IIN Agent's to be able to discover other IIN Agents, a config file for DNS is required. Create one `dnsconfig.json` by creating a copy of template `dnsconfig.json.template`, and replace the values with: + +* If Fabric networks are started with 1 org, and IIN Agent are to be started without TLS, use following values: +```json +{ + "network1": { + "Org1MSP": { + "endpoint": "localhost:9500", + "tls": false, + "tlsCACertPath": "" + } + }, + "network2": { + "Org1MSP": { + "endpoint": "localhost:9501", + "tls": false, + "tlsCACertPath": "" + } + } +} +``` + +* If Fabric networks are started with 1 org, and IIN Agent are to be started with TLS, use following values: +```json +{ + "network1": { + "Org1MSP": { + "endpoint": "localhost:9500", + "tls": true, + "tlsCACertPath": "../../relay/credentials/fabric_ca_cert.pem" + } + }, + "network2": { + "Org1MSP": { + "endpoint": "localhost:9501", + "tls": true, + "tlsCACertPath": "../../relay/credentials/fabric_ca_cert.pem" + } + } +} +``` + +* If Fabric networks are started with 2 orgs, and IIN Agent are to be started without TLS, use following values: +```json +{ + "network1": { + "Org1MSP": { + "endpoint": "localhost:9500", + "tls": false, + "tlsCACertPath": "" + }, + "Org2MSP": { + "endpoint": "localhost:9510", + "tls": false, + "tlsCACertPath": "" + } + }, + "network2": { + "Org1MSP": { + "endpoint": "localhost:9501", + "tls": false, + "tlsCACertPath": "" + }, + "Org2MSP": { + "endpoint": "localhost:9511", + "tls": false, + "tlsCACertPath": "" + } + } +} +``` + +* If Fabric networks are started with 2 orgs, and IIN Agent are to be started with TLS, use following values: +```json +{ + "network1": { + "Org1MSP": { + "endpoint": "localhost:9500", + "tls": true, + "tlsCACertPath": "../../relay/credentials/fabric_ca_cert.pem" + }, + "Org2MSP": { + "endpoint": "localhost:9510", + "tls": true, + "tlsCACertPath": "../../relay/credentials/fabric_ca_cert.pem" + } + }, + "network2": { + "Org1MSP": { + "endpoint": "localhost:9501", + "tls": true, + "tlsCACertPath": "../../relay/credentials/fabric_ca_cert.pem" + }, + "Org2MSP": { + "endpoint": "localhost:9511", + "tls": true, + "tlsCACertPath": "../../relay/credentials/fabric_ca_cert.pem" + } + } +} +``` + +| Notes | +|:------| +| The variables we specified earlier in the `.env` for `network1` are now passed in the command line. Alternatively, you can make a copy of the `fabric-driver` folder with a different name and create a separate `.env` file within it that contains links to the connection profile, relay, and driver for `network2`. | + +#### Environment Variables + +To configure environment variables for `Org1MSP`'s Fabric IIN Agent of `network1`, follow the steps: + +1. Create a copy of `.env.template` as `.env`, and update following values based on previous configuration file paths: +``` +IIN_AGENT_ENDPOINT=localhost:9500 +MEMBER_ID=Org1MSP +SECURITY_DOMAIN=network1 +DLT_TYPE=fabric +CONFIG_PATH=./src/fabric-ledger/config-n1-org1.json +DNS_CONFIG_PATH=./dnsconfig.json +SECURITY_DOMAIN_CONFIG_PATH=./docker-testnet/configs/security-domain-config.json +WEAVER_CONTRACT_ID=interop +AUTO_SYNC=true +``` +2. If IIN Agent has to be started with TLS enabled, also update following values: +``` +IIN_AGENT_TLS=false +IIN_AGENT_TLS_CERT_PATH=../../relay/credentials/fabric_cert.pem +IIN_AGENT_TLS_KEY_PATH=../../relay/credentials/fabric_key +``` + +#### Deployment + +Use the following steps to run Fabric IIN Agents in host machine: + +* To start IIN Agent for `Org1MSP` of `network1`, run: +```bash +npm run dev +``` +* To start IIN Agent for `Org2MSP` of `network1` (_only required if Fabric network was started with 2 orgs_), run: +```bash +IIN_AGENT_ENDPOINT=localhost:9510 MEMBER_ID=Org2MSP CONFIG_PATH=./src/fabric-ledger/config-n1-org2.json npm run dev +``` +* To start IIN Agent for `Org1MSP` of `network2`, run: +```bash +IIN_AGENT_ENDPOINT=localhost:9501 SECURITY_DOMAIN=network2 CONFIG_PATH=./src/fabric-ledger/config-n2-org1.json npm run dev +``` +* To start IIN Agent for `Org2MSP` of `network2` (_only required if Fabric network was started with 2 orgs_), run: +```bash +IIN_AGENT_ENDPOINT=localhost:9511 MEMBER_ID=Org2MSP SECURITY_DOMAIN=network2 CONFIG_PATH=./src/fabric-ledger/config-n2-org2.json npm run dev +``` + + +## Corda Components + +Using the sequence of instructions below, you can start a Corda network and run an application CorDapp on it. You can also run an interoperation CorDapp, a relay and a _driver_ acting on behalf of the network. You can initialize the network's vault with access control policies, foreign networks' security groups (i.e., membership providers' certificate chains), and some sample state values that can be shared during subsequent interoperation flows. + +### Corda Network + +The Corda networks' code lies in the `weaver/tests/network-setups/corda` folder. You can launch two separate Corda networks, namely `Corda_Network` and `Corda_Network2`. Each network runs the `weaver/samples/corda/corda-simple-application` CorDapp by default, which maintains a state named `SimpleState` containing a set of key-value pairs (of strings). + +The following steps will, in addition to launching the network, build the CorDapp and a Corda client in `weaver/samples/corda/corda-simple-application/client`. + +#### Running with Interoperation CorDapp from GitHub Packages + +Follow the instructions below to build and launch the network: + +- Navigate to the `weaver/tests/network-setups/corda` folder. +- Create a copy of `github.properties.template` as `github.properties`. +- Replace `` with your GitHub email, and `` with the access token created [above](#package-access-token). +- To spin up the Corda networks with the Interoperation CorDapps: + - Each consisting of 1 node and a notary (for data-transfer), run: + ```bash + make start + ``` + - Each consisting of 2 nodes and a notary (for asset-exchange/transfer), run: + ```bash + make start PROFILE="2-nodes" + ``` + - Each consisting of 3 nodes and a notary (for asset-exchange/transfer), run: + ```bash + make start PROFILE="3-nodes" + ``` + +You should see the following message in the terminal: +``` +Waiting for network node services to start +``` +The Corda nodes and notary may take a while (several minutes on memory-constrained systems) to start. If they start up successfully, you should something like the following for each network, though the number of node entries will depend on the profile you used to start the network with (replace `` with `Corda_Network` or `Corda_Network2`): +```bash +PartyA node services started for network +PartyB node services started for network +PartyC node services started for network +Notary node services started for network +``` + +### Corda Relay + +The relay was built earlier, so you just need to use a different configuration file to start a relay for the Corda network. + +Run a relay for `Corda_Network` as follows: + +- Navigate to the `weaver/core/relay` folder. +- (Make sure you've already built the relay by running `make`.) +- To launch the server without TLS, leave the configuration file `config/Corda_Relay.toml` in its default state. Otherwise, edit it to set TLS flags for this relay and the other relays and drivers it will connect to in this demonstration as follows: + ```toml + . + . + cert_path="credentials/fabric_cert.pem" + key_path="credentials/fabric_key" + tls=true + . + . + [relays] + [relays.Fabric_Relay] + hostname="localhost" + port="9080" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + [relays.Fabric_Relay2] + hostname="localhost" + port="9083" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + [relays.Corda_Relay2] + hostname="localhost" + port="9082" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + . + . + [drivers] + [drivers.Corda] + hostname="localhost" + port="9099" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + . + . + ``` +- To launch the server, simply run the following: + ```bash + RELAY_CONFIG=config/Corda_Relay.toml cargo run --bin server + ``` + + If the relay starts up successfully, the following will be logged on your terminal: + + ``` + Relay Name: "Corda_Relay" + RelayServer listening on [::1]:9081 + ``` + +Run a relay for `Corda_Network2` as follows (_do this only if you have launched both Corda networks `Corda_Network` and `Corda_Network2` and wish to test interoperation between them_) + +- Navigate to the `weaver/core/relay` folder. +- To launch the server without TLS, leave the configuration file `config/Corda_Relay2.toml` in its default state. Otherwise, edit it to set TLS flags for this relay and the other relays and drivers it will connect to in this demonstration as follows: + ```toml + . + . + cert_path="credentials/fabric_cert.pem" + key_path="credentials/fabric_key" + tls=true + . + . + [relays] + [relays.Fabric_Relay] + hostname="localhost" + port="9080" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + [relays.Fabric_Relay2] + hostname="localhost" + port="9083" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + [relays.Corda_Relay] + hostname="localhost" + port="9081" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + . + . + [drivers] + [drivers.Corda] + hostname="localhost" + port="9098" + tls=true + tlsca_cert_path="credentials/fabric_ca_cert.pem" + . + . + ``` +- To launch the server, simply run the following: + ```bash + RELAY_CONFIG=config/Corda_Relay2.toml cargo run --bin server + ``` + + If the relay starts up successfully, the following will be logged on your terminal: + + ``` + Relay Name: "Corda2_Relay" + RelayServer listening on [::1]:9082 + ``` + +### Corda Driver + +The code for this lies in the `weaver/core/drivers/corda-driver` folder. + +#### Building Corda Driver + +Build the Corda driver module as follows: + +- Navigate to the `weaver/core/drivers/corda-driver` folder. +- Create a copy of `github.properties.template` as `github.properties`. +- Replace `` with your GitHub email, and `` with the access token created [above](#package-access-token). +- Run the following: + ```bash + make build + ``` + +#### Configuring + +Configure the drivers as follows (you can skip this if you wish to run the drivers without TLS): + +- Navigate to the `weaver/core/drivers/corda-driver` folder and create a `.env` file. +- To run the drivers without TLS, set the following default values: + ``` + RELAY_TLS=false + RELAY_TLSCA_TRUST_STORE= + RELAY_TLSCA_TRUST_STORE_PASSWORD= + RELAY_TLSCA_CERT_PATHS= + ``` +- To run the drivers with TLS, set the following values (replace `` with the absolute path of the `weaver` folder within your Cacti repository clone): + ``` + RELAY_TLS=true + RELAY_TLSCA_TRUST_STORE=/core/relay/credentials/fabric_trust_store.jks + RELAY_TLSCA_TRUST_STORE_PASSWORD=trelay + RELAY_TLSCA_CERT_PATHS=/core/relay/credentials/fabric_ca_cert.pem + ``` + +#### Running + +Run a Corda driver as follows: + +- Navigate to the `weaver/core/drivers/corda-driver` folder. +- Run the following to start Corda driver for `Corda_Network`: + ```bash + ./build/install/corda-driver/bin/corda-driver + ``` + If the driver starts successfully, it should log the following message on your terminal: + ``` + Corda driver gRPC server started. Listening on port 9099 + ``` +- Run the following to start Corda driver for `Corda_Network2`: + ```bash + DRIVER_PORT=9098 ./build/install/corda-driver/bin/corda-driver + ``` + If the driver starts successfully, it should log the following message on your terminal: + ``` + Corda driver gRPC server started. Listening on port 9098 + ``` + +## Tear Down the Setup + +Bring down the test network's components as follows: + +- Simply terminate the various relays and drivers, which are running in the foreground in different terminals +- To bring down the running Corda network: + * Navigate to the `weaver/tests/network-setups/corda` folder. + * Run the following: + ```bash + make clean + ``` +- To bring down all the running Fabric networks: + * Navigate to the `weaver/tests/network-setups/fabric/dev` folder. + * Run the following: + ```bash + make clean + ``` diff --git a/docs/docs/weaver/interoperability-modes.md b/docs/docs/weaver/interoperability-modes.md new file mode 100644 index 0000000000..dca33d72a7 --- /dev/null +++ b/docs/docs/weaver/interoperability-modes.md @@ -0,0 +1,51 @@ +--- +id: interoperability-modes +title: Interoperability Modes +--- + + + +## Modes of Interoperability + +We identify distinct modes or patterns of interoperation based on the nature and purpose of the artifact that two networks (or parties within) have a common interest in and the purpose they wish to achieve. + +First, we will classify artifacts present on shared ledgers broadly into the following two types: + +- __Assets__: This is a ledger item that is associated with a single entity (or limited set of entities), representing the real-world ownership of that item by an entity. Bitcoins in the Bitcoin network and Ether on the Ethereum network are well-known examples, but assets repreenting a wide range of tangible goods can reside on blockchian ledgers, like property titles, bank drafts, precious stones, and financial instruments like bonds and securities. +- __Data Records__: This is any information held on a ledger that describes the state of the world, context, or properties of an entity or object. It is not "owned" by, or associated with, specific entities, but is rather common knowledge within a blockchain network. + +The salient distinction between assets and data from an interoperability perspective is that the former may be present only in one network at any given instant in order to maintain its integrity whereas the latter can have copies in multiple networks without losing its value. + +Three common modes in which independent networks will seek to interoperate are as follows. (We can also refer to them as three distinct purposes.) + +### Asset Transfer +This refers to the movement of an asset from its source ledger to a consuming ledger. Since assets has _singleton_ ownership and can't be _double spent_, the transfer of an asset should result in its burning or locking in the source ledger and its creation on the target ledger. + +A typical asset transfer use case is illustrated in the figure below, where Party X initially holds Asset in Network A, and through interoperation transfers Asset to Party Y in Network B. The loss of Asset to X in A must occur simultaneously with the gain of Asset for Y in B;. i.e, these transactions must be _atomic_. ("Holding an asset" refers to a record on a network's shared ledger representing the ownership of that asset by a given entity.) + +![alt text](../../images-weaver-docs/use-cases/asset-transfer.png) + +### Asset Exchange +This refers to the change of ownership of an asset in a source network and a corresponding change of ownership in another network. No asset leaves the network it resides in. The well-known terminology for asset exchange is 'Atomic Cross-Chain Swap'. + +_For example_: two parties with both Bitcoin and Ethereum accounts may trade Bitcoin forEthereum based on an exchange rate agreed upon off-chain. We generalize this to permissioned networks, where it may be harder to provide guarantees of finality, and therby, atomicity. + +The figure below illustrates a typical asset exchange. Initially, Party X holds Asset M in Network A and Party Y holds Asset N in Network B. Through interoperation, an exchange occurs whereby Y holds M in A and X holds N in B. The changes in these two networks occur atomically. (_Note_: in such a use case, both X and Y must be members of both networks.) See [DvP in Financial Markets](user-stories/financial-markets.md) for an example scenario illustrating asset exchanges. + +![alt text](../../images-weaver-docs/use-cases/asset-exchange.png) + +Both the asset transfer and exchange patterns can be extrapolated to scenarios involving more than 2 parties, 2 assets, and 2 networks. The only fixed criterion is that the actions on all networks happen atomically. For the same reason, the infrastructure and protocols to support both asset transfers and exchanges overlap significantly. + +### Data Sharing +This refers to the transfer of data from its source ledger to a consuming ledger. (In many scenarios, data records in one network ledger may need to be shared with another network ledger in order to drive forward a process on the latter.) The data transferred can be the result of invoking a contract or a database query. There are no technical limits to the number of times a given piece of data can be copied to other ledgers. + +The below figure illustrates this pattern, where initially, Data Record is maintained only on Network A's ledger, and through interoperation, a copy resides on Network B's ledger. (_Note_: the data record may be transformed within Network B during the sharing process before a transaction is committed to its ledger.) See [Global Trade](user-stories/global-trade.md) for an example scenario illustrating data sharing. + +![alt text](../../images-weaver-docs/use-cases/data-transfer.png) + +### Identity +This refers to the process by which identity can be expressed and comprehended beyond the boundaries of a single network. The ability to reason about identities as real-world entities along with credentials proving their membership in various networks is key to creating a trust basis that enables the three interoperability modes listed above. From that perspective, this kind of cross-network identity management lies on a higher plane than data and asset movements. For more details on our thinking, see the Interop RFC pages. diff --git a/docs/docs/weaver/introduction.md b/docs/docs/weaver/introduction.md new file mode 100644 index 0000000000..bb531c3133 --- /dev/null +++ b/docs/docs/weaver/introduction.md @@ -0,0 +1,31 @@ +--- +id: introduction +title: Weaver Framework +--- + + + +Weaver is a framework that enables scalable interconnectivity between disparate distributed ledgers in a manner that preserves core tenets of decentralisation and security. +The framework, consisting of a family of protocols, is designed and built with the following key guiding principles, which are further discussed in [Design Principles](design-principles.md): + +- **Inclusiveness**: Avoid approaches that are specific to a particular DLT implementation and design. +- **Independence**: Interoperable networks retain sovereignty on their own processes and access control rules. +- **Minimum Trust**: Reduce trust to only what is essentials (i.e. identity providers in the network). +- **Privacy by Design**: Interaction between parties across networks should be kept private and confidential and revealed only to the interested parties. +- **No Intermediaries**: No third-party intermediary should be relied upon for the purpose of cross-network data verification or settlement. +- **Minimal Shared Infrastructure**: Rely on external infrastucture only for discovery, identification, and tracking/auditing, and not for cross-network transactions. +- **Leverage Consensus**: Use the respective ledgers' native distributed consensus mechanisms as the trust basis for cross-network transactions. +- **Non-Intrusion**: Require no changes to the DLT platforms and consensus mechanisms on which the networks are built, nor any dilution of the networks' security models. +- **Transparency**: Facilitate tracking and auditing of cross-network transactions. + +The protocol is designed around the following key elements: + +1. *State Proofs*: these allow a network to independently verify that any state it consumes from another network is valid according to the rules and policies of that network, or adheres to validity policies it imposes on state from that network. +2. *Asset Locks and Claims*: these allow a network to freeze an asset for a given time period on behalf of a user or allow a user to claim a frozen asset from its previous owner, either within a network or from a different network. +3. *Relays*: these are decentralised peer-to-peer services that enable communication of messages between networks. + +Weaver has a specification outlined through a set of [RFCs](specifications.md) and a reference implementation of that specification, which is discussed in this documentation. diff --git a/docs/docs/weaver/publications.md b/docs/docs/weaver/publications.md new file mode 100644 index 0000000000..d02649f2b9 --- /dev/null +++ b/docs/docs/weaver/publications.md @@ -0,0 +1,48 @@ +--- +id: publications +title: Publications +--- + + + +[Visit the repository](https://github.com/hyperledger/cacti/blob/main/weaver/OVERVIEW.md#articles) to find the current list of articles, talks, and research papers. + +## 2021 + +### Verifiable Observation of Permissioned Ledgers + +*IEEE International Conference on Blockchain and Cryptocurrency*, 2021 + +Ermyas Abebe, Yining Hu, Allison Irvin, Dileban Karunamoorthy, Vinayaka Pandit, Venkatraman Ramakrishna, Jiangshan Yu + +[`[arXiv]`](https://arxiv.org/abs/2012.07339) + +### Decentralized Cross-Network Identity Management for Blockchain Interoperation + +*IEEE International Conference on Blockchain and Cryptocurrency*, 2021 + +Bishakh Chandra Ghosh, Sandip Chakraborty, Venkatraman Ramakrishna, Chander Govindarajan,Dushyant Behl, Dileban Karunamoorthy, Ermyas Abebe + +[`[arXiv]`](https://arxiv.org/abs/2104.03277) + + +## 2019 + +### Enabling Enterprise Blockchain Interoperability with Trusted Data Transfer + +*Proceedings of the 20th International Middleware Conference Industrial Track*, 2019 + +Ermyas Abebe, Dushyant Behl, Chander Govindarajan, Yining Hu, Dileban Karunamoorthy, Petr Novotny, Vinayaka Pandit, Venkatraman Ramakrishna, Christian Vecchiola + +[`[Proceedings]`](https://dl.acm.org/doi/abs/10.1145/3366626.3368129) [`[arXiv]`]( https://arxiv.org/abs/1911.01064) + + +### On the Interoperability of Distributed Ledgers, Medium + +Dileban Karunamoorthy, Ermyas Abebe + +[`[Medium]`](https://medium.com/thinkdecentralized/on-the-interoperability-of-distributed-ledgers-15f584b79808) diff --git a/docs/docs/weaver/roadmap.md b/docs/docs/weaver/roadmap.md new file mode 100644 index 0000000000..2e3f6bbe75 --- /dev/null +++ b/docs/docs/weaver/roadmap.md @@ -0,0 +1,10 @@ +--- +id: roadmap +title: Roadmap +--- + + diff --git a/docs/docs/weaver/security-model/access-control.md b/docs/docs/weaver/security-model/access-control.md new file mode 100644 index 0000000000..6fc8ab1243 --- /dev/null +++ b/docs/docs/weaver/security-model/access-control.md @@ -0,0 +1,11 @@ +--- +id: access-control +title: Access Control +--- + + + diff --git a/docs/docs/weaver/security-model/authentication.md b/docs/docs/weaver/security-model/authentication.md new file mode 100644 index 0000000000..329c07e8e5 --- /dev/null +++ b/docs/docs/weaver/security-model/authentication.md @@ -0,0 +1,10 @@ +--- +id: authentication +title: Authentication +--- + + diff --git a/docs/docs/weaver/security-model/end-to-end-security.md b/docs/docs/weaver/security-model/end-to-end-security.md new file mode 100644 index 0000000000..28b0d7caff --- /dev/null +++ b/docs/docs/weaver/security-model/end-to-end-security.md @@ -0,0 +1,149 @@ +--- +id: end-to-end-security +title: End-to-End Security +--- + + + +## Relay Security Model + +## A Relayer of Cryptographic Proofs + +The primary function of the relay is to orchestrate the flow of cyrptographic messages between networks enabling a variety of interoperability modes: + +* Transfer of data between networks +* Transfer of assets between networks +* Exchange of value between networks + +These cryptographic messages represent valid state in a distributed ledger and are generated using a range of cryptographic approaches, such as attestation by a set of authoritative nodes, a non-interactive proof of PoW, or a zero-knowledge proof (proof of computational integrity). The mechanisms for deriving such proofs rely on the model of trust provided by the underlying network of nodes. The relay thus plays no direct role in the generation of proofs, removing the need for remote agents (decentralized networks, applications or users) to trust the relay for proof veracity. + +The relay's message exchange protocol is in a state of development with a view towards supporting multiple interoperability modes. The current implementation however is limited to the transfer of data between networks. Future versions will enable asset and value transfers protocols. + +**NOTE:** The security models examined below is limited to the transfer of data where remote queries are initiated by applications. + +## Deployment Configurations and Security Implications + +The relay acts as a gateway between networks for enabling cross-chain communication and supports flexible deployment configurations. + +The configuration in any deployment must statisfy the goals of the parties involved in the message exchange. These goals inform the security policy and the adversarial assumptions. The mechanisms for threat mitigation is based on these assumptions. + +The configurations described below assume that: + +* A small fraction of the parties (e.g. f < n - m, where 'm' is the minimum threshold required for agreement) in a group or network might be byzantine. +* The threat imposed by a byzantine party with priviledges to construct a valid proof is no worse if the party is also in control of a relay. +* A valid proof is one that satisfies a consumer's proof critieria (policy). + +### 1. Confidential Message Exchange Between Groups of Parties + +![Confidential Message Exchange](../../../images-weaver-docs/relayd/confidential-message-exchange.png "Confidential Message Exchange") + +**Goals** + +A group of parties sharing confidential data agree to share a view of their data to remote group. The system configuration will provide the following properties: + +* Preserve confidentiality of messages exchanged between the groups involved. +* Preserve integrity of messages exchanged across the groups. +* The system must be available for servicing requests. + +**Threat Assumptions** + +An adversary in this configuration might seek to: + +* Gain access to the confidential data. +* Tamper with the integrity of the messages exchanged. +* Censor messages. +* Deny service. + +**Mechanisms for Threat Mitigation** + +A suitable deployment configuration that addresses these threat assumptions: + +* Relays will only be deployed and operated by organizations with access to the confidential data and privileges to construct valid proofs. +* A secure channel (mutual TLS) between the relays prevents external adversaries from evesdropping on the communication. +* The inclusion of a nonce in the proof enables replays of past messages to be detected. +* The deployment of multiple relays ensures availability and resistance to censorship. + +In the following configuration, a group in one network maintains confidential data and have similar goals as above. The data in the providing network is private but visible to all organizations. The relay in the providing network can be operated by any organization with access to the data (the implications of this are examined next). + +![Confidential Message Exchange](../../../images-weaver-docs/relayd/confidential-message-exchange2.png "Confidential Message Exchange") + +### 2. Private Message Exchange Between Networks + +**Goals** + +In the following configuration, the data is private to both networks but not confidential to any subset of the members. The system configuration must provide the following properties: + +* Preserve confidentiality of messages exchanged between the networks. +* Preserve integrity of messages exchanged across the networks. +* The system must be available for servicing requests. + +**Threat Assumptions** + +An adversary in this configuration might seek to: + +* Gain access to the private data. +* Tamper with the integrity of the messages exchanged. +* Censor messages. +* Deny service. + +**Mechanisms for Threat Mitigation** + +A suitable deployment configuration that addresses the threat assumptions: + +* Relays will be deployed and operated by organizations that are members of the network with access to the shared private data and privileges to construct valid proofs. +* A secure channel (mutual TLS) between the relays prevents external adversaries from evesdropping on the communication. +* The inclusion of a nonce in the proof enables replays of past messages to be detected. +* The deployment of multiple relays ensures availability and resistance to censorship. + +![Private Message Exchange](../../../images-weaver-docs/relayd/private-message-exchange.png "Private Message Exchange") + + +### 3. Public Message Exchange Between Networks + +**Goals** + +A private network consumes data from a public permissionless network. The system configuration must provide the following properties: + +* Preserve confidentiality of messages exchanged between the networks. +* Preserve integrity of messages exchanged across the networks. +* The system must be available for servicing requests. + +**Threat Assumptions** + +An adversary in this configuration might seek to: + +* Monitor data accessed by the private network. +* Tamper with the integrity of the messages exchanged. +* Censor messages. +* Deny service. + +**Mechanisms for Threat Mitigation** + +A suitable deployment configuration that addresses the threat assumptions: + +* Nodes (clients) of the public ledger will be deployed and operated by multiple organizations in the private network (a sufficient distribution to accomodate 'f' faulty nodes) + * Nodes modified to sign responses with a valid identity certificate (e.g. Hyperledger Besu as Ethereum mainnet client). +* Relays to private and public nodes will be deployed and operated by organizations within the network. +* The inclusion of a nonce in the proof enables replays of past messages to be detected. +* The deployment of multiple relays ensures availability and resistance to censorship. + +![Private Public Data Exchange](../../../images-weaver-docs/relayd/private-public-message-exchange.png "Private-Public Message Exchange") + +The following alternate configuration allows for a public node to be operated by a single organization. The oracle provides trusted meta-data to ensure proofs can be validated correctly (E.g. current validator set used for signing blocks in PoS/BFT sysmtems and block height to verify currency of state. A formal study on mechanisms for proof construction and their short-commings has been deferred). + +![Private Public Data Exchange](../../../images-weaver-docs/relayd/private-public-message-exchange2.png "Private-Public Message Exchange") + +In the following configuration an external notary acts as an authoritative source for public ledger data. A secure channel (mutual TLS) between the relays prevents external adversaries from evesdropping on the communication. + +![Private Public Data Exchange](../../../images-weaver-docs/relayd/private-public-message-exchange3.png "Private-Public Message Exchange") + + +## Nonces and Replay Attacks + + + + diff --git a/docs/docs/weaver/security-model/proofs-and-verification.md b/docs/docs/weaver/security-model/proofs-and-verification.md new file mode 100644 index 0000000000..b59e672643 --- /dev/null +++ b/docs/docs/weaver/security-model/proofs-and-verification.md @@ -0,0 +1,10 @@ +--- +id: proofs-and-verification +title: Proofs and Verification +--- + + diff --git a/docs/docs/weaver/specifications.md b/docs/docs/weaver/specifications.md new file mode 100644 index 0000000000..f20fda8bd9 --- /dev/null +++ b/docs/docs/weaver/specifications.md @@ -0,0 +1,14 @@ +--- +id: specifications +title: Specifications +--- + + + +The Weaver specifications ([RFCs](https://github.com/hyperledger/cacti/tree/main/weaver/rfcs)) capture abstractions, models, protocols and data formats for enabling cross-ledger communication. + +For newcomers who wish to find out more details about the Weaver design and wish to contribute to the code base, we recommend starting with the [models](https://github.com/hyperledger/cacti/tree/main/weaver/rfcs/models). Protocol engineers will find in [RFC: 01-009](https://github.com/hyperledger/cacti/blob/main/weaver/rfcs/models/infrastructure/relays.md) a useful overview of the relay model, and may then progress on to reading one of the existing protocols' design and implementation; e.g., the data sharing protocol in [RFC: 02-001](https://github.com/hyperledger/cacti/blob/main/weaver/rfcs/protocols/data-sharing/generic.md). If you are interested in adding support for a new ledger technology, see the [existing driver implementations](https://github.com/hyperledger/cacti/tree/main/weaver/core/drivers) and [existing interoperability module implementations](https://github.com/hyperledger/cacti/tree/main/weaver/core/network). Where relevant we use [ABNF](https://tools.ietf.org/html/rfc5234) for formal syntax definitions. diff --git a/docs/docs/weaver/user-stories/financial-markets.md b/docs/docs/weaver/user-stories/financial-markets.md new file mode 100644 index 0000000000..92fbc8f556 --- /dev/null +++ b/docs/docs/weaver/user-stories/financial-markets.md @@ -0,0 +1,39 @@ +--- +id: financial-markets +title: DvP in Financial Markets +--- + + + +In traditional financial markets parties trade assets such as securities and derivatives for cash or other assets. To reduce risk, various clearing and settlement processes and intermediaries are often involved. One form of settlement is a DvP (delivery versus payment) where the transfer of securities is performed only in the event of a corresponding payment. This arrangement reduces principal risk by ensuring that both parties receive their end of the exchange. However, settlement in financial markets are slow and time consuming. It also involves counterparty risks and requires intermediaries. + +Over the past few years, we have been seeing significant efforts in digitising and tokenising both currencies and securities on Distributed Ledger Technology (DLT) infrastructures. On the one hand we have seen concerted efforts around Central Bank Digital Currencies (CBDC) being added to the landscape of other blockchain based payment networks. On the other hand, we have also seen efforts such as that from the Australian Stock Exchange (ASX) to replace its current settlement system--Clearing House Electronic Subregister System (CHESS) with a DLT based platform by 2021. + +Against this backdrop, a number of central banks have been exploring the potential of performing DvP settlement across a currency ledger and a securities ledger. In this use case, we use this as a motivating use-case for our discussions. The scenario involves two decentralised ledgers, namely, a currency ledger and a securities ledger, based on different DLT protocols performing a coordinated transfer of assets in their respective ledgers. + +The figure below depicts this scenario in the context of two organisations--*Org-A* and *Org-B*. *Org-B* wants to purchase some securities owned by *Org-A* and both organisations have accounts on both ledgers. This scenario is simplified and leaves out a number of additional real world processes. For instance, the buyer and seller for securities need to discover each other and agree on the price and terms of a sale. In addition, an offer to sell securities might be fulfilled by multiple buyers taking smaller portions of the amount for sale. Such capabilities are often offered by centralised exchanges that offer capabilities such as order books and matching engines to address these needs. In this scenario we instead focus on the settlement process that follows such steps, once the parties of an exchange and the price of the exchange for an asset are determined. + +To effect the settlement of this exchange between *Org-A* and *Org-B*, the following two transactions will have to happen atomically across both networks: i) transfer of payment from *Org-B*'s currency account in the CBDC ledger to *Org-A* while at the same time ii) the entitlements of the designated securities are transferred from *Org-A* to *Org-B*. The scenario would need to guarantee that after the transaction execution, either both parties have their end of the exchange or neither does and that this exchange is performed in a timely manner. + +![Simple DvP scenario in financial markets](../../../images-weaver-docs/use-cases/financial-markets-1.png) + +The settlement of the exchange of securities from *Org-A* to *Org-B* in the Financial Securities Network for a simultaneous payment from *Org-B* to *Org-A* in the CBDC network is coordinated by Weaver using [Hashed Time Lock Contracts](https://en.bitcoin.it/wiki/Hash_Time_Locked_Contracts). +This protocol essentially has three phases: + +- Fund locking: To initialise an asset exchange, it is common for one or both parties to first lock up funds with a fund-withholding party on his or her own blockchain. Temporary fund locking ensures the locked fund cannot be used for other purposes while the exchange is being executed. This scheme is often used with a specified timeout to provide flexibility for reclaiming locked funds if the exchange does not take place. +- Fund redeeming: In general, the execution requires a pair of transactions to occur on both blockchains, e.g., from Org-A to Org-B on the FSN ledger and from Org-B to Org-A in CBDC ledger. When certain conditions are met, the locked funds can be redeemed by, or paid to the respective users. The execution of the exchange can be carried out by users themselves, or through other trusted third parties. These trusted third parties can be stand-alone parties that are not otherwise involved in both blockchains, or part of either blockchain.  +- Refund: For protocols that are initialised with a temporary fund-locking, the locked funds can usually be reclaimed by the initial owner after a specified timeout, if a redemption has not occurred.  + +The process proceeds as follows, and is further illustrated in the figure below: + +1. **Org-A locks its securities in FSN ledger**: *Org-A* first creates some secret S, known only to it and locks its securities using the hash of S. The securities are configured to redeemable by *Org-B* if it presents S within some specified time threshold. +2. **Org-B locks payments tokens in CBDC ledger**: Org-B, observes that *Org-A* has locked its securities in the FSN network and does a corresponding lock of its payment tokens with the hash of S, used by *Org-A* in locking its securities. The payment tokens are redeemable only by Org-A, if it submits a transaction that reveals S within a specified time. +3. **Org-A checks Org-B's contract in CBDC ledger**: *Org-A* checks the CBDC network to ensure that the payments tokens are locked by Org-B. +4. **Org-A claims payments in CBDC ledger**: *Org-A* submits a transaction to claim the payments tokens, by revealing the secret S. +5. **Org-B claims securities in FSN ledger**: *Org-B* observes that the value of S has been revealed in the CBDC network by *Org-A* in step 4, and submits a transaction to claim the securities in the FSN network using the revealed secret. + +![Simple DvP scenario in financial markets](../../../images-weaver-docs/use-cases/financial-markets-2.png) diff --git a/docs/docs/weaver/user-stories/global-trade.md b/docs/docs/weaver/user-stories/global-trade.md new file mode 100644 index 0000000000..3379bc0cda --- /dev/null +++ b/docs/docs/weaver/user-stories/global-trade.md @@ -0,0 +1,112 @@ +--- +id: global-trade +title: Global Trade +--- + + + +The examples in this page cover the __global trade__ application domain and the __data sharing__ pattern. + +## Process Overview +At its simplest, international trade is about a party in one country buying certain goods from a party in another country. Because the goods cross international boundaries, the buyer is called an _importer_ and the seller is called an _exporter_. For the same reason, this process is not as straightforward as, say, purchasing an item from a retailer. + +The exporting of goods in most countries is governed by a host of regulatory provisions and authorities, making the very act of clearing the sale and getting the goods ready for shipment a complex one. Further, an exporter must rely on one or more _carriers_ to move the shipment from source to destination while managing all of the risks this entails. + +But this only covers the shipping logistics. The trading parties, i.e., the exporter and importer, both face what is called _counterparty risk_, or the hazard of giving something up without a guarantee of receiving something in return. If the exporter ships the goods first, the importer may renege on the payment. And if the importer mmakes the payment first, the exporter may renege on the shipment. To hedge against this risk, sophisticated process of _trade finance_ have evolved over centuries, with banks or other financial institutions providing the sorts of guarantees (in exchange for fees) that enable exporters and importers to safely conduct trades. + +Permissioned blockchains are a great fit to manage such trade scenarios, involving multiple independent entities and no governing authorities, using smart contracts. Let us now see two kinds of processes in action, each of which can be managed in its own restricted network: + +1. __Trade logistics__: preparation, clearance, and export of goods +2. __Trade finance__: payment guarantees and fulfillment + +## Networks in Isolation +There exist real business networks in production that manage trade logistics and finance, but they can be very complex. We will present highly simplified versions of these processes, and focus on the aspects that will motivate the need for data sharing across networks. + +Also, we will henceforth use the terms _buyer_ and _seller_ instead of _importer_ and _exporter_ respectively. + +### Initiating a Trade +Our trade process begins offline, with buyer and seller negotiating and agreeing on the sale of particular goods for given payment. We will assume that a _purchase order_ is created and contains a unique id we can use as reference in subsequent steps. This is illustrated in the figure below. + +![alt text](../../../images-weaver-docs/use-cases/purchase-order.png) + +### Trade Logistics Network +The figure below represents a trade logistics network consisting of a seller and a carrier, loosely inspired by the TradeLens network built on Hyperledger Fabric. Think of the seller as a coffee plantation owner is Brazil, for example, and the carrier as a prominent shipping company like Maersk. + +![alt text](../../../images-weaver-docs/use-cases/trade-logistics-network.png) + +The seller begins by booking a shipping consignment (associated with the purchase order id) and then registering its creation. It then hands the consignment over to the carrier. In a real life export scenario, this process involves a lot of documentation and approval cycles, but we are going to ignore all of those here. The carrier supplies documents certifying its possession of the consignment and the contents within it. The _bill of lading_ (B/L for short) is one of these documents, and though there may be others, like a packing list and a shipping manifest, we only need one to motivate interoperability. So we will keep it simple and assume that the carrier simply uploads a B/L. The seller examines and accepts this document, following which the carrier dispatches the consignment. + +__Note that, at this point, a valid B/L is recorded on the trade logistics network ledger, a fact we will make use of soon enough.__ + +### Trade Finance Network +The figure below represents a trade finance network consisting of a seller, a buyer, and their respective banks. This is loosely inspired by the We.Trade network built on Hyperledger Fabric and the Marco Polo network built on R3 Corda. Think of the seller as our coffee plantation owner in the logistics network, the buyer as Starbucks, and the banks as Bank of America and HSBC Bank, for example. + +![alt text](../../../images-weaver-docs/use-cases/trade-finance-network.png) + +Traders and banks use a variety of mechanisms to mitigate counterparty risk, one of them being _open accounting_, used in networks like We.Trade. We pick the popular _letter of credit_ (L/C for short) instrument for our trade finance story as this exemplifies the inherent link between logistics and finance (we will see this later). The process begins with the buyer requesting an L/C from its bank for a given trade, referring to the id of the purchase order generated earlier. In simplest terms, an L/C is a promise made by a bank to pay a certain amount to the bearer of certain documents associated with a given export shipment. In our scenario, the buyer's bank issues an L/C promising to pay the seller (through its bank) the amount due to it upon production of a valid B/L. This L/C proposal is recorded on the ledger, and subsequently approved by the seller's bank. After the seller uploads a B/L, the seller's bank is allowed to register a request for payment. This leaves a payment obligation for the buyer's bank on the ledger, which is where we will conclude the scenario, as the actual payment is carried out through a separate process on a different network. + +__Note that the seller is supposed to produce and record a valid B/L in Step 4.__ + +## Linking Finance with Logistics +It is obvious that the logistics and finance processes are linked. Both begin with references to a common purchase order id and both involve bills of lading. Let us focus on the B/L, as it exemplifies a common pattern in these kinds of business networks: _that of being generated in one network and being used in another_. Because thee are two separate networks, the trade finance network depends on the seller to upload a B/L. But here, we encounter another kind of hazard, one we discussed earlier in the [challenges](./overview#challenges-to-overcome) section. The seller has an incentive to produce a fake bill of lading in order to get paid for goods it may not have dispatched and may have no intention of dispatching. In the present setup, the trade finance network as a whole, nor the buyer or its bank, has visibility into the trade logistics network's ledger, and hence have to trust the seller's word. + +This hazard can be avoided if the networks are interoperable, and can share data with each other. Specifically, if the trade logistics network can share a B/L recorded on its ledger _institutionally_ with the trade finance network. To see how this works, see the diagram below, which contains both the networks and merges their flows. + +![alt text](../../../images-weaver-docs/use-cases/interop-bl.png) + +Step 4 in the [isolated trade finance network](./global-trade#trade-finance-network) is now replaced with an interoperation step (Step 10) whereby the trade finance network obtains a B/L from the trade logistics network via a data-sharing protocol. This avoids the hazard of having to depend on an unreliable seller to supply a valid B/L. But it is not enough for the trade logistics network to share B/L data. It must also share some _proof_ or evidence that the B/L is presently on record in its shared ledger. + +__Note: in general, an interoperation mechanism for data sharing must communicate data as well as an associated proof that can be _independently verified_ by every memebr of the receiving network.__ + +## Extending the Scenario +The above example conforms to how the logistics and finance processes work today. Letters of credit typically specify bills of lading among the lists of documents that must be supplied to claim a payment. But state-of-the-art blockchain technology and permissioned networks can facilitate a lot more process innovation than earlier technology could. + +The present trade logistics network allows a consignment to be created and dispatched without any knowledge of how the trade will be financed. But in real life, there is a need to track imports and exports carefully to ensure that no regulations are broken, and secondarily, to avoid wasted effort. Therefore, we can envision trade logistics networks requiring some evidence of the financial arrangements of a trade before it allows a seller and a carrier to carry out with the shipping process. + +The process augmentation is illustrated in the figure below with the insertion of a new Step 6 between the booking and the creation of a shipping consignment. + +![alt text](../../../images-weaver-docs/use-cases/interop-lc-bl.png) + +Like Step 11 (Step 10 in the earlier figure), this is a data-sharing interoperation step where the L/C proposed and accepted on the trade finance network's ledger is copied to the trade logistics network's ledger. (As with the B/L sharing, proof of the L/C ledger record must accompany L/C data.) In this new process, the trade logistics network will not waste time processing shipments that do not have a backing L/C guarantee from the trade finance network. + +__Note that in the interoperation steps, the artifact being shared by one network with another (B/L or L/C) does not have to be copied verbatim to the receiving network's ledger. The process incorporates transformations carried out through smart contract transactions occurring through their networks' native consensus mechanisms.__ + +## Vision: Network of Networks +The promise of blockchain was a more decentralized yet trustworthy internet, but as we saw earlier, networks like Bitcoin and Ethereum may not fulfill that promise, largely because they have technical limitations when it comes to performance and scaling, privacy preservation, and auditability. At the same time, private blockchain networks are here to stay, and they do overcome these technical limitations, albeit at smaller scale. In the longer term, a more sustainable and achievable vision will be to allow private networks to exist while possessing the means to interoperate with other private networks. The interlinking of a trade logistics network with a trade finance network was just a sample. There is more aspects to an international trade scenario: more networks and more cross-network dependencies. But as long as we can institute mechanisms to link two networks directly for data-sharing, we can extrapolate our two-network scenario into a network-of-networks scenario. + +To show how this will work, we will add two more networks to the mix. Business networks exist to track the quality and health of perishable goods from the production source to the end retailer. These networks complement networks like Trade Lens, which manage the long-distance shipping that occurs in the middle but have no visibiity into the goods before consignment creation or after delivery at the destination by the carrier. To track goods at either ends is the function of networks like IBM Food Trust, which would be ideal for the coffee shipment example we used earlier. A separate aspect of our trade scenario is the actual payment a buyer makes to the seller. Our trade finance network ends by recording a payment obligation, but the transfer of money needs to occur on a separate payment network, like, for example, the Stellar Network. + +The figure below presents our vision for how cross-network data sharing can help smoothen and simplify all aspects of global trade despite the fact that different sub-processes occur on independent private networks. + +![alt text](../../../images-weaver-docs/use-cases/interop-four-networks-trade.png) + +The _Food Tracking Network_ is loosely inspired by IBM Food Trust and the _Payments Network_ loosely inspired by Stellar. + +- The seller and buyer, as the trading parties, belong to the food tracking network. The process in this network begins with a registration of a purchase order, following which perishable goods (think coffee seeds, for example) are tracked from farms to a warehouse where a shipping consignment is created. Whenever the carier delivers the shipment, the fact of delivery is recorded as is the condition of the goods within. +- The payment network has the buyer's and seller's bank as members. Action in this network is triggered by the buyer's bank making a payment, or a monetary transfer, to the seller's bank. Both banks have accounts in this network and the payment succeeds or fails depending on available account balance. + +There are two parallel timelines starting at Step 17: + +- One involves the trade finance network and the payments network (Steps 17-20). Step 18 contains both "Make Payment" and "Receive Payment" as these actions are supposed to occur atomically within the payments network. These pertain to the fulfilment of the payment promised to the seller by the buyer. +- Another involves the trade logistics network and the food tracking network (Steps 17-19). These pertain to the tracking of goods after dispatch and confirmation of their subsequent delivery and condition. + +You may notice we have augmented the trade logistics and trade finance processes as follows: + +- Step 17 in the trade logistics network illustrates a sequence of transactions, each recording the location and condition of the goods in transit at periodic intervals. We assume that this information can be procured using sensors deployed with the consignment. +- Step 20 in the trade finance network results in the cancelling of the payment obligation recorded by the seller's bank in Step 17 within that network ("Request Payment"), thereby concluding the trade instance associated with the purchase order id generated in Step 1. + +The data-sharing interoperation steps are as follows: + +- _Step 3_: The trade finance network fetches a purchase order from the food tracking network before permitting an L/C request to be made. +- _Step 8_: The trade logistics network fetches an L/C from the trade finance network before permitting a consignment to be created. +- _Step 9_: The food tracking network fetches a consignment booking record and an associated L/C from the trade logistics network before permitting tracking of goods from the source to the shipping warehouse. +- _Step 11_: The trade logistics network fetches tracking information indicating delivery of goods to the warehouse before permitting a consignment to be created. +- _Step 16_: The trade finance network fetches a B/L from the trade logistics network before permitting the seller's bank to register a payment request. +- _Step 18_: This is a recurring step, in each instance of which the food tracking network fetches location and condition information for a given consignment from the trade logistics network, and does not permit the confirmation of consignment delivery and the integrity of the goods within until the shipment reaches its destination and its condition meets the required standard. +- _Step 19_: The trade finance network gets confirmation of payment (from buyer's account to seller's account) from the payments network. + +To summarize, internationally traded goods can be tracked from a farm in one country to a retailer in another, the goods can be exported and shipped with all regulations complied with, financial guarantees can be put in place to safeguard the trading parties, and cross-border payments can be processed seamlessly and in a trustworthy manner. But this requires a combination of private blockchain networks willing to share data with each other and also have the ability to verify the authenticity of received data. We hope this scenario makes the motivation for data-sharing interoperation mechanisms perfectly clear. diff --git a/docs/docs/weaver/user-stories/legacy-integration.md b/docs/docs/weaver/user-stories/legacy-integration.md new file mode 100644 index 0000000000..b7431a84d3 --- /dev/null +++ b/docs/docs/weaver/user-stories/legacy-integration.md @@ -0,0 +1,18 @@ +--- +id: legacy-integration +title: Legacy Integration +--- + + + +A standard for self-contained messages respresenting state in distributed ledgers, along with proofs of validity, enables interoperability with legacy enterprise applications. These messages can be consumed, stored or forwarded by any traditional centralized application. + + +![](/legacy-integration.jpg) + + + diff --git a/docs/docs/weaver/user-stories/overview.md b/docs/docs/weaver/user-stories/overview.md new file mode 100644 index 0000000000..d9f4ef53cb --- /dev/null +++ b/docs/docs/weaver/user-stories/overview.md @@ -0,0 +1,27 @@ +--- +id: overview +title: Overview +--- + + + +In the [introduction](../interoperability-modes.md), we listed various modes (or patterns) of interoperation like asset transfers, asset exchanges, and data sharing. In IT parlance, we can think of this as a _horizontal_ classification of use cases for interoperability. In this section of the documentation, we will discuss the _verticals_, or application domains, that exemplify the use and necessity of interoperation mechanisms. + +## Application Domains + +Distributed ledger technology has been applied gainfully to several areas where legacy processes were inefficient, cumbersome, and error-prone. With the enablement of interoperation among these networks, they have the potential to take the next step toward a truly decentralized yet trustworthy internet. We call out two prominent focus areas. + +### Global Trade +Trade when seen from a global and international perspective is highly complex. In the absence of central coordinating and law-enforcing authorities at the world level, various ad hoc processes have been created and refined over centuries by merchants, financiers, and regulators, to manage complex supply-chain logistics and cross-border financing that underpin global trade. These processes exist to ensure that parties can hedge their risks, mitigate possibilities for non-compliance, and ship goods from one location to another while complying with regulatory guidelines. + +Multiple networks have emerged to handle trade processes limited in scope. There exist networks to handle trade logistics (like TradeLens, built on Hyperledger Fabric), food tracking (IBM Food Trust, built on Hyperledger Fabric), trade finance (like We.Trade, built on Hyperledger Fabric, and Marco Polo, built on R3 Corda), cross-border payments, and _know-your-customer_, or KYC, processes. An end-to-end trade scenario, involving shipment of goods, financing commitments, documentation, shipping, tracking, and payments, will rely on many or all of these networks. Interoperation will help us overcome this fragmentation and lack of visibility of one network into another, and enable trustworthy and efficient trades at global scale using blockchain technology. See [Global Trade](./global-trade.md) for a concrete example. + +### Financial Markets +Securities trading is a common and lucrative transaction in financial markets. As with any form of exchange, when a security is sold in exchange for money, the party that gives up its asset first faces a _non-compliance risk_; i.e., the other party may renege on the deal after it receives an asset. With the advent of blockchain-backed digital currencies maintained by countries' central banks, opportunities now exist to carry out security trades safely and efficiently. But this requires interoperation between networks managing digital currency on behalf of central banks (like private versions of Bitcoin networks with faster commitment times) and networks managing tracking securities and their ownerships. See [DvP in Financial Markets](./financial-markets.md) for a concrete example. + +### Other Scenarios +There are other domains or _verticals_ we can think of that would benefit from interoperation. Healthcare is one, where different networks may exist: citizens' identity records, employer network, healthcare provider network, insurance companies' network, etc. For efficiency of operation (with privacy preservation guarantees) and to ensure that service and payments occur promptly and accurately, these networks may seek to interoperate. Similarly, interoperation between networks that manage users' academic and professional credentials may help employers and job seekers. diff --git a/docs/docs/weaver/what-is-interoperability/integration-patterns.md b/docs/docs/weaver/what-is-interoperability/integration-patterns.md new file mode 100644 index 0000000000..33bd809239 --- /dev/null +++ b/docs/docs/weaver/what-is-interoperability/integration-patterns.md @@ -0,0 +1,42 @@ +--- +id: integration-patterns +title: Integration Patterns +--- + + + +Integration patterns are well-known reusable solutions for integrating systems together. A number of patterns exist for addressing various types integration problems. The specific pattern applied in practice depends on the nature of the integration problem, the overall objective of the integration task, trade-offs in alternate approaches, and potential risks. + + + +## Distributed Ledger Integration Patterns + +Here we present common patterns for integrating distributed ledgers. Not all problems are equal, some approaches to itegrating ledgers are preferred over others depending on the use case, the purpose of the itegration and the risks involved. + +### Consensus-based integration between ledgers + +Consensus-based integration aims to communicate the consensus view of one network to another. The consensus view is a representation of state on the ledger that is collectively agreed by the members of the network. This form of integration provides the highest assurance on the validity of state. The Weaver framework is designed to address consensus-based integration between ledgers built on different distributed ledger protocols. + +![](../../../images-weaver-docs/integration-pattern-consensus-driven.jpg) + +### Standard API integration between applications + +A standard API integration relies on a single party exposing an endpoint for state exchange. The validity of state relies entirely on the trust placed on the party exposing the endpoint. + +![](../../../images-weaver-docs/integration-pattern-single-party-api.jpg) + +### Single enterprise participating in multiple neworks + +A single enterprise participating in multiple networks can integrate state and contract logic across these networks using off-chain workflows. Unlike the previous pattern, this pattern relies on the enterprise having valid membership credentials on multiple networks. Significant trust must be placed on the organization coordianting the exchange of state across these networks. + +![](../../../images-weaver-docs/integration-pattern-single-enterprise-multiple-networks.jpg) + +### Single network deployed on multiple heterogenous infrastructure + +Although not an integration pattern, this pattern demonstrates interoperability at the infrastructure layer. The ability to run nodes on multiple cloud providers, as well as on-prem infrastructure, ensures networks are resilient to failures or censorship by infrastructure providers. + +![](../../../images-weaver-docs/integration-pattern-single-network-multiple-cloud.jpg) diff --git a/docs/docs/weaver/what-is-interoperability/levels-of-interoperability.md b/docs/docs/weaver/what-is-interoperability/levels-of-interoperability.md new file mode 100644 index 0000000000..37571986fc --- /dev/null +++ b/docs/docs/weaver/what-is-interoperability/levels-of-interoperability.md @@ -0,0 +1,32 @@ +--- +id: levels-of-interoperability +title: Levels of Interoperability +--- + + + +Established models of information systems interoperability stratify interoperability concerns into multiple levels. This includes technical, syntactic, semantic and application levels as shown below. + +Above the protocol and application levels there are two additional levels that require careful attention when enabling interoperability. These cover governance and policy decisions when communicating state as well as the legal and regulatory implications of networks under different jurisdictions. + +![](../../../images-weaver-docs/levels-of-interoperability.jpg) + + +* **Technical**: The technical level is a low-level concern that focuses on the underlying wire protocol used for communication. Examples of protocols at this level include gRPC, Apache Thrift, ASN.1 and CBOR. Protocols at this level are point-to-point and addresses additional concerns such as version negotiation and message delivery guarantees. + +* **Syntactic**: The syntactic level is concerned with the structure and format of the messages exchanged. This includes protocol elements such as keywords and types. Examples include protocols defined using Google's Protocol Buffers, JSON-RPC and ASN.1. + +* **Semantic**: The semantic level provides meaning to the messages exchanged. In the context of cross-chain communication, this includes messages that represent a data transfer or an asset exchange as well as other information such as validity proofs and actors involved. + +* **Application**: The application level addresses domain or use-case specific concerns. In this level, interoperability deals with industry standard data models (e.g. supply chain standards such as GS1) and business processes. This level is orthogonal to the technology concerns of interoperability. + +* **Governance and Policies**: The governing members of a ledger play a critical role in extending business processes to external systems. Interoperability necessitates that the governing bodies of the respective systems agree on the nature of their collaboration. The policies enforce these decisions and covers aspects such as access control and conditions for determining the validity of state proofs. + +* **Legal and Regulation**: Networks residing in different jurisdictions must be comply with existing laws and regulations when communicating state. + + + diff --git a/docs/docs/weaver/what-is-interoperability/understanding-interoperability.md b/docs/docs/weaver/what-is-interoperability/understanding-interoperability.md new file mode 100644 index 0000000000..a2260683f6 --- /dev/null +++ b/docs/docs/weaver/what-is-interoperability/understanding-interoperability.md @@ -0,0 +1,48 @@ +--- +id: understanding-interoperability +title: Understanding Interoperability +--- + + + +Permissioned DLTs have been gaining significant traction in industry since their inception. They have enabled enterprises to harness the innovation of public blockchains, while adhering to the privacy, confidentiality and regulatory constraints that businesses operate under. Permissioned DLTs offer enterprises an infrastructure for managing inter-firm asset, data and business workflow, without the need for a central intermediary that introduces additional sources of risk. Businesses are able to transact directly while reducing counter-party risk and mitigating the need for costly and time-consuming dispute resolution processes, often involving legal and judicial systems. Thus far, the application of this technology has enabled digitisation and disintermediation of many entrenched industry processes, resulting in significant improvements in efficiency, transparency, risk and fraud. + +For practical reasons, the adoption of permissioned blockchains has thus far been driven through use-cases. Enterprises have been coalescing into consortia to create specialised networks that address narrowly-scoped use-cases in isolation. +This use-case driven approach to blockchain adoption is creating a proliferation of niche and isolated networks that are quickly becoming data and value silos. +In addition, these use-cases often represent a slice of a complex end-to-end business process. To deliver real value, permissioned networks need to seamlessly integrate with each other and with existing systems in order to holistically transform industries. This requirement for interoperation is coming to the fore as networks transition to production and scale towards broader adoption. + +Interoperability in the context of Distributed Ledger Technologies involves enabling the seamless flow of data and value across disparate networks in a manner that preserves their trust and security tenets. This capability can offer a number of benefits such as: + +- Removing data and value silos +- Increasing market sizes, liquidity and overall efficiency +- Improving network effects +- Enabling orchestration of complex business functionality across networks +- Enabling scale and groawth of networks +- Encouraging further adoption of the technology + + +## Unique Technical Challenges +Enabling interoperation between distributed ledgers presents numerous technical challenges compared to traditional systems integration approaches. This primarily stems from the need to preserve the benefits of decentralised trust beyond the boundaries of a single network. Hence, a naive approach to interoperability based on traditional point-to-point API integration is insufficient for preserving the underlying trust decentralised networks provide. There are two unique challenges present in DLT interoperation: + +### Single-party vs Multi-party Trust  +In distributed ledger architectures, the authority over state lies in a collective and the protocol they employ to ensure its integrity. When one network or an entity consumes state from another, it would need to establish the veracity of the state according to the shared consensus view of parties in the network. This requirement is different than traditional integration with centralised systems wherein the trust for the validity of data is placed on the single party providing the data. Establishing the veracity of state in a decentralized network is not trivial. In most cases, a consumer of state might not be able to observe the full ledger of the network itself. Hence, a consumer needs to obtain an independently verifiable cryptographic proof on the validity of state according to the consensus rules and policies of the source network. + +![single-party vs multi-party trust model](../../../images-weaver-docs/multi-party-trust-model.png) + +### Data vs Asset +Interoperation should not compromise the invariants enforced by individual networks such as protections against double spends on assets. + + +## The Role of Standards + +The term ‘interoperability’ is used rather loosely in many contexts and oftentimes without the same implication. What some call ‘interoperability’, others refer to as ‘integration’, ‘interconnectivity’ or ‘compatibility’. + +The primary goal of interoperability is freedom of choice. Interoperability enables users to choose implementations of systems they find suitable for a given problem without constraints on the system’s ability to communicate with other implementations. + +Implicit in the term interoperability is open standards, which distinguishes it from any form of bespoke integration. Open standards can either be de jure standards ratified by a formal standards organization such as ANSI, IETF, or ISO, or de facto standards proposed and adopted by communities, industries and the market. Open standards enable and encourage implementors to build systems that can work together. + + diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml new file mode 100644 index 0000000000..f77a679bd7 --- /dev/null +++ b/docs/mkdocs.yml @@ -0,0 +1,203 @@ +site_name: Using and Developing with Hyperledger Cacti +site_url: https://VRamakrishna.github.io/cacti +repo_name: hyperledger/cacti +repo_url: https://github.com/VRamakrishna/cacti +theme: + name: material + custom_dir: overrides + logo: images/HL_Cacti_Logo_Colorreverse.svg + favicon: images/HL_Cacti_Logo_Colorreverse.svg + icon: + repo: fontawesome/brands/github + palette: + # Palette toggle for light mode + - media: "(prefers-color-scheme: light)" + scheme: default + toggle: + icon: material/brightness-7 + name: Switch to dark mode + # Palette toggle for dark mode + - media: "(prefers-color-scheme: dark)" + scheme: slate + toggle: + icon: material/brightness-4 + name: Switch to light mode + features: + - content.code.copy + - navigation.expand + - navigation.footer + - navigation.instant + - navigation.tabs + - navigation.tabs.sticky + - navigation.top + - navigation.tracking + - toc.follow + - toc.integrate +markdown_extensions: + - abbr + - admonition + - attr_list + - def_list + - footnotes + - md_in_html + - toc: + permalink: true + toc_depth: 3 + - pymdownx.arithmatex: + generic: true + - pymdownx.betterem: + smart_enable: all + - pymdownx.caret + - pymdownx.details + - pymdownx.emoji: + emoji_generator: !!python/name:materialx.emoji.to_svg + emoji_index: !!python/name:materialx.emoji.twemoji + - pymdownx.highlight: + anchor_linenums: true + - pymdownx.inlinehilite + - pymdownx.keys + - pymdownx.magiclink: + repo_url_shorthand: true + user: squidfunk + repo: mkdocs-material + - pymdownx.mark + - pymdownx.smartsymbols + - pymdownx.superfences: + custom_fences: + - name: mermaid + class: mermaid + format: !!python/name:pymdownx.superfences.fence_code_format + - pymdownx.tabbed: + alternate_style: true + - pymdownx.tasklist: + custom_checkbox: true + - pymdownx.tilde +plugins: + - search + - mike +extra: + analytics: + provider: google + property: !ENV GOOGLE_ANALYTICS_KEY + version: + provider: mike +nav: + - Introduction: index.md + - Vision: vision.md + - Architecture: architecture.md + - Key Concepts: + - Data Sharing: concepts/data-sharing.md + - Use Cases: use-cases.md + - Cactus: + - Introduction: cactus/introduction.md + - Building: cactus/build.md + - Examples: + - Overview: cactus/examples.md + - Supply Chain Application: cactus/examples/supply-chain-app.md + - Governance: cactus/governance.md + - Code of Conduct: cactus/code-of-conduct.md + - Contributing: cactus/contributing.md + - Whitepaper: cactus/whitepaper.md + - Regulatory and Industry Initiatives: cactus/regulatory-and-industry-initiatives-reading-list.md + - Components: + - Overview: cactus/packages.md + - Api Client: cactus/packages/cactus-api-client.md + - CMD Api Server: cactus/packages/cactus-cmd-api-server.md + - Cactus Common: cactus/packages/cactus-common.md + - Cactus Core: cactus/packages/cactus-core.md + - Consortium Manual: cactus/packages/cactus-plugin-consortium-manual.md + - Keychain Vault: cactus/packages/cactus-plugin-keychain-vault.md + - Connector Besu: cactus/packages/cactus-plugin-ledger-connector-besu.md + - Connector Corda: cactus/packages/cactus-plugin-ledger-connector-corda.md + - Connector Fabric: cactus/packages/cactus-plugin-ledger-connector-fabric.md + - Connector Quorum: cactus/packages/cactus-plugin-ledger-connector-quorum.md + - Test Api Client: cactus/packages/cactus-test-api-client.md + - Test CMD Api Server: cactus/packages/cactus-test-cmd-api-server.md + - Test Connector Quorum: cactus/packages/cactus-test-plugin-ledger-connector-quorum.md + - Test Tooling: cactus/packages/cactus-test-tooling.md + - Ledger Support: + - Overview: cactus/support.md + - Hyperledger Besu: cactus/support/besu.md + - R3 Corda: cactus/support/corda.md + - Hyperledger Fabric: cactus/support/fabric.md + - Hyperledger Iroha: cactus/support/iroha.md + - Quorum: cactus/support/quorum.md + - xDai: cactus/support/xdai.md + - Weaver: + - Framework: weaver/introduction.md + - Getting Started: + - Using Weaver: weaver/getting-started/guide.md + - Launching a Test Network: + - Component Overview: weaver/getting-started/test-network/overview.md + - Setup with Locally Built Weaver Components: weaver/getting-started/test-network/setup-local.md + - Setup with Locally Built Dockerized Weaver Components: weaver/getting-started/test-network/setup-local-docker.md + - Setup with Imported Weaver Components: weaver/getting-started/test-network/setup-packages.md + - Setup with Imported Dockerized Weaver Components: weaver/getting-started/test-network/setup-packages-docker.md + - Ledger Initialization: weaver/getting-started/test-network/ledger-initialization.md + - Advanced Configuration: weaver/getting-started/test-network/advanced-configuration.md + - Testing Interoperation Modes: + - Overview: weaver/getting-started/interop/overview.md + - Data Sharing: weaver/getting-started/interop/data-sharing.md + - Asset Exchange: + - Overview: weaver/getting-started/interop/asset-exchange/overview.md + - Fabric with Fabric: weaver/getting-started/interop/asset-exchange/fabric-fabric.md + - Fabric with Corda: weaver/getting-started/interop/asset-exchange/fabric-corda.md + - Fabric with Besu: weaver/getting-started/interop/asset-exchange/fabric-besu.md + - Corda with Corda: weaver/getting-started/interop/asset-exchange/corda-corda.md + - Corda with Besu: weaver/getting-started/interop/asset-exchange/corda-besu.md + - Besu with Besu: weaver/getting-started/interop/asset-exchange/besu-besu.md + - Asset Transfer: weaver/getting-started/interop/asset-transfer.md + - Enabling Weaver in your Network and Application: + - Overview: weaver/getting-started/enabling-weaver-network/overview.md + - Hyperledger Fabric: weaver/getting-started/enabling-weaver-network/fabric.md + - R3 Corda: weaver/getting-started/enabling-weaver-network/corda.md + - Hyperledger Besu: weaver/getting-started/enabling-weaver-network/besu.md + - What is Interoperability?: + - Understanding Interoperability: weaver/what-is-interoperability/understanding-interoperability.md + - Levels of Interoperability: weaver/what-is-interoperability/levels-of-interoperability.md + - Integration Patterns: weaver/what-is-interoperability/integration-patterns.md + - Interoperability Modes: weaver/interoperability-modes.md + - Design Principles: weaver/design-principles.md + - User Stories: + - Overview: weaver/user-stories/overview.md + - Global Trade: weaver/user-stories/global-trade.md + - DvP in Financial Markets: weaver/user-stories/financial-markets.md + - Legacy Integration: weaver/user-stories/legacy-integration.md + - Architecture and Design: + - Overview: weaver/architecture-and-design/overview.md + - Relay: weaver/architecture-and-design/relay.md + - Drivers: weaver/architecture-and-design/drivers.md + - Weaver DApps: weaver/architecture-and-design/weaver-dapps.md + - Decentralized Identity: weaver/architecture-and-design/decentralized-identity.md + - Security Model: + - Authentication: weaver/security-model/authentication.md + - Access Control: weaver/security-model/access-control.md + - Proofs and Verification: weaver/security-model/proofs-and-verification.md + - End-to-End Security: weaver/security-model/end-to-end-security.md + - Deployment Considerations: + - Deployment Patterns: weaver/deployment-considerations/deployment-patterns.md + - Governance and Policies: weaver/deployment-considerations/governance-and-policies.md + - Legal and Regulation: weaver/deployment-considerations/legal-and-regulation.md + - Specifications: weaver/specifications.md + - Roadmap: weaver/roadmap.md + - Publications: weaver/publications.md + - Guides: + - Operations: guides/operations.md + - Developers: guides/developers.md + - Upgrading: guides/upgrading.md + - References: + - Technical Specifications: references/specs.md + - Publications: references/publications.md + - Events and Podcasts: references/events.md + - Business Usage: references/business.md + - Project Best Practices: references/best-practices.md + - GitHub Contributions: references/github.md + - Contributing: + - How to Contribute: contributing/how-to-contribute.md + - Reporting a Bug: contributing/reporting-a-bug.md + - Requesting a Change: contributing/requesting-a-change.md + - Asking a Question: contributing/asking-a-question.md + - FAQs: faqs.md + - Glossary: glossary.md + - Contact Us: contact-us.md +copyright: Copyright © Hyperledger 2020-2023 diff --git a/docs/overrides/main.html b/docs/overrides/main.html new file mode 100644 index 0000000000..8d9f505096 --- /dev/null +++ b/docs/overrides/main.html @@ -0,0 +1,8 @@ +{% extends "base.html" %} + +{% block outdated %} + You're not viewing the latest version. + + Click here to go to latest. + +{% endblock %} diff --git a/docs/requirements.txt b/docs/requirements.txt new file mode 100644 index 0000000000..04ebb9bbf7 --- /dev/null +++ b/docs/requirements.txt @@ -0,0 +1,2 @@ +mkdocs-material +mike