From 6610727b4110b0e965f526dc689d65a05dc9dcd0 Mon Sep 17 00:00:00 2001 From: outsidethecode <49871473+outsidethecode@users.noreply.github.com> Date: Mon, 22 Jan 2024 13:18:58 +0000 Subject: [PATCH] feat(satp): satp first implementation (#11) * Implemented the two endpoints TransferProposalClaims and TransferProposalReceipt * implemented the lock assertion method * Added the lock-assertion-receipt and lock-assertion-broadcast methods * Added the request to the driver to lock an asset * corrected some variable names * Added the endpoints corresponding to the steps 3.1 to 3.9 * Implemented the step 2.1B so that the driver call the gateway to update the asset status * Implemented the status check functionality required for 2.1B, 3.2B, 3.4B, and 3.6B * First iteration of switching to real driver (fabric) * Added the required functions to call back the gateway after the asset is locked. * Colorful log to show different stages and steps * Initial commit for create-asset, extinguish, and assign-asset * Added the resources required to assign an asset * uncommented the perform lock part * implemented the lock assertion method * Added the lock-assertion-receipt and lock-assertion-broadcast methods * Added the request to the driver to lock an asset * corrected some variable names * Added the endpoints corresponding to the steps 3.1 to 3.9 * Implemented the step 2.1B so that the driver call the gateway to update the asset status * Implemented the status check functionality required for 2.1B, 3.2B, 3.4B, and 3.6B * First iteration of switching to real driver (fabric) * Added the required functions to call back the gateway after the asset is locked. * Initial commit for create-asset, extinguish, and assign-asset * Added the resources required to assign an asset * uncommented the perform lock part * corrected compile error due to merging issue * Squashed commit: first implementation version of satp * implemented the lock assertion method * Added the lock-assertion-receipt and lock-assertion-broadcast methods * Added the request to the driver to lock an asset * corrected some variable names * Added the endpoints corresponding to the steps 3.1 to 3.9 * Implemented the step 2.1B so that the driver call the gateway to update the asset status * Implemented the status check functionality required for 2.1B, 3.2B, 3.4B, and 3.6B * First iteration of switching to real driver (fabric) * Added the required functions to call back the gateway after the asset is locked. * Initial commit for create-asset, extinguish, and assign-asset * Added the resources required to assign an asset * uncommented the perform lock part * corrected compile error due to merging issue * Initial documentation on how to run the satp gateway and test it * feat(weaver): add application logs * Initial log functionality * feat: log statements are stored in sqlite db * feat: updated the .gitignore file * feat: added log entries to all requests * feat: removed the unnecessary * feat: removed unnecessary comments * feat: added the missing methods in driver * feat: remove the unnecessary log statements * feat: initial rfcs for satp * initial satp github action script * corrected the github actions * Corrected the protoc version to be 3.17.3 and rebuild * corrected the version of cacti_weaver_protos_rs and added the copyright statement * removed the code copied from fabric-cli * feat: initial rfcs for satp * initial satp github action script * corrected the github actions * Corrected the protoc version to be 3.17.3 and rebuild * corrected the version of cacti_weaver_protos_rs and added the copyright statement * removed the code copied from fabric-cli * refactored the code in satp.ts * corrected the satpsimpleasset smart contract --------- Peter's changes: 1. I've removed the Cargo.lock file from the diff because it seemed unrelated to the change at hand. 2. Applied some formatting (but not all because as I just realized we don't yet have the linter working for the ./weaver/ subdirectories) 3. Removed dead code/unused variables 4. Adjusted `var` to `let` 5. Not perfect by any means but I'll work on some more incremental upgrades later in follow-up pull requests. Co-authored-by: Peter Somogyvari Signed-off-by: outsidethecode <49871473+outsidethecode@users.noreply.github.com> Co-authored-by: Rafael Belchior Signed-off-by: outsidethecode Signed-off-by: Peter Somogyvari --- .../test_weaver-fabric-fabric-satp.yaml | 217 ++ tools/go-gen-checksum.sh | 1 + weaver/common/protos-go/build-protos.sh | 2 +- .../protos-go/common/access_control.pb.go | 4 + weaver/common/protos-go/common/ack.pb.go | 4 + .../common/protos-go/common/asset_locks.pb.go | 4 + .../protos-go/common/asset_transfer.pb.go | 4 + weaver/common/protos-go/common/events.pb.go | 4 + .../protos-go/common/interop_payload.pb.go | 4 + .../common/protos-go/common/membership.pb.go | 4 + weaver/common/protos-go/common/proofs.pb.go | 4 + weaver/common/protos-go/common/query.pb.go | 4 + weaver/common/protos-go/common/state.pb.go | 4 + .../common/verification_policy.pb.go | 4 + weaver/common/protos-go/corda/view_data.pb.go | 4 + weaver/common/protos-go/driver/driver.pb.go | 384 +++- .../common/protos-go/driver/driver_grpc.pb.go | 168 ++ .../common/protos-go/fabric/view_data.pb.go | 4 + weaver/common/protos-go/identity/agent.pb.go | 4 + .../protos-go/identity/agent_grpc.pb.go | 4 + .../common/protos-go/networks/networks.pb.go | 296 ++- .../protos-go/networks/networks_grpc.pb.go | 45 + weaver/common/protos-js/build-protos.sh | 4 +- weaver/common/protos-rs/Cargo.lock | 176 +- weaver/common/protos-rs/build.rs | 1 + weaver/common/protos-rs/pkg/Cargo.lock | 1059 ++++++++++ .../pkg/src/generated/driver.driver.rs | 318 +++ .../pkg/src/generated/networks.networks.rs | 98 +- .../pkg/src/generated/relay.asset_transfer.rs | 597 ++++++ .../protos-rs/pkg/src/generated/relay.satp.rs | 1265 +++++++++++ weaver/common/protos-rs/pkg/src/lib.rs | 3 + weaver/common/protos/driver/driver.proto | 32 + weaver/common/protos/networks/networks.proto | 16 + weaver/common/protos/relay/satp.proto | 175 ++ .../drivers/fabric-driver/.env.satp.template | 25 + .../core/drivers/fabric-driver/server/satp.ts | 348 +++ .../drivers/fabric-driver/server/server.ts | 87 +- weaver/core/relay/.env.template | 1 + weaver/core/relay/.env.template.2 | 1 + weaver/core/relay/.gitignore | 1 + weaver/core/relay/Cargo.lock | 770 ++++--- weaver/core/relay/Cargo.toml | 20 +- weaver/core/relay/README.md | 5 + weaver/core/relay/config/Corda_Relay.toml | 1 + weaver/core/relay/config/Corda_Relay2.toml | 1 + weaver/core/relay/config/Dummy_Relay.toml | 1 + weaver/core/relay/config/Dummy_Relay_tls.toml | 1 + weaver/core/relay/config/Fabric_Relay.toml | 1 + weaver/core/relay/config/Fabric_Relay2.toml | 1 + weaver/core/relay/config/Settings.toml | 1 + weaver/core/relay/docs/README.md | 155 ++ weaver/core/relay/driver/driver.rs | 228 +- weaver/core/relay/src/main.rs | 47 +- weaver/core/relay/src/satp_client.rs | 52 + weaver/core/relay/src/services/constants.rs | 0 weaver/core/relay/src/services/helpers.rs | 241 ++- weaver/core/relay/src/services/logger.rs | 94 + weaver/core/relay/src/services/mod.rs | 4 + .../relay/src/services/network_service.rs | 367 +++- weaver/core/relay/src/services/satp_helper.rs | 1207 +++++++++++ .../core/relay/src/services/satp_service.rs | 1867 +++++++++++++++++ weaver/rfcs/formats/assets/satp.md | 237 +++ .../rfcs/models/infrastructure/relay_satp.md | 91 + .../protocols/satp/asset-transfer/corda.md | 1 + .../protocols/satp/asset-transfer/fabric.md | 27 + .../protocols/satp/asset-transfer/generic.md | 59 + .../fabric-cli/config.satp.template.json | 18 + .../accessControlTemplate_ca.json | 29 + .../accessControlTemplate_certificate.json | 29 + .../verificationPolicyTemplate.json | 33 + .../samples/fabric/satpsimpleasset/.gitignore | 4 + .../samples/fabric/satpsimpleasset/Makefile | 27 + .../fabric/satpsimpleasset/assetmgmt.go | 356 ++++ .../fabric/satpsimpleasset/assetmgmt_test.go | 232 ++ .../fabric/satpsimpleasset/bondasset.go | 327 +++ .../fabric/satpsimpleasset/bondasset_test.go | 242 +++ weaver/samples/fabric/satpsimpleasset/go.mod | 42 + weaver/samples/fabric/satpsimpleasset/go.sum | 149 ++ .../samples/fabric/satpsimpleasset/helper.go | 53 + weaver/samples/fabric/satpsimpleasset/main.go | 59 + .../fabric/satpsimpleasset/tokenasset.go | 316 +++ .../fabric/satpsimpleasset/tokenasset_test.go | 326 +++ .../fabric/interoperation-node-sdk/index.js | 1 + .../src/SatpAssetManager.ts | 1111 ++++++++++ .../interoperation-node-sdk/types/index.d.ts | 2 + .../fabric/dev/scripts/deployCC.sh | 4 + 86 files changed, 13555 insertions(+), 664 deletions(-) create mode 100644 .github/workflows/test_weaver-fabric-fabric-satp.yaml create mode 100644 weaver/common/protos-rs/pkg/Cargo.lock create mode 100644 weaver/common/protos-rs/pkg/src/generated/relay.asset_transfer.rs create mode 100644 weaver/common/protos-rs/pkg/src/generated/relay.satp.rs create mode 100644 weaver/common/protos/relay/satp.proto create mode 100644 weaver/core/drivers/fabric-driver/.env.satp.template create mode 100644 weaver/core/drivers/fabric-driver/server/satp.ts create mode 100644 weaver/core/relay/docs/README.md create mode 100644 weaver/core/relay/src/satp_client.rs create mode 100644 weaver/core/relay/src/services/constants.rs create mode 100644 weaver/core/relay/src/services/logger.rs create mode 100644 weaver/core/relay/src/services/satp_helper.rs create mode 100644 weaver/core/relay/src/services/satp_service.rs create mode 100644 weaver/rfcs/formats/assets/satp.md create mode 100644 weaver/rfcs/models/infrastructure/relay_satp.md create mode 100644 weaver/rfcs/protocols/satp/asset-transfer/corda.md create mode 100644 weaver/rfcs/protocols/satp/asset-transfer/fabric.md create mode 100644 weaver/rfcs/protocols/satp/asset-transfer/generic.md create mode 100644 weaver/samples/fabric/fabric-cli/config.satp.template.json create mode 100644 weaver/samples/fabric/fabric-cli/src/data/interop/satpsimpleasset/accessControlTemplate_ca.json create mode 100644 weaver/samples/fabric/fabric-cli/src/data/interop/satpsimpleasset/accessControlTemplate_certificate.json create mode 100644 weaver/samples/fabric/fabric-cli/src/data/interop/satpsimpleasset/verificationPolicyTemplate.json create mode 100644 weaver/samples/fabric/satpsimpleasset/.gitignore create mode 100644 weaver/samples/fabric/satpsimpleasset/Makefile create mode 100644 weaver/samples/fabric/satpsimpleasset/assetmgmt.go create mode 100644 weaver/samples/fabric/satpsimpleasset/assetmgmt_test.go create mode 100644 weaver/samples/fabric/satpsimpleasset/bondasset.go create mode 100644 weaver/samples/fabric/satpsimpleasset/bondasset_test.go create mode 100644 weaver/samples/fabric/satpsimpleasset/go.mod create mode 100644 weaver/samples/fabric/satpsimpleasset/go.sum create mode 100644 weaver/samples/fabric/satpsimpleasset/helper.go create mode 100644 weaver/samples/fabric/satpsimpleasset/main.go create mode 100644 weaver/samples/fabric/satpsimpleasset/tokenasset.go create mode 100644 weaver/samples/fabric/satpsimpleasset/tokenasset_test.go create mode 100644 weaver/sdks/fabric/interoperation-node-sdk/src/SatpAssetManager.ts diff --git a/.github/workflows/test_weaver-fabric-fabric-satp.yaml b/.github/workflows/test_weaver-fabric-fabric-satp.yaml new file mode 100644 index 00000000000..e11b31bec48 --- /dev/null +++ b/.github/workflows/test_weaver-fabric-fabric-satp.yaml @@ -0,0 +1,217 @@ +# Copyright IBM Corp. All Rights Reserved. +# +# SPDX-License-Identifier: CC-BY-4.0 + +name: Secure Test Asset Transfer + +# Controls when the workflow will run +on: + # Triggers the workflow on push or pull request events but only for the main branch + push: + branches: [ main ] + pull_request: + branches: [ main ] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }} + cancel-in-progress: true + +jobs: + check_code_changed: + outputs: + status: ${{ steps.changes.outputs.weaver_code_changed }} + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3.5.2 + + - uses: dorny/paths-filter@v2.11.1 + id: changes + with: + filters: | + weaver_code_changed: + - './weaver/**!(*.md|*.css|*.html|*.jpg|*.jpeg|*.png)' + - '.github/workflows/test_weaver-fabric-fabric-satp.yaml' + + fabric-fabric-satp-local: + needs: check_code_changed + if: ${{ false && needs.check_code_changed.outputs.status == 'true' }} + # if: ${{ false }} + # The type of runner that the job will run on + runs-on: ubuntu-latest + + steps: + # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it + - uses: actions/checkout@v3.5.2 + + - name: Set up Docker Compose + run: | + curl -L "https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose + sudo chmod +x /usr/local/bin/docker-compose + docker-compose --version + + - name: Install Yarn + run: npm install -g yarn + + - name: Install Envsubst + run: apt-get update && apt-get install gettext-base + + - name: Set up JDK 8 + uses: actions/setup-java@v3.11.0 + with: + java-version: '8' + distribution: 'adopt' + + - name: Set up Go + uses: actions/setup-go@v4.0.0 + with: + go-version: '1.20.2' + + - name: Use Node.js 16.x + uses: actions/setup-node@v3.6.0 + with: + node-version: 16.x + + - name: Install RUST Toolchain minimal stable with clippy and rustfmt + uses: actions-rs/toolchain@v1.0.6 + with: + profile: minimal + toolchain: stable + components: rustfmt, clippy + + - name: Get Latest Relay Dependencies + run: | + make protos-local + cargo update -p nom + cargo update -p lexical-core + working-directory: weaver/core/relay + + - name: Use Protoc 3.15 + run: | + curl -LO https://github.com/protocolbuffers/protobuf/releases/download/v3.15.6/protoc-3.15.6-linux-x86_64.zip + unzip protoc-3.15.6-linux-x86_64.zip -d protoc + go install google.golang.org/protobuf/cmd/protoc-gen-go@latest + go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@latest + + # FABRIC NETWORK + - name: Start Fabric Network + run: make start-interop-local CHAINCODE_NAME=satpsimpleasset + working-directory: weaver/tests/network-setups/fabric/dev + + # PROTOS GO + - name: Build GO Protos + run: | + export PATH="$PATH:${GITHUB_WORKSPACE}/protoc/bin" + make build + working-directory: weaver/common/protos-go + + # PROTOS JS + - name: Build JS Protos + run: | + export PATH="$PATH:${GITHUB_WORKSPACE}/protoc/bin" + make build + working-directory: weaver/common/protos-js + + # Build Dependencies + - name: Build Fabric Interop SDK + run: make build-local + working-directory: weaver/sdks/fabric/interoperation-node-sdk + + - name: Build Fabric CLI + run: make build-local + working-directory: weaver/samples/fabric/fabric-cli + + - name: Build Relay + run: make + working-directory: weaver/core/relay + + - name: Build Fabric Driver + run: make build-local + working-directory: weaver/core/drivers/fabric-driver + + # GATEWAY + - name: Start Relay for network1 and network2 + run: RELAY_CONFIG=config/Dummy_Relay.toml cargo run --bin server &> gateway.out & + working-directory: weaver/core/relay + + # FABRIC DRIVER + - name: Setup Fabric Driver .env + run: | + cp .env.satp.template .env + sed -i "s##${GITHUB_WORKSPACE}/weaver#g" .env + working-directory: weaver/core/drivers/fabric-driver + + - name: Start Fabric Driver for network1 and network2 + run: npm run dev &> fdriver.out & + working-directory: weaver/core/drivers/fabric-driver + + # FABRIC CLI + - name: Setup Fabric CLI ENV + run: | + echo ${GITHUB_WORKSPACE} + cp .env.template .env + ./bin/fabric-cli env set-file ./.env + ./bin/fabric-cli env set MEMBER_CREDENTIAL_FOLDER ${GITHUB_WORKSPACE}/weaver/samples/fabric/fabric-cli/src/data/credentials + ./bin/fabric-cli env set CONFIG_PATH ${GITHUB_WORKSPACE}/weaver/samples/fabric/fabric-cli/config.json + ./bin/fabric-cli env set DEFAULT_APPLICATION_CHAINCODE satpsimpleasset + ./bin/fabric-cli env set REMOTE_CONFIG_PATH ${GITHUB_WORKSPACE}/weaver/samples/fabric/fabric-cli/remote-network-config.json + ./bin/fabric-cli env set CHAINCODE_PATH ${GITHUB_WORKSPACE}/weaver/samples/fabric/fabric-cli/chaincode.json + cat .env + working-directory: weaver/samples/fabric/fabric-cli + + - name: Setup Fabric CLI Config + run: | + echo ${GITHUB_WORKSPACE} + cp config.satp.template.json config.json + sed -i "s##${GITHUB_WORKSPACE}/weaver#g" config.json + ###### Change line number in following commands if config is modified ##### + ./bin/fabric-cli config set network2 aclPolicyPrincipalType ca + ./bin/fabric-cli config set network1 chaincode satpsimpleasset + ./bin/fabric-cli config set network2 chaincode satpsimpleasset + cp chaincode.json.template chaincode.json + cp remote-network-config.json.template remote-network-config.json + working-directory: weaver/samples/fabric/fabric-cli + + - name: Fabric CLI Init + run: | + ./bin/fabric-cli configure create all --local-network=network1 + ./bin/fabric-cli configure create all --local-network=network2 + ./bin/fabric-cli configure network --local-network=network1 + ./bin/fabric-cli configure network --local-network=network2 + ./scripts/initAsset.sh + working-directory: weaver/samples/fabric/fabric-cli + + # CLIENT + - name: Start the client to initiate the satp protocol + run: cargo run --bin satp_client "9085" "localhost:9085/Dummy_Network/abc:abc:abc:abc" &> client.out & + working-directory: weaver/core/relay + + # Test SATP + - name: Test SATP + run: | + COUNT=0 + TOTAL=1 + + ./bin/fabric-cli chaincode query --user=bob mychannel satpsimpleasset ReadAsset '["bond01","a04"]' --local-network=network1 &> tmp.out + cat tmp.out | tr '\n' ' ' | grep "Result from network query: { \"type\": \"bond01\", \"id\": \"a04\"" && COUNT=$(( COUNT + 1 )) && echo "PASS" + cat tmp.out + + # RESULT + echo "Passed $COUNT/$TOTAL Tests." + + if [ $COUNT == $TOTAL ]; then + exit 0 + else + exit 1 + fi + working-directory: weaver/samples/fabric/fabric-cli + + - name: DEBUG Logs - fabric n1 and n2 gateway + if: failure() + run: cat weaver/core/relay/gateway.out + + - name: DEBUG Logs - fabric n1 and n2 driver + if: failure() + run: cat weaver/core/drivers/fabric-driver/fdriver.out \ No newline at end of file diff --git a/tools/go-gen-checksum.sh b/tools/go-gen-checksum.sh index 87ef7760517..513a5afd049 100755 --- a/tools/go-gen-checksum.sh +++ b/tools/go-gen-checksum.sh @@ -16,6 +16,7 @@ GOMODULE_PATHS=("weaver/core/network/fabric-interop-cc/libs/utils" "weaver/sdks/fabric/go-sdk" "weaver/samples/fabric/go-cli" "weaver/samples/fabric/simpleasset" +"weaver/samples/fabric/satpsimpleasset" "weaver/samples/fabric/simpleassetandinterop" "weaver/samples/fabric/simpleassettransfer" "weaver/samples/fabric/simplestatewithacl" diff --git a/weaver/common/protos-go/build-protos.sh b/weaver/common/protos-go/build-protos.sh index 23b8d993519..d28d94115a3 100644 --- a/weaver/common/protos-go/build-protos.sh +++ b/weaver/common/protos-go/build-protos.sh @@ -12,6 +12,6 @@ protoc --proto_path=$PROTOSDIR --proto_path=$FABRIC_PROTOSDIR --go_out=$BUILDDIR protoc --proto_path=$PROTOSDIR --proto_path=$FABRIC_PROTOSDIR --go_out=$BUILDDIR --go_opt=paths=source_relative $PROTOSDIR/fabric/view_data.proto protoc --proto_path=$PROTOSDIR --proto_path=$FABRIC_PROTOSDIR --go_out=$BUILDDIR --go_opt=paths=source_relative $PROTOSDIR/corda/view_data.proto protoc --proto_path=$PROTOSDIR --proto_path=$FABRIC_PROTOSDIR --go-grpc_out=paths=source_relative:$BUILDDIR --go_out=paths=source_relative:$BUILDDIR $PROTOSDIR/networks/networks.proto -protoc --proto_path=$PROTOSDIR --proto_path=$FABRIC_PROTOSDIR --go-grpc_out=paths=source_relative:$BUILDDIR --go_out=paths=source_relative:$BUILDDIR $PROTOSDIR/relay/datatransfer.proto $PROTOSDIR/relay/events.proto +protoc --proto_path=$PROTOSDIR --proto_path=$FABRIC_PROTOSDIR --go-grpc_out=paths=source_relative:$BUILDDIR --go_out=paths=source_relative:$BUILDDIR $PROTOSDIR/relay/datatransfer.proto $PROTOSDIR/relay/events.proto PROTOSDIR/relay/satp.proto protoc --proto_path=$PROTOSDIR --proto_path=$FABRIC_PROTOSDIR --go-grpc_out=paths=source_relative:$BUILDDIR --go_out=paths=source_relative:$BUILDDIR $PROTOSDIR/driver/driver.proto protoc --proto_path=$PROTOSDIR --proto_path=$FABRIC_PROTOSDIR --go-grpc_out=paths=source_relative:$BUILDDIR --go_out=paths=source_relative:$BUILDDIR $PROTOSDIR/identity/agent.proto diff --git a/weaver/common/protos-go/common/access_control.pb.go b/weaver/common/protos-go/common/access_control.pb.go index 7e2383c003f..ee04dbca20d 100644 --- a/weaver/common/protos-go/common/access_control.pb.go +++ b/weaver/common/protos-go/common/access_control.pb.go @@ -1,3 +1,7 @@ +// Copyright IBM Corp. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.30.0 diff --git a/weaver/common/protos-go/common/ack.pb.go b/weaver/common/protos-go/common/ack.pb.go index 4d2fcb76b6f..74d14ab7c61 100644 --- a/weaver/common/protos-go/common/ack.pb.go +++ b/weaver/common/protos-go/common/ack.pb.go @@ -1,3 +1,7 @@ +// Copyright IBM Corp. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.30.0 diff --git a/weaver/common/protos-go/common/asset_locks.pb.go b/weaver/common/protos-go/common/asset_locks.pb.go index eebb5939abd..468d81a6daa 100644 --- a/weaver/common/protos-go/common/asset_locks.pb.go +++ b/weaver/common/protos-go/common/asset_locks.pb.go @@ -1,3 +1,7 @@ +// Copyright IBM Corp. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.30.0 diff --git a/weaver/common/protos-go/common/asset_transfer.pb.go b/weaver/common/protos-go/common/asset_transfer.pb.go index de8b050302c..3f8040a6692 100644 --- a/weaver/common/protos-go/common/asset_transfer.pb.go +++ b/weaver/common/protos-go/common/asset_transfer.pb.go @@ -1,3 +1,7 @@ +// Copyright IBM Corp. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.30.0 diff --git a/weaver/common/protos-go/common/events.pb.go b/weaver/common/protos-go/common/events.pb.go index 06eb16548ed..4e2bbdd5e80 100644 --- a/weaver/common/protos-go/common/events.pb.go +++ b/weaver/common/protos-go/common/events.pb.go @@ -1,3 +1,7 @@ +// Copyright IBM Corp. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.30.0 diff --git a/weaver/common/protos-go/common/interop_payload.pb.go b/weaver/common/protos-go/common/interop_payload.pb.go index 0f17f37359e..c8593d7e649 100644 --- a/weaver/common/protos-go/common/interop_payload.pb.go +++ b/weaver/common/protos-go/common/interop_payload.pb.go @@ -1,3 +1,7 @@ +// Copyright IBM Corp. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.30.0 diff --git a/weaver/common/protos-go/common/membership.pb.go b/weaver/common/protos-go/common/membership.pb.go index d851d53dbf3..71f48b97000 100644 --- a/weaver/common/protos-go/common/membership.pb.go +++ b/weaver/common/protos-go/common/membership.pb.go @@ -1,3 +1,7 @@ +// Copyright IBM Corp. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.30.0 diff --git a/weaver/common/protos-go/common/proofs.pb.go b/weaver/common/protos-go/common/proofs.pb.go index 9c225d199ca..cf8964ed0de 100644 --- a/weaver/common/protos-go/common/proofs.pb.go +++ b/weaver/common/protos-go/common/proofs.pb.go @@ -1,3 +1,7 @@ +// Copyright IBM Corp. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.30.0 diff --git a/weaver/common/protos-go/common/query.pb.go b/weaver/common/protos-go/common/query.pb.go index f4b9f17bedb..82753902a58 100644 --- a/weaver/common/protos-go/common/query.pb.go +++ b/weaver/common/protos-go/common/query.pb.go @@ -1,3 +1,7 @@ +// Copyright IBM Corp. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.30.0 diff --git a/weaver/common/protos-go/common/state.pb.go b/weaver/common/protos-go/common/state.pb.go index fa68086ea5d..1a56cb19e11 100644 --- a/weaver/common/protos-go/common/state.pb.go +++ b/weaver/common/protos-go/common/state.pb.go @@ -1,3 +1,7 @@ +// Copyright IBM Corp. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.30.0 diff --git a/weaver/common/protos-go/common/verification_policy.pb.go b/weaver/common/protos-go/common/verification_policy.pb.go index 26d80f91585..34012c8c03c 100644 --- a/weaver/common/protos-go/common/verification_policy.pb.go +++ b/weaver/common/protos-go/common/verification_policy.pb.go @@ -1,3 +1,7 @@ +// Copyright IBM Corp. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.30.0 diff --git a/weaver/common/protos-go/corda/view_data.pb.go b/weaver/common/protos-go/corda/view_data.pb.go index 37f9bd8b6aa..d334b774b2e 100644 --- a/weaver/common/protos-go/corda/view_data.pb.go +++ b/weaver/common/protos-go/corda/view_data.pb.go @@ -1,3 +1,7 @@ +// Copyright IBM Corp. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.30.0 diff --git a/weaver/common/protos-go/driver/driver.pb.go b/weaver/common/protos-go/driver/driver.pb.go index 764501f673e..2bc348cc640 100644 --- a/weaver/common/protos-go/driver/driver.pb.go +++ b/weaver/common/protos-go/driver/driver.pb.go @@ -1,3 +1,7 @@ +// Copyright IBM Corp. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.30.0 @@ -77,6 +81,194 @@ func (x *WriteExternalStateMessage) GetCtx() *common.ContractTransaction { return nil } +type PerformLockRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SessionId string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` +} + +func (x *PerformLockRequest) Reset() { + *x = PerformLockRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_driver_driver_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *PerformLockRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*PerformLockRequest) ProtoMessage() {} + +func (x *PerformLockRequest) ProtoReflect() protoreflect.Message { + mi := &file_driver_driver_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use PerformLockRequest.ProtoReflect.Descriptor instead. +func (*PerformLockRequest) Descriptor() ([]byte, []int) { + return file_driver_driver_proto_rawDescGZIP(), []int{1} +} + +func (x *PerformLockRequest) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +type CreateAssetRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SessionId string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` +} + +func (x *CreateAssetRequest) Reset() { + *x = CreateAssetRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_driver_driver_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *CreateAssetRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*CreateAssetRequest) ProtoMessage() {} + +func (x *CreateAssetRequest) ProtoReflect() protoreflect.Message { + mi := &file_driver_driver_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use CreateAssetRequest.ProtoReflect.Descriptor instead. +func (*CreateAssetRequest) Descriptor() ([]byte, []int) { + return file_driver_driver_proto_rawDescGZIP(), []int{2} +} + +func (x *CreateAssetRequest) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +type ExtinguishRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SessionId string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` +} + +func (x *ExtinguishRequest) Reset() { + *x = ExtinguishRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_driver_driver_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ExtinguishRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ExtinguishRequest) ProtoMessage() {} + +func (x *ExtinguishRequest) ProtoReflect() protoreflect.Message { + mi := &file_driver_driver_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ExtinguishRequest.ProtoReflect.Descriptor instead. +func (*ExtinguishRequest) Descriptor() ([]byte, []int) { + return file_driver_driver_proto_rawDescGZIP(), []int{3} +} + +func (x *ExtinguishRequest) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + +type AssignAssetRequest struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + SessionId string `protobuf:"bytes,1,opt,name=session_id,json=sessionId,proto3" json:"session_id,omitempty"` +} + +func (x *AssignAssetRequest) Reset() { + *x = AssignAssetRequest{} + if protoimpl.UnsafeEnabled { + mi := &file_driver_driver_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *AssignAssetRequest) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*AssignAssetRequest) ProtoMessage() {} + +func (x *AssignAssetRequest) ProtoReflect() protoreflect.Message { + mi := &file_driver_driver_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use AssignAssetRequest.ProtoReflect.Descriptor instead. +func (*AssignAssetRequest) Descriptor() ([]byte, []int) { + return file_driver_driver_proto_rawDescGZIP(), []int{4} +} + +func (x *AssignAssetRequest) GetSessionId() string { + if x != nil { + return x.SessionId + } + return "" +} + var File_driver_driver_proto protoreflect.FileDescriptor var file_driver_driver_proto_rawDesc = []byte{ @@ -96,36 +288,66 @@ var file_driver_driver_proto_rawDesc = []byte{ 0x34, 0x0a, 0x03, 0x63, 0x74, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x43, 0x6f, 0x6e, 0x74, 0x72, 0x61, 0x63, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x03, 0x63, 0x74, 0x78, 0x32, 0xcd, 0x02, 0x0a, 0x13, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, - 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x3c, 0x0a, - 0x12, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x44, 0x72, 0x69, 0x76, 0x65, 0x72, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x12, 0x13, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x71, 0x75, 0x65, - 0x72, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x1a, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, - 0x6e, 0x2e, 0x61, 0x63, 0x6b, 0x2e, 0x41, 0x63, 0x6b, 0x22, 0x00, 0x12, 0x45, 0x0a, 0x0e, 0x53, - 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x20, 0x2e, - 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, + 0x52, 0x03, 0x63, 0x74, 0x78, 0x22, 0x33, 0x0a, 0x12, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, + 0x4c, 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x33, 0x0a, 0x12, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, + 0x32, 0x0a, 0x11, 0x45, 0x78, 0x74, 0x69, 0x6e, 0x67, 0x75, 0x69, 0x73, 0x68, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x5f, + 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x65, 0x73, 0x73, 0x69, 0x6f, + 0x6e, 0x49, 0x64, 0x22, 0x33, 0x0a, 0x12, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x41, 0x73, 0x73, + 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x65, 0x73, + 0x73, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, + 0x65, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x32, 0xdf, 0x04, 0x0a, 0x13, 0x44, 0x72, 0x69, + 0x76, 0x65, 0x72, 0x43, 0x6f, 0x6d, 0x6d, 0x75, 0x6e, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x12, 0x3c, 0x0a, 0x12, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x44, 0x72, 0x69, 0x76, 0x65, + 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x13, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, + 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x1a, 0x0f, 0x2e, 0x63, 0x6f, + 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x61, 0x63, 0x6b, 0x2e, 0x41, 0x63, 0x6b, 0x22, 0x00, 0x12, 0x45, + 0x0a, 0x0e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x12, 0x20, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, + 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x1a, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x61, 0x63, 0x6b, 0x2e, + 0x41, 0x63, 0x6b, 0x22, 0x00, 0x12, 0x5e, 0x0a, 0x23, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x53, 0x69, 0x67, 0x6e, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x20, 0x2e, 0x63, + 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x13, + 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x51, 0x75, + 0x65, 0x72, 0x79, 0x22, 0x00, 0x12, 0x51, 0x0a, 0x12, 0x57, 0x72, 0x69, 0x74, 0x65, 0x45, 0x78, + 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x28, 0x2e, 0x64, 0x72, + 0x69, 0x76, 0x65, 0x72, 0x2e, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x2e, 0x57, 0x72, 0x69, 0x74, + 0x65, 0x45, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x65, + 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x61, + 0x63, 0x6b, 0x2e, 0x41, 0x63, 0x6b, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0b, 0x50, 0x65, 0x72, 0x66, + 0x6f, 0x72, 0x6d, 0x4c, 0x6f, 0x63, 0x6b, 0x12, 0x21, 0x2e, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, + 0x2e, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x2e, 0x50, 0x65, 0x72, 0x66, 0x6f, 0x72, 0x6d, 0x4c, + 0x6f, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, + 0x6d, 0x6f, 0x6e, 0x2e, 0x61, 0x63, 0x6b, 0x2e, 0x41, 0x63, 0x6b, 0x22, 0x00, 0x12, 0x43, 0x0a, + 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x12, 0x21, 0x2e, 0x64, + 0x72, 0x69, 0x76, 0x65, 0x72, 0x2e, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x41, 0x73, 0x73, 0x65, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x61, 0x63, 0x6b, 0x2e, 0x41, 0x63, 0x6b, - 0x22, 0x00, 0x12, 0x5e, 0x0a, 0x23, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x69, 0x67, - 0x6e, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x51, 0x75, 0x65, 0x72, 0x79, 0x12, 0x20, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, - 0x6f, 0x6e, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, - 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x13, 0x2e, 0x63, 0x6f, - 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x71, 0x75, 0x65, 0x72, 0x79, 0x2e, 0x51, 0x75, 0x65, 0x72, 0x79, - 0x22, 0x00, 0x12, 0x51, 0x0a, 0x12, 0x57, 0x72, 0x69, 0x74, 0x65, 0x45, 0x78, 0x74, 0x65, 0x72, - 0x6e, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x28, 0x2e, 0x64, 0x72, 0x69, 0x76, 0x65, - 0x72, 0x2e, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x2e, 0x57, 0x72, 0x69, 0x74, 0x65, 0x45, 0x78, - 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x1a, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x61, 0x63, 0x6b, 0x2e, - 0x41, 0x63, 0x6b, 0x22, 0x00, 0x42, 0x73, 0x0a, 0x31, 0x6f, 0x72, 0x67, 0x2e, 0x68, 0x79, 0x70, - 0x65, 0x72, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x72, 0x2e, 0x63, 0x61, 0x63, 0x74, 0x69, 0x2e, 0x77, - 0x65, 0x61, 0x76, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x64, 0x72, 0x69, - 0x76, 0x65, 0x72, 0x2e, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x5a, 0x3e, 0x67, 0x69, 0x74, 0x68, - 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x79, 0x70, 0x65, 0x72, 0x6c, 0x65, 0x64, 0x67, - 0x65, 0x72, 0x2f, 0x63, 0x61, 0x63, 0x74, 0x69, 0x2f, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x2f, - 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2d, 0x67, 0x6f, - 0x2f, 0x76, 0x32, 0x2f, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x22, 0x00, 0x12, 0x41, 0x0a, 0x0a, 0x45, 0x78, 0x74, 0x69, 0x6e, 0x67, 0x75, 0x69, 0x73, 0x68, + 0x12, 0x20, 0x2e, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x2e, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, + 0x2e, 0x45, 0x78, 0x74, 0x69, 0x6e, 0x67, 0x75, 0x69, 0x73, 0x68, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x61, 0x63, 0x6b, 0x2e, + 0x41, 0x63, 0x6b, 0x22, 0x00, 0x12, 0x43, 0x0a, 0x0b, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x41, + 0x73, 0x73, 0x65, 0x74, 0x12, 0x21, 0x2e, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x2e, 0x64, 0x72, + 0x69, 0x76, 0x65, 0x72, 0x2e, 0x41, 0x73, 0x73, 0x69, 0x67, 0x6e, 0x41, 0x73, 0x73, 0x65, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, + 0x2e, 0x61, 0x63, 0x6b, 0x2e, 0x41, 0x63, 0x6b, 0x22, 0x00, 0x42, 0x73, 0x0a, 0x31, 0x6f, 0x72, + 0x67, 0x2e, 0x68, 0x79, 0x70, 0x65, 0x72, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x72, 0x2e, 0x63, 0x61, + 0x63, 0x74, 0x69, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x73, 0x2e, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x2e, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x5a, + 0x3e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x79, 0x70, 0x65, + 0x72, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x72, 0x2f, 0x63, 0x61, 0x63, 0x74, 0x69, 0x2f, 0x77, 0x65, + 0x61, 0x76, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x73, 0x2d, 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x64, 0x72, 0x69, 0x76, 0x65, 0x72, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -140,31 +362,43 @@ func file_driver_driver_proto_rawDescGZIP() []byte { return file_driver_driver_proto_rawDescData } -var file_driver_driver_proto_msgTypes = make([]protoimpl.MessageInfo, 1) +var file_driver_driver_proto_msgTypes = make([]protoimpl.MessageInfo, 5) var file_driver_driver_proto_goTypes = []interface{}{ (*WriteExternalStateMessage)(nil), // 0: driver.driver.WriteExternalStateMessage - (*common.ViewPayload)(nil), // 1: common.state.ViewPayload - (*common.ContractTransaction)(nil), // 2: common.events.ContractTransaction - (*common.Query)(nil), // 3: common.query.Query - (*common.EventSubscription)(nil), // 4: common.events.EventSubscription - (*common.Ack)(nil), // 5: common.ack.Ack + (*PerformLockRequest)(nil), // 1: driver.driver.PerformLockRequest + (*CreateAssetRequest)(nil), // 2: driver.driver.CreateAssetRequest + (*ExtinguishRequest)(nil), // 3: driver.driver.ExtinguishRequest + (*AssignAssetRequest)(nil), // 4: driver.driver.AssignAssetRequest + (*common.ViewPayload)(nil), // 5: common.state.ViewPayload + (*common.ContractTransaction)(nil), // 6: common.events.ContractTransaction + (*common.Query)(nil), // 7: common.query.Query + (*common.EventSubscription)(nil), // 8: common.events.EventSubscription + (*common.Ack)(nil), // 9: common.ack.Ack } var file_driver_driver_proto_depIdxs = []int32{ - 1, // 0: driver.driver.WriteExternalStateMessage.view_payload:type_name -> common.state.ViewPayload - 2, // 1: driver.driver.WriteExternalStateMessage.ctx:type_name -> common.events.ContractTransaction - 3, // 2: driver.driver.DriverCommunication.RequestDriverState:input_type -> common.query.Query - 4, // 3: driver.driver.DriverCommunication.SubscribeEvent:input_type -> common.events.EventSubscription - 4, // 4: driver.driver.DriverCommunication.RequestSignedEventSubscriptionQuery:input_type -> common.events.EventSubscription - 0, // 5: driver.driver.DriverCommunication.WriteExternalState:input_type -> driver.driver.WriteExternalStateMessage - 5, // 6: driver.driver.DriverCommunication.RequestDriverState:output_type -> common.ack.Ack - 5, // 7: driver.driver.DriverCommunication.SubscribeEvent:output_type -> common.ack.Ack - 3, // 8: driver.driver.DriverCommunication.RequestSignedEventSubscriptionQuery:output_type -> common.query.Query - 5, // 9: driver.driver.DriverCommunication.WriteExternalState:output_type -> common.ack.Ack - 6, // [6:10] is the sub-list for method output_type - 2, // [2:6] is the sub-list for method input_type - 2, // [2:2] is the sub-list for extension type_name - 2, // [2:2] is the sub-list for extension extendee - 0, // [0:2] is the sub-list for field type_name + 5, // 0: driver.driver.WriteExternalStateMessage.view_payload:type_name -> common.state.ViewPayload + 6, // 1: driver.driver.WriteExternalStateMessage.ctx:type_name -> common.events.ContractTransaction + 7, // 2: driver.driver.DriverCommunication.RequestDriverState:input_type -> common.query.Query + 8, // 3: driver.driver.DriverCommunication.SubscribeEvent:input_type -> common.events.EventSubscription + 8, // 4: driver.driver.DriverCommunication.RequestSignedEventSubscriptionQuery:input_type -> common.events.EventSubscription + 0, // 5: driver.driver.DriverCommunication.WriteExternalState:input_type -> driver.driver.WriteExternalStateMessage + 1, // 6: driver.driver.DriverCommunication.PerformLock:input_type -> driver.driver.PerformLockRequest + 2, // 7: driver.driver.DriverCommunication.CreateAsset:input_type -> driver.driver.CreateAssetRequest + 3, // 8: driver.driver.DriverCommunication.Extinguish:input_type -> driver.driver.ExtinguishRequest + 4, // 9: driver.driver.DriverCommunication.AssignAsset:input_type -> driver.driver.AssignAssetRequest + 9, // 10: driver.driver.DriverCommunication.RequestDriverState:output_type -> common.ack.Ack + 9, // 11: driver.driver.DriverCommunication.SubscribeEvent:output_type -> common.ack.Ack + 7, // 12: driver.driver.DriverCommunication.RequestSignedEventSubscriptionQuery:output_type -> common.query.Query + 9, // 13: driver.driver.DriverCommunication.WriteExternalState:output_type -> common.ack.Ack + 9, // 14: driver.driver.DriverCommunication.PerformLock:output_type -> common.ack.Ack + 9, // 15: driver.driver.DriverCommunication.CreateAsset:output_type -> common.ack.Ack + 9, // 16: driver.driver.DriverCommunication.Extinguish:output_type -> common.ack.Ack + 9, // 17: driver.driver.DriverCommunication.AssignAsset:output_type -> common.ack.Ack + 10, // [10:18] is the sub-list for method output_type + 2, // [2:10] is the sub-list for method input_type + 2, // [2:2] is the sub-list for extension type_name + 2, // [2:2] is the sub-list for extension extendee + 0, // [0:2] is the sub-list for field type_name } func init() { file_driver_driver_proto_init() } @@ -185,6 +419,54 @@ func file_driver_driver_proto_init() { return nil } } + file_driver_driver_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*PerformLockRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_driver_driver_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*CreateAssetRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_driver_driver_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ExtinguishRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_driver_driver_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*AssignAssetRequest); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -192,7 +474,7 @@ func file_driver_driver_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_driver_driver_proto_rawDesc, NumEnums: 0, - NumMessages: 1, + NumMessages: 5, NumExtensions: 0, NumServices: 1, }, diff --git a/weaver/common/protos-go/driver/driver_grpc.pb.go b/weaver/common/protos-go/driver/driver_grpc.pb.go index 08d8741e82c..d7564b73fad 100644 --- a/weaver/common/protos-go/driver/driver_grpc.pb.go +++ b/weaver/common/protos-go/driver/driver_grpc.pb.go @@ -1,3 +1,7 @@ +// Copyright IBM Corp. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 + // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.3.0 @@ -24,6 +28,10 @@ const ( DriverCommunication_SubscribeEvent_FullMethodName = "/driver.driver.DriverCommunication/SubscribeEvent" DriverCommunication_RequestSignedEventSubscriptionQuery_FullMethodName = "/driver.driver.DriverCommunication/RequestSignedEventSubscriptionQuery" DriverCommunication_WriteExternalState_FullMethodName = "/driver.driver.DriverCommunication/WriteExternalState" + DriverCommunication_PerformLock_FullMethodName = "/driver.driver.DriverCommunication/PerformLock" + DriverCommunication_CreateAsset_FullMethodName = "/driver.driver.DriverCommunication/CreateAsset" + DriverCommunication_Extinguish_FullMethodName = "/driver.driver.DriverCommunication/Extinguish" + DriverCommunication_AssignAsset_FullMethodName = "/driver.driver.DriverCommunication/AssignAsset" ) // DriverCommunicationClient is the client API for DriverCommunication service. @@ -44,6 +52,18 @@ type DriverCommunicationClient interface { // Events Publication // the dest-relay calls the dest-driver on this end point to write the remote network state to the local ledger WriteExternalState(ctx context.Context, in *WriteExternalStateMessage, opts ...grpc.CallOption) (*common.Ack, error) + // As part of SATP, the source reply (sender gateway) sends a PerformLock request to its driver + // to lock a specific asset + PerformLock(ctx context.Context, in *PerformLockRequest, opts ...grpc.CallOption) (*common.Ack, error) + // As part of SATP, the destination reply (receiver gateway) sends a CreateAsset request to its driver + // to create a specific asset + CreateAsset(ctx context.Context, in *CreateAssetRequest, opts ...grpc.CallOption) (*common.Ack, error) + // As part of SATP, the source reply (sender gateway) sends a Extinguish request to its driver + // to extinguish a specific asset + Extinguish(ctx context.Context, in *ExtinguishRequest, opts ...grpc.CallOption) (*common.Ack, error) + // As part of SATP, the destination reply (receiver gateway) sends a AssignAsset request to its driver + // to assign a specific asset + AssignAsset(ctx context.Context, in *AssignAssetRequest, opts ...grpc.CallOption) (*common.Ack, error) } type driverCommunicationClient struct { @@ -90,6 +110,42 @@ func (c *driverCommunicationClient) WriteExternalState(ctx context.Context, in * return out, nil } +func (c *driverCommunicationClient) PerformLock(ctx context.Context, in *PerformLockRequest, opts ...grpc.CallOption) (*common.Ack, error) { + out := new(common.Ack) + err := c.cc.Invoke(ctx, DriverCommunication_PerformLock_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *driverCommunicationClient) CreateAsset(ctx context.Context, in *CreateAssetRequest, opts ...grpc.CallOption) (*common.Ack, error) { + out := new(common.Ack) + err := c.cc.Invoke(ctx, DriverCommunication_CreateAsset_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *driverCommunicationClient) Extinguish(ctx context.Context, in *ExtinguishRequest, opts ...grpc.CallOption) (*common.Ack, error) { + out := new(common.Ack) + err := c.cc.Invoke(ctx, DriverCommunication_Extinguish_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + +func (c *driverCommunicationClient) AssignAsset(ctx context.Context, in *AssignAssetRequest, opts ...grpc.CallOption) (*common.Ack, error) { + out := new(common.Ack) + err := c.cc.Invoke(ctx, DriverCommunication_AssignAsset_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + // DriverCommunicationServer is the server API for DriverCommunication service. // All implementations must embed UnimplementedDriverCommunicationServer // for forward compatibility @@ -108,6 +164,18 @@ type DriverCommunicationServer interface { // Events Publication // the dest-relay calls the dest-driver on this end point to write the remote network state to the local ledger WriteExternalState(context.Context, *WriteExternalStateMessage) (*common.Ack, error) + // As part of SATP, the source reply (sender gateway) sends a PerformLock request to its driver + // to lock a specific asset + PerformLock(context.Context, *PerformLockRequest) (*common.Ack, error) + // As part of SATP, the destination reply (receiver gateway) sends a CreateAsset request to its driver + // to create a specific asset + CreateAsset(context.Context, *CreateAssetRequest) (*common.Ack, error) + // As part of SATP, the source reply (sender gateway) sends a Extinguish request to its driver + // to extinguish a specific asset + Extinguish(context.Context, *ExtinguishRequest) (*common.Ack, error) + // As part of SATP, the destination reply (receiver gateway) sends a AssignAsset request to its driver + // to assign a specific asset + AssignAsset(context.Context, *AssignAssetRequest) (*common.Ack, error) mustEmbedUnimplementedDriverCommunicationServer() } @@ -127,6 +195,18 @@ func (UnimplementedDriverCommunicationServer) RequestSignedEventSubscriptionQuer func (UnimplementedDriverCommunicationServer) WriteExternalState(context.Context, *WriteExternalStateMessage) (*common.Ack, error) { return nil, status.Errorf(codes.Unimplemented, "method WriteExternalState not implemented") } +func (UnimplementedDriverCommunicationServer) PerformLock(context.Context, *PerformLockRequest) (*common.Ack, error) { + return nil, status.Errorf(codes.Unimplemented, "method PerformLock not implemented") +} +func (UnimplementedDriverCommunicationServer) CreateAsset(context.Context, *CreateAssetRequest) (*common.Ack, error) { + return nil, status.Errorf(codes.Unimplemented, "method CreateAsset not implemented") +} +func (UnimplementedDriverCommunicationServer) Extinguish(context.Context, *ExtinguishRequest) (*common.Ack, error) { + return nil, status.Errorf(codes.Unimplemented, "method Extinguish not implemented") +} +func (UnimplementedDriverCommunicationServer) AssignAsset(context.Context, *AssignAssetRequest) (*common.Ack, error) { + return nil, status.Errorf(codes.Unimplemented, "method AssignAsset not implemented") +} func (UnimplementedDriverCommunicationServer) mustEmbedUnimplementedDriverCommunicationServer() {} // UnsafeDriverCommunicationServer may be embedded to opt out of forward compatibility for this service. @@ -212,6 +292,78 @@ func _DriverCommunication_WriteExternalState_Handler(srv interface{}, ctx contex return interceptor(ctx, in, info, handler) } +func _DriverCommunication_PerformLock_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(PerformLockRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverCommunicationServer).PerformLock(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: DriverCommunication_PerformLock_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverCommunicationServer).PerformLock(ctx, req.(*PerformLockRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DriverCommunication_CreateAsset_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(CreateAssetRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverCommunicationServer).CreateAsset(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: DriverCommunication_CreateAsset_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverCommunicationServer).CreateAsset(ctx, req.(*CreateAssetRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DriverCommunication_Extinguish_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(ExtinguishRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverCommunicationServer).Extinguish(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: DriverCommunication_Extinguish_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverCommunicationServer).Extinguish(ctx, req.(*ExtinguishRequest)) + } + return interceptor(ctx, in, info, handler) +} + +func _DriverCommunication_AssignAsset_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(AssignAssetRequest) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(DriverCommunicationServer).AssignAsset(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: DriverCommunication_AssignAsset_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(DriverCommunicationServer).AssignAsset(ctx, req.(*AssignAssetRequest)) + } + return interceptor(ctx, in, info, handler) +} + // DriverCommunication_ServiceDesc is the grpc.ServiceDesc for DriverCommunication service. // It's only intended for direct use with grpc.RegisterService, // and not to be introspected or modified (even as a copy) @@ -235,6 +387,22 @@ var DriverCommunication_ServiceDesc = grpc.ServiceDesc{ MethodName: "WriteExternalState", Handler: _DriverCommunication_WriteExternalState_Handler, }, + { + MethodName: "PerformLock", + Handler: _DriverCommunication_PerformLock_Handler, + }, + { + MethodName: "CreateAsset", + Handler: _DriverCommunication_CreateAsset_Handler, + }, + { + MethodName: "Extinguish", + Handler: _DriverCommunication_Extinguish_Handler, + }, + { + MethodName: "AssignAsset", + Handler: _DriverCommunication_AssignAsset_Handler, + }, }, Streams: []grpc.StreamDesc{}, Metadata: "driver/driver.proto", diff --git a/weaver/common/protos-go/fabric/view_data.pb.go b/weaver/common/protos-go/fabric/view_data.pb.go index 42367f47beb..76a9d5243c1 100644 --- a/weaver/common/protos-go/fabric/view_data.pb.go +++ b/weaver/common/protos-go/fabric/view_data.pb.go @@ -1,3 +1,7 @@ +// Copyright IBM Corp. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.30.0 diff --git a/weaver/common/protos-go/identity/agent.pb.go b/weaver/common/protos-go/identity/agent.pb.go index 97cc217a01d..242b1cf27d6 100644 --- a/weaver/common/protos-go/identity/agent.pb.go +++ b/weaver/common/protos-go/identity/agent.pb.go @@ -1,3 +1,7 @@ +// Copyright IBM Corp. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.30.0 diff --git a/weaver/common/protos-go/identity/agent_grpc.pb.go b/weaver/common/protos-go/identity/agent_grpc.pb.go index 27005cdaa4e..af49e8f241f 100644 --- a/weaver/common/protos-go/identity/agent_grpc.pb.go +++ b/weaver/common/protos-go/identity/agent_grpc.pb.go @@ -1,3 +1,7 @@ +// Copyright IBM Corp. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 + // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.3.0 diff --git a/weaver/common/protos-go/networks/networks.pb.go b/weaver/common/protos-go/networks/networks.pb.go index 5e1f7164b53..377d1b430d4 100644 --- a/weaver/common/protos-go/networks/networks.pb.go +++ b/weaver/common/protos-go/networks/networks.pb.go @@ -1,3 +1,7 @@ +// Copyright IBM Corp. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 + // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.30.0 @@ -392,6 +396,117 @@ func (x *NetworkEventUnsubscription) GetRequestId() string { return "" } +type NetworkAssetTransfer struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Policy []string `protobuf:"bytes,1,rep,name=policy,proto3" json:"policy,omitempty"` + Address string `protobuf:"bytes,2,opt,name=address,proto3" json:"address,omitempty"` + RequestingRelay string `protobuf:"bytes,3,opt,name=requesting_relay,json=requestingRelay,proto3" json:"requesting_relay,omitempty"` + RequestingNetwork string `protobuf:"bytes,4,opt,name=requesting_network,json=requestingNetwork,proto3" json:"requesting_network,omitempty"` + Certificate string `protobuf:"bytes,5,opt,name=certificate,proto3" json:"certificate,omitempty"` + RequestorSignature string `protobuf:"bytes,6,opt,name=requestor_signature,json=requestorSignature,proto3" json:"requestor_signature,omitempty"` + Nonce string `protobuf:"bytes,7,opt,name=nonce,proto3" json:"nonce,omitempty"` + RequestingOrg string `protobuf:"bytes,8,opt,name=requesting_org,json=requestingOrg,proto3" json:"requesting_org,omitempty"` + Confidential bool `protobuf:"varint,9,opt,name=confidential,proto3" json:"confidential,omitempty"` +} + +func (x *NetworkAssetTransfer) Reset() { + *x = NetworkAssetTransfer{} + if protoimpl.UnsafeEnabled { + mi := &file_networks_networks_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NetworkAssetTransfer) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NetworkAssetTransfer) ProtoMessage() {} + +func (x *NetworkAssetTransfer) ProtoReflect() protoreflect.Message { + mi := &file_networks_networks_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NetworkAssetTransfer.ProtoReflect.Descriptor instead. +func (*NetworkAssetTransfer) Descriptor() ([]byte, []int) { + return file_networks_networks_proto_rawDescGZIP(), []int{6} +} + +func (x *NetworkAssetTransfer) GetPolicy() []string { + if x != nil { + return x.Policy + } + return nil +} + +func (x *NetworkAssetTransfer) GetAddress() string { + if x != nil { + return x.Address + } + return "" +} + +func (x *NetworkAssetTransfer) GetRequestingRelay() string { + if x != nil { + return x.RequestingRelay + } + return "" +} + +func (x *NetworkAssetTransfer) GetRequestingNetwork() string { + if x != nil { + return x.RequestingNetwork + } + return "" +} + +func (x *NetworkAssetTransfer) GetCertificate() string { + if x != nil { + return x.Certificate + } + return "" +} + +func (x *NetworkAssetTransfer) GetRequestorSignature() string { + if x != nil { + return x.RequestorSignature + } + return "" +} + +func (x *NetworkAssetTransfer) GetNonce() string { + if x != nil { + return x.Nonce + } + return "" +} + +func (x *NetworkAssetTransfer) GetRequestingOrg() string { + if x != nil { + return x.RequestingOrg + } + return "" +} + +func (x *NetworkAssetTransfer) GetConfidential() bool { + if x != nil { + return x.Confidential + } + return false +} + var File_networks_networks_proto protoreflect.FileDescriptor var file_networks_networks_proto_rawDesc = []byte{ @@ -459,53 +574,79 @@ var file_networks_networks_proto_rawDesc = []byte{ 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x07, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x32, 0xd3, 0x04, 0x0a, 0x07, 0x4e, 0x65, - 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x42, 0x0a, 0x0c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1f, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, - 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, - 0x6b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x1a, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, - 0x61, 0x63, 0x6b, 0x2e, 0x41, 0x63, 0x6b, 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x08, 0x47, 0x65, 0x74, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x49, 0x64, 0x22, 0xd6, 0x02, 0x0a, 0x14, 0x4e, 0x65, + 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, + 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x18, 0x01, 0x20, 0x03, + 0x28, 0x09, 0x52, 0x06, 0x70, 0x6f, 0x6c, 0x69, 0x63, 0x79, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, + 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, + 0x72, 0x65, 0x73, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, + 0x6e, 0x67, 0x5f, 0x72, 0x65, 0x6c, 0x61, 0x79, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0f, + 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x12, + 0x2d, 0x0a, 0x12, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x6e, 0x65, + 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x11, 0x72, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x20, + 0x0a, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, + 0x12, 0x2f, 0x0a, 0x13, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x5f, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x12, 0x72, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x6f, 0x72, 0x53, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, + 0x65, 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x6e, 0x6f, 0x6e, 0x63, 0x65, 0x12, 0x25, 0x0a, 0x0e, 0x72, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x6f, 0x72, 0x67, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0d, 0x72, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x67, 0x4f, 0x72, 0x67, 0x12, 0x22, + 0x0a, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, 0x61, 0x6c, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x08, 0x52, 0x0c, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x64, 0x65, 0x6e, 0x74, 0x69, + 0x61, 0x6c, 0x32, 0xa7, 0x05, 0x0a, 0x07, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x12, 0x42, + 0x0a, 0x0c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x1f, + 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, + 0x6b, 0x73, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x51, 0x75, 0x65, 0x72, 0x79, 0x1a, + 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x61, 0x63, 0x6b, 0x2e, 0x41, 0x63, 0x6b, + 0x22, 0x00, 0x12, 0x4c, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x22, + 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, + 0x6b, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x1a, 0x1a, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x73, 0x74, 0x61, 0x74, + 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0x00, + 0x12, 0x50, 0x0a, 0x0f, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, + 0x61, 0x73, 0x65, 0x12, 0x19, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x6e, + 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x44, 0x62, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x20, + 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, + 0x6b, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x52, 0x0a, 0x14, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x41, 0x73, 0x73, + 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, 0x66, 0x65, 0x72, 0x12, 0x27, 0x2e, 0x6e, 0x65, 0x74, + 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x4e, + 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x41, 0x73, 0x73, 0x65, 0x74, 0x54, 0x72, 0x61, 0x6e, 0x73, + 0x66, 0x65, 0x72, 0x1a, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x61, 0x63, 0x6b, + 0x2e, 0x41, 0x63, 0x6b, 0x22, 0x00, 0x12, 0x50, 0x0a, 0x0e, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, + 0x69, 0x62, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2b, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, + 0x72, 0x6b, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x4e, 0x65, 0x74, + 0x77, 0x6f, 0x72, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x61, + 0x63, 0x6b, 0x2e, 0x41, 0x63, 0x6b, 0x22, 0x00, 0x12, 0x68, 0x0a, 0x19, 0x47, 0x65, 0x74, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x22, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, - 0x74, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1a, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, - 0x6f, 0x6e, 0x2e, 0x73, 0x74, 0x61, 0x74, 0x65, 0x2e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x22, 0x00, 0x12, 0x50, 0x0a, 0x0f, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x44, 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x12, 0x19, 0x2e, 0x6e, 0x65, 0x74, - 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x44, - 0x62, 0x4e, 0x61, 0x6d, 0x65, 0x1a, 0x20, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, - 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x52, 0x65, 0x6c, 0x61, 0x79, 0x44, - 0x61, 0x74, 0x61, 0x62, 0x61, 0x73, 0x65, 0x22, 0x00, 0x12, 0x50, 0x0a, 0x0e, 0x53, 0x75, 0x62, - 0x73, 0x63, 0x72, 0x69, 0x62, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2b, 0x2e, 0x6e, 0x65, - 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, - 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, - 0x6e, 0x2e, 0x61, 0x63, 0x6b, 0x2e, 0x41, 0x63, 0x6b, 0x22, 0x00, 0x12, 0x68, 0x0a, 0x19, 0x47, - 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x22, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, - 0x72, 0x6b, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x47, 0x65, 0x74, - 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x25, 0x2e, 0x63, - 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x53, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, - 0x61, 0x74, 0x65, 0x22, 0x00, 0x12, 0x54, 0x0a, 0x10, 0x55, 0x6e, 0x73, 0x75, 0x62, 0x73, 0x63, - 0x72, 0x69, 0x62, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2d, 0x2e, 0x6e, 0x65, 0x74, 0x77, - 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x4e, 0x65, - 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x55, 0x6e, 0x73, 0x75, 0x62, 0x73, - 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, - 0x6e, 0x2e, 0x61, 0x63, 0x6b, 0x2e, 0x41, 0x63, 0x6b, 0x22, 0x00, 0x12, 0x52, 0x0a, 0x0e, 0x47, - 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x12, 0x22, 0x2e, - 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, - 0x73, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x1a, 0x1a, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x73, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x22, 0x00, 0x42, - 0x79, 0x0a, 0x35, 0x6f, 0x72, 0x67, 0x2e, 0x68, 0x79, 0x70, 0x65, 0x72, 0x6c, 0x65, 0x64, 0x67, - 0x65, 0x72, 0x2e, 0x63, 0x61, 0x63, 0x74, 0x69, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, - 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x68, 0x79, 0x70, 0x65, 0x72, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x72, - 0x2f, 0x63, 0x61, 0x63, 0x74, 0x69, 0x2f, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x2f, 0x63, 0x6f, - 0x6d, 0x6d, 0x6f, 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2d, 0x67, 0x6f, 0x2f, 0x76, - 0x32, 0x2f, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x74, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x25, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, + 0x6f, 0x6e, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, + 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x53, 0x74, 0x61, 0x74, 0x65, + 0x22, 0x00, 0x12, 0x54, 0x0a, 0x10, 0x55, 0x6e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, 0x62, + 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x2d, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, + 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x4e, 0x65, 0x74, 0x77, 0x6f, + 0x72, 0x6b, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x55, 0x6e, 0x73, 0x75, 0x62, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x1a, 0x0f, 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x61, + 0x63, 0x6b, 0x2e, 0x41, 0x63, 0x6b, 0x22, 0x00, 0x12, 0x52, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x12, 0x22, 0x2e, 0x6e, 0x65, 0x74, + 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x47, + 0x65, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1a, + 0x2e, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, 0x6e, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x2e, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x65, 0x73, 0x22, 0x00, 0x42, 0x79, 0x0a, 0x35, + 0x6f, 0x72, 0x67, 0x2e, 0x68, 0x79, 0x70, 0x65, 0x72, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x72, 0x2e, + 0x63, 0x61, 0x63, 0x74, 0x69, 0x2e, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x73, 0x2e, 0x6e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x2e, 0x6e, 0x65, 0x74, + 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, + 0x6d, 0x2f, 0x68, 0x79, 0x70, 0x65, 0x72, 0x6c, 0x65, 0x64, 0x67, 0x65, 0x72, 0x2f, 0x63, 0x61, + 0x63, 0x74, 0x69, 0x2f, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x2f, 0x63, 0x6f, 0x6d, 0x6d, 0x6f, + 0x6e, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x73, 0x2d, 0x67, 0x6f, 0x2f, 0x76, 0x32, 0x2f, 0x6e, + 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x73, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -520,7 +661,7 @@ func file_networks_networks_proto_rawDescGZIP() []byte { return file_networks_networks_proto_rawDescData } -var file_networks_networks_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_networks_networks_proto_msgTypes = make([]protoimpl.MessageInfo, 8) var file_networks_networks_proto_goTypes = []interface{}{ (*DbName)(nil), // 0: networks.networks.DbName (*RelayDatabase)(nil), // 1: networks.networks.RelayDatabase @@ -528,36 +669,39 @@ var file_networks_networks_proto_goTypes = []interface{}{ (*NetworkQuery)(nil), // 3: networks.networks.NetworkQuery (*NetworkEventSubscription)(nil), // 4: networks.networks.NetworkEventSubscription (*NetworkEventUnsubscription)(nil), // 5: networks.networks.NetworkEventUnsubscription - nil, // 6: networks.networks.RelayDatabase.PairsEntry - (*common.EventMatcher)(nil), // 7: common.events.EventMatcher - (*common.EventPublication)(nil), // 8: common.events.EventPublication - (*common.Ack)(nil), // 9: common.ack.Ack - (*common.RequestState)(nil), // 10: common.state.RequestState - (*common.EventSubscriptionState)(nil), // 11: common.events.EventSubscriptionState - (*common.EventStates)(nil), // 12: common.events.EventStates + (*NetworkAssetTransfer)(nil), // 6: networks.networks.NetworkAssetTransfer + nil, // 7: networks.networks.RelayDatabase.PairsEntry + (*common.EventMatcher)(nil), // 8: common.events.EventMatcher + (*common.EventPublication)(nil), // 9: common.events.EventPublication + (*common.Ack)(nil), // 10: common.ack.Ack + (*common.RequestState)(nil), // 11: common.state.RequestState + (*common.EventSubscriptionState)(nil), // 12: common.events.EventSubscriptionState + (*common.EventStates)(nil), // 13: common.events.EventStates } var file_networks_networks_proto_depIdxs = []int32{ - 6, // 0: networks.networks.RelayDatabase.pairs:type_name -> networks.networks.RelayDatabase.PairsEntry - 7, // 1: networks.networks.NetworkEventSubscription.event_matcher:type_name -> common.events.EventMatcher + 7, // 0: networks.networks.RelayDatabase.pairs:type_name -> networks.networks.RelayDatabase.PairsEntry + 8, // 1: networks.networks.NetworkEventSubscription.event_matcher:type_name -> common.events.EventMatcher 3, // 2: networks.networks.NetworkEventSubscription.query:type_name -> networks.networks.NetworkQuery - 8, // 3: networks.networks.NetworkEventSubscription.event_publication_spec:type_name -> common.events.EventPublication + 9, // 3: networks.networks.NetworkEventSubscription.event_publication_spec:type_name -> common.events.EventPublication 4, // 4: networks.networks.NetworkEventUnsubscription.request:type_name -> networks.networks.NetworkEventSubscription 3, // 5: networks.networks.Network.RequestState:input_type -> networks.networks.NetworkQuery 2, // 6: networks.networks.Network.GetState:input_type -> networks.networks.GetStateMessage 0, // 7: networks.networks.Network.RequestDatabase:input_type -> networks.networks.DbName - 4, // 8: networks.networks.Network.SubscribeEvent:input_type -> networks.networks.NetworkEventSubscription - 2, // 9: networks.networks.Network.GetEventSubscriptionState:input_type -> networks.networks.GetStateMessage - 5, // 10: networks.networks.Network.UnsubscribeEvent:input_type -> networks.networks.NetworkEventUnsubscription - 2, // 11: networks.networks.Network.GetEventStates:input_type -> networks.networks.GetStateMessage - 9, // 12: networks.networks.Network.RequestState:output_type -> common.ack.Ack - 10, // 13: networks.networks.Network.GetState:output_type -> common.state.RequestState - 1, // 14: networks.networks.Network.RequestDatabase:output_type -> networks.networks.RelayDatabase - 9, // 15: networks.networks.Network.SubscribeEvent:output_type -> common.ack.Ack - 11, // 16: networks.networks.Network.GetEventSubscriptionState:output_type -> common.events.EventSubscriptionState - 9, // 17: networks.networks.Network.UnsubscribeEvent:output_type -> common.ack.Ack - 12, // 18: networks.networks.Network.GetEventStates:output_type -> common.events.EventStates - 12, // [12:19] is the sub-list for method output_type - 5, // [5:12] is the sub-list for method input_type + 6, // 8: networks.networks.Network.RequestAssetTransfer:input_type -> networks.networks.NetworkAssetTransfer + 4, // 9: networks.networks.Network.SubscribeEvent:input_type -> networks.networks.NetworkEventSubscription + 2, // 10: networks.networks.Network.GetEventSubscriptionState:input_type -> networks.networks.GetStateMessage + 5, // 11: networks.networks.Network.UnsubscribeEvent:input_type -> networks.networks.NetworkEventUnsubscription + 2, // 12: networks.networks.Network.GetEventStates:input_type -> networks.networks.GetStateMessage + 10, // 13: networks.networks.Network.RequestState:output_type -> common.ack.Ack + 11, // 14: networks.networks.Network.GetState:output_type -> common.state.RequestState + 1, // 15: networks.networks.Network.RequestDatabase:output_type -> networks.networks.RelayDatabase + 10, // 16: networks.networks.Network.RequestAssetTransfer:output_type -> common.ack.Ack + 10, // 17: networks.networks.Network.SubscribeEvent:output_type -> common.ack.Ack + 12, // 18: networks.networks.Network.GetEventSubscriptionState:output_type -> common.events.EventSubscriptionState + 10, // 19: networks.networks.Network.UnsubscribeEvent:output_type -> common.ack.Ack + 13, // 20: networks.networks.Network.GetEventStates:output_type -> common.events.EventStates + 13, // [13:21] is the sub-list for method output_type + 5, // [5:13] is the sub-list for method input_type 5, // [5:5] is the sub-list for extension type_name 5, // [5:5] is the sub-list for extension extendee 0, // [0:5] is the sub-list for field type_name @@ -641,6 +785,18 @@ func file_networks_networks_proto_init() { return nil } } + file_networks_networks_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NetworkAssetTransfer); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } } type x struct{} out := protoimpl.TypeBuilder{ @@ -648,7 +804,7 @@ func file_networks_networks_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_networks_networks_proto_rawDesc, NumEnums: 0, - NumMessages: 7, + NumMessages: 8, NumExtensions: 0, NumServices: 1, }, diff --git a/weaver/common/protos-go/networks/networks_grpc.pb.go b/weaver/common/protos-go/networks/networks_grpc.pb.go index 089e1a295e8..250b64fcb30 100644 --- a/weaver/common/protos-go/networks/networks_grpc.pb.go +++ b/weaver/common/protos-go/networks/networks_grpc.pb.go @@ -1,3 +1,7 @@ +// Copyright IBM Corp. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 + // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.3.0 @@ -23,6 +27,7 @@ const ( Network_RequestState_FullMethodName = "/networks.networks.Network/RequestState" Network_GetState_FullMethodName = "/networks.networks.Network/GetState" Network_RequestDatabase_FullMethodName = "/networks.networks.Network/RequestDatabase" + Network_RequestAssetTransfer_FullMethodName = "/networks.networks.Network/RequestAssetTransfer" Network_SubscribeEvent_FullMethodName = "/networks.networks.Network/SubscribeEvent" Network_GetEventSubscriptionState_FullMethodName = "/networks.networks.Network/GetEventSubscriptionState" Network_UnsubscribeEvent_FullMethodName = "/networks.networks.Network/UnsubscribeEvent" @@ -40,6 +45,9 @@ type NetworkClient interface { GetState(ctx context.Context, in *GetStateMessage, opts ...grpc.CallOption) (*common.RequestState, error) // NOTE: This rpc is just for debugging. RequestDatabase(ctx context.Context, in *DbName, opts ...grpc.CallOption) (*RelayDatabase, error) + // SATP endpoints + // endpoint for a network to request asset transfer to a receiving gateway via local gateway + RequestAssetTransfer(ctx context.Context, in *NetworkAssetTransfer, opts ...grpc.CallOption) (*common.Ack, error) // Event endpoints // endpoint for a client to subscribe to event via local relay initiating subscription flow. SubscribeEvent(ctx context.Context, in *NetworkEventSubscription, opts ...grpc.CallOption) (*common.Ack, error) @@ -87,6 +95,15 @@ func (c *networkClient) RequestDatabase(ctx context.Context, in *DbName, opts .. return out, nil } +func (c *networkClient) RequestAssetTransfer(ctx context.Context, in *NetworkAssetTransfer, opts ...grpc.CallOption) (*common.Ack, error) { + out := new(common.Ack) + err := c.cc.Invoke(ctx, Network_RequestAssetTransfer_FullMethodName, in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *networkClient) SubscribeEvent(ctx context.Context, in *NetworkEventSubscription, opts ...grpc.CallOption) (*common.Ack, error) { out := new(common.Ack) err := c.cc.Invoke(ctx, Network_SubscribeEvent_FullMethodName, in, out, opts...) @@ -134,6 +151,9 @@ type NetworkServer interface { GetState(context.Context, *GetStateMessage) (*common.RequestState, error) // NOTE: This rpc is just for debugging. RequestDatabase(context.Context, *DbName) (*RelayDatabase, error) + // SATP endpoints + // endpoint for a network to request asset transfer to a receiving gateway via local gateway + RequestAssetTransfer(context.Context, *NetworkAssetTransfer) (*common.Ack, error) // Event endpoints // endpoint for a client to subscribe to event via local relay initiating subscription flow. SubscribeEvent(context.Context, *NetworkEventSubscription) (*common.Ack, error) @@ -160,6 +180,9 @@ func (UnimplementedNetworkServer) GetState(context.Context, *GetStateMessage) (* func (UnimplementedNetworkServer) RequestDatabase(context.Context, *DbName) (*RelayDatabase, error) { return nil, status.Errorf(codes.Unimplemented, "method RequestDatabase not implemented") } +func (UnimplementedNetworkServer) RequestAssetTransfer(context.Context, *NetworkAssetTransfer) (*common.Ack, error) { + return nil, status.Errorf(codes.Unimplemented, "method RequestAssetTransfer not implemented") +} func (UnimplementedNetworkServer) SubscribeEvent(context.Context, *NetworkEventSubscription) (*common.Ack, error) { return nil, status.Errorf(codes.Unimplemented, "method SubscribeEvent not implemented") } @@ -239,6 +262,24 @@ func _Network_RequestDatabase_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _Network_RequestAssetTransfer_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(NetworkAssetTransfer) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(NetworkServer).RequestAssetTransfer(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: Network_RequestAssetTransfer_FullMethodName, + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(NetworkServer).RequestAssetTransfer(ctx, req.(*NetworkAssetTransfer)) + } + return interceptor(ctx, in, info, handler) +} + func _Network_SubscribeEvent_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(NetworkEventSubscription) if err := dec(in); err != nil { @@ -330,6 +371,10 @@ var Network_ServiceDesc = grpc.ServiceDesc{ MethodName: "RequestDatabase", Handler: _Network_RequestDatabase_Handler, }, + { + MethodName: "RequestAssetTransfer", + Handler: _Network_RequestAssetTransfer_Handler, + }, { MethodName: "SubscribeEvent", Handler: _Network_SubscribeEvent_Handler, diff --git a/weaver/common/protos-js/build-protos.sh b/weaver/common/protos-js/build-protos.sh index 4322b209729..75e53b774a0 100755 --- a/weaver/common/protos-js/build-protos.sh +++ b/weaver/common/protos-js/build-protos.sh @@ -17,7 +17,7 @@ grpc_tools_node_protoc --proto_path=$PROTOSDIR --proto_path=$FABRIC_PROTOSDIR - grpc_tools_node_protoc --proto_path=$PROTOSDIR --proto_path=$FABRIC_PROTOSDIR --js_out=import_style=commonjs,binary:$BUILDDIR --plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin` $PROTOSDIR/fabric/view_data.proto grpc_tools_node_protoc --proto_path=$PROTOSDIR --proto_path=$FABRIC_PROTOSDIR --js_out=import_style=commonjs,binary:$BUILDDIR --grpc_out=grpc_js:$BUILDDIR --plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin` $PROTOSDIR/identity/agent.proto grpc_tools_node_protoc --proto_path=$PROTOSDIR --proto_path=$FABRIC_PROTOSDIR --js_out=import_style=commonjs,binary:$BUILDDIR --grpc_out=grpc_js:$BUILDDIR --plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin` $PROTOSDIR/networks/networks.proto -grpc_tools_node_protoc --proto_path=$PROTOSDIR --proto_path=$FABRIC_PROTOSDIR --js_out=import_style=commonjs,binary:$BUILDDIR --grpc_out=grpc_js:$BUILDDIR --plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin` $PROTOSDIR/relay/datatransfer.proto $PROTOSDIR/relay/events.proto +grpc_tools_node_protoc --proto_path=$PROTOSDIR --proto_path=$FABRIC_PROTOSDIR --js_out=import_style=commonjs,binary:$BUILDDIR --grpc_out=grpc_js:$BUILDDIR --plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin` $PROTOSDIR/relay/datatransfer.proto $PROTOSDIR/relay/events.proto $PROTOSDIR/relay/satp.proto grpc_tools_node_protoc --proto_path=$PROTOSDIR --proto_path=$FABRIC_PROTOSDIR --js_out=import_style=commonjs,binary:$BUILDDIR --plugin=protoc-gen-grpc=`which grpc_tools_node_protoc_plugin` $FABRIC_PROTOSDIR/msp/identities.proto $FABRIC_PROTOSDIR/peer/proposal_response.proto $FABRIC_PROTOSDIR/peer/proposal.proto $FABRIC_PROTOSDIR/peer/chaincode.proto $FABRIC_PROTOSDIR/common/policies.proto $FABRIC_PROTOSDIR/msp/msp_principal.proto # Typescript Build @@ -27,5 +27,5 @@ protoc --plugin=protoc-gen-ts=./node_modules/.bin/protoc-gen-ts --ts_out=grpc_js protoc --plugin=protoc-gen-ts=./node_modules/.bin/protoc-gen-ts --ts_out=$BUILDDIR -I $PROTOSDIR -I $FABRIC_PROTOSDIR $PROTOSDIR/fabric/view_data.proto protoc --plugin=protoc-gen-ts=./node_modules/.bin/protoc-gen-ts --ts_out=grpc_js:$BUILDDIR -I $PROTOSDIR -I $FABRIC_PROTOSDIR $PROTOSDIR/identity/agent.proto protoc --plugin=protoc-gen-ts=./node_modules/.bin/protoc-gen-ts --ts_out=grpc_js:$BUILDDIR -I $PROTOSDIR -I $FABRIC_PROTOSDIR $PROTOSDIR/networks/networks.proto -protoc --plugin=protoc-gen-ts=./node_modules/.bin/protoc-gen-ts --ts_out=grpc_js:$BUILDDIR -I $PROTOSDIR -I $FABRIC_PROTOSDIR $PROTOSDIR/relay/datatransfer.proto $PROTOSDIR/relay/events.proto +protoc --plugin=protoc-gen-ts=./node_modules/.bin/protoc-gen-ts --ts_out=grpc_js:$BUILDDIR -I $PROTOSDIR -I $FABRIC_PROTOSDIR $PROTOSDIR/relay/datatransfer.proto $PROTOSDIR/relay/events.proto $PROTOSDIR/relay/satp.proto protoc --plugin=protoc-gen-ts=./node_modules/.bin/protoc-gen-ts --ts_out=$BUILDDIR -I $PROTOSDIR -I $FABRIC_PROTOSDIR $FABRIC_PROTOSDIR/msp/identities.proto $FABRIC_PROTOSDIR/peer/proposal_response.proto $FABRIC_PROTOSDIR/peer/proposal.proto $FABRIC_PROTOSDIR/peer/chaincode.proto $FABRIC_PROTOSDIR/common/policies.proto $FABRIC_PROTOSDIR/msp/msp_principal.proto diff --git a/weaver/common/protos-rs/Cargo.lock b/weaver/common/protos-rs/Cargo.lock index acec77856c4..670570dba58 100644 --- a/weaver/common/protos-rs/Cargo.lock +++ b/weaver/common/protos-rs/Cargo.lock @@ -28,15 +28,15 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.70" +version = "1.0.71" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" +checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" [[package]] name = "async-stream" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad445822218ce64be7a341abfb0b1ea43b5c23aa83902542a4542e78309d8e5e" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" dependencies = [ "async-stream-impl", "futures-core", @@ -45,13 +45,13 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.22", ] [[package]] @@ -73,9 +73,9 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "axum" -version = "0.6.12" +version = "0.6.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f8ccfd9221ee7d1f3d4b33e1f8319b3a81ed8f61f2ea40b37b859794b4491" +checksum = "f8175979259124331c1d7bf6586ee7e0da434155e4b2d48ec2c8386281d8df39" dependencies = [ "async-trait", "axum-core", @@ -101,9 +101,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2f958c80c248b34b9a877a643811be8dbca03ca5ba827f2b63baf3a81e5fc4e" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" dependencies = [ "async-trait", "bytes", @@ -118,7 +118,22 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.69" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" dependencies = [ @@ -133,9 +148,9 @@ dependencies = [ [[package]] name = "base64" -version = "0.21.0" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" [[package]] name = "bitflags" @@ -156,9 +171,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.12.0" +version = "3.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" [[package]] name = "bytes" @@ -262,9 +277,9 @@ dependencies = [ [[package]] name = "getrandom" -version = "0.2.8" +version = "0.2.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c05aeb6a22b8f62540c194aac980f2115af067bfe15a0734d7277a768d396b31" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", "libc", @@ -447,9 +462,9 @@ checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" [[package]] name = "js-sys" -version = "0.3.61" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" dependencies = [ "wasm-bindgen", ] @@ -468,12 +483,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "log" -version = "0.4.17" +version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" [[package]] name = "matchit" @@ -530,15 +542,15 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "petgraph" @@ -552,22 +564,22 @@ dependencies = [ [[package]] name = "pin-project" -version = "1.0.12" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.12" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.22", ] [[package]] @@ -801,9 +813,9 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" dependencies = [ "base64", ] @@ -925,10 +937,11 @@ checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" [[package]] name = "tempfile" -version = "3.5.0" +version = "3.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +checksum = "31c0432476357e58790aaa47a8efb0c5138f137343f3b5f23bd36a27e3b0a6d6" dependencies = [ + "autocfg", "cfg-if", "fastrand", "redox_syscall", @@ -985,9 +998,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" dependencies = [ "futures-core", "pin-project-lite", @@ -996,9 +1009,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" dependencies = [ "bytes", "futures-core", @@ -1097,20 +1110,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.23" +version = "0.1.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.22", ] [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" dependencies = [ "once_cell", ] @@ -1123,9 +1136,9 @@ checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" [[package]] name = "untrusted" @@ -1141,11 +1154,10 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "want" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "log", "try-lock", ] @@ -1157,9 +1169,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1167,24 +1179,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.22", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-macro" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1192,28 +1204,28 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.22", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.84" +version = "0.2.87" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" [[package]] name = "web-sys" -version = "0.3.61" +version = "0.3.64" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" dependencies = [ "js-sys", "wasm-bindgen", @@ -1254,9 +1266,9 @@ checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] name = "windows-sys" -version = "0.45.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ "windows-targets 0.42.2", ] @@ -1281,9 +1293,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.42.2" +version = "0.48.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" dependencies = [ "windows_aarch64_gnullvm 0.42.2", "windows_aarch64_msvc 0.42.2", @@ -1326,9 +1338,9 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" [[package]] name = "windows_aarch64_gnullvm" @@ -1344,9 +1356,9 @@ checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" [[package]] name = "windows_aarch64_msvc" @@ -1362,9 +1374,9 @@ checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" [[package]] name = "windows_i686_gnu" @@ -1380,9 +1392,9 @@ checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" [[package]] name = "windows_i686_msvc" @@ -1398,9 +1410,9 @@ checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" [[package]] name = "windows_x86_64_gnu" @@ -1416,9 +1428,9 @@ checksum = "3d6fa32db2bc4a2f5abeacf2b69f7992cd09dca97498da74a151a3132c26befd" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" [[package]] name = "windows_x86_64_gnullvm" diff --git a/weaver/common/protos-rs/build.rs b/weaver/common/protos-rs/build.rs index ffd5d413f32..5d782fab867 100644 --- a/weaver/common/protos-rs/build.rs +++ b/weaver/common/protos-rs/build.rs @@ -11,6 +11,7 @@ fn main() -> Result<(), Box> { .compile( &[ "../protos/relay/datatransfer.proto", + "../protos/relay/satp.proto", "../protos/relay/events.proto", "../protos/networks/networks.proto", "../protos/driver/driver.proto", diff --git a/weaver/common/protos-rs/pkg/Cargo.lock b/weaver/common/protos-rs/pkg/Cargo.lock new file mode 100644 index 00000000000..993bf77f830 --- /dev/null +++ b/weaver/common/protos-rs/pkg/Cargo.lock @@ -0,0 +1,1059 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "addr2line" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a76fd60b23679b7d19bd066031410fb7e458ccc5e958eb5c325888ce4baedc97" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "anyhow" +version = "1.0.71" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8" + +[[package]] +name = "async-stream" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "async-trait" +version = "0.1.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "autocfg" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" + +[[package]] +name = "axum" +version = "0.6.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8175979259124331c1d7bf6586ee7e0da434155e4b2d48ec2c8386281d8df39" +dependencies = [ + "async-trait", + "axum-core", + "bitflags", + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + +[[package]] +name = "backtrace" +version = "0.3.67" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233d376d6d185f2a3093e58f283f60f880315b6c60075b01f36b3b85154564ca" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" + +[[package]] +name = "base64" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" + +[[package]] +name = "bumpalo" +version = "3.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" + +[[package]] +name = "bytes" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" + +[[package]] +name = "cacti_weaver_protos_rs" +version = "2.0.0-alpha.1" +dependencies = [ + "prost", + "serde", + "tonic", +] + +[[package]] +name = "cc" +version = "1.0.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50d30906286121d95be3d479533b458f87493b30a4b5f79a607db8f5d11aa91f" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "either" +version = "1.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" + +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "futures-channel" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +dependencies = [ + "futures-core", +] + +[[package]] +name = "futures-core" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" + +[[package]] +name = "futures-sink" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" + +[[package]] +name = "futures-task" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" + +[[package]] +name = "futures-util" +version = "0.3.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +dependencies = [ + "futures-core", + "futures-task", + "pin-project-lite", + "pin-utils", +] + +[[package]] +name = "getrandom" +version = "0.2.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "gimli" +version = "0.27.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6c80984affa11d98d1b88b66ac8853f143217b399d3c74116778ff8fdb4ed2e" + +[[package]] +name = "h2" +version = "0.3.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97ec8491ebaf99c8eaa73058b045fe58073cd6be7f596ac993ced0b0a0c01049" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + +[[package]] +name = "http" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +dependencies = [ + "bytes", + "fnv", + "itoa", +] + +[[package]] +name = "http-body" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d5f38f16d184e36f2408a55281cd658ecbd3ca05cce6d6510a176eca393e26d1" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" + +[[package]] +name = "hyper" +version = "0.14.27" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ffb1cfd654a8219eaef89881fdb3bb3b1cdc5fa75ded05d6933b2b382e395468" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown", +] + +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" + +[[package]] +name = "js-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c5f195fe497f702db0f318b07fdd68edb16955aed830df8363d837542f8f935a" +dependencies = [ + "wasm-bindgen", +] + +[[package]] +name = "libc" +version = "0.2.147" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" + +[[package]] +name = "log" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4" + +[[package]] +name = "matchit" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + +[[package]] +name = "miniz_oxide" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b275950c28b37e794e8c55d88aeb5e139d0ce23fdbbeda68f8d7174abdf9e8fa" +dependencies = [ + "adler", +] + +[[package]] +name = "mio" +version = "0.8.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "927a765cd3fc26206e66b296465fa9d3e5ab003e651c1b3c060e7956d96b19d2" +dependencies = [ + "libc", + "wasi", + "windows-sys", +] + +[[package]] +name = "object" +version = "0.30.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03b4680b86d9cfafba8fc491dc9b6df26b68cf40e9e6cd73909194759a63c385" +dependencies = [ + "memchr", +] + +[[package]] +name = "once_cell" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" + +[[package]] +name = "percent-encoding" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" + +[[package]] +name = "pin-project" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c95a7476719eab1e366eaf73d0260af3021184f18177925b07f54b30089ceead" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39407670928234ebc5e6e580247dd567ad73a3578460c5990f9503df207e8f07" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "pin-utils" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" + +[[package]] +name = "ppv-lite86" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" + +[[package]] +name = "proc-macro2" +version = "1.0.63" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7b368fba921b0dce7e60f5e04ec15e565b3303972b42bcfde1d0713b881959eb" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "prost" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b82eaa1d779e9a4bc1c3217db8ffbeabaae1dca241bf70183242128d48681cd" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.11.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5d2d8d10f3c6ded6da8b05b5fb3b8a5082514344d56c9f871412d29b4e075b4" +dependencies = [ + "anyhow", + "itertools", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "quote" +version = "1.0.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "rand" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" +dependencies = [ + "libc", + "rand_chacha", + "rand_core", +] + +[[package]] +name = "rand_chacha" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" +dependencies = [ + "ppv-lite86", + "rand_core", +] + +[[package]] +name = "rand_core" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +dependencies = [ + "getrandom", +] + +[[package]] +name = "ring" +version = "0.16.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3053cf52e236a3ed746dfc745aa9cacf1b791d846bdaf412f60a8d7d6e17c8fc" +dependencies = [ + "cc", + "libc", + "once_cell", + "spin", + "untrusted", + "web-sys", + "winapi", +] + +[[package]] +name = "rustc-demangle" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" + +[[package]] +name = "rustls" +version = "0.20.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fff78fc74d175294f4e83b28343315ffcfb114b156f0185e9741cb5570f50e2f" +dependencies = [ + "log", + "ring", + "sct", + "webpki", +] + +[[package]] +name = "rustls-pemfile" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2d3987094b1d07b653b7dfdc3f70ce9a1da9c51ac18c1b06b662e4f9a0e9f4b2" +dependencies = [ + "base64 0.21.2", +] + +[[package]] +name = "rustversion" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" + +[[package]] +name = "sct" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "serde" +version = "1.0.164" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.164" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "slab" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +dependencies = [ + "autocfg", +] + +[[package]] +name = "socket2" +version = "0.4.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +dependencies = [ + "libc", + "winapi", +] + +[[package]] +name = "spin" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" + +[[package]] +name = "syn" +version = "1.0.109" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "syn" +version = "2.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2efbeae7acf4eabd6bcdcbd11c92f45231ddda7539edc7806bd1a04a03b24616" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + +[[package]] +name = "tokio" +version = "1.29.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "374442f06ee49c3a28a8fc9f01a2596fed7559c6b99b31279c3261778e77d84f" +dependencies = [ + "autocfg", + "backtrace", + "bytes", + "libc", + "mio", + "pin-project-lite", + "socket2", + "tokio-macros", + "windows-sys", +] + +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-macros" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "tokio-rustls" +version = "0.23.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c43ee83903113e03984cb9e5cebe6c04a5116269e900e3ddba8f068a62adda59" +dependencies = [ + "rustls", + "tokio", + "webpki", +] + +[[package]] +name = "tokio-stream" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "806fe8c2c87eccc8b3267cbae29ed3ab2d0bd37fca70ab622e46aaa9375ddb7d" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + +[[package]] +name = "tonic" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f219fad3b929bef19b1f86fbc0358d35daed8f2cac972037ac0dc10bbb8d5fb" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64 0.13.1", + "bytes", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "hyper", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost", + "prost-derive", + "rustls-pemfile", + "tokio", + "tokio-rustls", + "tokio-stream", + "tokio-util", + "tower", + "tower-layer", + "tower-service", + "tracing", + "tracing-futures", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap", + "pin-project", + "pin-project-lite", + "rand", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + +[[package]] +name = "tracing" +version = "0.1.37" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", +] + +[[package]] +name = "tracing-core" +version = "0.1.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tracing-futures" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2" +dependencies = [ + "pin-project", + "tracing", +] + +[[package]] +name = "try-lock" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3528ecfd12c466c6f163363caf2d02a71161dd5e1cc6ae7b34207ea2d42d81ed" + +[[package]] +name = "unicode-ident" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b15811caf2415fb889178633e7724bad2509101cde276048e013b9def5e51fa0" + +[[package]] +name = "untrusted" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a156c684c91ea7d62626509bce3cb4e1d9ed5c4d978f7b4352658f96a4c26b4a" + +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + +[[package]] +name = "wasi" +version = "0.11.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" + +[[package]] +name = "wasm-bindgen" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7706a72ab36d8cb1f80ffbf0e071533974a60d0a308d01a5d0375bf60499a342" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ef2b6d3c510e9625e5fe6f509ab07d66a760f0885d858736483c32ed7809abd" +dependencies = [ + "bumpalo", + "log", + "once_cell", + "proc-macro2", + "quote", + "syn 2.0.22", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dee495e55982a3bd48105a7b947fd2a9b4a8ae3010041b9e0faab3f9cd028f1d" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.22", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.87" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca6ad05a4870b2bf5fe995117d3728437bd27d7cd5f06f13c17443ef369775a1" + +[[package]] +name = "web-sys" +version = "0.3.64" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b85cbef8c220a6abc02aefd892dfc0fc23afb1c6a426316ec33253a3877249b" +dependencies = [ + "js-sys", + "wasm-bindgen", +] + +[[package]] +name = "webpki" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f095d78192e208183081cc07bc5515ef55216397af48b873e5edcd72637fa1bd" +dependencies = [ + "ring", + "untrusted", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-sys" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.48.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05d4b17490f70499f20b9e791dcf6a299785ce8af4d709018206dc5b4953e95f" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ae572e1b79dba883e0d315474df7305d12f569b400fcf90581b06062f7e1bc" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2ef27e0d7bdfcfc7b868b317c1d32c641a6fe4629c171b8928c7b08d98d7cf3" + +[[package]] +name = "windows_i686_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "622a1962a7db830d6fd0a69683c80a18fda201879f0f447f065a3b7467daa241" + +[[package]] +name = "windows_i686_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4542c6e364ce21bf45d69fdd2a8e455fa38d316158cfd43b3ac1c5b1b19f8e00" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca2b8a661f7628cbd23440e50b05d705db3686f894fc9580820623656af974b1" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7896dbc1f41e08872e9d5e8f8baa8fdd2677f29468c4e156210174edc7f7b953" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a515f5799fe4961cb532f983ce2b23082366b898e52ffbce459c86f67c8378a" diff --git a/weaver/common/protos-rs/pkg/src/generated/driver.driver.rs b/weaver/common/protos-rs/pkg/src/generated/driver.driver.rs index 8fdc5519214..c28d6d2bc59 100644 --- a/weaver/common/protos-rs/pkg/src/generated/driver.driver.rs +++ b/weaver/common/protos-rs/pkg/src/generated/driver.driver.rs @@ -8,6 +8,34 @@ pub struct WriteExternalStateMessage { #[prost(message, optional, tag = "2")] pub ctx: ::core::option::Option, } +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct PerformLockRequest { + #[prost(string, tag = "1")] + pub session_id: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CreateAssetRequest { + #[prost(string, tag = "1")] + pub session_id: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct ExtinguishRequest { + #[prost(string, tag = "1")] + pub session_id: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AssignAssetRequest { + #[prost(string, tag = "1")] + pub session_id: ::prost::alloc::string::String, +} /// Generated client implementations. pub mod driver_communication_client { #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] @@ -227,6 +255,102 @@ pub mod driver_communication_client { ); self.inner.unary(req, path, codec).await } + /// As part of SATP, the source reply (sender gateway) sends a PerformLock request to its driver + /// to lock a specific asset + pub async fn perform_lock( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/driver.driver.DriverCommunication/PerformLock", + ); + self.inner.unary(request.into_request(), path, codec).await + } + /// As part of SATP, the destination reply (receiver gateway) sends a CreateAsset request to its driver + /// to create a specific asset + pub async fn create_asset( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/driver.driver.DriverCommunication/CreateAsset", + ); + self.inner.unary(request.into_request(), path, codec).await + } + /// As part of SATP, the source reply (sender gateway) sends a Extinguish request to its driver + /// to extinguish a specific asset + pub async fn extinguish( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/driver.driver.DriverCommunication/Extinguish", + ); + self.inner.unary(request.into_request(), path, codec).await + } + /// As part of SATP, the destination reply (receiver gateway) sends a AssignAsset request to its driver + /// to assign a specific asset + pub async fn assign_asset( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/driver.driver.DriverCommunication/AssignAsset", + ); + self.inner.unary(request.into_request(), path, codec).await + } } } /// Generated server implementations. @@ -278,6 +402,42 @@ pub mod driver_communication_server { tonic::Response, tonic::Status, >; + /// As part of SATP, the source reply (sender gateway) sends a PerformLock request to its driver + /// to lock a specific asset + async fn perform_lock( + &self, + request: tonic::Request, + ) -> Result< + tonic::Response, + tonic::Status, + >; + /// As part of SATP, the destination reply (receiver gateway) sends a CreateAsset request to its driver + /// to create a specific asset + async fn create_asset( + &self, + request: tonic::Request, + ) -> Result< + tonic::Response, + tonic::Status, + >; + /// As part of SATP, the source reply (sender gateway) sends a Extinguish request to its driver + /// to extinguish a specific asset + async fn extinguish( + &self, + request: tonic::Request, + ) -> Result< + tonic::Response, + tonic::Status, + >; + /// As part of SATP, the destination reply (receiver gateway) sends a AssignAsset request to its driver + /// to assign a specific asset + async fn assign_asset( + &self, + request: tonic::Request, + ) -> Result< + tonic::Response, + tonic::Status, + >; } #[derive(Debug)] pub struct DriverCommunicationServer { @@ -568,6 +728,164 @@ pub mod driver_communication_server { }; Box::pin(fut) } + "/driver.driver.DriverCommunication/PerformLock" => { + #[allow(non_camel_case_types)] + struct PerformLockSvc(pub Arc); + impl< + T: DriverCommunication, + > tonic::server::UnaryService + for PerformLockSvc { + type Response = super::super::super::common::ack::Ack; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).perform_lock(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = PerformLockSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/driver.driver.DriverCommunication/CreateAsset" => { + #[allow(non_camel_case_types)] + struct CreateAssetSvc(pub Arc); + impl< + T: DriverCommunication, + > tonic::server::UnaryService + for CreateAssetSvc { + type Response = super::super::super::common::ack::Ack; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).create_asset(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = CreateAssetSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/driver.driver.DriverCommunication/Extinguish" => { + #[allow(non_camel_case_types)] + struct ExtinguishSvc(pub Arc); + impl< + T: DriverCommunication, + > tonic::server::UnaryService + for ExtinguishSvc { + type Response = super::super::super::common::ack::Ack; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { (*inner).extinguish(request).await }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = ExtinguishSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/driver.driver.DriverCommunication/AssignAsset" => { + #[allow(non_camel_case_types)] + struct AssignAssetSvc(pub Arc); + impl< + T: DriverCommunication, + > tonic::server::UnaryService + for AssignAssetSvc { + type Response = super::super::super::common::ack::Ack; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).assign_asset(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = AssignAssetSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } _ => { Box::pin(async move { Ok( diff --git a/weaver/common/protos-rs/pkg/src/generated/networks.networks.rs b/weaver/common/protos-rs/pkg/src/generated/networks.networks.rs index e79c120c46d..b7a34640f7a 100644 --- a/weaver/common/protos-rs/pkg/src/generated/networks.networks.rs +++ b/weaver/common/protos-rs/pkg/src/generated/networks.networks.rs @@ -70,6 +70,29 @@ pub struct NetworkEventUnsubscription { #[prost(string, tag = "2")] pub request_id: ::prost::alloc::string::String, } +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct NetworkAssetTransfer { + #[prost(string, repeated, tag = "1")] + pub policy: ::prost::alloc::vec::Vec<::prost::alloc::string::String>, + #[prost(string, tag = "2")] + pub address: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub requesting_relay: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub requesting_network: ::prost::alloc::string::String, + #[prost(string, tag = "5")] + pub certificate: ::prost::alloc::string::String, + #[prost(string, tag = "6")] + pub requestor_signature: ::prost::alloc::string::String, + #[prost(string, tag = "7")] + pub nonce: ::prost::alloc::string::String, + #[prost(string, tag = "8")] + pub requesting_org: ::prost::alloc::string::String, + #[prost(bool, tag = "9")] + pub confidential: bool, +} /// Generated client implementations. pub mod network_client { #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] @@ -233,6 +256,30 @@ pub mod network_client { .insert(GrpcMethod::new("networks.networks.Network", "RequestDatabase")); self.inner.unary(req, path, codec).await } + /// SATP endpoints + /// endpoint for a network to request asset transfer to a receiving gateway via local gateway + pub async fn request_asset_transfer( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/networks.networks.Network/RequestAssetTransfer", + ); + self.inner.unary(request.into_request(), path, codec).await + } /// Event endpoints /// endpoint for a client to subscribe to event via local relay initiating subscription flow. pub async fn subscribe_event( @@ -376,7 +423,16 @@ pub mod network_server { async fn request_database( &self, request: tonic::Request, - ) -> std::result::Result, tonic::Status>; + ) -> Result, tonic::Status>; + /// SATP endpoints + /// endpoint for a network to request asset transfer to a receiving gateway via local gateway + async fn request_asset_transfer( + &self, + request: tonic::Request, + ) -> Result< + tonic::Response, + tonic::Status, + >; /// Event endpoints /// endpoint for a client to subscribe to event via local relay initiating subscription flow. async fn subscribe_event( @@ -625,6 +681,46 @@ pub mod network_server { }; Box::pin(fut) } + "/networks.networks.Network/RequestAssetTransfer" => { + #[allow(non_camel_case_types)] + struct RequestAssetTransferSvc(pub Arc); + impl< + T: Network, + > tonic::server::UnaryService + for RequestAssetTransferSvc { + type Response = super::super::super::common::ack::Ack; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).request_asset_transfer(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = RequestAssetTransferSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } "/networks.networks.Network/SubscribeEvent" => { #[allow(non_camel_case_types)] struct SubscribeEventSvc(pub Arc); diff --git a/weaver/common/protos-rs/pkg/src/generated/relay.asset_transfer.rs b/weaver/common/protos-rs/pkg/src/generated/relay.asset_transfer.rs new file mode 100644 index 00000000000..3f9d89fdb0f --- /dev/null +++ b/weaver/common/protos-rs/pkg/src/generated/relay.asset_transfer.rs @@ -0,0 +1,597 @@ +// Copyright IBM Corp. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 + +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AssetTransferInitializationClaims { + #[prost(string, tag = "1")] + pub asset_asset_id: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub asset_profile_id: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub verified_originator_entity_id: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub verified_beneficiary_entity_id: ::prost::alloc::string::String, + #[prost(string, tag = "5")] + pub originator_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "6")] + pub beneficiary_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "7")] + pub sender_gateway_network_id: ::prost::alloc::string::String, + #[prost(string, tag = "8")] + pub recipient_gateway_network_id: ::prost::alloc::string::String, + #[prost(string, tag = "9")] + pub client_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "10")] + pub server_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "11")] + pub sender_gateway_owner_id: ::prost::alloc::string::String, + #[prost(string, tag = "12")] + pub receiver_gateway_owner_id: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransferCommenceRequest { + #[prost(string, tag = "1")] + pub message_type: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub session_id: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub transfer_context_id: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub client_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "5")] + pub server_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "6")] + pub hash_transfer_init_claims: ::prost::alloc::string::String, + #[prost(string, tag = "7")] + pub hash_prev_message: ::prost::alloc::string::String, + #[prost(string, tag = "8")] + pub client_transfer_number: ::prost::alloc::string::String, + /// AssetTransferInitializationClaims asset_transfer_initialization_claims = 10; + #[prost(string, tag = "9")] + pub client_signature: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CommenceResponseRequest { + #[prost(string, tag = "1")] + pub message_type: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub session_id: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub transfer_context_id: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub client_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "5")] + pub server_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "6")] + pub hash_prev_message: ::prost::alloc::string::String, + #[prost(string, tag = "7")] + pub server_transfer_number: ::prost::alloc::string::String, + #[prost(string, tag = "8")] + pub server_signature: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LockAssertionRequest { + #[prost(string, tag = "1")] + pub message_type: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub session_id: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub transfer_context_id: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub client_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "5")] + pub server_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "6")] + pub lock_assertion_claim: ::prost::alloc::string::String, + #[prost(string, tag = "7")] + pub lock_assertion_claim_format: ::prost::alloc::string::String, + #[prost(string, tag = "8")] + pub lock_assertion_expiration: ::prost::alloc::string::String, + #[prost(string, tag = "9")] + pub hash_prev_message: ::prost::alloc::string::String, + #[prost(string, tag = "10")] + pub client_transfer_number: ::prost::alloc::string::String, + #[prost(string, tag = "11")] + pub client_signature: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LockAssertionReceiptRequest { + #[prost(string, tag = "1")] + pub message_type: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub session_id: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub transfer_context_id: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub client_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "5")] + pub server_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "6")] + pub hash_prev_message: ::prost::alloc::string::String, + #[prost(string, tag = "7")] + pub server_transfer_number: ::prost::alloc::string::String, + #[prost(string, tag = "8")] + pub server_signature: ::prost::alloc::string::String, +} +/// Generated client implementations. +pub mod satp_client { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct SatpClient { + inner: tonic::client::Grpc, + } + impl SatpClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: std::convert::TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl SatpClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + Send + 'static, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> SatpClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + Send + Sync, + { + SatpClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// The sender gateway sends a TransferCommence request to signal to the receiver gateway + /// that the it is ready to start the transfer of the digital asset + pub async fn transfer_commence( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/relay.asset_transfer.SATP/TransferCommence", + ); + self.inner.unary(request.into_request(), path, codec).await + } + /// The receiver gateway sends a CommenceResponse request to the sender gateway to indicate agreement + /// to proceed with the asset transfe + pub async fn commence_response( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/relay.asset_transfer.SATP/CommenceResponse", + ); + self.inner.unary(request.into_request(), path, codec).await + } + /// The sender gateway sends a LockAssertion request to convey a signed claim to the receiver gateway + /// declaring that the asset in question has been locked or escrowed by the sender gateway in + /// the origin network (e.g. to prevent double spending + pub async fn lock_assertion( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/relay.asset_transfer.SATP/LockAssertion", + ); + self.inner.unary(request.into_request(), path, codec).await + } + /// The receiver gateway sends a LockAssertionReceipt request to the sender gateway to indicate acceptance + /// of the claim(s) delivered by the sender gateway in the previous message + pub async fn lock_assertion_receipt( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/relay.asset_transfer.SATP/LockAssertionReceipt", + ); + self.inner.unary(request.into_request(), path, codec).await + } + } +} +/// Generated server implementations. +pub mod satp_server { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with SatpServer. + #[async_trait] + pub trait Satp: Send + Sync + 'static { + /// The sender gateway sends a TransferCommence request to signal to the receiver gateway + /// that the it is ready to start the transfer of the digital asset + async fn transfer_commence( + &self, + request: tonic::Request, + ) -> Result< + tonic::Response, + tonic::Status, + >; + /// The receiver gateway sends a CommenceResponse request to the sender gateway to indicate agreement + /// to proceed with the asset transfe + async fn commence_response( + &self, + request: tonic::Request, + ) -> Result< + tonic::Response, + tonic::Status, + >; + /// The sender gateway sends a LockAssertion request to convey a signed claim to the receiver gateway + /// declaring that the asset in question has been locked or escrowed by the sender gateway in + /// the origin network (e.g. to prevent double spending + async fn lock_assertion( + &self, + request: tonic::Request, + ) -> Result< + tonic::Response, + tonic::Status, + >; + /// The receiver gateway sends a LockAssertionReceipt request to the sender gateway to indicate acceptance + /// of the claim(s) delivered by the sender gateway in the previous message + async fn lock_assertion_receipt( + &self, + request: tonic::Request, + ) -> Result< + tonic::Response, + tonic::Status, + >; + } + #[derive(Debug)] + pub struct SatpServer { + inner: _Inner, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + } + struct _Inner(Arc); + impl SatpServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + let inner = _Inner(inner); + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + } + impl tonic::codegen::Service> for SatpServer + where + T: Satp, + B: Body + Send + 'static, + B::Error: Into + Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + let inner = self.inner.clone(); + match req.uri().path() { + "/relay.asset_transfer.SATP/TransferCommence" => { + #[allow(non_camel_case_types)] + struct TransferCommenceSvc(pub Arc); + impl< + T: Satp, + > tonic::server::UnaryService + for TransferCommenceSvc { + type Response = super::super::super::common::ack::Ack; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).transfer_commence(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = TransferCommenceSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/relay.asset_transfer.SATP/CommenceResponse" => { + #[allow(non_camel_case_types)] + struct CommenceResponseSvc(pub Arc); + impl< + T: Satp, + > tonic::server::UnaryService + for CommenceResponseSvc { + type Response = super::super::super::common::ack::Ack; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).commence_response(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = CommenceResponseSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/relay.asset_transfer.SATP/LockAssertion" => { + #[allow(non_camel_case_types)] + struct LockAssertionSvc(pub Arc); + impl< + T: Satp, + > tonic::server::UnaryService + for LockAssertionSvc { + type Response = super::super::super::common::ack::Ack; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).lock_assertion(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = LockAssertionSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/relay.asset_transfer.SATP/LockAssertionReceipt" => { + #[allow(non_camel_case_types)] + struct LockAssertionReceiptSvc(pub Arc); + impl< + T: Satp, + > tonic::server::UnaryService + for LockAssertionReceiptSvc { + type Response = super::super::super::common::ack::Ack; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).lock_assertion_receipt(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = LockAssertionReceiptSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + Ok( + http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap(), + ) + }) + } + } + } + } + impl Clone for SatpServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + } + } + } + impl Clone for _Inner { + fn clone(&self) -> Self { + Self(self.0.clone()) + } + } + impl std::fmt::Debug for _Inner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } + } + impl tonic::server::NamedService for SatpServer { + const NAME: &'static str = "relay.asset_transfer.SATP"; + } +} diff --git a/weaver/common/protos-rs/pkg/src/generated/relay.satp.rs b/weaver/common/protos-rs/pkg/src/generated/relay.satp.rs new file mode 100644 index 00000000000..69b6df5d897 --- /dev/null +++ b/weaver/common/protos-rs/pkg/src/generated/relay.satp.rs @@ -0,0 +1,1265 @@ +// Copyright IBM Corp. All Rights Reserved. +// +// SPDX-License-Identifier: Apache-2.0 + +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransferProposalClaimsRequest { + #[prost(string, tag = "1")] + pub message_type: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub asset_asset_id: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub asset_profile_id: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub verified_originator_entity_id: ::prost::alloc::string::String, + #[prost(string, tag = "5")] + pub verified_beneficiary_entity_id: ::prost::alloc::string::String, + #[prost(string, tag = "6")] + pub originator_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "7")] + pub beneficiary_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "8")] + pub sender_gateway_network_id: ::prost::alloc::string::String, + #[prost(string, tag = "9")] + pub recipient_gateway_network_id: ::prost::alloc::string::String, + #[prost(string, tag = "10")] + pub client_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "11")] + pub server_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "12")] + pub sender_gateway_owner_id: ::prost::alloc::string::String, + #[prost(string, tag = "13")] + pub receiver_gateway_owner_id: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransferProposalReceiptRequest { + #[prost(string, tag = "1")] + pub message_type: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub asset_asset_id: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub asset_profile_id: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub verified_originator_entity_id: ::prost::alloc::string::String, + #[prost(string, tag = "5")] + pub verified_beneficiary_entity_id: ::prost::alloc::string::String, + #[prost(string, tag = "6")] + pub originator_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "7")] + pub beneficiary_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "8")] + pub sender_gateway_network_id: ::prost::alloc::string::String, + #[prost(string, tag = "9")] + pub recipient_gateway_network_id: ::prost::alloc::string::String, + #[prost(string, tag = "10")] + pub client_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "11")] + pub server_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "12")] + pub sender_gateway_owner_id: ::prost::alloc::string::String, + #[prost(string, tag = "13")] + pub receiver_gateway_owner_id: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransferCommenceRequest { + #[prost(string, tag = "1")] + pub message_type: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub session_id: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub transfer_context_id: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub client_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "5")] + pub server_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "6")] + pub hash_transfer_init_claims: ::prost::alloc::string::String, + #[prost(string, tag = "7")] + pub hash_prev_message: ::prost::alloc::string::String, + #[prost(string, tag = "8")] + pub client_transfer_number: ::prost::alloc::string::String, + #[prost(string, tag = "9")] + pub client_signature: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AckCommenceRequest { + #[prost(string, tag = "1")] + pub message_type: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub session_id: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub transfer_context_id: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub client_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "5")] + pub server_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "6")] + pub hash_prev_message: ::prost::alloc::string::String, + #[prost(string, tag = "7")] + pub server_transfer_number: ::prost::alloc::string::String, + #[prost(string, tag = "8")] + pub server_signature: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct SendAssetStatusRequest { + #[prost(string, tag = "1")] + pub message_type: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub session_id: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub transfer_context_id: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub client_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "5")] + pub server_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "6")] + pub hash_prev_message: ::prost::alloc::string::String, + #[prost(string, tag = "7")] + pub server_transfer_number: ::prost::alloc::string::String, + #[prost(string, tag = "8")] + pub server_signature: ::prost::alloc::string::String, + #[prost(string, tag = "9")] + pub status: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LockAssertionRequest { + #[prost(string, tag = "1")] + pub message_type: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub session_id: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub transfer_context_id: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub client_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "5")] + pub server_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "6")] + pub lock_assertion_claim: ::prost::alloc::string::String, + #[prost(string, tag = "7")] + pub lock_assertion_claim_format: ::prost::alloc::string::String, + #[prost(string, tag = "8")] + pub lock_assertion_expiration: ::prost::alloc::string::String, + #[prost(string, tag = "9")] + pub hash_prev_message: ::prost::alloc::string::String, + #[prost(string, tag = "10")] + pub client_transfer_number: ::prost::alloc::string::String, + #[prost(string, tag = "11")] + pub client_signature: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct LockAssertionReceiptRequest { + #[prost(string, tag = "1")] + pub message_type: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub session_id: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub transfer_context_id: ::prost::alloc::string::String, + #[prost(string, tag = "4")] + pub client_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "5")] + pub server_identity_pubkey: ::prost::alloc::string::String, + #[prost(string, tag = "6")] + pub hash_prev_message: ::prost::alloc::string::String, + #[prost(string, tag = "7")] + pub server_transfer_number: ::prost::alloc::string::String, + #[prost(string, tag = "8")] + pub server_signature: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CommitPrepareRequest { + #[prost(string, tag = "1")] + pub message_type: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub session_id: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub transfer_context_id: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CommitReadyRequest { + #[prost(string, tag = "1")] + pub message_type: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub session_id: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub transfer_context_id: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct CommitFinalAssertionRequest { + #[prost(string, tag = "1")] + pub message_type: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub session_id: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub transfer_context_id: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct AckFinalReceiptRequest { + #[prost(string, tag = "1")] + pub message_type: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub session_id: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub transfer_context_id: ::prost::alloc::string::String, +} +#[derive(serde::Serialize, serde::Deserialize)] +#[allow(clippy::derive_partial_eq_without_eq)] +#[derive(Clone, PartialEq, ::prost::Message)] +pub struct TransferCompletedRequest { + #[prost(string, tag = "1")] + pub message_type: ::prost::alloc::string::String, + #[prost(string, tag = "2")] + pub session_id: ::prost::alloc::string::String, + #[prost(string, tag = "3")] + pub transfer_context_id: ::prost::alloc::string::String, +} +/// Generated client implementations. +pub mod satp_client { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + use tonic::codegen::http::Uri; + #[derive(Debug, Clone)] + pub struct SatpClient { + inner: tonic::client::Grpc, + } + impl SatpClient { + /// Attempt to create a new client by connecting to a given endpoint. + pub async fn connect(dst: D) -> Result + where + D: std::convert::TryInto, + D::Error: Into, + { + let conn = tonic::transport::Endpoint::new(dst)?.connect().await?; + Ok(Self::new(conn)) + } + } + impl SatpClient + where + T: tonic::client::GrpcService, + T::Error: Into, + T::ResponseBody: Body + Send + 'static, + ::Error: Into + Send, + { + pub fn new(inner: T) -> Self { + let inner = tonic::client::Grpc::new(inner); + Self { inner } + } + pub fn with_origin(inner: T, origin: Uri) -> Self { + let inner = tonic::client::Grpc::with_origin(inner, origin); + Self { inner } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> SatpClient> + where + F: tonic::service::Interceptor, + T::ResponseBody: Default, + T: tonic::codegen::Service< + http::Request, + Response = http::Response< + >::ResponseBody, + >, + >, + , + >>::Error: Into + Send + Sync, + { + SatpClient::new(InterceptedService::new(inner, interceptor)) + } + /// Compress requests with the given encoding. + /// + /// This requires the server to support it otherwise it might respond with an + /// error. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.send_compressed(encoding); + self + } + /// Enable decompressing responses. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.inner = self.inner.accept_compressed(encoding); + self + } + /// The sender gateway sends a TransferProposalClaims request to initiate an asset transfer. + /// Depending on the proposal, multiple rounds of communication between the two gateways may happen. + pub async fn transfer_proposal_claims( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/relay.satp.SATP/TransferProposalClaims", + ); + self.inner.unary(request.into_request(), path, codec).await + } + /// The sender gateway sends a TransferProposalClaims request to signal to the receiver gateway + /// that the it is ready to start the transfer of the digital asset + pub async fn transfer_proposal_receipt( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/relay.satp.SATP/TransferProposalReceipt", + ); + self.inner.unary(request.into_request(), path, codec).await + } + /// The sender gateway sends a TransferCommence request to signal to the receiver gateway + /// that the it is ready to start the transfer of the digital asset + pub async fn transfer_commence( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/relay.satp.SATP/TransferCommence", + ); + self.inner.unary(request.into_request(), path, codec).await + } + /// The receiver gateway sends a AckCommence request to the sender gateway to indicate agreement + /// to proceed with the asset transfe + pub async fn ack_commence( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/relay.satp.SATP/AckCommence", + ); + self.inner.unary(request.into_request(), path, codec).await + } + pub async fn send_asset_status( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/relay.satp.SATP/SendAssetStatus", + ); + self.inner.unary(request.into_request(), path, codec).await + } + /// The sender gateway sends a LockAssertion request to convey a signed claim to the receiver gateway + /// declaring that the asset in question has been locked or escrowed by the sender gateway in + /// the origin network (e.g. to prevent double spending) + pub async fn lock_assertion( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/relay.satp.SATP/LockAssertion", + ); + self.inner.unary(request.into_request(), path, codec).await + } + /// The receiver gateway sends a LockAssertionReceipt request to the sender gateway to indicate acceptance + /// of the claim(s) delivered by the sender gateway in the previous message + pub async fn lock_assertion_receipt( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/relay.satp.SATP/LockAssertionReceipt", + ); + self.inner.unary(request.into_request(), path, codec).await + } + pub async fn commit_prepare( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/relay.satp.SATP/CommitPrepare", + ); + self.inner.unary(request.into_request(), path, codec).await + } + pub async fn commit_ready( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/relay.satp.SATP/CommitReady", + ); + self.inner.unary(request.into_request(), path, codec).await + } + pub async fn commit_final_assertion( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/relay.satp.SATP/CommitFinalAssertion", + ); + self.inner.unary(request.into_request(), path, codec).await + } + pub async fn ack_final_receipt( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/relay.satp.SATP/AckFinalReceipt", + ); + self.inner.unary(request.into_request(), path, codec).await + } + pub async fn transfer_completed( + &mut self, + request: impl tonic::IntoRequest, + ) -> Result< + tonic::Response, + tonic::Status, + > { + self.inner + .ready() + .await + .map_err(|e| { + tonic::Status::new( + tonic::Code::Unknown, + format!("Service was not ready: {}", e.into()), + ) + })?; + let codec = tonic::codec::ProstCodec::default(); + let path = http::uri::PathAndQuery::from_static( + "/relay.satp.SATP/TransferCompleted", + ); + self.inner.unary(request.into_request(), path, codec).await + } + } +} +/// Generated server implementations. +pub mod satp_server { + #![allow(unused_variables, dead_code, missing_docs, clippy::let_unit_value)] + use tonic::codegen::*; + /// Generated trait containing gRPC methods that should be implemented for use with SatpServer. + #[async_trait] + pub trait Satp: Send + Sync + 'static { + /// The sender gateway sends a TransferProposalClaims request to initiate an asset transfer. + /// Depending on the proposal, multiple rounds of communication between the two gateways may happen. + async fn transfer_proposal_claims( + &self, + request: tonic::Request, + ) -> Result< + tonic::Response, + tonic::Status, + >; + /// The sender gateway sends a TransferProposalClaims request to signal to the receiver gateway + /// that the it is ready to start the transfer of the digital asset + async fn transfer_proposal_receipt( + &self, + request: tonic::Request, + ) -> Result< + tonic::Response, + tonic::Status, + >; + /// The sender gateway sends a TransferCommence request to signal to the receiver gateway + /// that the it is ready to start the transfer of the digital asset + async fn transfer_commence( + &self, + request: tonic::Request, + ) -> Result< + tonic::Response, + tonic::Status, + >; + /// The receiver gateway sends a AckCommence request to the sender gateway to indicate agreement + /// to proceed with the asset transfe + async fn ack_commence( + &self, + request: tonic::Request, + ) -> Result< + tonic::Response, + tonic::Status, + >; + async fn send_asset_status( + &self, + request: tonic::Request, + ) -> Result< + tonic::Response, + tonic::Status, + >; + /// The sender gateway sends a LockAssertion request to convey a signed claim to the receiver gateway + /// declaring that the asset in question has been locked or escrowed by the sender gateway in + /// the origin network (e.g. to prevent double spending) + async fn lock_assertion( + &self, + request: tonic::Request, + ) -> Result< + tonic::Response, + tonic::Status, + >; + /// The receiver gateway sends a LockAssertionReceipt request to the sender gateway to indicate acceptance + /// of the claim(s) delivered by the sender gateway in the previous message + async fn lock_assertion_receipt( + &self, + request: tonic::Request, + ) -> Result< + tonic::Response, + tonic::Status, + >; + async fn commit_prepare( + &self, + request: tonic::Request, + ) -> Result< + tonic::Response, + tonic::Status, + >; + async fn commit_ready( + &self, + request: tonic::Request, + ) -> Result< + tonic::Response, + tonic::Status, + >; + async fn commit_final_assertion( + &self, + request: tonic::Request, + ) -> Result< + tonic::Response, + tonic::Status, + >; + async fn ack_final_receipt( + &self, + request: tonic::Request, + ) -> Result< + tonic::Response, + tonic::Status, + >; + async fn transfer_completed( + &self, + request: tonic::Request, + ) -> Result< + tonic::Response, + tonic::Status, + >; + } + #[derive(Debug)] + pub struct SatpServer { + inner: _Inner, + accept_compression_encodings: EnabledCompressionEncodings, + send_compression_encodings: EnabledCompressionEncodings, + } + struct _Inner(Arc); + impl SatpServer { + pub fn new(inner: T) -> Self { + Self::from_arc(Arc::new(inner)) + } + pub fn from_arc(inner: Arc) -> Self { + let inner = _Inner(inner); + Self { + inner, + accept_compression_encodings: Default::default(), + send_compression_encodings: Default::default(), + } + } + pub fn with_interceptor( + inner: T, + interceptor: F, + ) -> InterceptedService + where + F: tonic::service::Interceptor, + { + InterceptedService::new(Self::new(inner), interceptor) + } + /// Enable decompressing requests with the given encoding. + #[must_use] + pub fn accept_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.accept_compression_encodings.enable(encoding); + self + } + /// Compress responses with the given encoding, if the client supports it. + #[must_use] + pub fn send_compressed(mut self, encoding: CompressionEncoding) -> Self { + self.send_compression_encodings.enable(encoding); + self + } + } + impl tonic::codegen::Service> for SatpServer + where + T: Satp, + B: Body + Send + 'static, + B::Error: Into + Send + 'static, + { + type Response = http::Response; + type Error = std::convert::Infallible; + type Future = BoxFuture; + fn poll_ready( + &mut self, + _cx: &mut Context<'_>, + ) -> Poll> { + Poll::Ready(Ok(())) + } + fn call(&mut self, req: http::Request) -> Self::Future { + let inner = self.inner.clone(); + match req.uri().path() { + "/relay.satp.SATP/TransferProposalClaims" => { + #[allow(non_camel_case_types)] + struct TransferProposalClaimsSvc(pub Arc); + impl< + T: Satp, + > tonic::server::UnaryService + for TransferProposalClaimsSvc { + type Response = super::super::super::common::ack::Ack; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).transfer_proposal_claims(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = TransferProposalClaimsSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/relay.satp.SATP/TransferProposalReceipt" => { + #[allow(non_camel_case_types)] + struct TransferProposalReceiptSvc(pub Arc); + impl< + T: Satp, + > tonic::server::UnaryService + for TransferProposalReceiptSvc { + type Response = super::super::super::common::ack::Ack; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request< + super::TransferProposalReceiptRequest, + >, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).transfer_proposal_receipt(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = TransferProposalReceiptSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/relay.satp.SATP/TransferCommence" => { + #[allow(non_camel_case_types)] + struct TransferCommenceSvc(pub Arc); + impl< + T: Satp, + > tonic::server::UnaryService + for TransferCommenceSvc { + type Response = super::super::super::common::ack::Ack; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).transfer_commence(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = TransferCommenceSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/relay.satp.SATP/AckCommence" => { + #[allow(non_camel_case_types)] + struct AckCommenceSvc(pub Arc); + impl tonic::server::UnaryService + for AckCommenceSvc { + type Response = super::super::super::common::ack::Ack; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).ack_commence(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = AckCommenceSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/relay.satp.SATP/SendAssetStatus" => { + #[allow(non_camel_case_types)] + struct SendAssetStatusSvc(pub Arc); + impl< + T: Satp, + > tonic::server::UnaryService + for SendAssetStatusSvc { + type Response = super::super::super::common::ack::Ack; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).send_asset_status(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = SendAssetStatusSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/relay.satp.SATP/LockAssertion" => { + #[allow(non_camel_case_types)] + struct LockAssertionSvc(pub Arc); + impl< + T: Satp, + > tonic::server::UnaryService + for LockAssertionSvc { + type Response = super::super::super::common::ack::Ack; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).lock_assertion(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = LockAssertionSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/relay.satp.SATP/LockAssertionReceipt" => { + #[allow(non_camel_case_types)] + struct LockAssertionReceiptSvc(pub Arc); + impl< + T: Satp, + > tonic::server::UnaryService + for LockAssertionReceiptSvc { + type Response = super::super::super::common::ack::Ack; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).lock_assertion_receipt(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = LockAssertionReceiptSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/relay.satp.SATP/CommitPrepare" => { + #[allow(non_camel_case_types)] + struct CommitPrepareSvc(pub Arc); + impl< + T: Satp, + > tonic::server::UnaryService + for CommitPrepareSvc { + type Response = super::super::super::common::ack::Ack; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).commit_prepare(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = CommitPrepareSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/relay.satp.SATP/CommitReady" => { + #[allow(non_camel_case_types)] + struct CommitReadySvc(pub Arc); + impl tonic::server::UnaryService + for CommitReadySvc { + type Response = super::super::super::common::ack::Ack; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).commit_ready(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = CommitReadySvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/relay.satp.SATP/CommitFinalAssertion" => { + #[allow(non_camel_case_types)] + struct CommitFinalAssertionSvc(pub Arc); + impl< + T: Satp, + > tonic::server::UnaryService + for CommitFinalAssertionSvc { + type Response = super::super::super::common::ack::Ack; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).commit_final_assertion(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = CommitFinalAssertionSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/relay.satp.SATP/AckFinalReceipt" => { + #[allow(non_camel_case_types)] + struct AckFinalReceiptSvc(pub Arc); + impl< + T: Satp, + > tonic::server::UnaryService + for AckFinalReceiptSvc { + type Response = super::super::super::common::ack::Ack; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).ack_final_receipt(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = AckFinalReceiptSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + "/relay.satp.SATP/TransferCompleted" => { + #[allow(non_camel_case_types)] + struct TransferCompletedSvc(pub Arc); + impl< + T: Satp, + > tonic::server::UnaryService + for TransferCompletedSvc { + type Response = super::super::super::common::ack::Ack; + type Future = BoxFuture< + tonic::Response, + tonic::Status, + >; + fn call( + &mut self, + request: tonic::Request, + ) -> Self::Future { + let inner = self.0.clone(); + let fut = async move { + (*inner).transfer_completed(request).await + }; + Box::pin(fut) + } + } + let accept_compression_encodings = self.accept_compression_encodings; + let send_compression_encodings = self.send_compression_encodings; + let inner = self.inner.clone(); + let fut = async move { + let inner = inner.0; + let method = TransferCompletedSvc(inner); + let codec = tonic::codec::ProstCodec::default(); + let mut grpc = tonic::server::Grpc::new(codec) + .apply_compression_config( + accept_compression_encodings, + send_compression_encodings, + ); + let res = grpc.unary(method, req).await; + Ok(res) + }; + Box::pin(fut) + } + _ => { + Box::pin(async move { + Ok( + http::Response::builder() + .status(200) + .header("grpc-status", "12") + .header("content-type", "application/grpc") + .body(empty_body()) + .unwrap(), + ) + }) + } + } + } + } + impl Clone for SatpServer { + fn clone(&self) -> Self { + let inner = self.inner.clone(); + Self { + inner, + accept_compression_encodings: self.accept_compression_encodings, + send_compression_encodings: self.send_compression_encodings, + } + } + } + impl Clone for _Inner { + fn clone(&self) -> Self { + Self(self.0.clone()) + } + } + impl std::fmt::Debug for _Inner { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{:?}", self.0) + } + } + impl tonic::server::NamedService for SatpServer { + const NAME: &'static str = "relay.satp.SATP"; + } +} diff --git a/weaver/common/protos-rs/pkg/src/lib.rs b/weaver/common/protos-rs/pkg/src/lib.rs index 69753025485..74e3785a899 100644 --- a/weaver/common/protos-rs/pkg/src/lib.rs +++ b/weaver/common/protos-rs/pkg/src/lib.rs @@ -6,6 +6,9 @@ pub mod relay { pub mod datatransfer { include!(concat!("./generated", "/relay.datatransfer.rs")); } + pub mod satp { + include!(concat!("./generated", "/relay.satp.rs")); + } pub mod events { include!(concat!("./generated", "/relay.events.rs")); } diff --git a/weaver/common/protos/driver/driver.proto b/weaver/common/protos/driver/driver.proto index fd12529aff0..b0681f8e4f5 100644 --- a/weaver/common/protos/driver/driver.proto +++ b/weaver/common/protos/driver/driver.proto @@ -20,6 +20,22 @@ message WriteExternalStateMessage { common.events.ContractTransaction ctx = 2; } +message PerformLockRequest { + string session_id = 1; +} + +message CreateAssetRequest { + string session_id = 1; +} + +message ExtinguishRequest { + string session_id = 1; +} + +message AssignAssetRequest { + string session_id = 1; +} + service DriverCommunication { // Data Sharing // the remote relay sends a RequestDriverState request to its driver with a @@ -38,4 +54,20 @@ service DriverCommunication { // Events Publication // the dest-relay calls the dest-driver on this end point to write the remote network state to the local ledger rpc WriteExternalState(WriteExternalStateMessage) returns (common.ack.Ack) {} + + // As part of SATP, the source reply (sender gateway) sends a PerformLock request to its driver + // to lock a specific asset + rpc PerformLock(PerformLockRequest) returns (common.ack.Ack) {} + + // As part of SATP, the destination reply (receiver gateway) sends a CreateAsset request to its driver + // to create a specific asset + rpc CreateAsset(CreateAssetRequest) returns (common.ack.Ack) {} + + // As part of SATP, the source reply (sender gateway) sends a Extinguish request to its driver + // to extinguish a specific asset + rpc Extinguish(ExtinguishRequest) returns (common.ack.Ack) {} + + // As part of SATP, the destination reply (receiver gateway) sends a AssignAsset request to its driver + // to assign a specific asset + rpc AssignAsset(AssignAssetRequest) returns (common.ack.Ack) {} } \ No newline at end of file diff --git a/weaver/common/protos/networks/networks.proto b/weaver/common/protos/networks/networks.proto index 24e8e1944fa..2784f14e1f9 100644 --- a/weaver/common/protos/networks/networks.proto +++ b/weaver/common/protos/networks/networks.proto @@ -24,6 +24,10 @@ service Network { // NOTE: This rpc is just for debugging. rpc RequestDatabase(DbName) returns (RelayDatabase) {} + // SATP endpoints + // endpoint for a network to request asset transfer to a receiving gateway via local gateway + rpc RequestAssetTransfer(NetworkAssetTransfer) returns (common.ack.Ack) {} + // Event endpoints // endpoint for a client to subscribe to event via local relay initiating subscription flow. rpc SubscribeEvent(NetworkEventSubscription) returns (common.ack.Ack) {} @@ -71,3 +75,15 @@ message NetworkEventUnsubscription { NetworkEventSubscription request = 1; string request_id = 2; } + +message NetworkAssetTransfer { + repeated string policy = 1; + string address = 2; + string requesting_relay = 3; + string requesting_network = 4; + string certificate = 5; + string requestor_signature = 6; + string nonce = 7; + string requesting_org = 8; + bool confidential = 9; +} \ No newline at end of file diff --git a/weaver/common/protos/relay/satp.proto b/weaver/common/protos/relay/satp.proto new file mode 100644 index 00000000000..3d207598796 --- /dev/null +++ b/weaver/common/protos/relay/satp.proto @@ -0,0 +1,175 @@ +syntax = "proto3"; + +package relay.satp; + +import "common/ack.proto"; +import "common/state.proto"; +import "common/query.proto"; + +option java_package = "org.hyperledger.cacti.weaver.protos.relay.datatransfer"; +option go_package = "github.com/hyperledger/cacti/weaver/common/protos-go/v2/relay"; + +service SATP { + // Stage 1 endpoints + + // The sender gateway sends a TransferProposalClaims request to initiate an asset transfer. + // Depending on the proposal, multiple rounds of communication between the two gateways may happen. + rpc TransferProposalClaims(TransferProposalClaimsRequest) returns (common.ack.Ack) {}; + + // The sender gateway sends a TransferProposalClaims request to signal to the receiver gateway + // that the it is ready to start the transfer of the digital asset + rpc TransferProposalReceipt(TransferProposalReceiptRequest) returns (common.ack.Ack) {}; + + // The sender gateway sends a TransferCommence request to signal to the receiver gateway + // that the it is ready to start the transfer of the digital asset + rpc TransferCommence(TransferCommenceRequest) returns (common.ack.Ack) {}; + + // The receiver gateway sends a AckCommence request to the sender gateway to indicate agreement + // to proceed with the asset transfe + rpc AckCommence(AckCommenceRequest) returns (common.ack.Ack) {}; + + // Stage 2 endpoints + + rpc SendAssetStatus(SendAssetStatusRequest) returns (common.ack.Ack) {}; + + // The sender gateway sends a LockAssertion request to convey a signed claim to the receiver gateway + // declaring that the asset in question has been locked or escrowed by the sender gateway in + // the origin network (e.g. to prevent double spending) + rpc LockAssertion(LockAssertionRequest) returns (common.ack.Ack) {}; + + // The receiver gateway sends a LockAssertionReceipt request to the sender gateway to indicate acceptance + // of the claim(s) delivered by the sender gateway in the previous message + rpc LockAssertionReceipt(LockAssertionReceiptRequest) returns (common.ack.Ack) {}; + + rpc CommitPrepare(CommitPrepareRequest) returns (common.ack.Ack) {}; + + rpc CommitReady(CommitReadyRequest) returns (common.ack.Ack) {}; + + rpc CommitFinalAssertion(CommitFinalAssertionRequest) returns (common.ack.Ack) {}; + + rpc AckFinalReceipt(AckFinalReceiptRequest) returns (common.ack.Ack) {}; + + rpc TransferCompleted(TransferCompletedRequest) returns (common.ack.Ack) {}; +} + +message TransferProposalClaimsRequest { + string message_type = 1; + string asset_asset_id = 2; + string asset_profile_id = 3; + string verified_originator_entity_id = 4; + string verified_beneficiary_entity_id = 5; + string originator_pubkey = 6; + string beneficiary_pubkey = 7; + string sender_gateway_network_id = 8; + string recipient_gateway_network_id = 9; + string client_identity_pubkey = 10; + string server_identity_pubkey = 11; + string sender_gateway_owner_id = 12; + string receiver_gateway_owner_id = 13; +} + +message TransferProposalReceiptRequest { + string message_type = 1; + string asset_asset_id = 2; + string asset_profile_id = 3; + string verified_originator_entity_id = 4; + string verified_beneficiary_entity_id = 5; + string originator_pubkey = 6; + string beneficiary_pubkey = 7; + string sender_gateway_network_id = 8; + string recipient_gateway_network_id = 9; + string client_identity_pubkey = 10; + string server_identity_pubkey = 11; + string sender_gateway_owner_id = 12; + string receiver_gateway_owner_id = 13; +} + +message TransferCommenceRequest { + string message_type = 1; + string session_id = 2; + string transfer_context_id = 3; + string client_identity_pubkey = 4; + string server_identity_pubkey = 5; + string hash_transfer_init_claims = 6; + string hash_prev_message = 7; + string client_transfer_number = 8; + string client_signature = 9; +} + +message AckCommenceRequest { + string message_type = 1; + string session_id = 2; + string transfer_context_id = 3; + string client_identity_pubkey = 4; + string server_identity_pubkey = 5; + string hash_prev_message = 6; + string server_transfer_number = 7; + string server_signature = 8; +} + +message SendAssetStatusRequest { + string message_type = 1; + string session_id = 2; + string transfer_context_id = 3; + string client_identity_pubkey = 4; + string server_identity_pubkey = 5; + string hash_prev_message = 6; + string server_transfer_number = 7; + string server_signature = 8; + string status = 9; +} + +message LockAssertionRequest { + string message_type = 1; + string session_id = 2; + string transfer_context_id = 3; + string client_identity_pubkey = 4; + string server_identity_pubkey = 5; + string lock_assertion_claim = 6; + string lock_assertion_claim_format = 7; + string lock_assertion_expiration = 8; + string hash_prev_message = 9; + string client_transfer_number = 10; + string client_signature = 11; +} + +message LockAssertionReceiptRequest { + string message_type = 1; + string session_id = 2; + string transfer_context_id = 3; + string client_identity_pubkey = 4; + string server_identity_pubkey = 5; + string hash_prev_message = 6; + string server_transfer_number = 7; + string server_signature = 8; +} + +message CommitPrepareRequest { + string message_type = 1; + string session_id = 2; + string transfer_context_id = 3; +} + +message CommitReadyRequest { + string message_type = 1; + string session_id = 2; + string transfer_context_id = 3; +} + +message CommitFinalAssertionRequest { + string message_type = 1; + string session_id = 2; + string transfer_context_id = 3; +} + +message AckFinalReceiptRequest { + string message_type = 1; + string session_id = 2; + string transfer_context_id = 3; +} + +message TransferCompletedRequest { + string message_type = 1; + string session_id = 2; + string transfer_context_id = 3; +} \ No newline at end of file diff --git a/weaver/core/drivers/fabric-driver/.env.satp.template b/weaver/core/drivers/fabric-driver/.env.satp.template new file mode 100644 index 00000000000..1be61e73414 --- /dev/null +++ b/weaver/core/drivers/fabric-driver/.env.satp.template @@ -0,0 +1,25 @@ +CONNECTION_PROFILE=/tests/network-setups/fabric/shared/network1/peerOrganizations/org1.network1.com/connection-org1.json +RELAY_ENDPOINT=localhost:9085 +RELAY_TLS=false +RELAY_TLSCA_CERT_PATH=path_to_tls_ca_cert_pem_for_relay +DRIVER_ENDPOINT=localhost:9090 +DRIVER_TLS=false +DRIVER_TLS_CERT_PATH=path_to_tls_cert_pem_for_driver +DRIVER_TLS_KEY_PATH=path_to_tls_key_pem_for_driver +NETWORK_NAME=network1 +DRIVER_CONFIG= +INTEROP_CHAINCODE=interop +MOCK=false +DB_PATH=driverdbs +#WALLET_PATH=/samples/fabric/fabric-cli/src/wallet-network1 +WALLET_PATH=/core/drivers/fabric-driver/wallet-network1 +DEBUG=true +LEVELDB_LOCKED_MAX_RETRIES= +LEVELDB_LOCKED_RETRY_BACKOFF_MSEC= +ENABLE_MONITOR=false +MONITOR_SYNC_PERIOD= +MEMBER_CREDENTIAL_FOLDER=/samples/fabric/fabric-cli/src/data/credentials +CONFIG_PATH=/samples/fabric/fabric-cli/config.json +DEFAULT_APPLICATION_CHAINCODE=simpleassettransfer +REMOTE_CONFIG_PATH=/samples/fabric/fabric-cli/remote-network-config.json +CHAINCODE_PATH=/samples/fabric/fabric-cli/chaincode.json diff --git a/weaver/core/drivers/fabric-driver/server/satp.ts b/weaver/core/drivers/fabric-driver/server/satp.ts new file mode 100644 index 00000000000..665039acfd7 --- /dev/null +++ b/weaver/core/drivers/fabric-driver/server/satp.ts @@ -0,0 +1,348 @@ +import satp_pb from '@hyperledger/cacti-weaver-protos-js/relay/satp_pb'; +import satp_grpc_pb from '@hyperledger/cacti-weaver-protos-js/relay/satp_grpc_pb'; +import driverPb from '@hyperledger/cacti-weaver-protos-js/driver/driver_pb'; +import logger from './logger'; +import { credentials } from '@grpc/grpc-js'; +import { SatpAssetManager, HashFunctions } from '@hyperledger/cacti-weaver-sdk-fabric' +import fs from 'fs'; +import { Gateway, Network } from 'fabric-network' +import { getNetworkGateway } from "./fabric-code"; +import { getDriverKeyCert } from './walletSetup'; + +async function performLockHelper( + performLockRequest: driverPb.PerformLockRequest, + networkName: string +): Promise { + + // TODO: remove the hardcoded values + let performLockRequest2 = {}; + performLockRequest2['target-network'] = 'network1'; + performLockRequest2['hashBase64'] = 'ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs='; + performLockRequest2['timeout-duration'] = parseInt('3600'); + performLockRequest2['locker'] = 'alice'; + performLockRequest2['recipient'] = 'bob'; + performLockRequest2['lockerWalletPath'] = '../wallet-network1/alice.id'; + performLockRequest2['recipientWalletPath'] = '../wallet-network1/bob.id'; + performLockRequest2['param'] = 'bond01:a05'; + performLockRequest2['channel'] = 'mychannel'; + performLockRequest2['chaincode-id'] = 'satpsimpleasset'; + + // Locker and recipient + const locker = performLockRequest2['locker']; + const recipient = performLockRequest2['recipient']; + const recipientWalletPath = performLockRequest2['recipientWalletPath']; + let hashFn = performLockRequest2['hash_fn']; + let hashBase64 = performLockRequest2['hashBase64']; + const targetNetwork = performLockRequest2['target-network']; + const channel = performLockRequest2['channel']; + const chaincodeId = performLockRequest2['chaincode-id']; + + // Hash + let hash: HashFunctions.Hash + if (hashFn == 'SHA512') { + hash = new HashFunctions.SHA512() + } else { + hash = new HashFunctions.SHA256() + } + + if (hashBase64) { + hash.setSerializedHashBase64(hashBase64) + } + else { + logger.info(`No hash provided, using random preimage`) + } + + // Timeout + let timeout = 0; + let timeout2 = 0; + + const currTime = Math.floor(Date.now() / 1000); + if (performLockRequest2['timeout-epoch']) { + let duration = performLockRequest2['timeout-epoch'] - currTime + timeout = performLockRequest2['timeout-epoch'] + timeout2 = performLockRequest2['timeout-epoch'] + duration + } + else if (performLockRequest2['timeout-duration']) { + timeout = currTime + performLockRequest2['timeout-duration'] + timeout2 = currTime + 2 * performLockRequest2['timeout-duration'] + } + + let gateway: Gateway = await getNetworkGateway(networkName); + const network: Network = await gateway.getNetwork(channel); + const contract = network.getContract(chaincodeId); + + const params = performLockRequest2['param'].split(':') + const recipientCert = Buffer.from(recipientWalletPath).toString('base64') + + let funcToCall, asset + + if (performLockRequest2['fungible']) { + funcToCall = SatpAssetManager.createFungibleHTLC + asset = 'Fungible Asset' + } else { + funcToCall = SatpAssetManager.createHTLC + asset = 'Asset' + } + + console.info(`Asset Lock: Lock ${asset}:\n`); + try { + console.info(`Trying ${asset} Lock: ${params[0]}, ${params[1]} by ${locker} for ${recipient}`) + const res = await funcToCall(contract, + params[0], + params[1], + recipientCert, + hash, + timeout, + null) + if (!res.result) { + throw new Error() + } + console.info(`${asset} Locked with Contract Id: ${res.result}, preimage: ${res.hash.getPreimage()}, hashvalue: ${res.hash.getSerializedHashBase64()}`) + console.info('Asset has been locked successfully') + + } catch (error) { + console.error(`Could not Lock ${asset} in ${targetNetwork}`) + } + + await gateway.disconnect() + logger.info('Gateways disconnected.') + + const client = getRelayClientForAssetStatusResponse(); + const request = new satp_pb.SendAssetStatusRequest(); + request.setSessionId(performLockRequest.getSessionId()); + request.setStatus("Locked"); + client.sendAssetStatus(request, relayCallback); +} + +async function createAssetHelper( + createAssetRequest: driverPb.CreateAssetRequest, + networkName: string +): Promise { + + // TODO: remove the hardcoded values + let createAssetRequest2 = {}; + createAssetRequest2['target-network'] = 'network1'; + createAssetRequest2['hashBase64'] = 'ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs='; + createAssetRequest2['timeout-duration'] = parseInt('3600'); + createAssetRequest2['owner'] = 'admin'; + createAssetRequest2['type'] = 'bond'; + createAssetRequest2['assetType'] = 'bond01'; + createAssetRequest2['id'] = 'a0demo'; + createAssetRequest2['issuer'] = 'admin'; + createAssetRequest2['facevalue'] = '300'; + createAssetRequest2['maturitydate'] = '05 May 48 00:00 MST'; + createAssetRequest2['channel'] = 'mychannel'; + createAssetRequest2['chaincode-id'] = 'satpsimpleasset'; + + const owner = createAssetRequest2['owner']; + const ccType = createAssetRequest2['type']; + const assetType = createAssetRequest2['assetType']; + const id = createAssetRequest2['id']; + const issuer = createAssetRequest2['issuer']; + const facevalue = createAssetRequest2['facevalue']; + const maturitydate = createAssetRequest2['maturitydate']; + const tokenassettype = createAssetRequest2['tokenassettype']; + const numunits = createAssetRequest2['numunits']; + const channel = createAssetRequest2['channel']; + const chaincodeId = createAssetRequest2['chaincode-id']; + + let gateway: Gateway = await getNetworkGateway(networkName); + const network: Network = await gateway.getNetwork(channel); + const contract = network.getContract(chaincodeId); + const currentQuery = { + channel: channel, + contractName: chaincodeId, + ccFunc: '', + args: [] + } + + const driverkeyCert = await getDriverKeyCert(); + const certificate = Buffer.from(driverkeyCert.cert).toString('base64') + + if (ccType == 'bond') { + currentQuery.ccFunc = 'CreateAsset' + currentQuery.args = [...currentQuery.args, assetType, id, certificate, issuer, facevalue, maturitydate] + } else if (ccType == 'token') { + currentQuery.ccFunc = 'IssueTokenAssets' + currentQuery.args = [...currentQuery.args, tokenassettype, numunits, certificate] + } else { + throw new Error(`Unrecognized asset category: ${ccType}`) + } + console.log(currentQuery) + + try { + console.info(`Trying creating the asset: type: ${ccType}, id: ${id}, by: ${owner}, facevalue: ${facevalue}, maturitydate: ${maturitydate}`) + const read = await contract.submitTransaction(currentQuery.ccFunc, ...currentQuery.args) + const state = Buffer.from(read).toString() + if (state) { + logger.debug(`Response From Network: ${state}`) + console.info('Asset has been created successfully') + } else { + logger.debug('No Response from network') + } + } catch (error) { + console.error(`Failed to submit transaction: ${error}`) + throw new Error(error) + } + + await gateway.disconnect() + logger.info('Gateways disconnected.') + + const client = getRelayClientForAssetStatusResponse(); + const request = new satp_pb.SendAssetStatusRequest(); + request.setSessionId(createAssetRequest.getSessionId()); + request.setStatus("Created"); + client.sendAssetStatus(request, relayCallback); +} + +async function extinguishHelper( + extinguishRequest: driverPb.ExtinguishRequest): Promise { + + // TODO + const client = getRelayClientForAssetStatusResponse(); + const request = new satp_pb.SendAssetStatusRequest(); + request.setSessionId(extinguishRequest.getSessionId()); + request.setStatus("Extinguished"); + client.sendAssetStatus(request, relayCallback); +} + +async function assignAssetHelper( + assignAssetRequest: driverPb.AssignAssetRequest, + networkName: string +): Promise { + + // TODO: remove the hardcoded values + let assignAssetRequest2 = {}; + assignAssetRequest2['target-network'] = 'network1'; + assignAssetRequest2['hashBase64'] = 'ivHErp1x4bJDKuRo6L5bApO/DdoyD/dG0mAZrzLZEIs='; + assignAssetRequest2['timeout-duration'] = parseInt('3600'); + assignAssetRequest2['locker'] = 'admin'; + assignAssetRequest2['recipient'] = 'bob'; + assignAssetRequest2['fungible'] = false; + assignAssetRequest2['contract-id'] = 'abc01'; + assignAssetRequest2['hash_fn'] = ''; + assignAssetRequest2['secret'] = 'secrettext'; + assignAssetRequest2['param'] = 'bond01:a0demo'; + assignAssetRequest2['channel'] = 'mychannel'; + assignAssetRequest2['chaincode-id'] = 'satpsimpleasset'; + + const targetNetwork = assignAssetRequest2['target-network']; + const locker = assignAssetRequest2['locker']; + const recipient = assignAssetRequest2['recipient']; + const fungible = assignAssetRequest2['fungible']; + const hashFn = assignAssetRequest2['hash_fn']; + const secret = assignAssetRequest2['secret']; + const channel = assignAssetRequest2['channel']; + const chaincodeId = assignAssetRequest2['chaincode-id']; + + let gateway: Gateway = await getNetworkGateway(networkName); + const network: Network = await gateway.getNetwork(channel); + const contract = network.getContract(chaincodeId); + + // Hash + let hash: HashFunctions.Hash + if (hashFn == 'SHA512') { + hash = new HashFunctions.SHA512() + } else { + hash = new HashFunctions.SHA256() + } + hash.setPreimage(secret) + + let contractId: string = null, params + if (assignAssetRequest2['contract-id']) { + contractId = assignAssetRequest2['contract-id'] + } + + params = assignAssetRequest2['param'].split(':') + + const funcToCall = SatpAssetManager.assignAsset + let asset = assignAssetRequest2['param'] + + if (assignAssetRequest2['fungible']) { + // funcToCall = SatpAssetManager.claimFungibleAssetInHTLC + asset = 'Fungible Asset' + } + + if (fungible) { + try { + console.info(`Trying assigning the asset with contract id ${contractId}`) + + // TODO + } catch (error) { + console.error(`Could not assign ${asset} in ${targetNetwork}`) + throw new Error(`Could not assign ${asset} in ${targetNetwork}`) + } + } else { + try { + const driverkeyCert = await getDriverKeyCert(); + const certificate = Buffer.from(driverkeyCert.cert).toString('base64') + + console.info(`Trying assign asset with params: ${params[0]}, ${params[1]} locked by ${locker} for ${recipient}`) + const res = await funcToCall(contract, + params[0], + params[1], + certificate, + hash) + if (!res) { + throw new Error("assignAssetHelper() funcToCall res falsy."); + } + console.info(`${asset} assigned complete: ${res}`) + console.info(`Asset ${asset} assign complete: ${res}`) + } catch (error) { + console.error(`Could not assign non-fungible ${asset} in ${targetNetwork}: ${error}`) + throw new Error(`Could not assign non-fungible ${asset} in ${targetNetwork}: ${error}`) + } + + await gateway.disconnect() + logger.info('Gateways disconnected.') + + const client = getRelayClientForAssetStatusResponse(); + const request = new satp_pb.SendAssetStatusRequest(); + request.setSessionId(assignAssetRequest.getSessionId()); + request.setStatus("Finalized"); + client.sendAssetStatus(request, relayCallback); + } +} + +function getRelayClientForAssetStatusResponse(): satp_grpc_pb.SATPClient { + let client: satp_grpc_pb.SATPClient; + if (process.env.RELAY_TLS === 'true') { + if (!process.env.RELAY_TLSCA_CERT_PATH || process.env.RELAY_TLSCA_CERT_PATH == "") { + client = new satp_grpc_pb.SATPClient( + process.env.RELAY_ENDPOINT, + credentials.createSsl() + ); + } else { + if (!(process.env.RELAY_TLSCA_CERT_PATH && fs.existsSync(process.env.RELAY_TLSCA_CERT_PATH))) { + throw new Error("Missing or invalid RELAY_TLSCA_CERT_PATH: " + process.env.RELAY_TLSCA_CERT_PATH); + } + const rootCert = fs.readFileSync(process.env.RELAY_TLSCA_CERT_PATH); + client = new satp_grpc_pb.SATPClient( + process.env.RELAY_ENDPOINT, + credentials.createSsl(rootCert) + ); + } + } else { + client = new satp_grpc_pb.SATPClient( + process.env.RELAY_ENDPOINT, + credentials.createInsecure() + ); + } + return client; +} + +// handle callback +function relayCallback(err: unknown, response: any) { + if (response) { + logger.info(`Relay Callback Response: ${JSON.stringify(response.toObject())}`); + } else if (err) { + logger.error(`Relay Callback Error: ${err}`); + } +} + +export { + performLockHelper, + createAssetHelper, + extinguishHelper, + assignAssetHelper +} diff --git a/weaver/core/drivers/fabric-driver/server/server.ts b/weaver/core/drivers/fabric-driver/server/server.ts index c645caece32..df0e1d696dc 100644 --- a/weaver/core/drivers/fabric-driver/server/server.ts +++ b/weaver/core/drivers/fabric-driver/server/server.ts @@ -12,13 +12,13 @@ import fabricViewPb from '@hyperledger/cacti-weaver-protos-js/fabric/view_data_p import eventsPb from '@hyperledger/cacti-weaver-protos-js/common/events_pb'; import driver_pb_grpc from '@hyperledger/cacti-weaver-protos-js/driver/driver_grpc_pb'; import datatransfer_grpc_pb from '@hyperledger/cacti-weaver-protos-js/relay/datatransfer_grpc_pb'; -import events_grpc_pb from '@hyperledger/cacti-weaver-protos-js/relay/events_grpc_pb'; import state_pb from '@hyperledger/cacti-weaver-protos-js/common/state_pb'; import { invoke, packageFabricView } from './fabric-code'; import 'dotenv/config'; import { loadEventSubscriptionsFromStorage, monitorBlockForMissedEvents } from './listener' import { walletSetup } from './walletSetup'; import { subscribeEventHelper, unsubscribeEventHelper, signEventSubscriptionQuery, writeExternalStateHelper } from "./events" +import { performLockHelper, createAssetHelper, extinguishHelper, assignAssetHelper } from "./satp" import * as path from 'path'; import { handlePromise, relayCallback, getRelayClientForQueryResponse, getRelayClientForEventSubscription, delay } from './utils'; import { dbConnectionTest, eventSubscriptionTest } from "./tests" @@ -233,6 +233,91 @@ server.addService(driver_pb_grpc.DriverCommunicationService, { callback(null, ack_err_response); }); }, + performLock: (call: { request: driverPb.PerformLockRequest }, callback: (_: any, object: ack_pb.Ack) => void) => { + const requestId: string = call.request.getSessionId(); + + performLockHelper(call.request, process.env.NETWORK_NAME ? process.env.NETWORK_NAME : 'network1').then(() => { + const ack_response = new ack_pb.Ack(); + ack_response.setRequestId(requestId); + ack_response.setMessage('Successfully locked the asset'); + ack_response.setStatus(ack_pb.Ack.STATUS.OK); + // gRPC response. + logger.info(`Responding to caller with Ack: ${JSON.stringify(ack_response.toObject())}`); + callback(null, ack_response); + }).catch((error) => { + const ack_err_response = new ack_pb.Ack(); + ack_err_response.setRequestId(requestId); + ack_err_response.setMessage(error.toString()); + ack_err_response.setStatus(ack_pb.Ack.STATUS.ERROR); + // gRPC response. + logger.info(`Responding to caller with error Ack: ${JSON.stringify(ack_err_response.toObject())}`); + callback(null, ack_err_response); + }); + }, + createAsset: (call: { request: driverPb.CreateAssetRequest }, callback: (_: any, object: ack_pb.Ack) => void) => { + const requestId: string = call.request.getSessionId(); + + createAssetHelper(call.request, process.env.NETWORK_NAME ? process.env.NETWORK_NAME : 'network1').then(() => { + const ack_response = new ack_pb.Ack(); + ack_response.setRequestId(requestId); + ack_response.setMessage('Successfully created the asset'); + ack_response.setStatus(ack_pb.Ack.STATUS.OK); + // gRPC response. + logger.info(`Responding to caller with Ack: ${JSON.stringify(ack_response.toObject())}`); + callback(null, ack_response); + }).catch((error) => { + const ack_err_response = new ack_pb.Ack(); + ack_err_response.setRequestId(requestId); + ack_err_response.setMessage(error.toString()); + ack_err_response.setStatus(ack_pb.Ack.STATUS.ERROR); + // gRPC response. + logger.info(`Responding to caller with error Ack: ${JSON.stringify(ack_err_response.toObject())}`); + callback(null, ack_err_response); + }); + }, + extinguish: (call: { request: driverPb.ExtinguishRequest }, callback: (_: any, object: ack_pb.Ack) => void) => { + const requestId: string = call.request.getSessionId(); + + extinguishHelper(call.request, process.env.NETWORK_NAME ? process.env.NETWORK_NAME : 'network1').then(() => { + const ack_response = new ack_pb.Ack(); + ack_response.setRequestId(requestId); + ack_response.setMessage('Successfully extinguished the asset'); + ack_response.setStatus(ack_pb.Ack.STATUS.OK); + // gRPC response. + logger.info(`Responding to caller with Ack: ${JSON.stringify(ack_response.toObject())}`); + callback(null, ack_response); + }).catch((error) => { + const ack_err_response = new ack_pb.Ack(); + ack_err_response.setRequestId(requestId); + ack_err_response.setMessage(error.toString()); + ack_err_response.setStatus(ack_pb.Ack.STATUS.ERROR); + // gRPC response. + logger.info(`Responding to caller with error Ack: ${JSON.stringify(ack_err_response.toObject())}`); + callback(null, ack_err_response); + }); + }, + assignAsset: (call: { request: driverPb.AssignAssetRequest }, callback: (_: any, object: ack_pb.Ack) => void) => { + const requestId: string = call.request.getSessionId(); + + assignAssetHelper(call.request, process.env.NETWORK_NAME ? process.env.NETWORK_NAME : 'network1').then(() => { + const ack_response = new ack_pb.Ack(); + ack_response.setRequestId(requestId); + ack_response.setMessage('Successfully assigned the asset'); + ack_response.setStatus(ack_pb.Ack.STATUS.OK); + // gRPC response. + logger.info(`Responding to caller with Ack: ${JSON.stringify(ack_response.toObject())}`); + callback(null, ack_response); + }).catch((error) => { + const ack_err_response = new ack_pb.Ack(); + ack_err_response.setRequestId(requestId); + ack_err_response.setMessage(error.toString()); + ack_err_response.setStatus(ack_pb.Ack.STATUS.ERROR); + // gRPC response. + logger.info(`Responding to caller with error Ack: ${JSON.stringify(ack_err_response.toObject())}`); + callback(null, ack_err_response); + }); + }, + }); // Prepares required crypto material for communication with the fabric network diff --git a/weaver/core/relay/.env.template b/weaver/core/relay/.env.template index e2c5c3e047b..9b8a335dd5f 100644 --- a/weaver/core/relay/.env.template +++ b/weaver/core/relay/.env.template @@ -6,3 +6,4 @@ DOCKER_TAG=2.0.0-alpha.2 EXTERNAL_NETWORK= COMPOSE_PROJECT_NAME= COMPOSE_PROJECT_NETWORK= +RUST_LOG="DEBUG" diff --git a/weaver/core/relay/.env.template.2 b/weaver/core/relay/.env.template.2 index c5c96c1218c..28cd85377ac 100644 --- a/weaver/core/relay/.env.template.2 +++ b/weaver/core/relay/.env.template.2 @@ -18,3 +18,4 @@ RELAY_TLS_CERT_PATH= RELAY_TLS_KEY_PATH= DRIVER_TLS=false DRIVER_TLSCA_CERT_PATH= +RUST_LOG="DEBUG" diff --git a/weaver/core/relay/.gitignore b/weaver/core/relay/.gitignore index bed3ac99529..d54cbf8c589 100644 --- a/weaver/core/relay/.gitignore +++ b/weaver/core/relay/.gitignore @@ -3,3 +3,4 @@ fingerprint.json protos-rs /db .env +*.db diff --git a/weaver/core/relay/Cargo.lock b/weaver/core/relay/Cargo.lock index 3136ba7df17..7cbad7864c4 100644 --- a/weaver/core/relay/Cargo.lock +++ b/weaver/core/relay/Cargo.lock @@ -18,6 +18,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] +name = "ahash" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91429305e9f0a25f6205c5b8e0d2db09e0708a7a6df0f42212bb56c32c8ac97a" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + +[[package]] + name = "aho-corasick" version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -26,11 +39,32 @@ dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0942ffc6dcaadf03badf6e6a2d0228460359d5e34b57ccdc720b7382dfbd5ec5" + +[[package]] +name = "android-tzdata" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e999941b234f3131b00bc13c22d06e8c5ff726d1b6318ac7eb276997bbb4fef0" + +[[package]] +name = "android_system_properties" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" +dependencies = [ + "libc", +] + [[package]] name = "anyhow" -version = "1.0.70" +version = "1.0.75" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4" +checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "arrayvec" @@ -40,9 +74,9 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "async-stream" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad445822218ce64be7a341abfb0b1ea43b5c23aa83902542a4542e78309d8e5e" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" dependencies = [ "async-stream-impl", "futures-core", @@ -51,20 +85,20 @@ dependencies = [ [[package]] name = "async-stream-impl" -version = "0.3.4" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4655ae1a7b0cdf149156f780c5bf3f1352bc53cbd9e0a361a7ef7b22947e965" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.39", ] [[package]] name = "async-trait" -version = "0.1.68" +version = "0.1.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9ccdd8f2a161be9bd5c023df56f1b2a0bd1d83872ae53b71a84a12c9bf6e842" +checksum = "a66537f1bb974b254c98ed142ff995236e81b9d0fe4db0575f46612cb15eb0f9" dependencies = [ "proc-macro2", "quote", @@ -79,13 +113,13 @@ checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa" [[package]] name = "axum" -version = "0.6.12" +version = "0.6.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "349f8ccfd9221ee7d1f3d4b33e1f8319b3a81ed8f61f2ea40b37b859794b4491" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" dependencies = [ "async-trait", "axum-core", - "bitflags", + "bitflags 1.3.2", "bytes", "futures-util", "http", @@ -107,9 +141,9 @@ dependencies = [ [[package]] name = "axum-core" -version = "0.3.3" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2f958c80c248b34b9a877a643811be8dbca03ca5ba827f2b63baf3a81e5fc4e" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" dependencies = [ "async-trait", "bytes", @@ -137,6 +171,21 @@ dependencies = [ "rustc-demangle", ] +[[package]] +name = "base64" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2089b7e3f35b9dd2d0ed921ead4f6d318c27680d4a5bd167b3ee120edb105837" +dependencies = [ + "addr2line", + "cc", + "cfg-if", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + [[package]] name = "base64" version = "0.20.0" @@ -145,9 +194,9 @@ checksum = "0ea22880d78093b0cbe17c89f64a7d457941e65759157ec6cb31a31d652b05e5" [[package]] name = "base64" -version = "0.21.0" +version = "0.21.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a4ddaa51a5bc52a6948f74c06d20aaaddb71924eab79b8c97a8c556e942d6a" +checksum = "35636a1494ede3b646cc98f74f8e62c773a38a659ebc777a2cf26b9b74171df9" [[package]] name = "bincode" @@ -164,23 +213,29 @@ version = "1.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +[[package]] +name = "bitflags" +version = "2.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07" + [[package]] name = "bumpalo" -version = "3.12.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d261e256854913907f67ed06efbc3338dfe6179796deefc1ff763fc1aee5535" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "byteorder" -version = "1.4.3" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "14c189c53d098945499cdfa7ecc63567cf3886b3332b312a5b4585d8d3a6a610" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cacti_weaver_protos_rs" @@ -206,6 +261,31 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chrono" +version = "0.4.31" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f2c685bad3eb3d45a01354cedb7d5faa66194d1d58ba6e267a8de788f79db38" +dependencies = [ + "android-tzdata", + "iana-time-zone", + "js-sys", + "num-traits 0.2.17", + "wasm-bindgen", + "windows-targets", +] + +[[package]] +name = "colored" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2674ec482fbc38012cf31e6c42ba0177b431a0cb6f15fe40efa5aab1bda516f6" +dependencies = [ + "is-terminal", + "lazy_static", + "windows-sys", +] + [[package]] name = "config" version = "0.11.0" @@ -249,9 +329,9 @@ dependencies = [ [[package]] name = "crossbeam-epoch" -version = "0.9.14" +version = "0.9.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46bd5f3f85273295a9d14aedfb86f6aadbff6d8f5295c4a9edb08e819dcf5695" +checksum = "ae211234986c545741a7dc064309f67ee1e5ad243d0e48335adc0484d960bcc7" dependencies = [ "autocfg", "cfg-if", @@ -262,24 +342,30 @@ dependencies = [ [[package]] name = "crossbeam-utils" -version = "0.8.15" +version = "0.8.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c063cd8cc95f5c377ed0d4b49a4b21f632396ff690e8470c29b3359b346984b" +checksum = "5a22b2d63d4d1dc0b7f1b6b2747dd0088008a9be28b6ddf0b1e7d335e3037294" dependencies = [ "cfg-if", ] +[[package]] +name = "dotenv" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77c90badedccf4105eca100756a0b1289e191f6fcbdadd3cee1d2f614f97da8f" + [[package]] name = "either" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91" +checksum = "a26ae43d7bcc3b814de94796a5e736d4029efb0ee900c12e2d54c993ad1a1e07" [[package]] name = "encoding_rs" -version = "0.8.32" +version = "0.8.33" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "071a31f4ee85403370b58aca746f01041ede6f0da2730960ad001edc2b71b394" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" dependencies = [ "cfg-if", ] @@ -294,31 +380,48 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" name = "errno" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50d6a0976c999d473fe89ad888d5a284e55366d9dc9038b1ba2aa15128c4afa0" +checksum = "95b3f3e67048839cb0d0781f445682a35113da7121f7c949db0e2be96a4fbece" dependencies = [ - "errno-dragonfly", - "libc", - "windows-sys 0.45.0", + "humantime", + "is-terminal", + "log", + "regex", + "termcolor", ] [[package]] -name = "errno-dragonfly" -version = "0.1.2" +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + +[[package]] +name = "errno" +version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa68f1b12764fab894d2755d2518754e71b4fd80ecfb822714a1206c2aab39bf" +checksum = "f258a7194e7f7c2a7837a8913aeab7fd8c383457034fa20ce4dd3dcb813e8eb8" dependencies = [ - "cc", "libc", + "windows-sys", ] +[[package]] +name = "fallible-iterator" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" + +[[package]] +name = "fallible-streaming-iterator" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7360491ce676a36bf9bb3c56c1aa791658183a54d2744120f27285738d90465a" + [[package]] name = "fastrand" -version = "1.9.0" +version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e51093e27b0797c359783294ca4f0a911c270184cb10f85783b118614a1501be" -dependencies = [ - "instant", -] +checksum = "25cbce373ec4653f1a01a31e8a5e5ec0c622dc27ff9c4e6606eefef5cbbed4a5" [[package]] name = "fixedbitset" @@ -349,9 +452,9 @@ checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" [[package]] name = "form_urlencoded" -version = "1.1.0" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9c384f161156f5260c24a097c56119f9be8c798586aecc13afbcbe7b7e26bf8" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" dependencies = [ "percent-encoding", ] @@ -368,9 +471,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23342abe12aba583913b2e62f22225ff9c950774065e4bfb61a19cd9770fec40" +checksum = "da0290714b38af9b4a7b094b8a37086d1b4e61f2df9122c3cad2577669145335" dependencies = [ "futures-channel", "futures-core", @@ -383,9 +486,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "955518d47e09b25bbebc7a18df10b81f0c766eaf4c4f1cccef2fca5f2a4fb5f2" +checksum = "ff4dd66668b557604244583e3e1e1eada8c5c2e96a6d0d6653ede395b78bbacb" dependencies = [ "futures-core", "futures-sink", @@ -393,15 +496,15 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4bca583b7e26f571124fe5b7561d49cb2868d79116cfa0eefce955557c6fee8c" +checksum = "eb1d22c66e66d9d72e1758f0bd7d4fd0bee04cad842ee34587d68c07e45d088c" [[package]] name = "futures-executor" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccecee823288125bd88b4d7f565c9e58e41858e47ab72e8ea2d64e93624386e0" +checksum = "0f4fb8693db0cf099eadcca0efe2a5a22e4550f98ed16aba6c48700da29597bc" dependencies = [ "futures-core", "futures-task", @@ -410,15 +513,15 @@ dependencies = [ [[package]] name = "futures-io" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fff74096e71ed47f8e023204cfd0aa1289cd54ae5430a9523be060cdb849964" +checksum = "8bf34a163b5c4c52d0478a4d757da8fb65cabef42ba90515efee0f6f9fa45aaa" [[package]] name = "futures-macro" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" +checksum = "53b153fd91e4b0147f4aced87be237c98248656bb01050b96bf3ee89220a8ddb" dependencies = [ "proc-macro2", "quote", @@ -427,21 +530,21 @@ dependencies = [ [[package]] name = "futures-sink" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f43be4fe21a13b9781a69afa4985b0f6ee0e1afab2c6f454a8cf30e2b2237b6e" +checksum = "e36d3378ee38c2a36ad710c5d30c2911d752cb941c00c72dbabfb786a7970817" [[package]] name = "futures-task" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76d3d132be6c0e6aa1534069c705a74a5997a356c0dc2f86a47765e5617c5b65" +checksum = "efd193069b0ddadc69c46389b740bbccdd97203899b48d09c5f7969591d6bae2" [[package]] name = "futures-util" -version = "0.3.28" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b01e40b772d54cf6c6d721c1d1abd0647a0106a12ecaa1c186273392a69533" +checksum = "a19526d624e703a3179b3d322efec918b6246ea0fa51d41124525f00f1cc8104" dependencies = [ "futures-channel", "futures-core", @@ -520,24 +623,24 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.2.6" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee512640fe35acbfb4bb779db6f0d80704c2cacfa2e39b601ef3e3f47d1ae4c7" -dependencies = [ - "libc", -] +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] -name = "hermit-abi" -version = "0.3.1" +name = "home" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed44880c466736ef9a5c5b5facefb5ed0785676d0c02d612db14e54f0d84286" +checksum = "5444c27eef6923071f7ebcc33e3444508466a76f7a2b93da00ed6e19f30c1ddb" +dependencies = [ + "windows-sys", +] [[package]] name = "http" -version = "0.2.9" +version = "0.2.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" +checksum = "8947b1a6fad4393052c7ba1f4cd97bed3e953a95c79c92ad9b051a04611d9fbb" dependencies = [ "bytes", "fnv", @@ -563,9 +666,15 @@ checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" [[package]] name = "httpdate" -version = "1.0.2" +version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + +[[package]] +name = "humantime" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" [[package]] name = "hyper" @@ -584,7 +693,7 @@ dependencies = [ "httpdate", "itoa", "pin-project-lite", - "socket2 0.4.9", + "socket2 0.4.10", "tokio", "tower-service", "tracing", @@ -616,11 +725,34 @@ dependencies = [ "tokio-native-tls", ] +[[package]] +name = "iana-time-zone" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8326b86b6cff230b97d0d312a6c40a60726df3332e721f72a1b035f451663b20" +dependencies = [ + "android_system_properties", + "core-foundation-sys", + "iana-time-zone-haiku", + "js-sys", + "wasm-bindgen", + "windows-core", +] + +[[package]] +name = "iana-time-zone-haiku" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" +dependencies = [ + "cc", +] + [[package]] name = "idna" -version = "0.3.0" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e14ddfc70884202db2244c223200c204c2bda1bc6e0998d11b5e024d657209e6" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" dependencies = [ "unicode-bidi", "unicode-normalization", @@ -656,21 +788,21 @@ dependencies = [ ] [[package]] -name = "io-lifetimes" -version = "1.0.9" +name = "ipnet" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09270fd4fa1111bc614ed2246c7ef56239a3063d5be0d1ec3b589c505d400aeb" -dependencies = [ - "hermit-abi 0.3.1", - "libc", - "windows-sys 0.45.0", -] +checksum = "8f518f335dce6725a761382244631d86cf0ccb2863413590b31338feb467f9c3" [[package]] -name = "ipnet" -version = "2.7.2" +name = "is-terminal" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b6ee2129af8d4fb011108c73d99a1b83a85977f23b82460c0ae2e25bb4b57f" +checksum = "cb0889898416213fab133e1d33a0e5858a48177452750691bde3666d0fdbaf8b" +dependencies = [ + "hermit-abi", + "rustix", + "windows-sys", +] [[package]] name = "itertools" @@ -683,15 +815,15 @@ dependencies = [ [[package]] name = "itoa" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6" +checksum = "af150ab688ff2122fcef229be89cb50dd66af9e01a4ff320cc137eecc9bacc38" [[package]] name = "js-sys" -version = "0.3.61" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "445dde2150c55e483f3d8416706b97ec8e8237c307e5b7b4b8dd15e6af2a0730" +checksum = "54c0c35952f67de54bb584e9fd912b3023117cbafc0a77d8f3dee1fb5f572fe8" dependencies = [ "wasm-bindgen", ] @@ -709,7 +841,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6607c62aa161d23d17a9072cc5da0be67cdfc89d3afb1e8d9c842bebc2525ffe" dependencies = [ "arrayvec", - "bitflags", + "bitflags 1.3.2", "cfg-if", "ryu", "static_assertions", @@ -721,6 +853,16 @@ version = "0.2.150" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89d92a4743f9a61002fae18374ed11e7973f530cb3a3255fb354818118b2203c" +[[package]] +name = "libsqlite3-sys" +version = "0.26.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "afc22eff61b133b115c6e8c74e818c628d6d5e7a502afea6f64dee076dd94326" +dependencies = [ + "pkg-config", + "vcpkg", +] + [[package]] name = "linked-hash-map" version = "0.5.6" @@ -729,9 +871,9 @@ checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f" [[package]] name = "linux-raw-sys" -version = "0.3.1" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d59d8c75012853d2e872fb56bc8a2e53718e2cafe1a4c823143141c6d90c322f" +checksum = "969488b55f8ac402214f3f5fd243ebb7206cf82de60d3172994707a4bcc2b829" [[package]] name = "listenfd" @@ -746,9 +888,9 @@ dependencies = [ [[package]] name = "lock_api" -version = "0.4.9" +version = "0.4.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435011366fe56583b16cf956f9df0095b405b82d76425bc8981c0e22e60ec4df" +checksum = "3c168f8615b12bc01f9c17e2eb0cc07dcae1940121185446edc3744920e8ef45" dependencies = [ "autocfg", "scopeguard", @@ -756,30 +898,27 @@ dependencies = [ [[package]] name = "log" -version = "0.4.17" +version = "0.4.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" -dependencies = [ - "cfg-if", -] +checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f" [[package]] name = "matchit" -version = "0.7.0" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b87248edafb776e59e6ee64a79086f65890d3510f2c656c000bf2a7e8a0aea40" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "f665ee40bc4a3c5590afb1e9677db74a508659dfd71e126420da8274909a0167" [[package]] name = "memoffset" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] @@ -851,25 +990,25 @@ version = "0.1.43" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92e5113e9fd4cc14ded8e499429f396a20f98c772a47cc8622a736e1ec843c31" dependencies = [ - "num-traits 0.2.15", + "num-traits 0.2.17", ] [[package]] name = "num-traits" -version = "0.2.15" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "578ede34cf02f8924ab9447f50c28075b4d3e5b269972345e7e0372b38c6cdcd" +checksum = "39e3200413f237f41ab11ad6d161bc7239c84dcb631773ccd7de3dfe4b5c267c" dependencies = [ "autocfg", ] [[package]] name = "num_cpus" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fac9e2da13b5eb447a6ce3d392f23a29d8694bff781bf03a16cd9ac8697593b" +checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" dependencies = [ - "hermit-abi 0.2.6", + "hermit-abi", "libc", ] @@ -884,17 +1023,17 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.17.1" +version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7e5500299e16ebb147ae15a00a942af264cf3688f47923b8fc2cd5858f23ad3" +checksum = "dd8b5dd2ae5ed71462c540258bedcb51965123ad7e7ccf4b9a8cafaa4a63576d" [[package]] name = "openssl" -version = "0.10.55" +version = "0.10.60" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "345df152bc43501c5eb9e4654ff05f794effb78d4efe3d53abc158baddc0703d" +checksum = "79a4c6c3a2b158f7f8f2a2fc5a969fa3a068df6fc9dbb4a43845436e3af7c800" dependencies = [ - "bitflags", + "bitflags 2.4.1", "cfg-if", "foreign-types", "libc", @@ -922,9 +1061,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.90" +version = "0.9.96" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "374533b0e45f3a7ced10fcaeccca020e66656bc03dac384f852e4e5a7a8104a6" +checksum = "3812c071ba60da8b5677cc12bcb1d42989a65553772897a7e0355545a819838f" dependencies = [ "cc", "libc", @@ -940,7 +1079,17 @@ checksum = "7d17b78036a60663b797adeaee46f5c9dfebb86948d1255007a1d6be0271ff99" dependencies = [ "instant", "lock_api", - "parking_lot_core", + "parking_lot_core 0.8.6", +] + +[[package]] +name = "parking_lot" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3742b2c103b9f06bc9fff0a37ff4912935851bee6d36f3c02bcc755bcfec228f" +dependencies = [ + "lock_api", + "parking_lot_core 0.9.9", ] [[package]] @@ -957,40 +1106,53 @@ dependencies = [ "winapi", ] +[[package]] +name = "parking_lot_core" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4c42a9226546d68acdd9c0a280d17ce19bfe27a46bf68784e4066115788d008e" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall 0.4.1", + "smallvec", + "windows-targets", +] + [[package]] name = "percent-encoding" -version = "2.2.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "478c572c3d73181ff3c2539045f6eb99e5491218eae919370993b890cdbdd98e" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" [[package]] name = "petgraph" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4dd7d28ee937e54fe3080c91faa1c3a46c06de6252988a7f4592ba2310ef22a4" +checksum = "e1d3afd2628e69da2be385eb6f2fd57c8ac7977ceeff6dc166ff1657b0e386a9" dependencies = [ "fixedbitset", - "indexmap 1.9.3", + "indexmap 2.1.0", ] [[package]] name = "pin-project" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" +checksum = "fda4ed1c6c173e3fc7a83629421152e01d7b1f9b7f65fb301e490e8cfc656422" dependencies = [ "pin-project-internal", ] [[package]] name = "pin-project-internal" -version = "1.0.12" +version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" +checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.39", ] [[package]] @@ -1007,9 +1169,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.26" +version = "0.3.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" +checksum = "26072860ba924cbfa98ea39c8c19b4dd6a4a25423dbdf219c1eca91aa0cf6964" [[package]] name = "ppv-lite86" @@ -1099,6 +1261,28 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "r2d2" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" +dependencies = [ + "log", + "parking_lot 0.12.1", + "scheduled-thread-pool", +] + +[[package]] +name = "r2d2_sqlite" +version = "0.22.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99f31323d6161385f385046738df520e0e8694fa74852d35891fc0be08348ddc" +dependencies = [ + "r2d2", + "rusqlite", + "uuid", +] + [[package]] name = "rand" version = "0.8.5" @@ -1135,23 +1319,23 @@ version = "0.2.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] name = "redox_syscall" -version = "0.3.5" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "567664f262709473930a4bf9e51bf2ebf3348f2e748ccc50dea20646858f8f29" +checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" dependencies = [ - "bitflags", + "bitflags 1.3.2", ] [[package]] name = "regex" -version = "1.9.4" +version = "1.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12de2eff854e5fa4b1295edd650e227e9d8fb0c9e90b12e7f36d6a6811791a29" +checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343" dependencies = [ "aho-corasick", "memchr", @@ -1161,9 +1345,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.7" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49530408a136e16e5b486e883fbb6ba058e8e4e8ae6621a77b048b314336e629" +checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f" dependencies = [ "aho-corasick", "memchr", @@ -1172,9 +1356,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.5" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" +checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" [[package]] name = "relay" @@ -1183,10 +1367,19 @@ dependencies = [ "base64 0.20.0", "bincode", "cacti_weaver_protos_rs", + "chrono", + "colored", "config", + "dotenv", + "env_logger", "futures", + "lazy_static", "listenfd", + "log", + "r2d2", + "r2d2_sqlite", "reqwest", + "rusqlite", "serde 1.0.193", "serde_json", "sled", @@ -1198,11 +1391,11 @@ dependencies = [ [[package]] name = "reqwest" -version = "0.11.16" +version = "0.11.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b71749df584b7f4cac2c426c127a7c785a5106cc98f7a8feb044115f0fa254" +checksum = "046cd98826c46c2ac8ddecae268eb5c2e58628688a5fc7a2643704a73faba95b" dependencies = [ - "base64 0.21.0", + "base64 0.21.5", "bytes", "encoding_rs", "futures-core", @@ -1223,6 +1416,7 @@ dependencies = [ "serde 1.0.193", "serde_json", "serde_urlencoded", + "system-configuration", "tokio", "tokio-native-tls", "tower-service", @@ -1276,16 +1470,15 @@ checksum = "d626bb9dae77e28219937af045c257c28bfd3f69333c512553507f5f9798cb76" [[package]] name = "rustix" -version = "0.37.6" +version = "0.38.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d097081ed288dfe45699b72f5b5d648e5f15d64d900c7080273baa20c16a6849" +checksum = "dc99bc2d4f1fed22595588a013687477aedf3cdcfb26558c559edb67b4d9b22e" dependencies = [ - "bitflags", + "bitflags 2.4.1", "errno", - "io-lifetimes", "libc", "linux-raw-sys", - "windows-sys 0.45.0", + "windows-sys", ] [[package]] @@ -1302,11 +1495,11 @@ dependencies = [ [[package]] name = "rustls-pemfile" -version = "1.0.2" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d194b56d58803a43635bdc398cd17e383d6f71f9182b9a192c127ca42494a59b" +checksum = "1c74cae0a4cf6ccbbf5f359f08efdf8ee7e1dc532573bf0db71968cb56b1448c" dependencies = [ - "base64 0.21.0", + "base64 0.21.5", ] [[package]] @@ -1321,48 +1514,57 @@ dependencies = [ [[package]] name = "rustversion" -version = "1.0.12" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4f3208ce4d8448b3f3e7d168a73f5e0c43a61e32930de3bceeccedb388b6bf06" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "ryu" -version = "1.0.13" +version = "1.0.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041" +checksum = "1ad4cc8da4ef723ed60bced201181d83791ad433213d8c24efffda1eec85d741" [[package]] name = "schannel" -version = "0.1.21" +version = "0.1.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c3733bf4cf7ea0880754e19cb5a462007c4a8c1914bff372ccc95b464f1df88" +dependencies = [ + "windows-sys", +] + +[[package]] +name = "scheduled-thread-pool" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "713cfb06c7059f3588fb8044c0fad1d09e3c01d225e25b9220dbfdcf16dbb1b3" +checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" dependencies = [ - "windows-sys 0.42.0", + "parking_lot 0.12.1", ] [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "sct" -version = "0.7.0" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d53dcdb7c9f8158937a7981b48accfd39a43af418591a5d008c7b22b5e1b7ca4" +checksum = "da046153aa2352493d6cb7da4b6e5c0c057d8a1d0a9aa8560baffdd945acd414" dependencies = [ - "ring 0.16.20", - "untrusted 0.7.1", + "ring 0.17.5", + "untrusted 0.9.0", ] [[package]] name = "security-framework" -version = "2.8.2" +version = "2.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a332be01508d814fed64bf28f798a146d73792121129962fdf335bb3c49a4254" +checksum = "05b64fb303737d99b81884b2c63433e9ae28abebe5eb5045dcdd175dc2ecf4de" dependencies = [ - "bitflags", + "bitflags 1.3.2", "core-foundation", "core-foundation-sys", "libc", @@ -1371,9 +1573,9 @@ dependencies = [ [[package]] name = "security-framework-sys" -version = "2.8.0" +version = "2.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31c9bb296072e961fcbd8853511dd39c2d8be2deb1e17c6860b1d30732b323b4" +checksum = "e932934257d3b408ed8f30db49d85ea163bfe74961f017f405b025af298f0c7a" dependencies = [ "core-foundation-sys", "libc", @@ -1442,9 +1644,9 @@ dependencies = [ [[package]] name = "slab" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6528351c9bc8ab22353f9d776db39a20288e8d6c37ef8cfe3317cf875eecfc2d" +checksum = "8f92a496fb766b417c996b9c5e57daf2f7ad3b0bebe1ccfca4856390e3d3bb67" dependencies = [ "autocfg", ] @@ -1462,20 +1664,20 @@ dependencies = [ "fxhash", "libc", "log", - "parking_lot", + "parking_lot 0.11.2", ] [[package]] name = "smallvec" -version = "1.10.0" +version = "1.11.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +checksum = "4dccd0940a2dcdf68d092b8cbab7dc0ad8fa938bf95787e1b916b0e3d0e8e970" [[package]] name = "socket2" -version = "0.4.9" +version = "0.4.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64a4a911eed85daf18834cfaa86a79b7d266ff93ff5ba14005426219480ed662" +checksum = "9f7916fc008ca5542385b89a3d3ce689953c143e9304a9bf8beec1de48994c0d" dependencies = [ "libc", "winapi", @@ -1537,17 +1739,47 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "system-configuration" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3a3adc5c275d719af8cb4272ea1c4a6d668a777f37e115f6d11ddbc1c8e0e7" +dependencies = [ + "bitflags 1.3.2", + "core-foundation", + "system-configuration-sys", +] + +[[package]] +name = "system-configuration-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a75fb188eb626b924683e3b95e3a48e63551fcfb51949de2f06a9d91dbee93c9" +dependencies = [ + "core-foundation-sys", + "libc", +] + [[package]] name = "tempfile" -version = "3.5.0" +version = "3.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b9fbec84f381d5795b08656e4912bec604d162bff9291d6189a78f4c8ab87998" +checksum = "7ef1adac450ad7f4b3c28589471ade84f25f731a7a0fe30d71dfa9f60fd808e5" dependencies = [ "cfg-if", "fastrand", - "redox_syscall 0.3.5", + "redox_syscall 0.4.1", "rustix", - "windows-sys 0.45.0", + "windows-sys", +] + +[[package]] +name = "termcolor" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff1bc3d3f05aff0403e8ac0d92ced918ec05b666a43f83297ccef5bea8a3d449" +dependencies = [ + "winapi-util", ] [[package]] @@ -1625,9 +1857,9 @@ dependencies = [ [[package]] name = "tokio-stream" -version = "0.1.12" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb52b74f05dbf495a8fba459fdc331812b96aa086d9eb78101fa0d4569c3313" +checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842" dependencies = [ "futures-core", "pin-project-lite", @@ -1636,9 +1868,9 @@ dependencies = [ [[package]] name = "tokio-util" -version = "0.7.7" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5427d89453009325de0d8f342c9490009f76e999cb7672d77e46267448f7e6b2" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" dependencies = [ "bytes", "futures-core", @@ -1734,11 +1966,10 @@ checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-attributes", "tracing-core", @@ -1746,20 +1977,20 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.23" +version = "0.1.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.39", ] [[package]] name = "tracing-core" -version = "0.1.30" +version = "0.1.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24eb03ba0eab1fd845050058ce5e616558e8f8d8fca633e6b163fe25c797213a" +checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" dependencies = [ "once_cell", ] @@ -1778,9 +2009,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.8" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5464a87b239f13a63a501f2701565754bae92d243d4bb7eb12f6d57d2269bf4" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" @@ -1805,9 +2036,9 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" -version = "2.3.1" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d68c799ae75762b8c3fe375feb6600ef5602c883c5d21eb51c09f22b83c4643" +checksum = "31e6302e3bb753d46e83516cae55ae196fc0c309407cf11ab35cc51a4c2a4633" dependencies = [ "form_urlencoded", "idna", @@ -1816,11 +2047,12 @@ dependencies = [ [[package]] name = "uuid" -version = "1.3.0" +version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1674845326ee10d37ca60470760d4288a6f80f304007d92e5c53bab78c9cfd79" +checksum = "5e395fcf16a7a3d8127ec99782007af141946b4795001f876d54fb0d55978560" dependencies = [ "getrandom", + "rand", ] [[package]] @@ -1837,11 +2069,10 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" [[package]] name = "want" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ce8a968cb1cd110d136ff8b819a556d6fb6d919363c61534f6860c7eb172ba0" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" dependencies = [ - "log", "try-lock", ] @@ -1853,9 +2084,9 @@ checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" [[package]] name = "wasm-bindgen" -version = "0.2.84" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "31f8dcbc21f30d9b8f2ea926ecb58f6b91192c17e9d33594b3df58b2007ca53b" +checksum = "7daec296f25a1bae309c0cd5c29c4b260e510e6d813c286b19eaadf409d40fce" dependencies = [ "cfg-if", "wasm-bindgen-macro", @@ -1863,24 +2094,24 @@ dependencies = [ [[package]] name = "wasm-bindgen-backend" -version = "0.2.84" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95ce90fd5bcc06af55a641a86428ee4229e44e07033963a2290a8e241607ccb9" +checksum = "e397f4664c0e4e428e8313a469aaa58310d302159845980fd23b0f22a847f217" dependencies = [ "bumpalo", "log", "once_cell", "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.39", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-futures" -version = "0.4.34" +version = "0.4.38" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f219e0d211ba40266969f6dbdd90636da12f75bee4fc9d6c23d1260dadb51454" +checksum = "9afec9963e3d0994cac82455b2b3502b81a7f40f9a0d32181f7528d9f4b43e02" dependencies = [ "cfg-if", "js-sys", @@ -1890,9 +2121,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.84" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4c21f77c0bedc37fd5dc21f897894a5ca01e7bb159884559461862ae90c0b4c5" +checksum = "5961017b3b08ad5f3fe39f1e79877f8ee7c23c5e5fd5eb80de95abc41f1f16b2" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1900,42 +2131,53 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.84" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2aff81306fcac3c7515ad4e177f521b5c9a15f2b08f4e32d823066102f35a5f6" +checksum = "c5353b8dab669f5e10f5bd76df26a9360c748f054f862ff5f3f8aae0c7fb3907" dependencies = [ "proc-macro2", "quote", - "syn 1.0.109", + "syn 2.0.39", "wasm-bindgen-backend", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.84" +version = "0.2.88" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0046fef7e28c3804e5e38bfa31ea2a0f73905319b677e57ebe37e49358989b5d" +checksum = "0d046c5d029ba91a1ed14da14dca44b68bf2f124cfbaf741c54151fdb3e0750b" [[package]] name = "web-sys" -version = "0.3.61" +version = "0.3.65" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e33b99f4b23ba3eec1a53ac264e35a755f00e966e0065077d6027c0f575b0b97" +checksum = "5db499c5f66323272151db0e666cd34f78617522fb0c1604d31a27c50c206a85" dependencies = [ "js-sys", "wasm-bindgen", ] +[[package]] +name = "webpki" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed63aea5ce73d0ff405984102c42de94fc55a6b75765d621c65262469b3c9b53" +dependencies = [ + "ring 0.17.5", + "untrusted 0.9.0", +] + [[package]] name = "which" -version = "4.4.0" +version = "4.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2441c784c52b289a054b7201fc93253e288f094e2f4be9058343127c4226a269" +checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7" dependencies = [ "either", - "libc", + "home", "once_cell", + "rustix", ] [[package]] @@ -1954,6 +2196,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" +dependencies = [ + "winapi", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -1961,10 +2212,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows-sys" -version = "0.42.0" +name = "windows-core" +version = "0.51.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a3e1820f08b8513f676f7ab6c1f99ff312fb97b553d30ff4dd86f9f15728aa7" +checksum = "f1f8cf84f35d2db49a46868f947758c7a1138116f7fac3bc844f43ade1292e64" dependencies = [ "windows_aarch64_gnullvm 0.42.2", "windows_aarch64_msvc 0.42.2", @@ -1977,9 +2228,9 @@ dependencies = [ [[package]] name = "windows-sys" -version = "0.45.0" +version = "0.48.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9" dependencies = [ "windows-targets 0.42.2", ] @@ -1995,9 +2246,9 @@ dependencies = [ [[package]] name = "windows-targets" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c" dependencies = [ "windows_aarch64_gnullvm 0.42.2", "windows_aarch64_msvc 0.42.2", @@ -2025,9 +2276,9 @@ dependencies = [ [[package]] name = "windows_aarch64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" +checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_gnullvm" @@ -2037,9 +2288,9 @@ checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8" [[package]] name = "windows_aarch64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" +checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_aarch64_msvc" @@ -2049,9 +2300,9 @@ checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc" [[package]] name = "windows_i686_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" +checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_gnu" @@ -2061,9 +2312,9 @@ checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e" [[package]] name = "windows_i686_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" +checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_i686_msvc" @@ -2073,9 +2324,9 @@ checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406" [[package]] name = "windows_x86_64_gnu" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" +checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnu" @@ -2085,9 +2336,9 @@ checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e" [[package]] name = "windows_x86_64_gnullvm" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" +checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_gnullvm" @@ -2097,9 +2348,9 @@ checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc" [[package]] name = "windows_x86_64_msvc" -version = "0.42.2" +version = "0.48.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" +checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "windows_x86_64_msvc" @@ -2109,11 +2360,12 @@ checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538" [[package]] name = "winreg" -version = "0.10.1" +version = "0.50.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80d0f4e272c85def139476380b12f9ac60926689dd2e01d4923222f40580869d" +checksum = "524e57b2c537c0f9b1e69f1965311ec12182b4122e45035b1508cd24d2adadb1" dependencies = [ - "winapi", + "cfg-if", + "windows-sys", ] [[package]] @@ -2124,3 +2376,23 @@ checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85" dependencies = [ "linked-hash-map", ] + +[[package]] +name = "zerocopy" +version = "0.7.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e97e415490559a91254a2979b4829267a57d2fcd741a98eee8b722fb57289aa0" +dependencies = [ + "zerocopy-derive", +] + +[[package]] +name = "zerocopy-derive" +version = "0.7.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd7e48ccf166952882ca8bd778a43502c64f33bf94c12ebe2a7f08e5a0f6689f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.39", +] diff --git a/weaver/core/relay/Cargo.toml b/weaver/core/relay/Cargo.toml index fe4457ea477..335b0a7174e 100644 --- a/weaver/core/relay/Cargo.toml +++ b/weaver/core/relay/Cargo.toml @@ -11,6 +11,11 @@ path = "src/main.rs" [[bin]] name = "client" path = "src/client.rs" + +[[bin]] +name = "satp_client" +path = "src/satp_client.rs" + [[bin]] name = "client-tls" path = "src/client_tls.rs" @@ -19,8 +24,6 @@ path = "src/client_tls.rs" name = "dummy-driver" path = "driver/driver.rs" - - [dependencies] tonic = { version="0.10.2", features = ["tls"] } tokio = { version = "1.34.0", features = ["macros", "fs", "rt", "rt-multi-thread", "sync"] } @@ -36,10 +39,15 @@ reqwest = { version = "0.11.16", features = ["json"] } serde_json = "1.0.108" cacti_weaver_protos_rs = { path = "./protos-rs" } # cacti_weaver_protos_rs = "2.0.0-alpha.2" +colored = {version="2.0.4"} +rusqlite = "0.29.0" +chrono = "0.4" +dotenv = "0.15" +log = "0.4.20" +r2d2 = "0.8.10" +r2d2_sqlite = "0.22.0" +lazy_static = "1.4" +env_logger = "0.10.0" [build-dependencies] tonic-build = "0.10.2" - - - - diff --git a/weaver/core/relay/README.md b/weaver/core/relay/README.md index af709ce41fc..f864902de82 100644 --- a/weaver/core/relay/README.md +++ b/weaver/core/relay/README.md @@ -49,6 +49,11 @@ Corda example: `localhost:9081/Corda_Network/localhost:10006#com.cordaSimpleApplication.flow.GetStateByKey:H` +## Logging +We use a simple logger for messaging. In the future we can use ``log4rs``to persist applicational log. +On the other hand, we persist message flow payloads, but we want to support the [gateway crash-recovery logging procedure](https://www.techrxiv.org/articles/preprint/HERMES_Fault-Tolerant_Middleware_for_Blockchain_Interoperability/14120291). + + ### Settings The `Settings.toml` file is used for storing configurations as well as acting as the remote relay discovery service. diff --git a/weaver/core/relay/config/Corda_Relay.toml b/weaver/core/relay/config/Corda_Relay.toml index ea47a431793..3d41dfc2b6b 100644 --- a/weaver/core/relay/config/Corda_Relay.toml +++ b/weaver/core/relay/config/Corda_Relay.toml @@ -5,6 +5,7 @@ hostname="localhost" db_path="db/Corda_Relay/requests" # This will be replaced by the task queue. remote_db_path="db/Corda_Relay/remote_request" +db_satp_path="db/Corda_Relay" # max retries opening sled db if it is locked db_open_max_retries=500 # retry back off time in ms if sled db is locked diff --git a/weaver/core/relay/config/Corda_Relay2.toml b/weaver/core/relay/config/Corda_Relay2.toml index 84293fe036c..172dfa4c91a 100644 --- a/weaver/core/relay/config/Corda_Relay2.toml +++ b/weaver/core/relay/config/Corda_Relay2.toml @@ -5,6 +5,7 @@ hostname="localhost" db_path="db/Corda_Relay2/requests" # This will be replaced by the task queue. remote_db_path="db/Corda_Relay2/remote_request" +db_satp_path="db/Corda_Relay2" # max retries opening sled db if it is locked db_open_max_retries=500 # retry back off time in ms if sled db is locked diff --git a/weaver/core/relay/config/Dummy_Relay.toml b/weaver/core/relay/config/Dummy_Relay.toml index 5d68da94403..125d18af270 100644 --- a/weaver/core/relay/config/Dummy_Relay.toml +++ b/weaver/core/relay/config/Dummy_Relay.toml @@ -4,6 +4,7 @@ hostname="localhost" db_path="db/Dummy_Relay/requests" # This will be replaced by the task queue. remote_db_path="db/Dummy_Relay/remote_request" +db_satp_path="db/Dummy_Relay" # max retries opening sled db if it is locked db_open_max_retries=500 # retry back off time in ms if sled db is locked diff --git a/weaver/core/relay/config/Dummy_Relay_tls.toml b/weaver/core/relay/config/Dummy_Relay_tls.toml index 17677e6f2c0..fd191ff93fc 100644 --- a/weaver/core/relay/config/Dummy_Relay_tls.toml +++ b/weaver/core/relay/config/Dummy_Relay_tls.toml @@ -4,6 +4,7 @@ hostname="localhost" db_path="db/Dummy_Relay_tls/requests" # This will be replaced by the task queue. remote_db_path="db/Dummy_Relay_tls/remote_request" +db_satp_path="db/Dummy_Relay_tls" # max retries opening sled db if it is locked db_open_max_retries=500 # retry back off time in ms if sled db is locked diff --git a/weaver/core/relay/config/Fabric_Relay.toml b/weaver/core/relay/config/Fabric_Relay.toml index 98536a597df..aabe72b2a84 100644 --- a/weaver/core/relay/config/Fabric_Relay.toml +++ b/weaver/core/relay/config/Fabric_Relay.toml @@ -4,6 +4,7 @@ hostname="localhost" db_path="db/Fabric_Relay/requests" # This will be replaced by the task queue. remote_db_path="db/Fabric_Relay/remote_request" +db_satp_path="db/Fabric_Relay" # max retries opening sled db if it is locked db_open_max_retries=500 # retry back off time in ms if sled db is locked diff --git a/weaver/core/relay/config/Fabric_Relay2.toml b/weaver/core/relay/config/Fabric_Relay2.toml index 995f7250e84..c7449f72e15 100644 --- a/weaver/core/relay/config/Fabric_Relay2.toml +++ b/weaver/core/relay/config/Fabric_Relay2.toml @@ -4,6 +4,7 @@ hostname="localhost" db_path="db/Fabric_Relay2/requests" # This will be replaced by the task queue. remote_db_path="db/Fabric_Relay2/remote_request" +db_satp_path="db/Fabric_Relay2" # max retries opening sled db if it is locked db_open_max_retries=500 # retry back off time in ms if sled db is locked diff --git a/weaver/core/relay/config/Settings.toml b/weaver/core/relay/config/Settings.toml index 4628dba61fd..6299bce1198 100644 --- a/weaver/core/relay/config/Settings.toml +++ b/weaver/core/relay/config/Settings.toml @@ -4,6 +4,7 @@ hostname="localhost" db_path="db/requests" # This will be replaced by the task queue. remote_db_path="db/remote_requests" +db_satp_path="db" # max retries opening sled db if it is locked db_open_max_retries=500 # retry back off time in ms if sled db is locked diff --git a/weaver/core/relay/docs/README.md b/weaver/core/relay/docs/README.md new file mode 100644 index 00000000000..16d1cd21272 --- /dev/null +++ b/weaver/core/relay/docs/README.md @@ -0,0 +1,155 @@ +# SATP Gateway + +The Weaver rely has been augmented to include the SATP implementation. Here are the steps to run and test this implementation: + +## Run two test Fabric networks +``` +$ cd weaver/tests/network-setups/fabric/dev +$ make start-interop-local CHAINCODE_NAME=satpsimpleasset +``` + +## Run the gateway + +Before running the gateway, you need to ensure SQLite (the default database for logs) is installed: + +``` +sudo apt-get update +sudo apt-get install libsqlite3-dev +``` + +Use your favorite tool to create a SQLite database named 'gateway_log.db' and create the following table: +``` +CREATE TABLE log_entries ( + id INTEGER PRIMARY KEY, + debug_level TEXT, + timestamp TEXT, + request_id TEXT, + request TEXT, + step_id TEXT, + operation TEXT, + network_id TEXT, + gateway_id TEXT, + received TEXT, + details TEXT +); +``` + +In a new terminal, run the following commands: +``` +$ cd weaver/core/relay +$ RELAY_CONFIG=config/Dummy_Relay.toml cargo run --bin server +``` + +## Run the Fabric driver + +Ensure that you have the correct configuration in the file .env +In a new terminal, run the following commands: + +``` +$ cd weaver/core/drivers/fabric-driver +$ cat .env + +CONNECTION_PROFILE=/home/user/cacti/weaver/tests/network-setups/fabric/network-artifacts/network1/peerOrganizations/org1.network1.com/connection-org1.json +RELAY_ENDPOINT=localhost:9085 +RELAY_TLS=false +RELAY_TLSCA_CERT_PATH=path_to_tls_ca_cert_pem_for_relay +DRIVER_ENDPOINT=localhost:9090 +DRIVER_TLS=false +DRIVER_TLS_CERT_PATH=path_to_tls_cert_pem_for_driver +DRIVER_TLS_KEY_PATH=path_to_tls_key_pem_for_driver +NETWORK_NAME=network1 +DRIVER_CONFIG= +INTEROP_CHAINCODE=interop +MOCK=false +DB_PATH=driverdbs +#WALLET_PATH=/home/user/cacti/weaver/samples/fabric/fabric-cli/src/wallet-network1 +WALLET_PATH=/home/user/cacti/weaver/core/drivers/fabric-driver/wallet-network1 +DEBUG=true +LEVELDB_LOCKED_MAX_RETRIES= +LEVELDB_LOCKED_RETRY_BACKOFF_MSEC= +ENABLE_MONITOR=false +MONITOR_SYNC_PERIOD= +MEMBER_CREDENTIAL_FOLDER=/home/user/cacti/weaver/samples/fabric/fabric-cli/src/data/credentials +CONFIG_PATH=/home/user/cacti/weaver/samples/fabric/fabric-cli/config.json +DEFAULT_APPLICATION_CHAINCODE=simpleassettransfer +REMOTE_CONFIG_PATH=/home/user/cacti/weaver/samples/fabric/fabric-cli/remote-network-config.json +CHAINCODE_PATH=/home/user/cacti/weaver/samples/fabric/fabric-cli/chaincode.json + +``` + +Run the driver + +``` +$ cd weaver/core/drivers/fabric-driver +$ make build-local +$ npm run dev +``` + +# Build the satpsimpleasset chaincode + +In a new terminal, run the following commands: + +``` +$ cd weaver/samples/fabric/satpsimpleasset +$ make build-local +``` + +# Run the Fabric cli + +The Fabric-cli could be used for creating testing assets. Ensure you have the correct configuration. In a new terminal, run the following commands: + +``` +$ cd weaver/samples/fabric/fabric-cli +$ cat config.json + +{ + "network1": { + "connProfilePath": "/home/user/cacti/weaver/tests/network-setups/fabric/network-artifacts/network1/peerOrganizations/org1.network1.com/connection-org1.json", + "relayEndpoint": "localhost:9080", + "mspId": "Org1MSP", + "channelName": "mychannel", + "chaincode": "satpsimpleasset", + "aclPolicyPrincipalType": "ca" + }, + "network2": { + "connProfilePath": "/home/user/cacti/weaver/tests/network-setups/fabric/network-artifacts/network2/peerOrganizations/org1.network2.com/connection-org1.json", + "relayEndpoint": "localhost:9083", + "mspId": "Org1MSP", + "channelName": "mychannel", + "chaincode": "satpsimpleasset", + "aclPolicyPrincipalType": "certificate" + } +} +``` + +Create sample assets: + +``` +$ cd weaver/samples/fabric/fabric-cli +$ ./bin/fabric-cli configure asset add --target-network=network1 --type=bond --data-file=./src/data/assets.json + +``` + +Ensure Alice and Bob ids are available: + +``` +$~/cacti/weaver/samples/fabric/fabric-cli/src/wallet-network1$ cp alice.id /home/user/cacti/weaver/core/drivers/fabric-driver/wallet-network1 +$~/cacti/weaver/samples/fabric/fabric-cli/src/wallet-network1$ cp bob.id /home/user/cacti/weaver/core/drivers/fabric-driver/wallet-network1 +$~/cacti/weaver/samples/fabric/fabric-cli/src/wallet-network1$ cd ../wallet-network2 +$~/cacti/weaver/samples/fabric/fabric-cli/src/wallet-network2$ cp alice.id /home/user/cacti/weaver/core/drivers/fabric-driver/wallet-network2 +$~/cacti/weaver/samples/fabric/fabric-cli/src/wallet-network2$ cp bob.id /home/user/cacti/weaver/core/drivers/fabric-driver/wallet-network2 + +``` + +## Run the client + +This client will trigger the SATP protocol by sending an asset transfer request. In a new terminal, run the following commands: + +``` +$ cd weaver/core/relay +$ cargo run --bin satp_client "9085" "localhost:9085/Dummy_Network/abc:abc:abc:abc" + +``` + +You should noticed that the messages started to be exchanged between the two gateways. The logs can be seen in the corresponding terminals. + diff --git a/weaver/core/relay/driver/driver.rs b/weaver/core/relay/driver/driver.rs index 9e4bc76150e..8d3005d1b8c 100644 --- a/weaver/core/relay/driver/driver.rs +++ b/weaver/core/relay/driver/driver.rs @@ -6,11 +6,16 @@ // Internal modules use weaverpb::common::ack::{ack, Ack}; -use weaverpb::common::query::Query; use weaverpb::common::events::EventSubscription; -use weaverpb::common::state::{view_payload, Meta, meta, ViewPayload, View}; -use weaverpb::driver::driver::driver_communication_server::{DriverCommunication, DriverCommunicationServer}; -use weaverpb::driver::driver::WriteExternalStateMessage; +use weaverpb::common::query::Query; +use weaverpb::common::state::{meta, view_payload, Meta, View, ViewPayload}; +use weaverpb::driver::driver::driver_communication_server::{ + DriverCommunication, DriverCommunicationServer, +}; +use weaverpb::driver::driver::{ + AssignAssetRequest, CreateAssetRequest, ExtinguishRequest, PerformLockRequest, + WriteExternalStateMessage, +}; use weaverpb::relay::datatransfer::data_transfer_client::DataTransferClient; use weaverpb::relay::events::event_subscribe_client::EventSubscribeClient; @@ -22,8 +27,10 @@ use std::net::ToSocketAddrs; use std::thread::sleep; use std::time; use tokio::sync::RwLock; -use tonic::transport::{Identity, Server, ServerTlsConfig, Certificate, Channel, ClientTlsConfig}; +use tonic::transport::{Certificate, Channel, ClientTlsConfig, Identity, Server, ServerTlsConfig}; use tonic::{Request, Response, Status}; +use weaverpb::relay::satp::satp_client::SatpClient; +use weaverpb::relay::satp::SendAssetStatusRequest; pub struct DriverCommunicationService { pub config_lock: RwLock, @@ -42,7 +49,7 @@ impl DriverCommunication for DriverCommunicationService { println!("Got a request from {:?}", request.remote_addr()); let query = request.into_inner().clone(); let request_id = query.request_id.to_string(); - + let relays_table = self .config_lock .read() @@ -52,16 +59,18 @@ impl DriverCommunication for DriverCommunicationService { let relay_uri = relays_table .get(&query.requesting_relay.to_string()) .expect("Requesting relay not found in config file relays table"); - let uri = relay_uri.clone().try_into::() + let uri = relay_uri + .clone() + .try_into::() .expect("Syntax for relays table in config file not correct"); let relay_port = uri.port.to_string(); let relay_hostname = uri.hostname.to_string(); let use_tls = uri.tls; let tlsca_cert_path = uri.tlsca_cert_path.to_string(); - + let client_addr = format!("http://{}:{}", relay_hostname, relay_port); + if use_tls { - let client_addr = format!("https://{}:{}", relay_hostname, relay_port); let pem = tokio::fs::read(tlsca_cert_path).await.unwrap(); let ca = Certificate::from_pem(pem); @@ -69,8 +78,13 @@ impl DriverCommunication for DriverCommunicationService { .ca_certificate(ca) .domain_name(relay_hostname); - let channel = Channel::from_shared(client_addr.to_string()).unwrap() - .tls_config(tls).expect(&format!("Error in TLS configuration for client: {}", client_addr.to_string())) + let channel = Channel::from_shared(client_addr.to_string()) + .unwrap() + .tls_config(tls) + .expect(&format!( + "Error in TLS configuration for client: {}", + client_addr.to_string() + )) .connect() .await .unwrap(); @@ -100,8 +114,14 @@ impl DriverCommunication for DriverCommunicationService { return Ok(Response::new(reply)); } - async fn subscribe_event(&self, request: Request) -> Result, Status> { - println!("Driver: Got a event subscription request from {:?}", request.remote_addr()); + async fn subscribe_event( + &self, + request: Request, + ) -> Result, Status> { + println!( + "Driver: Got a event subscription request from {:?}", + request.remote_addr() + ); let into_inner = request.into_inner().clone(); let query = into_inner.query.clone().expect(""); let request_id = query.clone().request_id.to_string(); @@ -115,9 +135,11 @@ impl DriverCommunication for DriverCommunicationService { let relay_uri = relays_table .get(&query.requesting_relay.to_string()) .expect("Requesting relay not found in config file relays table"); - let uri = relay_uri.clone().try_into::() + let uri = relay_uri + .clone() + .try_into::() .expect("Syntax for relays table in config file not correct"); - + let relay_port = uri.port.to_string(); let relay_hostname = uri.hostname.to_string(); let use_tls = uri.tls; @@ -132,8 +154,13 @@ impl DriverCommunication for DriverCommunicationService { .ca_certificate(ca) .domain_name(relay_hostname); - let channel = Channel::from_shared(client_addr.to_string()).unwrap() - .tls_config(tls).expect(&format!("Error in TLS configuration for client: {}", client_addr.to_string())) + let channel = Channel::from_shared(client_addr.to_string()) + .unwrap() + .tls_config(tls) + .expect(&format!( + "Error in TLS configuration for client: {}", + client_addr.to_string() + )) .connect() .await .unwrap(); @@ -164,7 +191,10 @@ impl DriverCommunication for DriverCommunicationService { return Ok(Response::new(reply)); } - async fn request_signed_event_subscription_query(&self, request: Request) -> Result, Status> { + async fn request_signed_event_subscription_query( + &self, + request: Request, + ) -> Result, Status> { let received_query = request.into_inner().clone().query.expect("Err"); let signed_query: Query = Query { policy: received_query.policy, @@ -180,7 +210,10 @@ impl DriverCommunication for DriverCommunicationService { }; return Ok(Response::new(signed_query)); } - async fn write_external_state(&self, request: Request) -> Result, Status> { + async fn write_external_state( + &self, + request: Request, + ) -> Result, Status> { let view_payload = request.into_inner().view_payload.expect("Error"); let request_id = view_payload.clone().request_id.to_string(); match view_payload.state { @@ -201,7 +234,7 @@ impl DriverCommunication for DriverCommunicationService { }; return Ok(Response::new(reply)); } - } + }, None => {} } let reply_error = Ack { @@ -211,6 +244,123 @@ impl DriverCommunication for DriverCommunicationService { }; return Ok(Response::new(reply_error)); } + + async fn perform_lock( + &self, + request: Request, + ) -> Result, Status> { + println!("Got a request from {:?}", request.remote_addr()); + let perform_lock_request = request.into_inner().clone(); + println!("The asset has been locked"); + let request_id = perform_lock_request.session_id.to_string(); + + let relays_table = self + .config_lock + .read() + .await + .get_table("relays") + .expect("No relays table in config file"); + let requesting_relay = get_relay_from_perform_lock(perform_lock_request); + let relay_uri = relays_table + .get(&requesting_relay.to_string()) + .expect("Requesting relay not found in config file relays table"); + let uri = relay_uri + .clone() + .try_into::() + .expect("Syntax for relays table in config file not correct"); + + let relay_port = uri.port.to_string(); + let relay_hostname = uri.hostname.to_string(); + let use_tls = uri.tls; + let tlsca_cert_path = uri.tlsca_cert_path.to_string(); + let client_addr = format!("http://{}:{}", relay_hostname, relay_port); + + if use_tls { + let pem = tokio::fs::read(tlsca_cert_path).await.unwrap(); + let ca = Certificate::from_pem(pem); + + let tls = ClientTlsConfig::new() + .ca_certificate(ca) + .domain_name(relay_hostname); + + let channel = Channel::from_shared(client_addr.to_string()) + .unwrap() + .tls_config(tls) + .expect(&format!( + "Error in TLS configuration for client: {}", + client_addr.to_string() + )) + .connect() + .await + .unwrap(); + + let client = SatpClient::new(channel); + send_driver_mock_send_asset_status_helper(client, request_id.to_string()); + } else { + let client_result = SatpClient::connect(client_addr).await; + match client_result { + Ok(client) => { + // Sends Mocked payload back. + send_driver_mock_send_asset_status_helper(client, request_id.to_string()); + } + Err(e) => { + // TODO: Add better error handling (Attempt a few times?) + panic!("Failed to connect to client. Error: {}", e.to_string()); + } + } + } + + let reply = Ack { + status: ack::Status::Ok as i32, + request_id: request_id, + message: "".to_string(), + }; + return Ok(Response::new(reply)); + } + + async fn create_asset( + &self, + _request: Request, + ) -> Result, Status> { + // TODO + let reply = Ack { + status: ack::Status::Ok as i32, + request_id: "".to_string(), + message: "".to_string(), + }; + return Ok(Response::new(reply)); + } + + async fn extinguish( + &self, + _request: Request, + ) -> Result, Status> { + // TODO + let reply = Ack { + status: ack::Status::Ok as i32, + request_id: "".to_string(), + message: "".to_string(), + }; + return Ok(Response::new(reply)); + } + + async fn assign_asset( + &self, + _request: Request, + ) -> Result, Status> { + // TODO + let reply = Ack { + status: ack::Status::Ok as i32, + request_id: "".to_string(), + message: "".to_string(), + }; + return Ok(Response::new(reply)); + } +} + +pub fn get_relay_from_perform_lock(perform_lock_request: PerformLockRequest) -> String { + // TODO + return "Dummy_Relay".to_string(); } fn send_driver_mock_state_helper(client: DataTransferClient, request_id: String) { @@ -223,7 +373,7 @@ fn send_driver_mock_state_helper(client: DataTransferClient, request_id timestamp: "I am time".to_string(), proof_type: "I am proof".to_string(), serialization_format: "Proto".to_string(), - protocol: meta::Protocol::Fabric as i32 + protocol: meta::Protocol::Fabric as i32, }), data: "This is a mocked payload".as_bytes().to_vec(), })), @@ -234,7 +384,10 @@ fn send_driver_mock_state_helper(client: DataTransferClient, request_id println!("Ack from remote relay={:?}", response); }); } -fn send_driver_mock_subscription_state_helper(client: EventSubscribeClient, request_id: String) { +fn send_driver_mock_subscription_state_helper( + client: EventSubscribeClient, + request_id: String, +) { tokio::spawn(async move { let my_time = time::Duration::from_millis(3000); sleep(my_time); @@ -249,6 +402,31 @@ fn send_driver_mock_subscription_state_helper(client: EventSubscribeClient, request_id: String) { + tokio::spawn(async move { + let my_time = time::Duration::from_millis(3000); + sleep(my_time); + + let send_asset_status_request = SendAssetStatusRequest { + message_type: "message_type1".to_string(), + session_id: "session_id1".to_string(), + transfer_context_id: "transfer_context_id1".to_string(), + client_identity_pubkey: "client_identity_pubkey1".to_string(), + server_identity_pubkey: "server_identity_pubkey1".to_string(), + hash_prev_message: "hash_prev_message1".to_string(), + server_transfer_number: "server_transfer_number1".to_string(), + server_signature: "server_signature1".to_string(), + status: "status1".to_string(), + }; + println!("Sending send asset status request to remote gateway ..."); + let response = client + .clone() + .send_asset_status(send_asset_status_request) + .await; + println!("Ack from remote relay={:?}", response); + }); +} + #[tokio::main] async fn main() -> Result<(), Box> { // NOTE: This will need cleaning up @@ -285,7 +463,7 @@ async fn main() -> Result<(), Box> { .to_socket_addrs()? .next() .expect("Port number is potentially invalid. Unable to create SocketAddr"); - + let driver = DriverCommunicationService { config_lock: RwLock::new(settings.clone()), }; @@ -300,11 +478,11 @@ async fn main() -> Result<(), Box> { .tls_config(ServerTlsConfig::new().identity(identity))? .add_service(DriverCommunicationServer::new(driver)); server.serve(addr).await?; - } else { println!("DriverServer listening on {}", addr); // Spins up two gRPC services in a tonic server. One for relay to relay and one for network to relay communication. - let server = Server::builder().add_service(DriverCommunicationServer::new(driver)); + let server = + Server::builder().add_service(DriverCommunicationServer::new(driver)); server.serve(addr).await?; } } diff --git a/weaver/core/relay/src/main.rs b/weaver/core/relay/src/main.rs index 79b02cd58b4..0b2caeebddf 100644 --- a/weaver/core/relay/src/main.rs +++ b/weaver/core/relay/src/main.rs @@ -2,16 +2,19 @@ // // SPDX-License-Identifier: Apache-2.0 +use log::debug; +use log::info; // Internal generated modules use weaverpb::networks::networks::network_server::NetworkServer; use weaverpb::relay::datatransfer::data_transfer_server::DataTransferServer; -use weaverpb::relay::events::event_subscribe_server::EventSubscribeServer; use weaverpb::relay::events::event_publish_server::EventPublishServer; +use weaverpb::relay::events::event_subscribe_server::EventSubscribeServer; +use weaverpb::relay::satp::satp_server::SatpServer; // Internal modules use services::data_transfer_service::DataTransferService; -use services::event_subscribe_service::EventSubscribeService; use services::event_publish_service::EventPublishService; +use services::event_subscribe_service::EventSubscribeService; use services::network_service::NetworkService; // External modules @@ -22,20 +25,45 @@ use std::net::ToSocketAddrs; use tokio::sync::RwLock; use tonic::transport::{Identity, Server, ServerTlsConfig}; +use crate::services::satp_service::SatpService; +use lazy_static::lazy_static; +use crate::services::logger::DbLogger; + mod db; mod error; mod relay_proto; mod services; +const SQLITE_DATABASE_FILE: &str = "gateway_log.db"; +lazy_static! { + static ref DB_LOGGER: DbLogger = DbLogger::new(SQLITE_DATABASE_FILE); +} + #[tokio::main] async fn main() -> Result<(), Box> { + log::set_logger(&*DB_LOGGER) + // TODO: database name and debug level should be configurable + .map(|()| log::set_max_level(log::LevelFilter::Debug)) + .expect("Logger should not have been set up yet"); + let mut settings = config::Config::default(); // Either get config path from environment variable or uses default. let config_file_name = env::var("RELAY_CONFIG").unwrap_or_else(|_| { println!("Using default config `config/Settings`"); "config/Settings".to_string() }); + let log_level = env::var("RUST_LOG").unwrap_or_else(|_| { + println!("Using default log level"); + return "debug".to_string(); + }); + println!("Log level: {}", log_level); + // Set the RUST_LOG environment variable + env::set_var("RUST_LOG", &log_level); + + // // Initialize the logger + // env_logger::init(); + settings .merge(config::File::with_name(&config_file_name)) .unwrap() @@ -44,9 +72,11 @@ async fn main() -> Result<(), Box> { .unwrap(); let relay_name = settings.get_str("name").expect("No Relay name provided"); - println!("Relay Name: {:?}", relay_name); + info!("Relay Name: {:?}", relay_name); let relay_port = settings.get_str("port").expect(&format!("Port does not exist for relay name {}. Make sure the config file <{}> has the name and port specified.", relay_name, config_file_name.to_string())); - let host = settings.get_str("hostname").unwrap_or("localhost".to_string()); + let host = settings + .get_str("hostname") + .unwrap_or("localhost".to_string()); let with_tls = settings.get_bool("tls").unwrap_or(false); // Converts port to a valid socket address @@ -58,6 +88,9 @@ async fn main() -> Result<(), Box> { let relay = DataTransferService { config_lock: RwLock::new(settings.clone()), }; + let gateway = SatpService { + config_lock: RwLock::new(settings.clone()), + }; let event_subscribe = EventSubscribeService { config_lock: RwLock::new(settings.clone()), }; @@ -67,9 +100,9 @@ async fn main() -> Result<(), Box> { let network = NetworkService { config_lock: RwLock::new(settings.clone()), }; - println!("RelayServer listening on {}", addr); + info!("RelayServer listening on {}", addr); if with_tls == true { - println!("Starting Server with TLS"); + debug!("Starting Server with TLS"); let cert = tokio::fs::read(settings.get_str("cert_path").unwrap()).await?; let key = tokio::fs::read(settings.get_str("key_path").unwrap()).await?; let identity = Identity::from_pem(cert, key); @@ -77,6 +110,7 @@ async fn main() -> Result<(), Box> { let server = Server::builder() .tls_config(ServerTlsConfig::new().identity(identity))? .add_service(DataTransferServer::new(relay)) + .add_service(SatpServer::new(gateway)) .add_service(EventSubscribeServer::new(event_subscribe)) .add_service(EventPublishServer::new(event_publish)) .add_service(NetworkServer::new(network)); @@ -85,6 +119,7 @@ async fn main() -> Result<(), Box> { // Spins up two gRPC services in a tonic server. One for relay to relay and one for network to relay communication. let server = Server::builder() .add_service(DataTransferServer::new(relay)) + .add_service(SatpServer::new(gateway)) .add_service(EventSubscribeServer::new(event_subscribe)) .add_service(EventPublishServer::new(event_publish)) .add_service(NetworkServer::new(network)); diff --git a/weaver/core/relay/src/satp_client.rs b/weaver/core/relay/src/satp_client.rs new file mode 100644 index 00000000000..84bedb7f2c5 --- /dev/null +++ b/weaver/core/relay/src/satp_client.rs @@ -0,0 +1,52 @@ +mod relay_proto; +use relay_proto::get_url; +use std::env; +use weaverpb::common::ack::ack; +use weaverpb::networks::networks::{network_client::NetworkClient, NetworkAssetTransfer}; + +#[tokio::main] +async fn main() -> Result<(), Box> { + println!("\nAsset Transfer Test"); + asset_transfer().await?; + Ok(()) +} + +async fn asset_transfer() -> Result<(), Box> { + let args: Vec = env::args().collect(); + let net_addr = format!("http://{}", get_url(&args)); + let mut network_client = NetworkClient::connect(net_addr).await?; + // localhost:9081/Corda_Network/test + // {locationsegment}/{Network_id}/{query} + // localhost:9081/Corda_Network/mychannel:simplestate:read:TestState + let request = tonic::Request::new(NetworkAssetTransfer { + policy: vec!["test".to_string()], + address: args[2].to_string(), + requesting_relay: "Dummy_relay".to_string(), + requesting_network: "".to_string(), + requesting_org: "".to_string(), + certificate: "test".to_string(), + requestor_signature: "test".to_string(), + nonce: "test".to_string(), + confidential: false, + }); + let response = network_client.request_asset_transfer(request).await?; + println!("RESPONSE={:?}", response); + + match ack::Status::from_i32(response.get_ref().status) { + Some(ack_status) => match ack_status { + ack::Status::Ok => { + // TODO poll for asset transfer status + println!("Asset Transfer: Success!"); + } + ack::Status::Error => { + println!("An error occurred in request_asset_transfer call"); + std::process::exit(1); + } + }, + None => { + println!("The returned Ack has no status"); + std::process::exit(1); + } + } + Ok(()) +} diff --git a/weaver/core/relay/src/services/constants.rs b/weaver/core/relay/src/services/constants.rs new file mode 100644 index 00000000000..e69de29bb2d diff --git a/weaver/core/relay/src/services/helpers.rs b/weaver/core/relay/src/services/helpers.rs index aa4479ce518..d852bcc9fd8 100644 --- a/weaver/core/relay/src/services/helpers.rs +++ b/weaver/core/relay/src/services/helpers.rs @@ -1,21 +1,18 @@ -// Copyright IBM Corp. All Rights Reserved. -// -// SPDX-License-Identifier: Apache-2.0 - -use weaverpb::common::ack::{ack}; +use colored::Colorize; +use weaverpb::common::ack::ack; +use weaverpb::common::events::{event_subscription_state, EventSubscriptionState}; +use weaverpb::common::events::{EventPublication, EventState, EventStates, EventSubscription}; use weaverpb::common::query::Query; use weaverpb::common::state::{request_state, RequestState}; -use weaverpb::common::events::{event_subscription_state, EventSubscriptionState}; -use weaverpb::common::events::{EventSubscription, EventStates, EventState, EventPublication}; use weaverpb::driver::driver::driver_communication_client::DriverCommunicationClient; use crate::db::Database; -use crate::services::types::{Driver, Network}; use crate::error::Error; +use crate::services::types::{Driver, Network}; use config; -use tonic::transport::{Certificate, Channel, ClientTlsConfig}; use std::fs; +use tonic::transport::{Certificate, Channel, ClientTlsConfig}; // Locally scoped function to update request status in db. This function is // called for the first time after an Ack is received from the remote relay. @@ -30,11 +27,20 @@ pub fn update_event_subscription_status( db_open_retry_backoff_msec: u32, message: String, ) { - let driver_error_constants = fs::read_to_string("./driver/driver-error-constants.json").expect("Unable to read file: ./driver/driver-error-constants.json"); + let driver_error_constants = fs::read_to_string("./driver/driver-error-constants.json") + .expect("Unable to read file: ./driver/driver-error-constants.json"); let driver_error_constants_json: serde_json::Value = serde_json::from_str(&driver_error_constants).expect("JSON was not well-formatted"); - let driver_sub_exists_error = driver_error_constants_json.get("SUB_EXISTS").unwrap().as_str().unwrap(); - let driver_sub_exists_error_without_args = *(driver_sub_exists_error.split("{0}").collect::>().first().unwrap()); + let driver_sub_exists_error = driver_error_constants_json + .get("SUB_EXISTS") + .unwrap() + .as_str() + .unwrap(); + let driver_sub_exists_error_without_args = *(driver_sub_exists_error + .split("{0}") + .collect::>() + .first() + .unwrap()); let db = Database { db_path: curr_db_path, @@ -53,42 +59,52 @@ pub fn update_event_subscription_status( target = EventSubscriptionState { status: event_subscription_state::Status::UnsubscribePending as i32, request_id: curr_request_id.clone(), - publishing_request_id: fetched_event_sub_state.publishing_request_id.to_string(), + publishing_request_id: fetched_event_sub_state + .publishing_request_id + .to_string(), message: message.to_string(), event_matcher: fetched_event_sub_state.event_matcher, - event_publication_specs: fetched_event_sub_state.event_publication_specs + event_publication_specs: fetched_event_sub_state + .event_publication_specs, }; - }, + } event_subscription_state::Status::UnsubscribePending => { target = EventSubscriptionState { status: event_subscription_state::Status::Unsubscribed as i32, request_id: curr_request_id.clone(), - publishing_request_id: fetched_event_sub_state.publishing_request_id.to_string(), + publishing_request_id: fetched_event_sub_state + .publishing_request_id + .to_string(), message: message.to_string(), event_matcher: fetched_event_sub_state.event_matcher, - event_publication_specs: fetched_event_sub_state.event_publication_specs + event_publication_specs: fetched_event_sub_state + .event_publication_specs, }; - }, - event_subscription_state::Status::SubscribePendingAck => { + } + event_subscription_state::Status::SubscribePendingAck => { target = EventSubscriptionState { status: event_subscription_state::Status::SubscribePending as i32, request_id: curr_request_id.clone(), publishing_request_id: "".to_string(), message: message.to_string(), event_matcher: fetched_event_sub_state.event_matcher.clone(), - event_publication_specs: fetched_event_sub_state.event_publication_specs.clone(), + event_publication_specs: fetched_event_sub_state + .event_publication_specs + .clone(), }; - }, - event_subscription_state::Status::SubscribePending => { + } + event_subscription_state::Status::SubscribePending => { target = EventSubscriptionState { status: event_subscription_state::Status::Subscribed as i32, request_id: curr_request_id.clone(), publishing_request_id: curr_request_id.clone(), message: message.to_string(), event_matcher: fetched_event_sub_state.event_matcher.clone(), - event_publication_specs: fetched_event_sub_state.event_publication_specs.clone(), + event_publication_specs: fetched_event_sub_state + .event_publication_specs + .clone(), }; - }, + } _ => { target = EventSubscriptionState { status: event_subscription_state::Status::Error as i32, @@ -96,9 +112,11 @@ pub fn update_event_subscription_status( publishing_request_id: "".to_string(), message: "Status is not supported or is invalid".to_string(), event_matcher: fetched_event_sub_state.event_matcher.clone(), - event_publication_specs: fetched_event_sub_state.event_publication_specs.clone(), + event_publication_specs: fetched_event_sub_state + .event_publication_specs + .clone(), }; - }, + } }, None => { target = EventSubscriptionState { @@ -107,41 +125,61 @@ pub fn update_event_subscription_status( publishing_request_id: "".to_string(), message: "No event subscription status set in database".to_string(), event_matcher: fetched_event_sub_state.event_matcher.clone(), - event_publication_specs: fetched_event_sub_state.event_publication_specs.clone(), + event_publication_specs: fetched_event_sub_state + .event_publication_specs + .clone(), }; - }, + } } } else { match message.find(driver_sub_exists_error_without_args) { Some(_index) => { - let old_request_id = *(message.split(driver_sub_exists_error_without_args).collect::>().last().unwrap()); + let old_request_id = *(message + .split(driver_sub_exists_error_without_args) + .collect::>() + .last() + .unwrap()); println!("Adding event publication spec to existing EventSubscriptionState. Extracted request id from message: {}", old_request_id.to_string()); - let old_event_sub_key = get_event_subscription_key(old_request_id.to_string()); - let mut existing_event_sub_state = db.get::(old_event_sub_key.to_string()) - .expect(&format!("No EventSubscriptionState found in DB for request_id provided {}", old_request_id.to_string())); - - let new_event_pub_spec = fetched_event_sub_state.event_publication_specs.first().unwrap(); + let old_event_sub_key = + get_event_subscription_key(old_request_id.to_string()); + let mut existing_event_sub_state = db + .get::(old_event_sub_key.to_string()) + .expect(&format!( + "No EventSubscriptionState found in DB for request_id provided {}", + old_request_id.to_string() + )); + + let new_event_pub_spec = fetched_event_sub_state + .event_publication_specs + .first() + .unwrap(); let mut unique_pub_spec_flag = true; - for event_pub_spec in existing_event_sub_state.event_publication_specs.iter() { + for event_pub_spec in + existing_event_sub_state.event_publication_specs.iter() + { if *new_event_pub_spec == *event_pub_spec { unique_pub_spec_flag = false; break; } } if unique_pub_spec_flag { - existing_event_sub_state.event_publication_specs.push((*new_event_pub_spec).clone()); + existing_event_sub_state + .event_publication_specs + .push((*new_event_pub_spec).clone()); let updated_event_sub_state = EventSubscriptionState { status: event_subscription_state::Status::Subscribed as i32, request_id: old_request_id.to_string(), publishing_request_id: old_request_id.to_string(), message: existing_event_sub_state.message.to_string(), event_matcher: existing_event_sub_state.event_matcher.clone(), - event_publication_specs: existing_event_sub_state.event_publication_specs.clone(), + event_publication_specs: existing_event_sub_state + .event_publication_specs + .clone(), }; db.set(&old_event_sub_key.to_string(), &updated_event_sub_state) .expect("Failed to insert into DB"); - + target = EventSubscriptionState { status: event_subscription_state::Status::DuplicateQuerySubscribed as i32, request_id: curr_request_id.clone(), @@ -157,10 +195,12 @@ pub fn update_event_subscription_status( publishing_request_id: "".to_string(), message: message.to_string(), event_matcher: fetched_event_sub_state.event_matcher.clone(), - event_publication_specs: fetched_event_sub_state.event_publication_specs.clone(), + event_publication_specs: fetched_event_sub_state + .event_publication_specs + .clone(), } }; - }, + } None => { target = EventSubscriptionState { status: event_subscription_state::Status::Error as i32, @@ -168,28 +208,31 @@ pub fn update_event_subscription_status( publishing_request_id: "".to_string(), message: message.to_string(), event_matcher: fetched_event_sub_state.event_matcher.clone(), - event_publication_specs: fetched_event_sub_state.event_publication_specs.clone(), + event_publication_specs: fetched_event_sub_state + .event_publication_specs + .clone(), }; } } } - + // Panic if this fails, atm the panic is just logged by the tokio runtime db.set(&event_sub_key.to_string(), &target) .expect("Failed to insert into DB"); println!("Successfully written EventSubscriptionState to database"); - println!("{:?}\n", db.get::(event_sub_key.to_string()).unwrap()) - }, + println!( + "{:?}\n", + db.get::(event_sub_key.to_string()) + .unwrap() + ) + } Err(e) => { println!("EventSubscription Request not found. Error: {:?}", e); - }, + } } } -pub fn get_driver( - network_id: String, - conf: config::Config, -) -> Result { +pub fn get_driver(network_id: String, conf: config::Config) -> Result { // get the driver type from the networks map let networks_table = conf .get_table("networks") @@ -239,7 +282,8 @@ pub async fn get_driver_client( .ca_certificate(ca) .domain_name(hostname); - let channel = Channel::from_shared(driver_address).unwrap() + let channel = Channel::from_shared(driver_address) + .unwrap() .tls_config(tls)? .connect() .await @@ -250,10 +294,9 @@ pub async fn get_driver_client( let driver_address = format!("http://{}:{}", hostname, port); client = DriverCommunicationClient::connect(driver_address).await?; } - return Ok(client) + return Ok(client); } - pub async fn driver_sign_subscription_helper( event_subscription: EventSubscription, request_id: String, @@ -264,7 +307,10 @@ pub async fn driver_sign_subscription_helper( match result { Ok(driver_info) => { let client = get_driver_client(driver_info).await?; - println!("Sending Sign EventSubscription Request to driver: {:?}", event_subscription.clone()); + println!( + "Sending Sign EventSubscription Request to driver: {:?}", + event_subscription.clone() + ); let signed_query = client .clone() .request_signed_event_subscription_query(event_subscription) @@ -272,10 +318,13 @@ pub async fn driver_sign_subscription_helper( .into_inner(); if signed_query.clone().request_id.to_string() == request_id.to_string() { println!("Signed Query Response from driver={:?}\n", signed_query); - return Ok(signed_query) + return Ok(signed_query); } - Err(Error::Simple(format!("Error while requesting signature from driver: {:?}", signed_query))) - }, + Err(Error::Simple(format!( + "Error while requesting signature from driver: {:?}", + signed_query + ))) + } Err(e) => Err(e), } } @@ -312,8 +361,7 @@ pub fn update_event_state( message: message.to_string(), }; updated_event_states.push(new_event_state); - } - else { + } else { updated_event_states.push(fetched_event_state); } } @@ -321,17 +369,18 @@ pub fn update_event_state( db.set(&event_publish_key.to_string(), &updated_event_states) .expect("Failed to insert into DB"); println!("Successfully updated EventStates in database"); - }, + } Err(e) => { println!("EventStates not found. Error: {:?}", e); - }, + } } } pub fn try_mark_request_state_deleted(state: RequestState, request_id: String, db: Database) { let state_status = request_state::Status::from_i32(state.clone().status).expect("No Status"); - if state_status == request_state::Status::Error || - state_status == request_state::Status::Completed { + if state_status == request_state::Status::Error + || state_status == request_state::Status::Completed + { let deleted_request_state = RequestState { status: request_state::Status::Deleted as i32, request_id: request_id.to_string(), @@ -342,7 +391,12 @@ pub fn try_mark_request_state_deleted(state: RequestState, request_id: String, d } } -pub fn mark_event_states_deleted(fetched_event_states: EventStates, request_id: String, event_publish_key: String, db: Database) { +pub fn mark_event_states_deleted( + fetched_event_states: EventStates, + request_id: String, + event_publish_key: String, + db: Database, +) { let mut updated_event_states: Vec = Vec::new(); for fetched_event_state in fetched_event_states.states { let deleted_request_state = RequestState { @@ -357,7 +411,7 @@ pub fn mark_event_states_deleted(fetched_event_states: EventStates, request_id: }; updated_event_states.push(deleted_event_state); } - + db.set(&event_publish_key.to_string(), &updated_event_states) .expect("EventState Delete: Failed to insert into DB"); } @@ -382,11 +436,15 @@ pub fn delete_event_pub_spec( db_open_retry_backoff_msec: db_open_retry_backoff_msec, }; let mut event_sub_key = get_event_subscription_key(request_id.to_string()); - let mut event_sub_state = db.get::(event_sub_key.to_string()) - .expect(&format!("No EventSubscriptionState found in DB for request_id provided {}", request_id.to_string())); - + let mut event_sub_state = db + .get::(event_sub_key.to_string()) + .expect(&format!( + "No EventSubscriptionState found in DB for request_id provided {}", + request_id.to_string() + )); + let mut del_event_pub_spec = event_pub_spec; - + if event_sub_state.status == event_subscription_state::Status::DuplicateQuerySubscribed as i32 { let updated_state = EventSubscriptionState { status: event_subscription_state::Status::Unsubscribed as i32, @@ -394,18 +452,30 @@ pub fn delete_event_pub_spec( publishing_request_id: event_sub_state.publishing_request_id.to_string(), message: "Unsubscription successful".to_string(), event_matcher: event_sub_state.event_matcher, - event_publication_specs: event_sub_state.event_publication_specs + event_publication_specs: event_sub_state.event_publication_specs, }; db.set(&event_sub_key.to_string(), &updated_state) .expect("Failed to insert into DB"); - del_event_pub_spec = updated_state.clone().event_publication_specs.first().unwrap().clone(); - println!("Removed EventSubscriptionState from database: {:?}", updated_state); + del_event_pub_spec = updated_state + .clone() + .event_publication_specs + .first() + .unwrap() + .clone(); + println!( + "Removed EventSubscriptionState from database: {:?}", + updated_state + ); event_sub_key = get_event_subscription_key(updated_state.publishing_request_id.to_string()); - event_sub_state = db.get::(event_sub_key.to_string()) - .expect(&format!("No EventSubscriptionState found in DB for request_id provided {}", updated_state.publishing_request_id.to_string())); + event_sub_state = db + .get::(event_sub_key.to_string()) + .expect(&format!( + "No EventSubscriptionState found in DB for request_id provided {}", + updated_state.publishing_request_id.to_string() + )); } - + let mut flag = true; for (i, curr_event_pub_spec) in event_sub_state.event_publication_specs.iter().enumerate() { if *curr_event_pub_spec == del_event_pub_spec { @@ -423,13 +493,32 @@ pub fn delete_event_pub_spec( db.set(&event_sub_key.to_string(), &event_sub_state) .expect("Failed to insert into DB"); println!("Successfully deleted Event Publication from existing EventSubscriptionState from DB"); - + return 0; } pub fn get_event_subscription_key(request_id: String) -> String { return format!("event_sub_{}", request_id); } + pub fn get_event_publication_key(request_id: String) -> String { return format!("event_pub_{}", request_id); -} \ No newline at end of file +} + +pub fn println_stage_heading(stage_id: String) { + println!( + "{} {} {}", + "\n --------- Stage".yellow().bold(), + stage_id.yellow().bold(), + "started --------- \n".yellow().bold() + ); +} + +pub fn println_step_heading(step_id: String) { + println!( + "{} {} {}", + "\n --------- Step".bright_cyan().bold(), + step_id.bright_cyan().bold(), + " --------- \n".bright_cyan().bold() + ); +} diff --git a/weaver/core/relay/src/services/logger.rs b/weaver/core/relay/src/services/logger.rs new file mode 100644 index 00000000000..1aae635923e --- /dev/null +++ b/weaver/core/relay/src/services/logger.rs @@ -0,0 +1,94 @@ +use log::{Log, Metadata, Record}; +use rusqlite::Connection; +use serde::{Serialize, Deserialize}; +use std::sync::Mutex; + +#[derive(Serialize, Deserialize)] +pub struct LogEntry { + pub request_id: String, + pub request: String, + pub step_id: String, + pub operation: Operation, + pub network_id: String, + pub gateway_id: String, + pub received: bool, + pub details: Option, +} + +#[derive(Debug, Serialize, Deserialize)] +pub enum Operation { + Init, + Exec, + Done, + Failed, +} + +impl std::fmt::Display for Operation { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + match self { + Operation::Init => write!(f, "Init"), + Operation::Exec => write!(f, "Exec"), + Operation::Done => write!(f, "Done"), + Operation::Failed => write!(f, "Failed"), + } + } +} + +impl std::fmt::Display for LogEntry { + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + let json_str = serde_json::to_string(self).expect("Failed to serialize LogEntry to JSON"); + write!(f, "{}", json_str) + } +} + +pub(crate) struct DbLogger { + conn: Mutex, +} + +impl DbLogger { + pub fn new(database_path: &str) -> Self { + let conn = Connection::open(database_path).expect("Failed to open database"); + DbLogger { + conn: Mutex::new(conn), + } + } +} + +impl Log for DbLogger { + fn enabled(&self, _metadata: &Metadata) -> bool { + true + } + + fn log(&self, record: &Record) { + if self.enabled(record.metadata()) { + let conn = self.conn.lock().unwrap(); + + if let Ok(log_entry) = serde_json::from_str::(&record.args().to_string()) { + let mut details = "".to_string(); + if let Some(d) = log_entry.details.as_ref() { + details = d.to_string(); + } + + conn.execute( + "INSERT INTO log_entries (debug_level, timestamp, request_id, request, step_id, operation, gateway_id, received, details) VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9)", + &[ + &record.level().to_string(), // Log level + &format!("{}", chrono::Local::now()), // Timestamp + &log_entry.request_id, + &log_entry.request, + &log_entry.step_id, + &log_entry.operation.to_string(), + &log_entry.gateway_id, + &log_entry.received.to_string(), + &details, + ], + ) + .expect("Failed to insert log entry"); + + } + } + } + + fn flush(&self) {} +} + diff --git a/weaver/core/relay/src/services/mod.rs b/weaver/core/relay/src/services/mod.rs index fb36de980ea..ddd7dc195d0 100644 --- a/weaver/core/relay/src/services/mod.rs +++ b/weaver/core/relay/src/services/mod.rs @@ -3,8 +3,12 @@ // SPDX-License-Identifier: Apache-2.0 pub mod data_transfer_service; +pub mod satp_service; pub mod network_service; pub mod event_subscribe_service; pub mod event_publish_service; pub mod helpers; +pub mod satp_helper; pub mod types; +pub mod constants; +pub mod logger; \ No newline at end of file diff --git a/weaver/core/relay/src/services/network_service.rs b/weaver/core/relay/src/services/network_service.rs index d14dbeb59e5..8ad97302e73 100644 --- a/weaver/core/relay/src/services/network_service.rs +++ b/weaver/core/relay/src/services/network_service.rs @@ -3,21 +3,37 @@ // SPDX-License-Identifier: Apache-2.0 // Internal generated modules +use crate::relay_proto::{parse_address, LocationSegment}; use weaverpb::common::ack::{ack, Ack}; +use weaverpb::common::events::{ + event_publication, event_subscription_state, EventPublication, EventStates, EventSubOperation, + EventSubscription, EventSubscriptionState, +}; use weaverpb::common::query::Query; use weaverpb::common::state::{request_state, RequestState}; -use weaverpb::common::events::{EventSubscription, event_subscription_state, EventSubscriptionState, EventSubOperation, event_publication, EventPublication, EventStates}; use weaverpb::networks::networks::network_server::Network; -use weaverpb::networks::networks::{DbName, GetStateMessage, NetworkQuery, RelayDatabase, NetworkEventSubscription, NetworkEventUnsubscription}; +use weaverpb::networks::networks::{ + DbName, GetStateMessage, NetworkAssetTransfer, NetworkEventSubscription, + NetworkEventUnsubscription, NetworkQuery, RelayDatabase, +}; use weaverpb::relay::datatransfer::data_transfer_client::DataTransferClient; use weaverpb::relay::events::event_subscribe_client::EventSubscribeClient; -use crate::relay_proto::{parse_address, LocationSegment}; +use weaverpb::relay::satp::TransferProposalClaimsRequest; // Internal modules use crate::db::Database; -use crate::services::helpers::{update_event_subscription_status, driver_sign_subscription_helper, try_mark_request_state_deleted, mark_event_states_deleted, delete_event_pub_spec, get_event_publication_key, get_event_subscription_key}; +use crate::services::helpers::{ + delete_event_pub_spec, driver_sign_subscription_helper, get_event_publication_key, + get_event_subscription_key, mark_event_states_deleted, try_mark_request_state_deleted, + update_event_subscription_status, +}; +use crate::services::satp_helper::{ + create_transfer_proposal_claims_request, get_relay_from_transfer_proposal_claims, + get_relay_params, get_request_id_from_transfer_proposal_claims, + spawn_send_transfer_proposal_claims_request, +}; // External modules -use config; +use config::{self}; use sled::open; use tokio::sync::RwLock; use tonic::{Code, Request, Response, Status}; @@ -42,29 +58,38 @@ impl Network for NetworkService { let db = Database { db_path: conf.get_str("db_path").unwrap(), db_open_max_retries: conf.get_int("db_open_max_retries").unwrap_or(500) as u32, - db_open_retry_backoff_msec: conf.get_int("db_open_retry_backoff_msec").unwrap_or(10) as u32, + db_open_retry_backoff_msec: conf.get_int("db_open_retry_backoff_msec").unwrap_or(10) + as u32, }; let request_id = request.into_inner().request_id; let result = db.get::(request_id.to_string()); match result { Ok(request_state) => { - println!("Sending back RequestState to network: Request ID = {:?}, Status = {:?}", - request_state.request_id, - request_state.status - ); + println!( + "Sending back RequestState to network: Request ID = {:?}, Status = {:?}", + request_state.request_id, request_state.status + ); match request_state.state.as_ref() { Some(state) => { // Because already state is passed to client, deleting the state if status is completed or error - try_mark_request_state_deleted(request_state.clone(), request_id.to_string(), db); + try_mark_request_state_deleted( + request_state.clone(), + request_id.to_string(), + db, + ); match state { - request_state::State::View(v) => println!("View Meta: {:?}, View Data: {:?}", v.meta, base64::encode(&v.data)), + request_state::State::View(v) => println!( + "View Meta: {:?}, View Data: {:?}", + v.meta, + base64::encode(&v.data) + ), request_state::State::Error(e) => println!("Error: {:?}", e), } - }, - None => {}, + } + None => {} } return Ok(Response::new(request_state)); - }, + } Err(e) => Err(Status::new( Code::NotFound, format!("Request not found. Error: {:?}", e), @@ -85,7 +110,7 @@ impl Network for NetworkService { while let Some(key) = curr_key { // println!("{:?}", key); let decoded_key = std::str::from_utf8(&key.0[..]).unwrap(); - + if decoded_key.to_string().contains(&"event_sub".to_string()) { let decoded_result: Result = bincode::deserialize(&key.1[..]); @@ -130,7 +155,8 @@ impl Network for NetworkService { let db = Database { db_path: conf.get_str("db_path").unwrap(), db_open_max_retries: conf.get_int("db_open_max_retries").unwrap_or(500) as u32, - db_open_retry_backoff_msec: conf.get_int("db_open_retry_backoff_msec").unwrap_or(10) as u32, + db_open_retry_backoff_msec: conf.get_int("db_open_retry_backoff_msec").unwrap_or(10) + as u32, }; let request_id = Uuid::new_v4(); @@ -174,7 +200,7 @@ impl Network for NetworkService { network_query, request_id.to_string(), address.location.hostname.to_string(), - address.location.port.to_string() + address.location.port.to_string(), ); // Send Ack back to network while request is happening in a thread let reply = Ack { @@ -197,9 +223,12 @@ impl Network for NetworkService { } } } - + // Subscribe Event Endpoints - async fn subscribe_event(&self, request: Request) -> Result, Status> { + async fn subscribe_event( + &self, + request: Request, + ) -> Result, Status> { println!( "Got a Network Event Subscription request from {:?} - {:?}", request.remote_addr(), @@ -210,15 +239,21 @@ impl Network for NetworkService { let db = Database { db_path: conf.get_str("db_path").unwrap(), db_open_max_retries: conf.get_int("db_open_max_retries").unwrap_or(500) as u32, - db_open_retry_backoff_msec: conf.get_int("db_open_retry_backoff_msec").unwrap_or(10) as u32, + db_open_retry_backoff_msec: conf.get_int("db_open_retry_backoff_msec").unwrap_or(10) + as u32, }; let request_id = Uuid::new_v4(); let network_event_subscription = request.into_inner().clone(); - + let mut event_publication_specs: Vec = Vec::new(); - event_publication_specs.push(network_event_subscription.event_publication_spec.clone().expect("Event publication spec not found in NetworkEventSubscription request")); - + event_publication_specs.push( + network_event_subscription + .event_publication_spec + .clone() + .expect("Event publication spec not found in NetworkEventSubscription request"), + ); + // Initial request state stored in DB. let target: EventSubscriptionState = EventSubscriptionState { status: event_subscription_state::Status::SubscribePendingAck as i32, @@ -226,11 +261,14 @@ impl Network for NetworkService { publishing_request_id: "".to_string(), message: "".to_string(), event_matcher: network_event_subscription.event_matcher.clone(), - event_publication_specs: event_publication_specs + event_publication_specs: event_publication_specs, }; - + // Create EventSubscription - let network_query = network_event_subscription.query.clone().expect("No query passed with NetworkEventSubscription request"); + let network_query = network_event_subscription + .query + .clone() + .expect("No query passed with NetworkEventSubscription request"); let relay_name = conf.get_str("name").unwrap(); let query: Query = Query { policy: network_query.policy, @@ -249,21 +287,38 @@ impl Network for NetworkService { query: Some(query), operation: EventSubOperation::Subscribe as i32, }; - let event_publication_spec = network_event_subscription.event_publication_spec.clone().expect("No Event Publication Specification passed with NetworkEventSubscription request"); + let event_publication_spec = network_event_subscription + .event_publication_spec + .clone() + .expect( + "No Event Publication Specification passed with NetworkEventSubscription request", + ); - return event_subscription_helper(event_subscription, event_publication_spec, target, request_id.to_string(), db, conf).await; + return event_subscription_helper( + event_subscription, + event_publication_spec, + target, + request_id.to_string(), + db, + conf, + ) + .await; } - + async fn get_event_subscription_state( &self, request: Request, ) -> Result, Status> { - println!("\nReceived GetEventSubscriptionState request from network: {:?}", request); + println!( + "\nReceived GetEventSubscriptionState request from network: {:?}", + request + ); let conf = self.config_lock.read().await.clone(); let db = Database { db_path: conf.get_str("db_path").unwrap(), db_open_max_retries: conf.get_int("db_open_max_retries").unwrap_or(500) as u32, - db_open_retry_backoff_msec: conf.get_int("db_open_retry_backoff_msec").unwrap_or(10) as u32, + db_open_retry_backoff_msec: conf.get_int("db_open_retry_backoff_msec").unwrap_or(10) + as u32, }; let event_sub_key = get_event_subscription_key(request.into_inner().request_id); let result = db.get::(event_sub_key.to_string()); @@ -272,19 +327,23 @@ impl Network for NetworkService { match event_subscription_state::Status::from_i32(fetched_event_sub_state.status) { Some(status) => match status { event_subscription_state::Status::Unsubscribed => { - let result = db.unset::(event_sub_key.to_string()); + let result = + db.unset::(event_sub_key.to_string()); match result { Ok(old_state) => { - println!("Removed EventSubscription from database: {:?}", old_state); - }, + println!( + "Removed EventSubscription from database: {:?}", + old_state + ); + } Err(e) => { println!("EventSubscription Request not found. Error: {:?}", e); } } - }, - _ => {}, + } + _ => {} }, - None => {}, + None => {} } println!("Sending back EventSubscriptionState to network: Request ID = {:?}, Status = {:?}", @@ -292,7 +351,7 @@ impl Network for NetworkService { fetched_event_sub_state.status ); return Ok(Response::new(fetched_event_sub_state)); - }, + } Err(e) => Err(Status::new( Code::NotFound, format!("Event Subscription Request not found. Error: {:?}", e), @@ -300,7 +359,10 @@ impl Network for NetworkService { } } // Unsubscribe Event Endpoints - async fn unsubscribe_event(&self, request: Request) -> Result, Status> { + async fn unsubscribe_event( + &self, + request: Request, + ) -> Result, Status> { println!( "Got a Network Event Unubscription request from {:?} - {:?}", request.remote_addr(), @@ -311,22 +373,29 @@ impl Network for NetworkService { let db = Database { db_path: conf.get_str("db_path").unwrap(), db_open_max_retries: conf.get_int("db_open_max_retries").unwrap_or(500) as u32, - db_open_retry_backoff_msec: conf.get_int("db_open_retry_backoff_msec").unwrap_or(10) as u32, + db_open_retry_backoff_msec: conf.get_int("db_open_retry_backoff_msec").unwrap_or(10) + as u32, }; - + let net_event_sub = request.into_inner().clone(); - let network_event_subscription = net_event_sub.request.clone().expect("No network event subscription passed"); + let network_event_subscription = net_event_sub + .request + .clone() + .expect("No network event subscription passed"); let request_id = net_event_sub.request_id.to_string(); - let requested_unsub_pub_spec = network_event_subscription.event_publication_spec.clone().expect("No event publication spec provided for unsubscription request."); - + let requested_unsub_pub_spec = network_event_subscription + .event_publication_spec + .clone() + .expect("No event publication spec provided for unsubscription request."); + let delete_pub_spec_status = delete_event_pub_spec( - request_id.to_string(), - requested_unsub_pub_spec, + request_id.to_string(), + requested_unsub_pub_spec, conf.get_str("db_path").unwrap().to_string(), conf.get_int("db_open_max_retries").unwrap_or(500) as u32, - conf.get_int("db_open_retry_backoff_msec").unwrap_or(10) as u32 + conf.get_int("db_open_retry_backoff_msec").unwrap_or(10) as u32, ); - + if delete_pub_spec_status == 0 { let reply = Ack { status: ack::Status::Ok as i32, @@ -345,8 +414,13 @@ impl Network for NetworkService { Ok(Response::new(reply)) } else { let mut event_publication_specs: Vec = Vec::new(); - event_publication_specs.push(network_event_subscription.event_publication_spec.clone().expect("Event publication spec not found in NetworkEventSubscription request")); - + event_publication_specs.push( + network_event_subscription + .event_publication_spec + .clone() + .expect("Event publication spec not found in NetworkEventSubscription request"), + ); + // Initial request state stored in DB. let target: EventSubscriptionState = EventSubscriptionState { status: event_subscription_state::Status::UnsubscribePendingAck as i32, @@ -354,11 +428,14 @@ impl Network for NetworkService { publishing_request_id: request_id.to_string(), message: "".to_string(), event_matcher: network_event_subscription.event_matcher.clone(), - event_publication_specs: event_publication_specs + event_publication_specs: event_publication_specs, }; - + // Create EventSubscription - let network_query = network_event_subscription.query.clone().expect("No query passed with NetworkEventSubscription request"); + let network_query = network_event_subscription + .query + .clone() + .expect("No query passed with NetworkEventSubscription request"); let relay_name = conf.get_str("name").unwrap(); let query: Query = Query { policy: network_query.policy, @@ -377,42 +454,131 @@ impl Network for NetworkService { query: Some(query), operation: EventSubOperation::Unsubscribe as i32, }; - let event_publication_spec = network_event_subscription.event_publication_spec.clone().expect("No Event Publication Specification passed with NetworkEventSubscription request"); + let event_publication_spec = network_event_subscription + .event_publication_spec + .clone() + .expect( + "No Event Publication Specification passed with NetworkEventSubscription request", + ); - return event_subscription_helper(event_subscription, event_publication_spec, target, request_id.to_string(), db, conf).await; + return event_subscription_helper( + event_subscription, + event_publication_spec, + target, + request_id.to_string(), + db, + conf, + ) + .await; } } - + // Fetch EventStates for given subscription request identified by request_id. async fn get_event_states( &self, request: Request, ) -> Result, Status> { - println!("\nReceived GetEventStates request from network: {:?}", request); + println!( + "\nReceived GetEventStates request from network: {:?}", + request + ); let conf = self.config_lock.read().await.clone(); let db = Database { db_path: conf.get_str("db_path").unwrap(), db_open_max_retries: conf.get_int("db_open_max_retries").unwrap_or(500) as u32, - db_open_retry_backoff_msec: conf.get_int("db_open_retry_backoff_msec").unwrap_or(10) as u32, + db_open_retry_backoff_msec: conf.get_int("db_open_retry_backoff_msec").unwrap_or(10) + as u32, }; let request_id = request.into_inner().request_id; let event_publish_key = get_event_publication_key(request_id.to_string()); let result = db.get::(event_publish_key.to_string()); match result { Ok(fetched_event_states) => { - mark_event_states_deleted(fetched_event_states.clone(), request_id.to_string(), event_publish_key.to_string(), db); - println!("Sending back EventStates to network: Request ID = {:?}: {:?}", - request_id.to_string(), - fetched_event_states.clone() - ); + mark_event_states_deleted( + fetched_event_states.clone(), + request_id.to_string(), + event_publish_key.to_string(), + db, + ); + println!( + "Sending back EventStates to network: Request ID = {:?}: {:?}", + request_id.to_string(), + fetched_event_states.clone() + ); return Ok(Response::new(fetched_event_states)); - }, + } Err(e) => Err(Status::new( Code::NotFound, - format!("EventStates not found for request_id: {}. Error: {:?}", request_id.to_string(), e), + format!( + "EventStates not found for request_id: {}. Error: {:?}", + request_id.to_string(), + e + ), )), } } + + /// request_asset_transfer is called from the client to query the sending gateway to transfer an asset. + /// The request info/state machine is stored in a db on the sending gateway + async fn request_asset_transfer( + &self, + request: Request, + ) -> Result, Status> { + println!( + "Got a NetworkAssetTransfer request from {:?} - {:?}", + request.remote_addr(), + request + ); + let conf = self.config_lock.read().await.clone(); + let network_asset_transfer = request.into_inner().clone(); + let transfer_proposal_claims_request: TransferProposalClaimsRequest = + create_transfer_proposal_claims_request(network_asset_transfer.clone()); + let request_id = + get_request_id_from_transfer_proposal_claims(transfer_proposal_claims_request.clone()); + // TODO refactor / add log entry + + let parsed_address = parse_address(network_asset_transfer.address.to_string()); + match parsed_address { + Ok(_address) => { + let (relay_host, relay_port) = get_relay_from_transfer_proposal_claims( + transfer_proposal_claims_request.clone(), + ); + let (use_tls, tlsca_cert_path) = + get_relay_params(relay_host.clone(), relay_port.clone(), conf.clone()); + + // TODO: verify that host and port are valid + // Spawns a child process to handle sending request + spawn_send_transfer_proposal_claims_request( + transfer_proposal_claims_request, + relay_host, + relay_port, + use_tls, + tlsca_cert_path, + ); + // Send Ack back to network while request is happening in a thread + let reply = Ack { + status: ack::Status::Ok as i32, + request_id: request_id, + message: "Ack of the asset transfer request".to_string(), + }; + println!( + "Sending Ack of the asset transfer request back to network: {:?}\n", + reply + ); + Ok(Response::new(reply)) + } + Err(e) => { + println!("Invalid Address"); + let reply = Ack { + status: ack::Status::Error as i32, + request_id: request_id, + message: format!("Error: Ack of the asset transfer request {:?}", e), + }; + println!("Sending Ack back with an error to network: {:?}\n", reply); + Ok(Response::new(reply)) + } + } + } } async fn event_subscription_helper( @@ -424,19 +590,23 @@ async fn event_subscription_helper( conf: config::Config, ) -> Result, Status> { let event_subscription; - + // Check if driver is subscribing/unsubscribing match event_publication_spec.publication_target { Some(data) => match data { event_publication::PublicationTarget::Ctx(ctx) => { let driver_id = ctx.clone().driver_id.to_string(); - println!("Requesting Driver {} to sign", driver_id.clone().to_string()); + println!( + "Requesting Driver {} to sign", + driver_id.clone().to_string() + ); let result = driver_sign_subscription_helper( req_event_subscription.clone(), request_id.to_string(), driver_id.to_string(), conf.clone(), - ).await; + ) + .await; match result { Ok(signed_query) => { event_subscription = EventSubscription { @@ -453,12 +623,15 @@ async fn event_subscription_helper( message: format!("Error: {:?}", e), }; println!("Sending Ack back to network: {:?}\n", reply); - return Ok(Response::new(reply)) + return Ok(Response::new(reply)); } } } event_publication::PublicationTarget::AppUrl(app_url) => { - println!("Registering for Client using App URL: {}", app_url.to_string()); + println!( + "Registering for Client using App URL: {}", + app_url.to_string() + ); event_subscription = req_event_subscription; } }, @@ -470,10 +643,10 @@ async fn event_subscription_helper( message: format!("No Publication Target provided"), }; println!("Sending Ack back to network: {:?}\n", reply); - return Ok(Response::new(reply)) + return Ok(Response::new(reply)); } }; - + let event_sub_key = get_event_subscription_key(request_id.to_string()); let message_insert = db.set(&event_sub_key.to_string(), &target_status); // Kept this as a match as the error case returns an Ok. @@ -540,7 +713,10 @@ fn spawn_send_request( relay_host: String, relay_port: String, ) { - println!("Sending Query to remote relay: {:?}:{:?}", relay_host, relay_port); + println!( + "Sending Query to remote relay: {:?}:{:?}", + relay_host, relay_port + ); // Locally scoped function to update request status in db. This function is // called for the first time after an Ack is received from the remote relay. // A locally created RequestState with status Pending or Error is stored. @@ -578,12 +754,12 @@ fn spawn_send_request( // Iterate through the relay entries in the configuration to find a match let relays_table = conf.get_table("relays").unwrap(); let mut relay_tls = false; - let mut relay_tlsca_cert_path = "".to_string(); + let mut tlsca_cert_path = "".to_string(); for (_relay_name, relay_spec) in relays_table { let relay_uri = relay_spec.clone().try_into::().unwrap(); if relay_host == relay_uri.hostname && relay_port == relay_uri.port { relay_tls = relay_uri.tls; - relay_tlsca_cert_path = relay_uri.tlsca_cert_path; + tlsca_cert_path = relay_uri.tlsca_cert_path; } } @@ -594,7 +770,7 @@ fn spawn_send_request( network_query, request_id.clone(), relay_tls, - relay_tlsca_cert_path.to_string(), + tlsca_cert_path.to_string(), ) .await; println!("Received Ack from remote relay: {:?}\n", result); @@ -695,7 +871,6 @@ async fn data_transfer_call( Ok(response) } - // Sends a request to the remote relay fn spawn_send_event_subscription_request( conf: config::Config, @@ -704,23 +879,27 @@ fn spawn_send_event_subscription_request( relay_host: String, relay_port: String, ) { - println!("Sending EventSubscription to remote relay: {:?}:{:?}", relay_host, relay_port); - + println!( + "Sending EventSubscription to remote relay: {:?}:{:?}", + relay_host, relay_port + ); + // Spawning new thread to make the subscribe_event_call to remote relay tokio::spawn(async move { let db_path = conf.get_str("db_path").unwrap(); let db_open_max_retries = conf.get_int("db_open_max_retries").unwrap_or(500) as u32; - let db_open_retry_backoff_msec = conf.get_int("db_open_retry_backoff_msec").unwrap_or(10) as u32; + let db_open_retry_backoff_msec = + conf.get_int("db_open_retry_backoff_msec").unwrap_or(10) as u32; // Iterate through the relay entries in the configuration to find a match let relays_table = conf.get_table("relays").unwrap(); let mut relay_tls = false; - let mut relay_tlsca_cert_path = "".to_string(); + let mut tlsca_cert_path = "".to_string(); for (_relay_name, relay_spec) in relays_table { let relay_uri = relay_spec.clone().try_into::().unwrap(); if relay_host == relay_uri.hostname && relay_port == relay_uri.port { relay_tls = relay_uri.tls; - relay_tlsca_cert_path = relay_uri.tlsca_cert_path; + tlsca_cert_path = relay_uri.tlsca_cert_path; } } @@ -729,7 +908,7 @@ fn spawn_send_event_subscription_request( relay_port, event_subscription, relay_tls, - relay_tlsca_cert_path.to_string(), + tlsca_cert_path.to_string(), ) .await; println!("Received Ack from remote relay: {:?}\n", result); @@ -741,12 +920,12 @@ fn spawn_send_event_subscription_request( // This match first checks if the status is valid. match ack::Status::from_i32(ack_response_into_inner.status) { Some(status) => update_event_subscription_status( - request_id.to_string(), - status, - db_path.to_string(), - db_open_max_retries.clone(), - db_open_retry_backoff_msec.clone(), - ack_response_into_inner.message.to_string(), + request_id.to_string(), + status, + db_path.to_string(), + db_open_max_retries.clone(), + db_open_retry_backoff_msec.clone(), + ack_response_into_inner.message.to_string(), ), None => update_event_subscription_status( request_id.to_string(), @@ -782,22 +961,22 @@ async fn suscribe_event_call( let client_addr = format!("https://{}:{}", relay_host, relay_port); let pem = tokio::fs::read(tlsca_cert_path).await?; let ca = Certificate::from_pem(pem); - + let tls = ClientTlsConfig::new() .ca_certificate(ca) .domain_name(relay_host); - + let channel = Channel::from_shared(client_addr)? .tls_config(tls)? .connect() .await?; - + client = EventSubscribeClient::new(channel); } else { let client_addr = format!("http://{}:{}", relay_host, relay_port); client = EventSubscribeClient::connect(client_addr).await?; } - + let event_subscription_request = tonic::Request::new(event_subscription); println!("EventSubscription: {:?}", event_subscription_request); let response = client.subscribe_event(event_subscription_request).await?; diff --git a/weaver/core/relay/src/services/satp_helper.rs b/weaver/core/relay/src/services/satp_helper.rs new file mode 100644 index 00000000000..283b44373d0 --- /dev/null +++ b/weaver/core/relay/src/services/satp_helper.rs @@ -0,0 +1,1207 @@ +use crate::error::Error; +use crate::relay_proto::LocationSegment; +use crate::services::helpers::get_driver_client; +use crate::services::logger::Operation; +use config::Config; +use tonic::transport::{Certificate, Channel, ClientTlsConfig}; +use tonic::Response; +use weaverpb::common::ack::{ack, Ack}; +use weaverpb::driver::driver::{ + AssignAssetRequest, CreateAssetRequest, ExtinguishRequest, PerformLockRequest, +}; +use weaverpb::networks::networks::NetworkAssetTransfer; +use weaverpb::relay::satp::satp_client::SatpClient; +use weaverpb::relay::satp::{ + AckCommenceRequest, AckFinalReceiptRequest, CommitFinalAssertionRequest, CommitPrepareRequest, + CommitReadyRequest, LockAssertionReceiptRequest, LockAssertionRequest, SendAssetStatusRequest, + TransferCommenceRequest, TransferCompletedRequest, TransferProposalClaimsRequest, + TransferProposalReceiptRequest, +}; +use super::logger::LogEntry; +use super::types::Driver; + +// Sends a request to the receiving gateway +pub fn spawn_send_transfer_proposal_claims_request( + transfer_proposal_claims_request: TransferProposalClaimsRequest, + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, +) { + println!( + "Sending transfer proposal claims request to receiver gateway: {:?}:{:?}", + relay_host, relay_port + ); + // Spawning new thread to make the call_transfer_proposal_claims to receiver gateway + tokio::spawn(async move { + let request_id = + get_request_id_from_transfer_proposal_claims(transfer_proposal_claims_request.clone()); + println!( + "Sending transfer proposal claims request to receiver gateway: Request ID = {:?}", + request_id + ); + let result = call_transfer_proposal_claims( + relay_host, + relay_port, + use_tls, + tlsca_cert_path.to_string(), + transfer_proposal_claims_request.clone(), + ) + .await; + + println!("Received Ack from sending gateway: {:?}\n", result); + // Updates the request in the DB depending on the response status from the sending gateway + log_request_result(&request_id, result); + }); +} + +// Sends a request to the receiving gateway +pub fn spawn_send_transfer_commence_request( + transfer_commence_request: TransferCommenceRequest, + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, +) { + println!( + "Sending transfer commence request to receiver gateway: {:?}:{:?}", + relay_host, relay_port + ); + // Spawning new thread to make the call_transfer_commence to receiver gateway + tokio::spawn(async move { + let request_id = transfer_commence_request.session_id.to_string(); + println!( + "Sending transfer commence request to receiver gateway: Request ID = {:?}", + request_id + ); + let result = call_transfer_commence( + relay_host, + relay_port, + use_tls, + tlsca_cert_path.to_string(), + transfer_commence_request.clone(), + ) + .await; + + println!("Received Ack from sending gateway: {:?}\n", result); + // Updates the request in the DB depending on the response status from the sending gateway + log_request_result(&request_id, result); + }); +} + +pub fn spawn_send_transfer_proposal_receipt_request( + transfer_proposal_receipt_request: TransferProposalReceiptRequest, + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, +) { + tokio::spawn(async move { + let request_id = get_request_id_from_transfer_proposal_receipt( + transfer_proposal_receipt_request.clone(), + ); + println!( + "Sending transfer proposal receipt back to sending gateway: Request ID = {:?}", + request_id + ); + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&transfer_proposal_receipt_request.clone()).unwrap(), + step_id: "1.2".to_string(), + operation: Operation::Init, + network_id: "todo_network_id".to_string(), + gateway_id: transfer_proposal_receipt_request + .clone() + .sender_gateway_network_id, + received: false, + details: None, + }; + log::debug!("{}", log_entry); + + let result = call_transfer_proposal_receipt( + relay_host, + relay_port, + use_tls, + tlsca_cert_path.to_string(), + transfer_proposal_receipt_request.clone(), + ) + .await; + + println!("Received Ack from sending gateway: {:?}\n", result); + // Updates the request in the DB depending on the response status from the sending gateway + log_request_result(&request_id, result); + }); +} + +pub fn spawn_send_ack_commence_request( + ack_commence_request: AckCommenceRequest, + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, +) { + tokio::spawn(async move { + let request_id = ack_commence_request.session_id.to_string(); + println!( + "Sending commence response back to sending gateway: Request ID = {:?}", + request_id + ); + let result = call_ack_commence( + relay_host, + relay_port, + use_tls, + tlsca_cert_path.to_string(), + ack_commence_request.clone(), + ) + .await; + + println!("Received Ack from sending gateway: {:?}\n", result); + // Updates the request in the DB depending on the response status from the sending gateway + log_request_result(&request_id, result); + }); +} + +pub fn spawn_send_perform_lock_request( + driver_info: Driver, + perform_lock_request: PerformLockRequest, +) { + tokio::spawn(async move { + let request_id = perform_lock_request.session_id.to_string(); + println!( + "Locking the asset of the lock assertion request id: {:?}", + request_id + ); + // TODO: pass the required info to lock the relevant asset + // Call the driver to lock the asset + let result = call_perform_lock(driver_info, perform_lock_request).await; + match result { + Ok(_) => { + println!("Perform lock request sent to driver\n") + } + Err(e) => { + println!("Error sending perform lock request to driver: {:?}\n", e); + // TODO: what to do in this case? + } + } + }); +} + +pub fn spawn_send_lock_assertion_broadcast_request( + lock_assertion_request: LockAssertionRequest, + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, +) { + tokio::spawn(async move { + let request_id = lock_assertion_request.session_id.to_string(); + println!("Broadcasting the lock assertion request {:?}", request_id); + // TODO + // Broadcast the message to the network + // Subscribe to the status event + // Once the message is broadcast, call the call_lock_assertion_receipt endpoint + // log the results + + let lock_assertion_receipt_request = + create_lock_assertion_receipt_request(lock_assertion_request.clone()); + let result = call_lock_assertion_receipt( + relay_host, + relay_port, + use_tls, + tlsca_cert_path.to_string(), + lock_assertion_receipt_request.clone(), + ) + .await; + + println!("Received Ack from sending gateway: {:?}\n", result); + // Updates the request in the DB depending on the response status from the sending gateway + let request_id = lock_assertion_receipt_request.session_id.to_string(); + log_request_result(&request_id, result); + }); +} + +pub fn spawn_send_lock_assertion_request( + lock_assertion_request: LockAssertionRequest, + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, +) { + tokio::spawn(async move { + let request_id = lock_assertion_request.session_id.to_string(); + println!("Sending the lock assertion request {:?}", request_id); + let result = call_lock_assertion( + relay_host, + relay_port, + use_tls, + tlsca_cert_path.to_string(), + lock_assertion_request.clone(), + ) + .await; + + println!("Received Ack from sending gateway: {:?}\n", result); + // Updates the request in the DB depending on the response status from the sending gateway + let request_id = lock_assertion_request.session_id.to_string(); + log_request_result(&request_id, result); + }); +} + +// Sends a request to the receiving gateway +pub fn spawn_send_commit_prepare_request( + commit_prepare_request: CommitPrepareRequest, + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, +) { + println!( + "Sending commit prepare request to receiver gateway: {:?}:{:?}", + relay_host, relay_port + ); + // Spawning new thread to make the call_commit_prepare to receiver gateway + tokio::spawn(async move { + let request_id = commit_prepare_request.session_id.to_string(); + let result = call_commit_prepare( + relay_host, + relay_port, + use_tls, + tlsca_cert_path.to_string(), + commit_prepare_request.clone(), + ) + .await; + + println!("Received Ack from sending gateway: {:?}\n", result); + // Updates the request in the DB depending on the response status from the sending gateway + log_request_result(&request_id, result); + }); +} + +pub fn spawn_send_create_asset_request( + driver_info: Driver, + create_asset_request: CreateAssetRequest, +) { + tokio::spawn(async move { + let request_id = create_asset_request.session_id.to_string(); + println!( + "Creating the asset corresponding to the create asset request {:?}", + request_id + ); + + // TODO: pass the required info to lock the relevant asset + // Call the driver to lock the asset + let result = call_create_asset(driver_info, create_asset_request).await; + match result { + Ok(_) => { + println!("Create asset request sent to driver\n") + } + Err(e) => { + println!("Error sending create asset request to driver: {:?}\n", e); + // TODO: what to do in this case? + } + } + }); +} + +pub fn spawn_send_commit_ready_request( + commit_ready_request: CommitReadyRequest, + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, +) { + tokio::spawn(async move { + let result = call_commit_ready( + relay_host, + relay_port, + use_tls, + tlsca_cert_path, + commit_ready_request.clone(), + ) + .await; + + println!("Received Ack from sending gateway: {:?}\n", result); + // Updates the request in the DB depending on the response status from the sending gateway + let request_id = commit_ready_request.session_id.to_string(); + log_request_result(&request_id, result); + }); +} + +pub fn spawn_send_assign_asset_request( + driver_info: Driver, + assign_asset_request: AssignAssetRequest, +) { + tokio::spawn(async move { + let request_id = assign_asset_request.session_id.to_string(); + println!( + "Assigning the asset corresponding to the assign asset request {:?}", + request_id + ); + + // TODO: pass the required info to assign the relevant asset + // Call the driver to assign the asset + let result = call_assign_asset(driver_info, assign_asset_request).await; + match result { + Ok(_) => { + println!("Assign asset request sent to driver\n") + } + Err(e) => { + println!("Error sending assign asset request to driver: {:?}\n", e); + // TODO: what to do in this case? + } + } + }); +} + +pub fn spawn_send_ack_final_receipt_request( + ack_final_receipt_request: AckFinalReceiptRequest, + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, +) { + tokio::spawn(async move { + let result = call_ack_final_receipt( + relay_host, + relay_port, + use_tls, + tlsca_cert_path, + ack_final_receipt_request.clone(), + ) + .await; + + println!("Received Ack from sending gateway: {:?}\n", result); + // Updates the request in the DB depending on the response status from the sending gateway + let request_id = ack_final_receipt_request.session_id.to_string(); + log_request_result(&request_id, result); + }); +} + +pub fn spawn_send_ack_final_receipt_broadcast_request( + ack_final_receipt_request: AckFinalReceiptRequest, + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, +) { + tokio::spawn(async move { + let request_id = ack_final_receipt_request.session_id.to_string(); + println!( + "Acknowledge final receipt broadcast of the ack final receipt request {:?}", + request_id + ); + // TODO + // Ack final receipt broadcast + // Once the broadcast is done, call the call_transfer_completed endpoint + // log the results + + let transfer_completed_request = + create_transfer_completed_request(ack_final_receipt_request); + let result = call_transfer_completed( + relay_host, + relay_port, + use_tls, + tlsca_cert_path, + transfer_completed_request.clone(), + ) + .await; + + println!("Received Ack from sending gateway: {:?}\n", result); + // Updates the request in the DB depending on the response status from the sending gateway + let request_id = transfer_completed_request.session_id.to_string(); + log_request_result(&request_id, result); + }); +} + +pub fn spawn_send_extinguish_request(driver_info: Driver, extinguish_request: ExtinguishRequest) { + tokio::spawn(async move { + let request_id = extinguish_request.session_id.to_string(); + println!( + "Extinguishing the asset corresponding to the extinguish request {:?}", + request_id + ); + + // TODO: pass the required info to lock the relevant asset + // Call the driver to lock the asset + let result = call_extinguish(driver_info, extinguish_request).await; + match result { + Ok(_) => { + println!("Extinguishing asset request sent to driver\n") + } + Err(e) => { + println!( + "Error sending extinguishing asset request to driver: {:?}\n", + e + ); + // TODO: what to do in this case? + } + } + }); +} + +pub fn spawn_send_commit_final_assertion_request( + commit_final_assertion_request: CommitFinalAssertionRequest, + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, +) { + tokio::spawn(async move { + let request_id = commit_final_assertion_request.session_id.to_string(); + println!( + "Extinguishing the asset corresponding to the commit final assertion request {:?}", + request_id + ); + let result = call_commit_final_assertion_receipt( + relay_host, + relay_port, + use_tls, + tlsca_cert_path, + commit_final_assertion_request.clone(), + ) + .await; + + println!("Received Ack from sending gateway: {:?}\n", result); + // Updates the request in the DB depending on the response status from the sending gateway + let request_id = commit_final_assertion_request.session_id.to_string(); + log_request_result(&request_id, result); + }); +} + +async fn call_perform_lock( + driver_info: Driver, + perform_lock_request: PerformLockRequest, +) -> Result<(), Error> { + let client = get_driver_client(driver_info).await?; + println!("Sending request to driver to lock the asset"); + let ack = client + .clone() + .perform_lock(perform_lock_request) + .await? + .into_inner(); + println!("Response ACK from driver to perform lock {:?}\n", ack); + let status = ack::Status::from_i32(ack.status) + .ok_or(Error::Simple("Status from Driver error".to_string()))?; + match status { + ack::Status::Ok => { + // Do nothing + return Ok(()); + } + ack::Status::Error => Err(Error::Simple(format!("Error from driver: {}", ack.message))), + } +} + +async fn call_create_asset( + driver_info: Driver, + create_asset_request: CreateAssetRequest, +) -> Result<(), Error> { + let client = get_driver_client(driver_info).await?; + println!("Sending request to driver to create the asset"); + let ack = client + .clone() + .create_asset(create_asset_request) + .await? + .into_inner(); + println!("Response ACK from driver to create the asset {:?}\n", ack); + let status = ack::Status::from_i32(ack.status) + .ok_or(Error::Simple("Status from Driver error".to_string()))?; + match status { + ack::Status::Ok => { + // Do nothing + return Ok(()); + } + ack::Status::Error => Err(Error::Simple(format!("Error from driver: {}", ack.message))), + } +} + +async fn call_extinguish( + driver_info: Driver, + extinguish_request: ExtinguishRequest, +) -> Result<(), Error> { + let client = get_driver_client(driver_info).await?; + println!("Sending request to driver to extinguish the asset"); + let ack = client + .clone() + .extinguish(extinguish_request) + .await? + .into_inner(); + println!( + "Response ACK from driver to extinguish the asset {:?}\n", + ack + ); + let status = ack::Status::from_i32(ack.status) + .ok_or(Error::Simple("Status from Driver error".to_string()))?; + match status { + ack::Status::Ok => { + // Do nothing + return Ok(()); + } + ack::Status::Error => Err(Error::Simple(format!("Error from driver: {}", ack.message))), + } +} + +async fn call_assign_asset( + driver_info: Driver, + assign_asset_request: AssignAssetRequest, +) -> Result<(), Error> { + let client = get_driver_client(driver_info).await?; + println!("Sending request to driver to assign the asset"); + let ack = client + .clone() + .assign_asset(assign_asset_request) + .await? + .into_inner(); + println!("Response ACK from driver to assign the asset {:?}\n", ack); + let status = ack::Status::from_i32(ack.status) + .ok_or(Error::Simple("Status from Driver error".to_string()))?; + match status { + ack::Status::Ok => { + // Do nothing + return Ok(()); + } + ack::Status::Error => Err(Error::Simple(format!("Error from driver: {}", ack.message))), + } +} + +// Call the transfer_commence endpoint on the receiver gateway +pub async fn call_transfer_commence( + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, + transfer_commence_request: TransferCommenceRequest, +) -> Result, Box> { + let mut satp_client: SatpClient = + create_satp_client(relay_host, relay_port, use_tls, tlsca_cert_path).await?; + println!( + "Sending the transfer commence request: {:?}", + transfer_commence_request.clone() + ); + let response = satp_client + .transfer_commence(transfer_commence_request.clone()) + .await?; + Ok(response) +} + +// Call the call_transfer_proposal_claims endpoint on the receiver gateway +pub async fn call_transfer_proposal_claims( + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, + transfer_proposal_claims_request: TransferProposalClaimsRequest, +) -> Result, Box> { + let mut satp_client: SatpClient = + create_satp_client(relay_host, relay_port, use_tls, tlsca_cert_path).await?; + println!( + "Sending the transfer proposal claims request: {:?}", + transfer_proposal_claims_request.clone() + ); + let response = satp_client + .transfer_proposal_claims(transfer_proposal_claims_request.clone()) + .await?; + Ok(response) +} + +// Call the call_transfer_proposal_receipt endpoint on the sending gateway +pub async fn call_transfer_proposal_receipt( + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, + transfer_proposal_receipt_request: TransferProposalReceiptRequest, +) -> Result, Box> { + let mut satp_client: SatpClient = + create_satp_client(relay_host, relay_port, use_tls, tlsca_cert_path).await?; + println!( + "Sending the transfer proposal receipt request: {:?}", + transfer_proposal_receipt_request.clone() + ); + let response = satp_client + .transfer_proposal_receipt(transfer_proposal_receipt_request.clone()) + .await?; + Ok(response) +} + +// Call the ack_commence endpoint on the sending gateway +pub async fn call_ack_commence( + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, + ack_commence_request: AckCommenceRequest, +) -> Result, Box> { + let mut satp_client: SatpClient = + create_satp_client(relay_host, relay_port, use_tls, tlsca_cert_path).await?; + println!( + "Sending the commence response request: {:?}", + ack_commence_request.clone() + ); + let response = satp_client + .ack_commence(ack_commence_request.clone()) + .await?; + Ok(response) +} + +// Call the lock_assertion endpoint on the sending gateway +pub async fn call_lock_assertion( + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, + lock_assertion_request: LockAssertionRequest, +) -> Result, Box> { + let mut satp_client: SatpClient = + create_satp_client(relay_host, relay_port, use_tls, tlsca_cert_path).await?; + println!( + "Sending the lock assertion request: {:?}", + lock_assertion_request.clone() + ); + let response = satp_client + .lock_assertion(lock_assertion_request.clone()) + .await?; + Ok(response) +} + +// Call the ack_commence endpoint on the sending gateway +pub async fn call_lock_assertion_receipt( + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, + lock_assertion_receipt_request: LockAssertionReceiptRequest, +) -> Result, Box> { + let mut satp_client: SatpClient = + create_satp_client(relay_host, relay_port, use_tls, tlsca_cert_path).await?; + println!( + "Sending the lock assertion receipt request: {:?}", + lock_assertion_receipt_request.clone() + ); + let response = satp_client + .lock_assertion_receipt(lock_assertion_receipt_request.clone()) + .await?; + Ok(response) +} + +// Call the call_commit_prepare endpoint on the sending gateway +pub async fn call_commit_prepare( + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, + commit_prepare_request: CommitPrepareRequest, +) -> Result, Box> { + let mut satp_client: SatpClient = + create_satp_client(relay_host, relay_port, use_tls, tlsca_cert_path).await?; + println!( + "Sending the commit prepare request: {:?}", + commit_prepare_request.clone() + ); + let response = satp_client + .commit_prepare(commit_prepare_request.clone()) + .await?; + Ok(response) +} + +// Call the call_commit_ready endpoint on the sending gateway +pub async fn call_commit_ready( + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, + commit_ready_request: CommitReadyRequest, +) -> Result, Box> { + let mut satp_client: SatpClient = + create_satp_client(relay_host, relay_port, use_tls, tlsca_cert_path).await?; + println!( + "Sending the commit ready request: {:?}", + commit_ready_request.clone() + ); + let response = satp_client + .commit_ready(commit_ready_request.clone()) + .await?; + Ok(response) +} + +// Call the call_ack_final_receipt endpoint on the sending gateway +pub async fn call_ack_final_receipt( + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, + ack_final_receipt_request: AckFinalReceiptRequest, +) -> Result, Box> { + let mut satp_client: SatpClient = + create_satp_client(relay_host, relay_port, use_tls, tlsca_cert_path).await?; + println!( + "Sending the ack final receipt request: {:?}", + ack_final_receipt_request.clone() + ); + let response = satp_client + .ack_final_receipt(ack_final_receipt_request.clone()) + .await?; + Ok(response) +} + +// Call the call_transfer_completed endpoint on the sending gateway +pub async fn call_transfer_completed( + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, + transfer_completed_request: TransferCompletedRequest, +) -> Result, Box> { + let mut satp_client: SatpClient = + create_satp_client(relay_host, relay_port, use_tls, tlsca_cert_path).await?; + println!( + "Sending the transfer completed request: {:?}", + transfer_completed_request.clone() + ); + let response = satp_client + .transfer_completed(transfer_completed_request.clone()) + .await?; + Ok(response) +} + +// Call the call_commit_final_assertion_receipt endpoint on the sending gateway +pub async fn call_commit_final_assertion_receipt( + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, + commit_final_assertion_request: CommitFinalAssertionRequest, +) -> Result, Box> { + let mut satp_client: SatpClient = + create_satp_client(relay_host, relay_port, use_tls, tlsca_cert_path).await?; + println!( + "Sending the commit final assertion request: {:?}", + commit_final_assertion_request.clone() + ); + let response = satp_client + .commit_final_assertion(commit_final_assertion_request.clone()) + .await?; + Ok(response) +} + +pub fn log_request_result( + request_id: &String, + result: Result, Box>, +) { + match result { + Ok(ack_response) => { + let ack_response_into_inner = ack_response.into_inner().clone(); + // This match first checks if the status is valid. + match ack::Status::from_i32(ack_response_into_inner.status) { + Some(status) => match status { + ack::Status::Ok => { + let log_entry = LogEntry { + request_id: request_id.clone(), + request: "".to_string(), + step_id: "".to_string(), + operation: Operation::Done, + network_id: "".to_string(), + gateway_id: "".to_string(), + received: false, + details: None, + }; + log::debug!("{}", log_entry); + } + ack::Status::Error => { + let log_entry = LogEntry { + request_id: request_id.clone(), + request: "".to_string(), + step_id: "".to_string(), + operation: Operation::Failed, + network_id: "".to_string(), + gateway_id: "".to_string(), + received: false, + details: Some(ack_response_into_inner.message), + }; + log::debug!("{}", log_entry); + } + }, + None => { + // TODO + } + } + } + Err(result_error) => { + let log_entry = LogEntry { + request_id: request_id.clone(), + request: "".to_string(), + step_id: "".to_string(), + operation: Operation::Failed, + network_id: "".to_string(), + gateway_id: "".to_string(), + received: false, + details: Some(result_error.to_string()), + }; + log::debug!("{}", log_entry); + } + } +} + +pub fn create_ack_error_message( + request_id: String, + error_message: String, + e: Error, +) -> Result, tonic::Status> { + println!("{}: {}", error_message, request_id); + let reply: Result, tonic::Status> = Ok(Response::new(Ack { + status: ack::Status::Error as i32, + request_id: request_id, + message: format!("{} {:?}", error_message, e), + })); + println!("Sending Ack back with an error: {:?}\n", reply); + return reply; +} + +pub fn create_transfer_proposal_claims_request( + _network_asset_transfer: NetworkAssetTransfer, +) -> TransferProposalClaimsRequest { + let transfer_proposal_claims_request = TransferProposalClaimsRequest { + message_type: "message_type1".to_string(), + client_identity_pubkey: "client_identity_pubkey1".to_string(), + server_identity_pubkey: "server_identity_pubkey1".to_string(), + asset_asset_id: "asset_asset_id".to_string(), + asset_profile_id: "asset_profile_id".to_string(), + verified_originator_entity_id: "verified_originator_entity_id".to_string(), + verified_beneficiary_entity_id: "verified_beneficiary_entity_id".to_string(), + originator_pubkey: "originator_pubkey".to_string(), + beneficiary_pubkey: "beneficiary_pubkey".to_string(), + sender_gateway_network_id: "sender_gateway_network_id".to_string(), + recipient_gateway_network_id: "recipient_gateway_network_id".to_string(), + sender_gateway_owner_id: "sender_gateway_owner_id".to_string(), + receiver_gateway_owner_id: "receiver_gateway_owner_id".to_string(), + }; + return transfer_proposal_claims_request; +} + +pub fn create_transfer_commence_request( + _transfer_proposal_receipt_request: TransferProposalReceiptRequest, +) -> TransferCommenceRequest { + let session_id = "to_be_calculated_session_id"; + let transfer_commence_request = TransferCommenceRequest { + message_type: "message_type1".to_string(), + session_id: session_id.to_string(), + transfer_context_id: "transfer_context_id1".to_string(), + client_identity_pubkey: "client_identity_pubkey1".to_string(), + server_identity_pubkey: "server_identity_pubkey1".to_string(), + hash_transfer_init_claims: "hash_transfer_init_claims1".to_string(), + hash_prev_message: "hash_prev_message1".to_string(), + client_transfer_number: "client_transfer_number1".to_string(), + client_signature: "client_signature1".to_string(), + }; + return transfer_commence_request; +} + +pub fn create_transfer_proposal_receipt_request( + _transfer_proposal_claims_request: TransferProposalClaimsRequest, +) -> TransferProposalReceiptRequest { + // TODO: remove hard coded values + let transfer_proposal_receipt_request = TransferProposalReceiptRequest { + message_type: "message_type1".to_string(), + client_identity_pubkey: "client_identity_pubkey1".to_string(), + server_identity_pubkey: "server_identity_pubkey1".to_string(), + asset_asset_id: "asset_asset_id".to_string(), + asset_profile_id: "asset_profile_id".to_string(), + verified_originator_entity_id: "verified_originator_entity_id".to_string(), + verified_beneficiary_entity_id: "verified_beneficiary_entity_id".to_string(), + originator_pubkey: "originator_pubkey".to_string(), + beneficiary_pubkey: "beneficiary_pubkey".to_string(), + sender_gateway_network_id: "sender_gateway_network_id".to_string(), + recipient_gateway_network_id: "recipient_gateway_network_id".to_string(), + sender_gateway_owner_id: "sender_gateway_owner_id".to_string(), + receiver_gateway_owner_id: "receiver_gateway_owner_id".to_string(), + }; + return transfer_proposal_receipt_request; +} + +pub fn create_ack_commence_request( + _transfer_commence_request: TransferCommenceRequest, +) -> AckCommenceRequest { + // TODO: remove hard coded values + let ack_commence_request = AckCommenceRequest { + message_type: "message_type1".to_string(), + session_id: "session_id1".to_string(), + transfer_context_id: "transfer_context_id1".to_string(), + client_identity_pubkey: "client_identity_pubkey1".to_string(), + server_identity_pubkey: "server_identity_pubkey1".to_string(), + hash_prev_message: "hash_prev_message1".to_string(), + server_transfer_number: "server_transfer_number1".to_string(), + server_signature: "server_signature1".to_string(), + }; + return ack_commence_request; +} + +pub fn create_lock_assertion_request( + _send_asset_status_request: SendAssetStatusRequest, +) -> LockAssertionRequest { + // TODO: remove hard coded values + let lock_assertion_request = LockAssertionRequest { + message_type: "message_type1".to_string(), + session_id: "session_id1".to_string(), + transfer_context_id: "transfer_context_id1".to_string(), + client_identity_pubkey: "client_identity_pubkey1".to_string(), + server_identity_pubkey: "server_identity_pubkey1".to_string(), + hash_prev_message: "hash_prev_message1".to_string(), + lock_assertion_claim: "lock_assertion_claim1".to_string(), + lock_assertion_claim_format: "lock_assertion_claim_format1".to_string(), + lock_assertion_expiration: "lock_assertion_expiration".to_string(), + client_transfer_number: "client_transfer_number1".to_string(), + client_signature: "client_signature1".to_string(), + }; + return lock_assertion_request; +} + +pub fn create_lock_assertion_receipt_request( + _lock_assertion_request: LockAssertionRequest, +) -> LockAssertionReceiptRequest { + // TODO: remove hard coded values + let lock_assertion_receipt_request = LockAssertionReceiptRequest { + message_type: "message_type1".to_string(), + session_id: "session_id1".to_string(), + transfer_context_id: "transfer_context_id1".to_string(), + client_identity_pubkey: "client_identity_pubkey1".to_string(), + server_identity_pubkey: "server_identity_pubkey1".to_string(), + hash_prev_message: "hash_prev_message1".to_string(), + server_transfer_number: "server_transfer_number1".to_string(), + server_signature: "server_signature1".to_string(), + }; + return lock_assertion_receipt_request; +} + +pub fn create_commit_prepare_request( + _lock_assertion_receipt_request: LockAssertionReceiptRequest, +) -> CommitPrepareRequest { + // TODO: remove hard coded values + let commit_prepare_request = CommitPrepareRequest { + message_type: "message_type1".to_string(), + session_id: "session_id1".to_string(), + transfer_context_id: "transfer_context_id1".to_string(), + }; + return commit_prepare_request; +} + +pub fn create_commit_ready_request( + _send_asset_status_request: SendAssetStatusRequest, +) -> CommitReadyRequest { + // TODO: remove hard coded values + let commit_ready_request = CommitReadyRequest { + message_type: "message_type1".to_string(), + session_id: "session_id1".to_string(), + transfer_context_id: "transfer_context_id1".to_string(), + }; + return commit_ready_request; +} + +pub fn create_commit_final_assertion_request( + _send_asset_status_request: SendAssetStatusRequest, +) -> CommitFinalAssertionRequest { + // TODO: remove hard coded values + let commit_final_assertion_request = CommitFinalAssertionRequest { + message_type: "message_type1".to_string(), + session_id: "session_id1".to_string(), + transfer_context_id: "transfer_context_id1".to_string(), + }; + return commit_final_assertion_request; +} + +pub fn create_ack_final_receipt_request( + _send_asset_status_request: SendAssetStatusRequest, +) -> AckFinalReceiptRequest { + // TODO: remove hard coded values + let ack_final_receipt_request = AckFinalReceiptRequest { + message_type: "message_type1".to_string(), + session_id: "session_id1".to_string(), + transfer_context_id: "transfer_context_id1".to_string(), + }; + return ack_final_receipt_request; +} + +pub fn create_transfer_completed_request( + _ack_final_receipt_request: AckFinalReceiptRequest, +) -> TransferCompletedRequest { + // TODO: remove hard coded values + let transfer_completed_request = TransferCompletedRequest { + message_type: "message_type1".to_string(), + session_id: "session_id1".to_string(), + transfer_context_id: "transfer_context_id1".to_string(), + }; + return transfer_completed_request; +} + +pub fn create_perform_lock_request(_ack_commence_request: AckCommenceRequest) -> PerformLockRequest { + // TODO: remove hard coded values + let perform_lock_request = PerformLockRequest { + session_id: "session_id1".to_string(), + }; + return perform_lock_request; +} + +pub fn create_create_asset_request( + _commit_prepare_request: CommitPrepareRequest, +) -> CreateAssetRequest { + // TODO: remove hard coded values + let create_asset_request = CreateAssetRequest { + session_id: "session_id1".to_string(), + }; + return create_asset_request; +} + +pub fn create_extinguish_request(_commit_ready_request: CommitReadyRequest) -> ExtinguishRequest { + // TODO: remove hard coded values + let extinguish_request = ExtinguishRequest { + session_id: "session_id1".to_string(), + }; + return extinguish_request; +} + +pub fn create_assign_asset_request( + _commit_final_assertion_request: CommitFinalAssertionRequest, +) -> AssignAssetRequest { + // TODO: remove hard coded values + let assign_asset_request = AssignAssetRequest { + session_id: "session_id1".to_string(), + }; + return assign_asset_request; +} + +pub fn get_relay_from_transfer_proposal_claims( + _transfer_proposal_claims_request: TransferProposalClaimsRequest, +) -> (String, String) { + // TODO + return ("localhost".to_string(), "9085".to_string()); +} + +pub fn get_relay_from_transfer_proposal_receipt( + _transfer_proposal_receipt_request: TransferProposalReceiptRequest, +) -> (String, String) { + // TODO + return ("localhost".to_string(), "9085".to_string()); +} + +pub fn get_relay_from_transfer_commence( + _transfer_commence_request: TransferCommenceRequest, +) -> (String, String) { + // TODO + return ("localhost".to_string(), "9085".to_string()); +} + +pub fn get_relay_from_ack_commence(_ack_commence_request: AckCommenceRequest) -> (String, String) { + // TODO + return ("localhost".to_string(), "9085".to_string()); +} + +pub fn get_relay_from_lock_assertion( + _lock_assertion_request: LockAssertionRequest, +) -> (String, String) { + // TODO + return ("localhost".to_string(), "9085".to_string()); +} + +pub fn get_relay_from_commit_prepare( + _commit_prepare_request: CommitPrepareRequest, +) -> (String, String) { + // TODO + return ("localhost".to_string(), "9085".to_string()); +} + +pub fn get_relay_from_commit_ready(_commit_ready_request: CommitReadyRequest) -> (String, String) { + // TODO + return ("localhost".to_string(), "9085".to_string()); +} + +pub fn get_relay_from_commit_final_assertion( + _commit_final_assertion_request: CommitFinalAssertionRequest, +) -> (String, String) { + // TODO + return ("localhost".to_string(), "9085".to_string()); +} + +pub fn get_relay_from_ack_final_receipt( + _ack_final_receipt_request: AckFinalReceiptRequest, +) -> (String, String) { + // TODO + return ("localhost".to_string(), "9085".to_string()); +} + +pub fn get_driver_address_from_perform_lock(_perform_lock_request: PerformLockRequest) -> String { + // TODO + return "localhost:9085/Dummy_Network/abc:abc:abc:abc".to_string(); +} + +pub fn get_driver_address_from_create_asset(_create_asset_request: CreateAssetRequest) -> String { + // TODO + return "localhost:9085/Dummy_Network/abc:abc:abc:abc".to_string(); +} + +pub fn get_driver_address_from_extinguish(_extinguish_request: ExtinguishRequest) -> String { + // TODO + return "localhost:9085/Dummy_Network/abc:abc:abc:abc".to_string(); +} + +pub fn get_driver_address_from_assign_asset(_assign_asset_request: AssignAssetRequest) -> String { + // TODO + return "localhost:9085/Dummy_Network/abc:abc:abc:abc".to_string(); +} + +pub fn get_relay_params(relay_host: String, relay_port: String, conf: Config) -> (bool, String) { + let relays_table = conf.get_table("relays").unwrap(); + let mut relay_tls = false; + let mut tlsca_cert_path = "".to_string(); + for (_relay_name, relay_spec) in relays_table { + let relay_uri = relay_spec.clone().try_into::().unwrap(); + if relay_host == relay_uri.hostname && relay_port == relay_uri.port { + relay_tls = relay_uri.tls; + tlsca_cert_path = relay_uri.tlsca_cert_path; + } + } + (relay_tls, tlsca_cert_path) +} + +fn create_client_address(relay_host: String, relay_port: String) -> String { + return format!("http://{}:{}", relay_host, relay_port); +} + +pub async fn create_satp_client( + relay_host: String, + relay_port: String, + use_tls: bool, + tlsca_cert_path: String, +) -> Result, Box> { + let client_addr = create_client_address(relay_host.clone(), relay_port.clone()); + let satp_client; + if use_tls { + let pem = tokio::fs::read(tlsca_cert_path).await?; + let ca = Certificate::from_pem(pem); + + let tls = ClientTlsConfig::new() + .ca_certificate(ca) + .domain_name(relay_host); + + let channel = Channel::from_shared(client_addr)? + .tls_config(tls)? + .connect() + .await?; + + satp_client = SatpClient::new(channel); + } else { + satp_client = SatpClient::connect(client_addr).await?; + } + return Ok(satp_client); +} + +pub fn get_request_id_from_transfer_proposal_claims( + _request: TransferProposalClaimsRequest, +) -> String { + // TODO + return "hard_coded_transfer_proposal_claims_request_id".to_string(); +} + +pub fn get_request_id_from_transfer_proposal_receipt( + _request: TransferProposalReceiptRequest, +) -> String { + // TODO + return "hard_coded_transfer_proposal_receipt_request_id".to_string(); +} diff --git a/weaver/core/relay/src/services/satp_service.rs b/weaver/core/relay/src/services/satp_service.rs new file mode 100644 index 00000000000..61d28bab9a0 --- /dev/null +++ b/weaver/core/relay/src/services/satp_service.rs @@ -0,0 +1,1867 @@ +// Internal generated modules +use weaverpb::common::ack::{ack, Ack}; +use weaverpb::driver::driver::{ + AssignAssetRequest, CreateAssetRequest, ExtinguishRequest, PerformLockRequest, +}; +use weaverpb::relay::satp::satp_server::Satp; +use weaverpb::relay::satp::{ + AckCommenceRequest, AckFinalReceiptRequest, CommitFinalAssertionRequest, CommitPrepareRequest, + CommitReadyRequest, LockAssertionReceiptRequest, LockAssertionRequest, SendAssetStatusRequest, + TransferCommenceRequest, TransferCompletedRequest, TransferProposalClaimsRequest, + TransferProposalReceiptRequest, +}; + +// Internal modules +use crate::error::Error; +use crate::relay_proto::parse_address; +use crate::services::helpers::{println_stage_heading, println_step_heading}; +use crate::services::logger::{LogEntry, Operation}; +use crate::services::satp_helper::{ + create_ack_error_message, create_assign_asset_request, create_create_asset_request, + create_extinguish_request, create_perform_lock_request, + get_request_id_from_transfer_proposal_receipt, +}; + +use super::helpers::get_driver; +// external modules +use super::satp_helper::{ + create_ack_commence_request, create_ack_final_receipt_request, + create_commit_final_assertion_request, create_commit_prepare_request, + create_commit_ready_request, create_lock_assertion_request, create_transfer_commence_request, + create_transfer_proposal_receipt_request, get_driver_address_from_assign_asset, + get_driver_address_from_create_asset, get_driver_address_from_extinguish, + get_driver_address_from_perform_lock, get_relay_from_ack_commence, + get_relay_from_ack_final_receipt, get_relay_from_commit_final_assertion, + get_relay_from_commit_prepare, get_relay_from_commit_ready, get_relay_from_lock_assertion, + get_relay_from_transfer_commence, get_relay_from_transfer_proposal_receipt, get_relay_params, + get_request_id_from_transfer_proposal_claims, spawn_send_ack_commence_request, + spawn_send_ack_final_receipt_broadcast_request, spawn_send_ack_final_receipt_request, + spawn_send_assign_asset_request, spawn_send_commit_final_assertion_request, + spawn_send_commit_prepare_request, spawn_send_commit_ready_request, + spawn_send_create_asset_request, spawn_send_extinguish_request, + spawn_send_lock_assertion_broadcast_request, spawn_send_lock_assertion_request, + spawn_send_perform_lock_request, spawn_send_transfer_commence_request, + spawn_send_transfer_proposal_receipt_request, +}; +use tokio::sync::RwLock; +use tonic::{Request, Response, Status}; + +#[derive(Debug, Default)] +pub struct SatpService { + pub config_lock: RwLock, +} + +/// AssetTransferService is the gRPC server implementation that handles the logic for +/// communication of the asset transfer protocol SATP between two gateways. +#[tonic::async_trait] +impl Satp for SatpService { + /// transfer_proposal_claims is run on the receiver gateway to allow the sender gateway to initiate an asset transfer. + async fn transfer_proposal_claims( + &self, + request: Request, + ) -> Result, Status> { + let step_id = "1.1".to_string(); + + println_stage_heading("1".to_string()); + println_step_heading(step_id.clone()); + println!( + "Got a TransferProposalClaimsRequest from {:?} - {:?}", + request.remote_addr(), + request + ); + + let transfer_proposal_claims_request = request.into_inner().clone(); + let request_id = + get_request_id_from_transfer_proposal_claims(transfer_proposal_claims_request.clone()); + let conf = self.config_lock.read().await; + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&transfer_proposal_claims_request.clone()).unwrap(), + step_id: step_id.clone(), + operation: Operation::Init, + network_id: "todo_network_id".to_string(), + gateway_id: transfer_proposal_claims_request + .clone() + .sender_gateway_network_id, + received: true, + details: None, + }; + log::debug!("{}", log_entry); + + match process_transfer_proposal_claims_request( + transfer_proposal_claims_request.clone(), + conf.clone(), + ) { + Ok(ack) => { + let reply = Ok(Response::new(ack)); + println!( + "Sending Ack of transfer proposal claims request back: {:?}\n", + reply + ); + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&transfer_proposal_claims_request).unwrap(), + step_id: step_id.clone(), + operation: Operation::Done, + network_id: "todo_network_id".to_string(), + gateway_id: transfer_proposal_claims_request + .clone() + .sender_gateway_network_id, + received: true, + details: None, + }; + log::debug!("{}", log_entry); + reply + } + Err(e) => { + let error_message = "Transfer proposal claims failed.".to_string(); + let reply = create_ack_error_message(request_id.clone(), error_message.clone(), e); + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&transfer_proposal_claims_request).unwrap(), + step_id: step_id.clone(), + operation: Operation::Failed, + network_id: "todo_network_id".to_string(), + gateway_id: transfer_proposal_claims_request + .clone() + .sender_gateway_network_id, + received: true, + details: Some(error_message), + }; + log::error!("{}", log_entry); + reply + } + } + } + + async fn transfer_proposal_receipt( + &self, + request: Request, + ) -> Result, Status> { + let step_id = "1.2".to_string(); + println_step_heading(step_id.clone()); + println!( + "Got an ack transfer proposal receipt request from {:?} - {:?}", + request.remote_addr(), + request + ); + + let transfer_proposal_receipt_request = request.into_inner().clone(); + let request_id = get_request_id_from_transfer_proposal_receipt( + transfer_proposal_receipt_request.clone(), + ); + let conf = self.config_lock.read().await; + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&transfer_proposal_receipt_request.clone()).unwrap(), + step_id: step_id.clone(), + operation: Operation::Init, + network_id: "todo_network_id".to_string(), + gateway_id: transfer_proposal_receipt_request + .clone() + .sender_gateway_network_id, + received: true, + details: None, + }; + log::debug!("{}", log_entry); + + match process_transfer_proposal_receipt_request( + transfer_proposal_receipt_request.clone(), + conf.clone(), + ) { + Ok(ack) => { + let reply = Ok(Response::new(ack)); + println!( + "Sending Ack of transfer proposal receipt request back: {:?}\n", + reply + ); + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&transfer_proposal_receipt_request).unwrap(), + step_id: step_id.clone(), + operation: Operation::Done, + network_id: "todo_network_id".to_string(), + gateway_id: transfer_proposal_receipt_request + .clone() + .sender_gateway_network_id, + received: true, + details: None, + }; + log::debug!("{}", log_entry); + reply + } + Err(e) => { + let error_message = "Ack transfer proposal receipt failed.".to_string(); + let reply = create_ack_error_message(request_id.clone(), error_message.clone(), e); + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&transfer_proposal_receipt_request).unwrap(), + step_id: step_id.clone(), + operation: Operation::Failed, + network_id: "todo_network_id".to_string(), + gateway_id: transfer_proposal_receipt_request + .clone() + .sender_gateway_network_id, + received: true, + details: Some(error_message), + }; + log::error!("{}", log_entry); + reply + } + } + } + + /// transfer_commence is run on the receiver gateway to allow the sender gateway to signal to the + /// receiver gateway that it is ready to start the transfer of the digital asset + async fn transfer_commence( + &self, + request: Request, + ) -> Result, Status> { + let step_id = "1.3".to_string(); + println_step_heading(step_id.clone()); + println!( + "Got a TransferCommenceRequest from {:?} - {:?}", + request.remote_addr(), + request + ); + + let transfer_commence_request = request.into_inner().clone(); + let request_id = transfer_commence_request.session_id.to_string(); + let conf = self.config_lock.read().await; + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&transfer_commence_request.clone()).unwrap(), + step_id: step_id.clone(), + operation: Operation::Init, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + + match process_transfer_commence_request(transfer_commence_request.clone(), conf.clone()) { + Ok(ack) => { + let reply = Ok(Response::new(ack)); + println!( + "Sending Ack of transfer commence request back: {:?}\n", + reply + ); + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&transfer_commence_request).unwrap(), + step_id: step_id.clone(), + operation: Operation::Done, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + reply + } + Err(e) => { + let error_message = "Transfer commence failed.".to_string(); + let reply = create_ack_error_message(request_id.clone(), error_message.clone(), e); + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&transfer_commence_request).unwrap(), + step_id: step_id.clone(), + operation: Operation::Failed, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: Some(error_message), + }; + log::error!("{}", log_entry); + reply + } + } + } + + async fn ack_commence( + &self, + request: Request, + ) -> Result, Status> { + let step_id = "1.4".to_string(); + println_step_heading(step_id.clone()); + println!( + "Got an ack commence request from {:?} - {:?}", + request.remote_addr(), + request + ); + + let ack_commence_request = request.into_inner().clone(); + let request_id = ack_commence_request.session_id.to_string(); + let conf = self.config_lock.read().await; + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&ack_commence_request.clone()).unwrap(), + step_id: step_id.clone(), + operation: Operation::Init, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + + match process_ack_commence_request(ack_commence_request.clone(), conf.clone()) { + Ok(ack) => { + let reply = Ok(Response::new(ack)); + println!("Sending Ack of ack commence request back: {:?}\n", reply); + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&ack_commence_request).unwrap(), + step_id: step_id.clone(), + operation: Operation::Done, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + reply + } + Err(e) => { + let error_message = "Ack commence failed.".to_string(); + let reply = create_ack_error_message(request_id.clone(), error_message.clone(), e); + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&ack_commence_request).unwrap(), + step_id: step_id.clone(), + operation: Operation::Failed, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: Some(error_message), + }; + log::error!("{}", log_entry); + reply + } + } + } + + async fn send_asset_status( + &self, + request: Request, + ) -> Result, Status> { + println!( + "Got a send asset status request from {:?} - {:?}", + request.remote_addr(), + request + ); + + let send_asset_status_request = request.into_inner().clone(); + let request_id = send_asset_status_request.session_id.to_string(); + let conf = self.config_lock.read().await; + + match process_send_asset_status_request(send_asset_status_request.clone(), conf.clone()) { + Ok(ack) => { + let reply = Ok(Response::new(ack)); + println!( + "Sending Ack of send asset status request back: {:?}\n", + reply + ); + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&send_asset_status_request).unwrap(), + step_id: "todo_step_id".to_string(), + operation: Operation::Done, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + reply + } + Err(e) => { + let error_message = "Send asset status failed.".to_string(); + let reply = create_ack_error_message(request_id.clone(), error_message.clone(), e); + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&send_asset_status_request).unwrap(), + step_id: "todo_step_id".to_string(), + operation: Operation::Failed, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: Some(error_message), + }; + log::error!("{}", log_entry); + reply + } + } + } + + async fn lock_assertion( + &self, + request: Request, + ) -> Result, Status> { + let step_id = "2.2".to_string(); + println_step_heading(step_id.clone()); + println!( + "Got a LockAssertionRequest from {:?} - {:?}", + request.remote_addr(), + request + ); + + let lock_assertion_request = request.into_inner().clone(); + let request_id = lock_assertion_request.session_id.to_string(); + let conf = self.config_lock.read().await; + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&lock_assertion_request.clone()).unwrap(), + step_id: step_id.clone(), + operation: Operation::Init, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + + match process_lock_assertion_request(lock_assertion_request.clone(), conf.clone()) { + Ok(ack) => { + let reply = Ok(Response::new(ack)); + println!("Sending Ack of lock assertion request back: {:?}\n", reply); + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&lock_assertion_request).unwrap(), + step_id: step_id.clone(), + operation: Operation::Done, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + reply + } + Err(e) => { + let error_message = "Lock assertion failed.".to_string(); + let reply = create_ack_error_message(request_id.clone(), error_message.clone(), e); + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&lock_assertion_request).unwrap(), + step_id: step_id.clone(), + operation: Operation::Failed, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: Some(error_message), + }; + log::error!("{}", log_entry); + reply + } + } + } + + async fn lock_assertion_receipt( + &self, + request: Request, + ) -> Result, Status> { + let step_id = "2.4".to_string(); + println_step_heading(step_id.clone()); + println!( + "Got an lock assertion receipt request from {:?} - {:?}", + request.remote_addr(), + request + ); + + let lock_assertion_receipt_request = request.into_inner().clone(); + let request_id = lock_assertion_receipt_request.session_id.to_string(); + let conf = self.config_lock.read().await; + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&lock_assertion_receipt_request.clone()).unwrap(), + step_id: step_id.clone(), + operation: Operation::Init, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + + match process_lock_assertion_receipt_request( + lock_assertion_receipt_request.clone(), + conf.clone(), + ) { + Ok(ack) => { + let reply = Ok(Response::new(ack)); + println!( + "Sending Ack of lock assertion receipt request back: {:?}\n", + reply + ); + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&lock_assertion_receipt_request).unwrap(), + step_id: step_id.clone(), + operation: Operation::Done, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + reply + } + Err(e) => { + let error_message = "Lock assertion receipt failed.".to_string(); + let reply = create_ack_error_message(request_id.clone(), error_message.clone(), e); + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&lock_assertion_receipt_request).unwrap(), + step_id: step_id.clone(), + operation: Operation::Failed, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: Some(error_message), + }; + log::error!("{}", log_entry); + reply + } + } + } + + async fn commit_prepare( + &self, + request: Request, + ) -> Result, Status> { + let step_id = "3.1".to_string(); + println_step_heading(step_id.clone()); + println!( + "Got commit prepare request from {:?} - {:?}", + request.remote_addr(), + request + ); + + let commit_prepare_request = request.into_inner().clone(); + let request_id = commit_prepare_request.session_id.to_string(); + let conf = self.config_lock.read().await; + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&commit_prepare_request.clone()).unwrap(), + step_id: step_id.clone(), + operation: Operation::Init, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + + match process_commit_prepare_request(commit_prepare_request.clone(), conf.clone()) { + Ok(ack) => { + let reply = Ok(Response::new(ack)); + println!("Sending Ack of commit prepare request back: {:?}\n", reply); + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&commit_prepare_request).unwrap(), + step_id: step_id.clone(), + operation: Operation::Done, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + reply + } + Err(e) => { + let error_message = "Commit prepare failed.".to_string(); + let reply = create_ack_error_message(request_id.clone(), error_message.clone(), e); + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&commit_prepare_request).unwrap(), + step_id: step_id.clone(), + operation: Operation::Failed, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: Some(error_message), + }; + log::error!("{}", log_entry); + reply + } + } + } + + async fn commit_ready( + &self, + request: Request, + ) -> Result, Status> { + let step_id = "3.3".to_string(); + println_step_heading(step_id.clone()); + println!( + "Got commit ready request from {:?} - {:?}", + request.remote_addr(), + request + ); + + let commit_ready_request = request.into_inner().clone(); + let request_id = commit_ready_request.session_id.to_string(); + let conf = self.config_lock.read().await; + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&commit_ready_request.clone()).unwrap(), + step_id: step_id.clone(), + operation: Operation::Init, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + + match process_commit_ready_request(commit_ready_request.clone(), conf.clone()) { + Ok(ack) => { + let reply = Ok(Response::new(ack)); + println!("Sending Ack of commit ready request back: {:?}\n", reply); + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&commit_ready_request).unwrap(), + step_id: step_id.clone(), + operation: Operation::Done, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + reply + } + Err(e) => { + let error_message = "Commit ready failed.".to_string(); + let reply = create_ack_error_message(request_id.clone(), error_message.clone(), e); + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&commit_ready_request).unwrap(), + step_id: step_id.clone(), + operation: Operation::Failed, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: Some(error_message), + }; + log::error!("{}", log_entry); + reply + } + } + } + + async fn commit_final_assertion( + &self, + request: Request, + ) -> Result, Status> { + let step_id = "3.5".to_string(); + println_step_heading(step_id.clone()); + println!( + "Got commit final assertion request from {:?} - {:?}", + request.remote_addr(), + request + ); + + let commit_final_assertion_request = request.into_inner().clone(); + let request_id = commit_final_assertion_request.session_id.to_string(); + let conf = self.config_lock.read().await; + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&commit_final_assertion_request.clone()).unwrap(), + step_id: step_id.clone(), + operation: Operation::Init, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + + match process_commit_final_assertion_request( + commit_final_assertion_request.clone(), + conf.clone(), + ) { + Ok(ack) => { + let reply = Ok(Response::new(ack)); + println!( + "Sending Ack of commit final assertion request back: {:?}\n", + reply + ); + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&commit_final_assertion_request).unwrap(), + step_id: step_id.clone(), + operation: Operation::Done, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + reply + } + Err(e) => { + let error_message = "Commit final assertion failed.".to_string(); + let reply = create_ack_error_message(request_id.clone(), error_message.clone(), e); + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&commit_final_assertion_request).unwrap(), + step_id: step_id.clone(), + operation: Operation::Failed, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: Some(error_message), + }; + log::error!("{}", log_entry); + reply + } + } + } + + async fn ack_final_receipt( + &self, + request: Request, + ) -> Result, Status> { + let step_id = "3.7".to_string(); + println_step_heading(step_id.clone()); + println!( + "Got commit final assertion request from {:?} - {:?}", + request.remote_addr(), + request + ); + + let ack_final_receipt_request = request.into_inner().clone(); + let request_id = ack_final_receipt_request.session_id.to_string(); + let conf = self.config_lock.read().await; + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&ack_final_receipt_request.clone()).unwrap(), + step_id: step_id.clone(), + operation: Operation::Init, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + + match process_ack_final_receipt_request(ack_final_receipt_request.clone(), conf.clone()) { + Ok(ack) => { + let reply = Ok(Response::new(ack)); + println!( + "Sending Ack of ack final receipt request back: {:?}\n", + reply + ); + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&ack_final_receipt_request).unwrap(), + step_id: step_id.clone(), + operation: Operation::Done, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + reply + } + Err(e) => { + let error_message = "Ack final receipt failed.".to_string(); + let reply = create_ack_error_message(request_id.clone(), error_message.clone(), e); + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&ack_final_receipt_request).unwrap(), + step_id: step_id.clone(), + operation: Operation::Failed, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: Some(error_message), + }; + log::error!("{}", log_entry); + reply + } + } + } + + async fn transfer_completed( + &self, + request: Request, + ) -> Result, Status> { + let step_id = "3.9".to_string(); + println_step_heading(step_id.clone()); + println!( + "Got commit final assertion request from {:?} - {:?}", + request.remote_addr(), + request + ); + + let transfer_completed_request = request.into_inner().clone(); + let request_id = transfer_completed_request.session_id.to_string(); + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&transfer_completed_request.clone()).unwrap(), + step_id: step_id.clone(), + operation: Operation::Init, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + + let reply = Ack { + status: ack::Status::Ok as i32, + request_id: request_id.to_string(), + message: "Ack of the Transfer Completed request".to_string(), + }; + return Ok(Response::new(reply)); + } +} + +pub fn process_transfer_proposal_claims_request( + transfer_proposal_claims_request: TransferProposalClaimsRequest, + conf: config::Config, +) -> Result { + let request_id = + get_request_id_from_transfer_proposal_claims(transfer_proposal_claims_request.clone()); + let is_valid_request = + is_valid_transfer_proposal_claims_request(transfer_proposal_claims_request.clone()); + + if is_valid_request { + println!("The transfer proposal claims request is valid\n"); + let transfer_proposal_receipt_request = + create_transfer_proposal_receipt_request(transfer_proposal_claims_request.clone()); + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&transfer_proposal_claims_request.clone()).unwrap(), + step_id: "1.1".to_string(), + operation: Operation::Exec, + network_id: "todo_network_id".to_string(), + gateway_id: transfer_proposal_claims_request + .clone() + .sender_gateway_network_id, + received: true, + details: None, + }; + log::debug!("{}", log_entry); + + match send_transfer_proposal_receipt_request(transfer_proposal_receipt_request, conf) { + Ok(ack) => { + println!("Ack transfer proposal claims request."); + let reply = Ok(ack); + println!("Sending back Ack: {:?}\n", reply); + reply + } + Err(e) => { + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: format!("Error: Ack transfer proposal claims failed. {:?}", e), + }); + } + } + } else { + println!("The transfer proposal claims request is invalid\n"); + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: "Error: The transfer proposal claims request is invalid".to_string(), + }); + } +} + +pub fn process_transfer_proposal_receipt_request( + transfer_proposal_receipt_request: TransferProposalReceiptRequest, + conf: config::Config, +) -> Result { + let request_id = + get_request_id_from_transfer_proposal_receipt(transfer_proposal_receipt_request.clone()); + let is_valid_request = + is_valid_transfer_proposal_receipt_request(transfer_proposal_receipt_request.clone()); + + if is_valid_request { + println!("The transfer proposal receipt request is valid\n"); + let transfer_commence_request = + create_transfer_commence_request(transfer_proposal_receipt_request.clone()); + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&transfer_commence_request.clone()).unwrap(), + step_id: "1.2".to_string(), + operation: Operation::Exec, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + + match send_transfer_commence_request(transfer_commence_request.clone(), conf) { + Ok(ack) => { + println!("Ack transfer proposal receipt request."); + let reply = Ok(ack); + println!("Sending back Ack: {:?}\n", reply); + reply + } + Err(e) => { + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: format!("Error: Ack transfer proposal receipt failed. {:?}", e), + }); + } + } + } else { + println!("The transfer proposal receipt request is invalid\n"); + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: "Error: The transfer proposal receipt request is invalid".to_string(), + }); + } +} + +/// process_transfer_commence_request is run on the receiver gateway to initiate asset transfer protocol that was +/// requested from the sender gateway +pub fn process_transfer_commence_request( + transfer_commence_request: TransferCommenceRequest, + conf: config::Config, +) -> Result { + let request_id = transfer_commence_request.session_id.to_string(); + let is_valid_request = is_valid_transfer_commence_request(transfer_commence_request.clone()); + + if is_valid_request { + println!("The transfer commence request is valid\n"); + let ack_commence_request = create_ack_commence_request(transfer_commence_request.clone()); + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&ack_commence_request.clone()).unwrap(), + step_id: "1.3".to_string(), + operation: Operation::Exec, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + + match send_ack_commence_request(ack_commence_request.clone(), conf) { + Ok(ack) => { + println!("Ack transfer commence request."); + let reply = Ok(ack); + println!("Sending back Ack: {:?}\n", reply); + reply + } + Err(e) => { + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: format!("Error: Ack commence request failed. {:?}", e), + }); + } + } + } else { + println!("The transfer commence request is invalid\n"); + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: "Error: The transfer commence request is invalid".to_string(), + }); + } +} + +/// process_ack_commence_request is invoked by the receiver gateway to ack the transfer commence request +/// requested ed by the sender gateway +pub fn process_ack_commence_request( + ack_commence_request: AckCommenceRequest, + conf: config::Config, +) -> Result { + let request_id = ack_commence_request.session_id.to_string(); + let is_valid_request = is_valid_ack_commence_request(ack_commence_request.clone()); + + // TODO some processing + if is_valid_request { + println!("The ack commence request is valid\n"); + let perform_lock_request: PerformLockRequest = + create_perform_lock_request(ack_commence_request); + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&perform_lock_request.clone()).unwrap(), + step_id: "1.4".to_string(), + operation: Operation::Exec, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + + match send_perform_lock_request(perform_lock_request.clone(), conf) { + Ok(ack) => { + println!("Ack ack commence request."); + let reply = Ok(ack); + println!("Sending back Ack: {:?}\n", reply); + reply + } + Err(e) => { + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: format!("Error: perform lock request failed. {:?}", e), + }); + } + } + } else { + println!("The ack commence request is invalid\n"); + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: "Error: The ack commence request is invalid".to_string(), + }); + } +} + +pub fn process_send_asset_status_request( + send_asset_status_request: SendAssetStatusRequest, + conf: config::Config, +) -> Result { + let request_id = send_asset_status_request.session_id.to_string(); + let is_valid_request = is_valid_send_asset_status_request(send_asset_status_request.clone()); + + // TODO some processing + if is_valid_request { + println!("The send asset status request is valid\n"); + + let result; + let status = send_asset_status_request.status.as_str(); + match status { + "Locked" => { + println_step_heading("2.1B".to_string()); + println!("Received asset status as Locked. Sending the lock assertion request"); + let lock_assertion_request = + create_lock_assertion_request(send_asset_status_request); + result = send_lock_assertion_request(lock_assertion_request, conf) + } + "Created" => { + println_step_heading("3.2B".to_string()); + println!("Received asset status as Created. Sending the commit ready request"); + let commit_ready_request = create_commit_ready_request(send_asset_status_request); + result = send_commit_ready_request(commit_ready_request, conf); + } + "Extinguished" => { + println_step_heading("3.4B".to_string()); + println!("Received asset status as Extinguished. Sending the commit final assertion request"); + let commit_final_assertion_request = + create_commit_final_assertion_request(send_asset_status_request); + result = send_commit_final_assertion_request(commit_final_assertion_request, conf) + } + "Finalized" => { + println_step_heading("3.6B".to_string()); + println!( + "Received asset status as Finalized. Sending the ack final receipt request" + ); + let ack_final_receipt_request = + create_ack_final_receipt_request(send_asset_status_request.clone()); + result = send_ack_final_receipt_request(ack_final_receipt_request, conf) + } + _ => result = Err(Error::Simple(format!("Invalid asset status: {}", status))), + } + + match result { + Ok(ack) => { + let reply = Ok(ack); + println!("Sending back Ack: {:?}\n", reply); + reply + } + Err(e) => { + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: format!("Error: sending request failed. {:?}", e), + }); + } + } + } else { + println!("The send asset status request is invalid\n"); + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: "Error: The send asset status request is invalid".to_string(), + }); + } +} + +pub fn process_lock_assertion_request( + lock_assertion_request: LockAssertionRequest, + conf: config::Config, +) -> Result { + let request_id = lock_assertion_request.session_id.to_string(); + let is_valid_request = is_valid_lock_assertion_request(lock_assertion_request.clone()); + + if is_valid_request { + println!("The lock assertion request is valid\n"); + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&lock_assertion_request.clone()).unwrap(), + step_id: "2.2".to_string(), + operation: Operation::Exec, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + + match send_lock_assertion_broadcast_request(lock_assertion_request, conf) { + Ok(ack) => { + println!("Ack lock assertion request."); + let reply = Ok(ack); + println!("Sending back Ack: {:?}\n", reply); + reply + } + Err(e) => { + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: format!("Error: Ack lock assertion failed. {:?}", e), + }); + } + } + } else { + println!("The lock assertion request is invalid\n"); + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: "Error: The lock assertion request is invalid".to_string(), + }); + } +} + +pub fn process_lock_assertion_receipt_request( + lock_assertion_receipt_request: LockAssertionReceiptRequest, + conf: config::Config, +) -> Result { + let request_id = lock_assertion_receipt_request.session_id.to_string(); + let is_valid_request = + is_valid_lock_assertion_receipt_request(lock_assertion_receipt_request.clone()); + + // TODO some processing + if is_valid_request { + println!("The lock assertion receipt request is valid\n"); + let commit_prepare_request = + create_commit_prepare_request(lock_assertion_receipt_request.clone()); + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&commit_prepare_request.clone()).unwrap(), + step_id: "2.4".to_string(), + operation: Operation::Exec, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + + match send_commit_prepare_request(commit_prepare_request, conf) { + Ok(ack) => { + println!("Ack lock assertion receipt request."); + let reply = Ok(ack); + println!("Sending back Ack: {:?}\n", reply); + reply + } + Err(e) => { + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: format!("Error: perform lock request failed. {:?}", e), + }); + } + } + } else { + println!("The lock assertion receipt request is invalid\n"); + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: "Error: The lock assertion receipt request is invalid".to_string(), + }); + } +} + +pub fn process_commit_prepare_request( + commit_prepare_request: CommitPrepareRequest, + conf: config::Config, +) -> Result { + let request_id = commit_prepare_request.session_id.to_string(); + let is_valid_request = is_valid_commit_prepare_request(commit_prepare_request.clone()); + + // TODO some processing + if is_valid_request { + println!("The commit prepare request is valid\n"); + let create_asset_request: CreateAssetRequest = + create_create_asset_request(commit_prepare_request); + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&create_asset_request.clone()).unwrap(), + step_id: "3.1".to_string(), + operation: Operation::Exec, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + + match send_create_asset_request(create_asset_request, conf) { + Ok(ack) => { + println!("Ack commit prepare request."); + let reply = Ok(ack); + println!("Sending back Ack: {:?}\n", reply); + reply + } + Err(e) => { + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: format!("Error: commit prepare request failed. {:?}", e), + }); + } + } + } else { + println!("The commit prepare request is invalid\n"); + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: "Error: The commit prepare request is invalid".to_string(), + }); + } +} + +pub fn process_commit_ready_request( + commit_ready_request: CommitReadyRequest, + conf: config::Config, +) -> Result { + let request_id = commit_ready_request.session_id.to_string(); + let is_valid_request = is_valid_commit_ready_request(commit_ready_request.clone()); + + // TODO some processing + if is_valid_request { + println!("The commit ready request is valid\n"); + let extinguish_request: ExtinguishRequest = create_extinguish_request(commit_ready_request); + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&extinguish_request.clone()).unwrap(), + step_id: "3.3".to_string(), + operation: Operation::Exec, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + + match send_extinguish_request(extinguish_request, conf) { + Ok(ack) => { + println!("Ack commit ready request."); + let reply = Ok(ack); + println!("Sending back Ack: {:?}\n", reply); + reply + } + Err(e) => { + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: format!("Error: commit ready request failed. {:?}", e), + }); + } + } + } else { + println!("The commit ready request is invalid\n"); + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: "Error: The commit ready request is invalid".to_string(), + }); + } +} + +pub fn process_commit_final_assertion_request( + commit_final_assertion_request: CommitFinalAssertionRequest, + conf: config::Config, +) -> Result { + let request_id = commit_final_assertion_request.session_id.to_string(); + let is_valid_request = + is_valid_commit_final_assertion_request(commit_final_assertion_request.clone()); + + // TODO some processing + if is_valid_request { + println!("The commit final assertion request is valid\n"); + let assign_asset_request: AssignAssetRequest = + create_assign_asset_request(commit_final_assertion_request); + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&assign_asset_request.clone()).unwrap(), + step_id: "3.5".to_string(), + operation: Operation::Exec, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + + match send_assign_asset_request(assign_asset_request, conf) { + Ok(ack) => { + println!("Ack commit final assertion request."); + let reply = Ok(ack); + println!("Sending back Ack: {:?}\n", reply); + reply + } + Err(e) => { + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: format!("Error: commit final assertion request failed. {:?}", e), + }); + } + } + } else { + println!("The commit final assertion request is invalid\n"); + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: "Error: The commit final assertion request is invalid".to_string(), + }); + } +} + +pub fn process_ack_final_receipt_request( + ack_final_receipt_request: AckFinalReceiptRequest, + conf: config::Config, +) -> Result { + let request_id = ack_final_receipt_request.session_id.to_string(); + let is_valid_request = is_valid_ack_final_receipt_request(ack_final_receipt_request.clone()); + + // TODO some processing + if is_valid_request { + println!("The ack final receipt request is valid\n"); + + let log_entry = LogEntry { + request_id: request_id.clone(), + request: serde_json::to_string(&ack_final_receipt_request.clone()).unwrap(), + step_id: "3.7".to_string(), + operation: Operation::Exec, + network_id: "todo_network_id".to_string(), + gateway_id: "todo_gateway_id".to_string(), + received: true, + details: None, + }; + log::debug!("{}", log_entry); + + match send_ack_final_receipt_broadcast_request(ack_final_receipt_request, conf) { + Ok(ack) => { + println!("Ack ack final receipt request."); + let reply = Ok(ack); + println!("Sending back Ack: {:?}\n", reply); + reply + } + Err(e) => { + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: format!("Error: ack final receipt request failed. {:?}", e), + }); + } + } + } else { + println!("The ack final receipt request is invalid\n"); + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: "Error: The ack final receipt request is invalid".to_string(), + }); + } +} + +fn send_transfer_proposal_receipt_request( + transfer_proposal_receipt_request: TransferProposalReceiptRequest, + conf: config::Config, +) -> Result { + let request_id = + get_request_id_from_transfer_proposal_receipt(transfer_proposal_receipt_request.clone()); + let (relay_host, relay_port) = + get_relay_from_transfer_proposal_receipt(transfer_proposal_receipt_request.clone()); + let (use_tls, tlsca_cert_path) = + get_relay_params(relay_host.clone(), relay_port.clone(), conf.clone()); + + spawn_send_transfer_proposal_receipt_request( + transfer_proposal_receipt_request.clone(), + relay_host, + relay_port, + use_tls, + tlsca_cert_path, + ); + + let reply = Ack { + status: ack::Status::Ok as i32, + request_id: request_id.to_string(), + message: "Ack of the Transfer Proposal Claims request".to_string(), + }; + return Ok(reply); +} + +fn send_transfer_commence_request( + transfer_commence_request: TransferCommenceRequest, + conf: config::Config, +) -> Result { + let request_id = transfer_commence_request.session_id.clone(); + let (relay_host, relay_port) = + get_relay_from_transfer_commence(transfer_commence_request.clone()); + let (use_tls, tlsca_cert_path) = + get_relay_params(relay_host.clone(), relay_port.clone(), conf.clone()); + + spawn_send_transfer_commence_request( + transfer_commence_request, + relay_host, + relay_port, + use_tls, + tlsca_cert_path, + ); + let reply = Ack { + status: ack::Status::Ok as i32, + request_id: request_id.to_string(), + message: "Ack of the Transfer Proposal Claims request".to_string(), + }; + return Ok(reply); +} + +fn send_ack_commence_request( + ack_commence_request: AckCommenceRequest, + conf: config::Config, +) -> Result { + let request_id = &ack_commence_request.session_id.to_string(); + let (relay_host, relay_port) = get_relay_from_ack_commence(ack_commence_request.clone()); + let (use_tls, tlsca_cert_path) = + get_relay_params(relay_host.clone(), relay_port.clone(), conf.clone()); + + spawn_send_ack_commence_request( + ack_commence_request, + relay_host, + relay_port, + use_tls, + tlsca_cert_path, + ); + let reply = Ack { + status: ack::Status::Ok as i32, + request_id: request_id.to_string(), + message: "Ack of the Commence Response request".to_string(), + }; + return Ok(reply); +} + +fn send_lock_assertion_request( + lock_assertion_request: LockAssertionRequest, + conf: config::Config, +) -> Result { + let request_id = &lock_assertion_request.session_id.to_string(); + let (relay_host, relay_port) = get_relay_from_lock_assertion(lock_assertion_request.clone()); + let (use_tls, tlsca_cert_path) = + get_relay_params(relay_host.clone(), relay_port.clone(), conf.clone()); + + spawn_send_lock_assertion_request( + lock_assertion_request, + relay_host, + relay_port, + use_tls, + tlsca_cert_path, + ); + let reply = Ack { + status: ack::Status::Ok as i32, + request_id: request_id.to_string(), + message: "Ack of the Send Asset Status request".to_string(), + }; + return Ok(reply); +} + +fn send_lock_assertion_broadcast_request( + lock_assertion_request: LockAssertionRequest, + conf: config::Config, +) -> Result { + println_step_heading("2.3".to_string()); + + let request_id = &lock_assertion_request.session_id.to_string(); + let (relay_host, relay_port) = get_relay_from_lock_assertion(lock_assertion_request.clone()); + let (use_tls, tlsca_cert_path) = + get_relay_params(relay_host.clone(), relay_port.clone(), conf.clone()); + + spawn_send_lock_assertion_broadcast_request( + lock_assertion_request, + relay_host, + relay_port, + use_tls, + tlsca_cert_path, + ); + let reply = Ack { + status: ack::Status::Ok as i32, + request_id: request_id.to_string(), + message: "Ack of the Lock Assertion request".to_string(), + }; + return Ok(reply); +} + +fn send_perform_lock_request( + perform_lock_request: PerformLockRequest, + conf: config::Config, +) -> Result { + println_stage_heading("2".to_string()); + println_step_heading("2.1A".to_string()); + + let request_id = &perform_lock_request.session_id.to_string(); + let driver_address = get_driver_address_from_perform_lock(perform_lock_request.clone()); + let parsed_address = parse_address(driver_address)?; + let result = get_driver(parsed_address.network_id.to_string(), conf.clone()); + match result { + Ok(driver_info) => { + spawn_send_perform_lock_request(driver_info, perform_lock_request); + let reply = Ack { + status: ack::Status::Ok as i32, + request_id: request_id.to_string(), + message: "Ack of the ack commence request".to_string(), + }; + return Ok(reply); + } + Err(e) => { + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: format!( + "Error: Ack of the ack commence request failed. Driver not found {:?}", + e + ), + }); + } + } +} + +fn send_commit_prepare_request( + commit_prepare_request: CommitPrepareRequest, + conf: config::Config, +) -> Result { + println_stage_heading("3".to_string()); + let request_id = &commit_prepare_request.session_id.to_string(); + let (relay_host, relay_port) = get_relay_from_commit_prepare(commit_prepare_request.clone()); + let (use_tls, tlsca_cert_path) = + get_relay_params(relay_host.clone(), relay_port.clone(), conf.clone()); + + spawn_send_commit_prepare_request( + commit_prepare_request, + relay_host, + relay_port, + use_tls, + tlsca_cert_path, + ); + let reply = Ack { + status: ack::Status::Ok as i32, + request_id: request_id.to_string(), + message: "Ack of the Lock Assertion request".to_string(), + }; + return Ok(reply); +} + +fn send_commit_ready_request( + commit_ready_request: CommitReadyRequest, + conf: config::Config, +) -> Result { + // TODO + let request_id = &commit_ready_request.session_id.to_string(); + let (relay_host, relay_port) = get_relay_from_commit_ready(commit_ready_request.clone()); + let (use_tls, tlsca_cert_path) = + get_relay_params(relay_host.clone(), relay_port.clone(), conf.clone()); + + spawn_send_commit_ready_request( + commit_ready_request, + relay_host, + relay_port, + use_tls, + tlsca_cert_path, + ); + + let reply = Ack { + status: ack::Status::Ok as i32, + request_id: request_id.to_string(), + message: "Ack of the commit prepare request".to_string(), + }; + return Ok(reply); +} + +fn send_create_asset_request( + create_asset_request: CreateAssetRequest, + conf: config::Config, +) -> Result { + // TODO + println_step_heading("3.2A".to_string()); + + let request_id = &create_asset_request.session_id.to_string(); + let driver_address = get_driver_address_from_create_asset(create_asset_request.clone()); + let parsed_address = parse_address(driver_address)?; + let result = get_driver(parsed_address.network_id.to_string(), conf.clone()); + + match result { + Ok(driver_info) => { + spawn_send_create_asset_request(driver_info, create_asset_request); + let reply = Ack { + status: ack::Status::Ok as i32, + request_id: request_id.to_string(), + message: "Ack of the commit prepare request".to_string(), + }; + return Ok(reply); + } + Err(e) => { + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: format!( + "Error: Ack of the commit prepare request failed. Driver not found {:?}", + e + ), + }); + } + } +} + +fn send_extinguish_request( + extinguish_request: ExtinguishRequest, + conf: config::Config, +) -> Result { + // TODO + println_step_heading("3.4A".to_string()); + let request_id = &extinguish_request.session_id.to_string(); + let driver_address = get_driver_address_from_extinguish(extinguish_request.clone()); + let parsed_address = parse_address(driver_address)?; + let result = get_driver(parsed_address.network_id.to_string(), conf.clone()); + + match result { + Ok(driver_info) => { + spawn_send_extinguish_request(driver_info, extinguish_request); + let reply = Ack { + status: ack::Status::Ok as i32, + request_id: request_id.to_string(), + message: "Ack of the commit prepare request".to_string(), + }; + return Ok(reply); + } + Err(e) => { + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: format!( + "Error: Ack of the commit prepare request failed. Driver not found {:?}", + e + ), + }); + } + } +} + +fn send_commit_final_assertion_request( + commit_final_assertion_request: CommitFinalAssertionRequest, + conf: config::Config, +) -> Result { + // TODO + let request_id = &commit_final_assertion_request.session_id.to_string(); + let (relay_host, relay_port) = + get_relay_from_commit_final_assertion(commit_final_assertion_request.clone()); + let (use_tls, tlsca_cert_path) = + get_relay_params(relay_host.clone(), relay_port.clone(), conf.clone()); + + spawn_send_commit_final_assertion_request( + commit_final_assertion_request, + relay_host, + relay_port, + use_tls, + tlsca_cert_path, + ); + + let reply = Ack { + status: ack::Status::Ok as i32, + request_id: request_id.to_string(), + message: "Commit final assertion request sent".to_string(), + }; + return Ok(reply); +} + +fn send_ack_final_receipt_request( + ack_final_receipt_request: AckFinalReceiptRequest, + conf: config::Config, +) -> Result { + // TODO + let request_id = &ack_final_receipt_request.session_id.to_string(); + let (relay_host, relay_port) = + get_relay_from_ack_final_receipt(ack_final_receipt_request.clone()); + let (use_tls, tlsca_cert_path) = + get_relay_params(relay_host.clone(), relay_port.clone(), conf.clone()); + + spawn_send_ack_final_receipt_request( + ack_final_receipt_request, + relay_host, + relay_port, + use_tls, + tlsca_cert_path, + ); + + let reply = Ack { + status: ack::Status::Ok as i32, + request_id: request_id.to_string(), + message: "Ack final receipt request sent".to_string(), + }; + return Ok(reply); +} + +fn send_assign_asset_request( + assign_asset_request: AssignAssetRequest, + conf: config::Config, +) -> Result { + // TODO + println_step_heading("3.6A".to_string()); + let request_id = &assign_asset_request.session_id.to_string(); + let driver_address = get_driver_address_from_assign_asset(assign_asset_request.clone()); + let parsed_address = parse_address(driver_address)?; + let result = get_driver(parsed_address.network_id.to_string(), conf.clone()); + + match result { + Ok(driver_info) => { + spawn_send_assign_asset_request(driver_info, assign_asset_request); + let reply = Ack { + status: ack::Status::Ok as i32, + request_id: request_id.to_string(), + message: "Ack of the commit final assertion request".to_string(), + }; + return Ok(reply); + } + Err(e) => { + return Ok(Ack { + status: ack::Status::Error as i32, + request_id: request_id.to_string(), + message: format!( + "Error: Ack of the commit final assertion request failed. Driver not found {:?}", + e + ), + }); + } + } +} + +fn send_ack_final_receipt_broadcast_request( + ack_final_receipt_request: AckFinalReceiptRequest, + conf: config::Config, +) -> Result { + // TODO + println_step_heading("3.8".to_string()); + let request_id = &ack_final_receipt_request.session_id.to_string(); + let (relay_host, relay_port) = + get_relay_from_ack_final_receipt(ack_final_receipt_request.clone()); + let (use_tls, tlsca_cert_path) = + get_relay_params(relay_host.clone(), relay_port.clone(), conf.clone()); + + spawn_send_ack_final_receipt_broadcast_request( + ack_final_receipt_request, + relay_host, + relay_port, + use_tls, + tlsca_cert_path, + ); + + let reply = Ack { + status: ack::Status::Ok as i32, + request_id: request_id.to_string(), + message: "Ack of the commit prepare request".to_string(), + }; + return Ok(reply); +} + +fn is_valid_transfer_proposal_claims_request( + _transfer_proposal_claims_request: TransferProposalClaimsRequest, +) -> bool { + //TODO + true +} + +fn is_valid_transfer_proposal_receipt_request( + _transfer_proposal_receipt_request: TransferProposalReceiptRequest, +) -> bool { + //TODO + true +} + +fn is_valid_transfer_commence_request(_transfer_commence_request: TransferCommenceRequest) -> bool { + //TODO + true +} + +fn is_valid_ack_commence_request(_ack_commence_request: AckCommenceRequest) -> bool { + //TODO + true +} + +fn is_valid_lock_assertion_request(_lock_assertion_request: LockAssertionRequest) -> bool { + //TODO + true +} + +fn is_valid_lock_assertion_receipt_request( + _lock_assertion_receipt_request: LockAssertionReceiptRequest, +) -> bool { + //TODO + true +} + +fn is_valid_commit_prepare_request(_commit_prepare_request: CommitPrepareRequest) -> bool { + //TODO + true +} + +fn is_valid_commit_ready_request(_commit_ready_request: CommitReadyRequest) -> bool { + //TODO + true +} + +fn is_valid_commit_final_assertion_request( + _commit_final_assertion_request: CommitFinalAssertionRequest, +) -> bool { + //TODO + true +} + +fn is_valid_ack_final_receipt_request(_ack_final_receipt_request: AckFinalReceiptRequest) -> bool { + //TODO + true +} + +fn is_valid_send_asset_status_request(_send_asset_status_request: SendAssetStatusRequest) -> bool { + //TODO + true +} diff --git a/weaver/rfcs/formats/assets/satp.md b/weaver/rfcs/formats/assets/satp.md new file mode 100644 index 00000000000..9d92b02d82b --- /dev/null +++ b/weaver/rfcs/formats/assets/satp.md @@ -0,0 +1,237 @@ + +# Secure Asset Transfer (SAT) + +- RFC: +- Authors: Zakwan Jaroucheh, Venkatraman Ramakrishna, Sandeep Nishad, Rafael Belchior +- Status: Proposed +- Since: 04-Sep-2023 + +## Summary +This document specifies the data formats used in the [secure asset transfer protocol (SATP)](../../protocols/satp/asset-transfer/generic.md). The structures defined in this document are generic and the operations on them are generic (see the protocol specification for details.) These structures are oblivious to the specifications and semantics of any digital asset maintained by any DLT application (e.g., any application chaincode in Fabric or any CorDapp in Corda). + +## Transfer Initiation Claims negotiations (Stage-1) + +The purpose of this stage is for the sender gateway (G1) and the receiver gateway (G2) to agree on the asset instance to be transferred from the origin network NW1 to the destination network NW2. In addition, the gateways must exchange validated information or artifacts regarding the originator and beneficiary of the asset transfer, and exchange gateway-specific and network-specific parameters. + +These artifacts are contained in the Transfer Initiation Claims set that is sent from gateway G1 to G2. The set of claims may be negotiated between GH1 and G2 in multi-round set of messages. The first message (Transfer Proposal Claims) maybe multi-round in the sense there is a negotiation of the claims between G1 and G2. G1 sends the signed Transfer Initialization Claim to G2: + +```protobuf +message TransferProposalClaimsRequest { + string message_type = 1; + string asset_asset_id = 2; + string asset_profile_id = 3; + string verified_originator_entity_id = 4; + string verified_beneficiary_entity_id = 5; + string originator_pubkey = 6; + string beneficiary_pubkey = 7; + string sender_gateway_network_id = 8; + string recipient_gateway_network_id = 9; + string client_identity_pubkey = 10; + string server_identity_pubkey = 11; + string sender_gateway_owner_id = 12; + string receiver_gateway_owner_id = 13; +} +``` + +G2 accepts by signing Receipt containing hash of the TransferProposalClaimsRequest: + +```protobuf +message TransferProposalReceiptRequest { + string message_type = 1; + string asset_asset_id = 2; + string asset_profile_id = 3; + string verified_originator_entity_id = 4; + string verified_beneficiary_entity_id = 5; + string originator_pubkey = 6; + string beneficiary_pubkey = 7; + string sender_gateway_network_id = 8; + string recipient_gateway_network_id = 9; + string client_identity_pubkey = 10; + string server_identity_pubkey = 11; + string sender_gateway_owner_id = 12; + string receiver_gateway_owner_id = 13; +} +``` + +G1 chooses and opens a new session (SESSION_ID): +```protobuf +message TransferCommenceRequest { + string message_type = 1; + string session_id = 2; + string transfer_context_id = 3; + string client_identity_pubkey = 4; + string server_identity_pubkey = 5; + string hash_transfer_init_claims = 6; + string hash_prev_message = 7; + string client_transfer_number = 8; + string client_signature = 9; +} +``` + +G2 agree to proceed (using the SESSION_ID): +```protobuf +message AckCommenceRequest { + string message_type = 1; + string session_id = 2; + string transfer_context_id = 3; + string client_identity_pubkey = 4; + string server_identity_pubkey = 5; + string hash_prev_message = 6; + string server_transfer_number = 7; + string server_signature = 8; +} +``` + + +## Asset Lock Assertion and Receipt (Stage 2) + +In this stage, gateway G1 must issue a signed assertion that the asset in origin network NW1 has been immobilized and under the control of G1. + +G1 lock/escrow asset (2.1): Gateway G1 proceeds to establish a lock or escrow the asset belonging to the originator. This prevents other local transactions in NW1 from changing the state of the asset until such time the lock by G1 is finalized or released. A time-lock or escrow may also be employed: + +```protobuf +message PerformLockRequest { + string session_id = 1; +} +``` + +Lock Assertion (2.2): Gateway G1 sends a digitally signed assertion regarding the locked (escrowed or immobilized) state on the asset in network NW1. The signature by G1 is performed using its entity public-key pair. This signature signifies that G1 (i.e. its owner/operator) is legally standing behind its statement regarding the locked/escrowed state on the asset. The mechanism to lock or immobilize the asset is outside the scope of SATP: + +```protobuf +message LockAssertionRequest { + string message_type = 1; + string session_id = 2; + string transfer_context_id = 3; + string client_identity_pubkey = 4; + string server_identity_pubkey = 5; + string lock_assertion_claim = 6; + string lock_assertion_claim_format = 7; + string lock_assertion_expiration = 8; + string hash_prev_message = 9; + string client_transfer_number = 10; + string client_signature = 11; +} +``` + +G2 Logs and Broadcasts lock-assertion information (2.3): Gateway G2 logs a copy of the signed lock-assertion message received in Step 2.4 to its local state data DB2. G2 may also broadcast the fasts of the lock-assertion to all members of network NW2. The mechanism to log and to broadcast is out of scope for SATP: + +```protobuf +message LockAssertionBroadcastRequest { +} +``` + +Lock-Assertion Receipt (2.4): If gateway G2 accepts the signed assertion from G1, then G2 responds with a digitally signed receipt message which includes a hash of the previous lock-assertion message. The signature by G2 is performed using its entity public-key pair. Otherwise, if G2 declines accepting the assertion then G2 can simply ignore the transfer and let the session time-out (i.e. transfer attempt has failed): + +```protobuf +message LockAssertionReceiptRequest { + string message_type = 1; + string session_id = 2; + string transfer_context_id = 3; + string client_identity_pubkey = 4; + string server_identity_pubkey = 5; + string hash_prev_message = 6; + string server_transfer_number = 7; + string server_signature = 8; +} +``` + +## Commitment Preparation and Finalization (Stage 3) + +In Stage 3 the gateways G1 and G2 finalizes to the asset transfer by performing a commitment protocol (e.g. 2PC or 3PC) as a process (sub-protocol) embedded within the overall SATP asset transfer protocol. + +Commit-prepare (3.1): Gateway G1 indicates to G2 to prepare for the commitment of the transfer. This message must include a hash of the previous messages (message 2.5 and 2.6): + +```protobuf +message CommitPrepareRequest { + string message_type = 1; + string session_id = 2; + string transfer_context_id = 3; +} +``` + +Temporary asset mint (3.2): Gateway G2 creates (mints) an equivalent asset in NW2 assigned to itself as the owner. This step can be reversed (i.e. asset destroyed) in the case of the failure in the commitment steps because G2 is still the owner of the asset in NW2: + +```protobuf +message CreateAssetRequest { + string session_id = 1; +} +``` + +Commit-ready (3.3): Gateway G2 sends a commit-ready message to G1 indicating that it is ready to carry-out the last steps of the commitment subprotocol. Note that that the entire asset transfer session can be aborted before this step without affecting the asset state in the respective networks: + +```protobuf +message CommitReadyRequest { + string message_type = 1; + string session_id = 2; + string transfer_context_id = 3; +} +``` + +Asset burn (3.4): Gateway G1 extinguishes (burns) the asset in network NW1 which it has locked since Step 2.3: + +```protobuf +message ExtinguishRequest { + string session_id = 1; +} +``` + +Commit-final assertion (3.5): Gateway G1 indicates to G2 that G1 has performed the extinguishment of the asset in NW1. This message must be digitally signed by G1: + +```protobuf +message CommitFinalAssertionRequest { + string message_type = 1; + string session_id = 2; + string transfer_context_id = 3; +} +``` + +Asset-assignment (3.6): Gateway G2 assigns the minted asset (which it has been self-holding since Step 3.2) to the Beneficiary: + +```protobuf +message AssignAssetRequest { + string session_id = 1; +} +``` + +ACK-final receipt (3.7): Gateway G2 sends a signed assertion that it has assigned the asset to the intended Beneficiary: + +```protobuf +message AckFinalReceiptRequest { + string message_type = 1; + string session_id = 2; + string transfer_context_id = 3; +} +``` + +Receipt broadcast (3.8) Gateway G1 logs a copy of the signed receipt message to its local state data DB2. G1 may also broadcast the fasts of the signed receipt to all members of network NW1. The mechanism to log and to broadcast is out of scope for SATP: + +```protobuf +message AckFinalReceiptBroadcastRequest { +} +``` + +Transfer complete (3.9): Gateway G1 must explicitly close the asset transfer session with gateway G2. This allows both sides to close down the secure channel established earlier in Stage 1: + + +```protobuf +message TransferCompletedRequest { + string message_type = 1; + string session_id = 2; + string transfer_context_id = 3; +} +``` + + + + + + + + + + + diff --git a/weaver/rfcs/models/infrastructure/relay_satp.md b/weaver/rfcs/models/infrastructure/relay_satp.md new file mode 100644 index 00000000000..d2fe9e5394b --- /dev/null +++ b/weaver/rfcs/models/infrastructure/relay_satp.md @@ -0,0 +1,91 @@ + +# Relay Messages + +- RFC: +- Authors: Zakwan Jaroucheh, Venkatraman Ramakrishna, Sandeep Nishad, Rafael Belchior +- Status: Proposed +- Since: 04-Sep-2023 + +## Summary + +This document specifies the GRPC services whenever the gateway is involved. + +## SATP Service + +```protobuf +service SATP { + // Stage 1 endpoints + + // The sender gateway sends a TransferProposalClaims request to initiate an asset transfer. + // Depending on the proposal, multiple rounds of communication between the two gateways may happen. + rpc TransferProposalClaims(TransferProposalClaimsRequest) returns (common.ack.Ack) {}; + + // The sender gateway sends a TransferProposalClaims request to signal to the receiver gateway + // that the it is ready to start the transfer of the digital asset + rpc TransferProposalReceipt(TransferProposalReceiptRequest) returns (common.ack.Ack) {}; + + // The sender gateway sends a TransferCommence request to signal to the receiver gateway + // that the it is ready to start the transfer of the digital asset + rpc TransferCommence(TransferCommenceRequest) returns (common.ack.Ack) {}; + + // The receiver gateway sends a AckCommence request to the sender gateway to indicate agreement + // to proceed with the asset transfer + rpc AckCommence(AckCommenceRequest) returns (common.ack.Ack) {}; + + // Stage 2 endpoints + + rpc SendAssetStatus(SendAssetStatusRequest) returns (common.ack.Ack) {}; + + // The sender gateway sends a LockAssertion request to convey a signed claim to the receiver gateway + // declaring that the asset in question has been locked or escrowed by the sender gateway in + // the origin network (e.g. to prevent double spending) + rpc LockAssertion(LockAssertionRequest) returns (common.ack.Ack) {}; + + // The receiver gateway sends a LockAssertionReceipt request to the sender gateway to indicate acceptance + // of the claim(s) delivered by the sender gateway in the previous message + rpc LockAssertionReceipt(LockAssertionReceiptRequest) returns (common.ack.Ack) {}; + + rpc CommitPrepare(CommitPrepareRequest) returns (common.ack.Ack) {}; + + rpc CommitReady(CommitReadyRequest) returns (common.ack.Ack) {}; + + rpc CommitFinalAssertion(CommitFinalAssertionRequest) returns (common.ack.Ack) {}; + + rpc AckFinalReceipt(AckFinalReceiptRequest) returns (common.ack.Ack) {}; + + rpc TransferCompleted(TransferCompletedRequest) returns (common.ack.Ack) {}; +} + +``` + +## Driver Service + +```protobuf +service DriverCommunication { + // As part of SATP, the source reply (sender gateway) sends a PerformLock request to its driver + // to lock a specific asset + rpc PerformLock(PerformLockRequest) returns (common.ack.Ack) {} + + // As part of SATP, the destination reply (receiver gateway) sends a CreateAsset request to its driver + // to create a specific asset + rpc CreateAsset(CreateAssetRequest) returns (common.ack.Ack) {} + + // As part of SATP, the source reply (sender gateway) sends a Extinguish request to its driver + // to extinguish a specific asset + rpc Extinguish(ExtinguishRequest) returns (common.ack.Ack) {} + + // As part of SATP, the destination reply (receiver gateway) sends a AssignAsset request to its driver + // to assign a specific asset + rpc AssignAsset(AssignAssetRequest) returns (common.ack.Ack) {} +} +``` + +## Database + +A gateway should maintain a database to store remote queries and state of the local queries at different stages of the [asset transfer](../../protocols/satp/asset-transfer/generic.md) protocol. Before running the gateway, you need to ensure SQLite (the default database for logs) is installed by following the [database initiaization documentation](../../../../../weaver/core/relay/docs/README.md). + + diff --git a/weaver/rfcs/protocols/satp/asset-transfer/corda.md b/weaver/rfcs/protocols/satp/asset-transfer/corda.md new file mode 100644 index 00000000000..f87f5c14cbb --- /dev/null +++ b/weaver/rfcs/protocols/satp/asset-transfer/corda.md @@ -0,0 +1 @@ +# TODO \ No newline at end of file diff --git a/weaver/rfcs/protocols/satp/asset-transfer/fabric.md b/weaver/rfcs/protocols/satp/asset-transfer/fabric.md new file mode 100644 index 00000000000..a6f68141e98 --- /dev/null +++ b/weaver/rfcs/protocols/satp/asset-transfer/fabric.md @@ -0,0 +1,27 @@ + +# Asset Transfer Protocol Units in Fabric Networks + +- RFC: +- Authors: Zakwan Jaroucheh, Venkatraman Ramakrishna, Sandeep Nishad, Rafael Belchior +- Status: Proposed +- Since: 04-Sep-2023 + +## Summary + +- This document specifies the Hyperledger Fabric implementation of modules, and application adaptation guidelines, for the secure asset transfer protocol. +- Within Weaver, the protocol units to operate on the asset being transferred will be implemented in the Fabric Asset Transfer Chaincode for a Fabric-based network. +- The protocol unit functions are implemented in a library package that can be imported in any chaincode. +- Within Weaver, the SDK will provide user agents (clients) the capability to trigger transfer operations on particular chaincodes maintaining particular digital assets. + +## Fabric Asset Transfer Chaincode + +The following functions should be implemented in a separate package within the Fabric Asset Transfer Chaincode (*Note*: we use Golang syntax here because this chaincode is implemented within Weaver in Golang): + +- `func (s *SmartContract) LockAsset(ctx contractapi.TransactionContextInterface, assetExchangeAgreementSerializedProto64 string, lockInfoSerializedProto64 string) (string, error)`: locks an asset +- `func (s *SmartContract) AssignAsset(ctx contractapi.TransactionContextInterface, assetAgreementSerializedProto64 string, claimInfoSerializedProto64 string) (bool, error)`: changes the ownser of an asset +- `func (s *SmartContract) DeleteAsset(ctx contractapi.TransactionContextInterface, assetType, id string) error` deletes an asset + diff --git a/weaver/rfcs/protocols/satp/asset-transfer/generic.md b/weaver/rfcs/protocols/satp/asset-transfer/generic.md new file mode 100644 index 00000000000..8891b0eec19 --- /dev/null +++ b/weaver/rfcs/protocols/satp/asset-transfer/generic.md @@ -0,0 +1,59 @@ + +# Secure Asset Transfer Protocol + +- RFC: +- Authors: Zakwan Jaroucheh, Venkatraman Ramakrishna, Sandeep Nishad, Rafael Belchior +- Status: Proposed +- Since: 04-Sep-2023 + +## Summary + +Secure asset transfer protocol in Weaver allows transferring an asset from one network to another. It is implemented by the gateways in the respective +networks. The two gateways implement the protocol in a direct interaction (unmediated). A successful transfer results in the asset being extinguished +(burned) or marked on the origin network, and for the asset to be regenerated (minted) at the destination network. + + +## Protocol Overview + +The secure asset transfer protocol provides a coordination between the two gateways through the various message flows in the protocol that is communicated over a secure channel. The protocol implements a commitment mechanism between the two gateways to ensure that the relevant properties atomicity, consistency, isolation, and durability are achieved in the transfer. + +The mechanism to extinguish (burn) or regenerate (mint) an asset from/into a network by its gateway is dependent on the specific network and is outside the scope of the current architecture. + +In a nutshell, the protocol can be described intuitively as follows: +- **Stage 0**: The two applications utilized by the originator and beneficiary is assumed to interact as part of the asset transfer. In this stage, +the applications App1 and App2 may establish some shared transfer context information (e.g. Context-ID) at the application level that will be made available to their respective gateways G1 and G2. +- **Stage 1**: In this stage gateways G1 and G2 must exchange information (claims) regarding the asset to be transferred, the identity information of the +Originator and Beneficiary and other information regarding relevant actors (e.g. gateway owner/operator). +- **Stage 2**: Gateway G1 must provide gateway G2 with a signed assertion that the asset in NW1 has been immobilized and under the control on G1. +- **Stage 3**: Gateways G1 and G2 commit to the unidirectional asset transfer using a 3PC (3-phase commit) subprotocol. + +## Generic Asset Transfer Flow + +The asset transfer flow is illustrated in more detail in the following figure, and in the description further below. It shows the protocol followed by Alice and Bob, using transaction within the ledgers and cross-network data sharing queries across the ledgers: + + + +## Prerequisites: Smart Contract Developer Responsibilities + +The triggers for each step in the SATP flow must come from the distributed applications pledging and acquiring the asset in question. Because the transfer involves ledger updates, the smart contract portion of the application (e.g., chaincode in Hyperledger Fabric, CorDapp contract in Corda) that processes ledger data through consensus must implement and expose (through its transaction API) several functions. See the [Fabric](./fabric.md) and [Corda](./corda.md) specifications for detailed guidelines when developing applications on those platforms. (*Note*: the function names specified in these pages are suggestive; the developer may pick any suitable names.) + +The application smart contract or distributed application offering these functions must already have mechanisms to: +- Uniquely identify assets and fetch their specifications +- Unambiguously identify the owner(s) of an asset +- Perform lock (or freeze) an asset; i.e., prevent any operations (state or ownership changes) on an asset +- Determine whether an asset is currently in the locked state +- Create an asset and specify the network as the owner +- Assign an asset to an owner by transferring the ownership of the asset from the network to the new owner +- Extinguish an asset by deleting it from the corresponding network + +How the smart contract implements these functions is beyond the purview of Weaver. + +## DLT-Specific Designs + +Implementation of the protocol is DLT-specific. See the following for details on currently supported DLTs: +- [Hyperledger Fabric](./fabric.md) +- [R3 Corda](./corda.md) diff --git a/weaver/samples/fabric/fabric-cli/config.satp.template.json b/weaver/samples/fabric/fabric-cli/config.satp.template.json new file mode 100644 index 00000000000..171ab04eb02 --- /dev/null +++ b/weaver/samples/fabric/fabric-cli/config.satp.template.json @@ -0,0 +1,18 @@ +{ + "network1": { + "connProfilePath": "/tests/network-setups/fabric/shared/network1/peerOrganizations/org1.network1.com/connection-org1.json", + "relayEndpoint": "localhost:9080", + "mspId": "Org1MSP", + "channelName": "mychannel", + "chaincode": "satpsimpleasset", + "aclPolicyPrincipalType": "ca" + }, + "network2": { + "connProfilePath": "/tests/network-setups/fabric/shared/network2/peerOrganizations/org1.network2.com/connection-org1.json", + "relayEndpoint": "localhost:9083", + "mspId": "Org1MSP", + "channelName": "mychannel", + "chaincode": "satpsimpleasset", + "aclPolicyPrincipalType": "certificate" + } +} diff --git a/weaver/samples/fabric/fabric-cli/src/data/interop/satpsimpleasset/accessControlTemplate_ca.json b/weaver/samples/fabric/fabric-cli/src/data/interop/satpsimpleasset/accessControlTemplate_ca.json new file mode 100644 index 00000000000..9d804676106 --- /dev/null +++ b/weaver/samples/fabric/fabric-cli/src/data/interop/satpsimpleasset/accessControlTemplate_ca.json @@ -0,0 +1,29 @@ +{ + "securityDomain": "", + "rules": [ + { + "principal": "", + "principalType": "ca", + "resource": "mychannel:satpsimpleasset:GetHTLCHash:*", + "read": true + }, + { + "principal": "", + "principalType": "ca", + "resource": "mychannel:satpsimpleasset:GetHTLCHashByContractId:*", + "read": true + }, + { + "principal": "", + "principalType": "ca", + "resource": "mychannel:satpsimpleasset:GetHTLCHashPreImage:*", + "read": true + }, + { + "principal": "", + "principalType": "ca", + "resource": "mychannel:satpsimpleasset:GetHTLCHashPreImageByContractId:*", + "read": true + } + ] +} diff --git a/weaver/samples/fabric/fabric-cli/src/data/interop/satpsimpleasset/accessControlTemplate_certificate.json b/weaver/samples/fabric/fabric-cli/src/data/interop/satpsimpleasset/accessControlTemplate_certificate.json new file mode 100644 index 00000000000..79a86da0f84 --- /dev/null +++ b/weaver/samples/fabric/fabric-cli/src/data/interop/satpsimpleasset/accessControlTemplate_certificate.json @@ -0,0 +1,29 @@ +{ + "securityDomain": "", + "rules": [ + { + "principal": "", + "principalType": "certificate", + "resource": "mychannel:satpsimpleasset:GetHTLCHash:*", + "read": true + }, + { + "principal": "", + "principalType": "certificate", + "resource": "mychannel:satpsimpleasset:GetHTLCHashByContractId:*", + "read": true + }, + { + "principal": "", + "principalType": "certificate", + "resource": "mychannel:satpsimpleasset:GetHTLCHashPreImage:*", + "read": true + }, + { + "principal": "", + "principalType": "certificate", + "resource": "mychannel:satpsimpleasset:GetHTLCHashPreImageByContractId:*", + "read": true + } + ] +} diff --git a/weaver/samples/fabric/fabric-cli/src/data/interop/satpsimpleasset/verificationPolicyTemplate.json b/weaver/samples/fabric/fabric-cli/src/data/interop/satpsimpleasset/verificationPolicyTemplate.json new file mode 100644 index 00000000000..747b48bd31f --- /dev/null +++ b/weaver/samples/fabric/fabric-cli/src/data/interop/satpsimpleasset/verificationPolicyTemplate.json @@ -0,0 +1,33 @@ +{ + "securityDomain": "", + "identifiers": [ + { + "pattern": "mychannel:satpsimpleasset:GetHTLCHash:*", + "policy": { + "type": "Signature", + "criteria": [] + } + }, + { + "pattern": "mychannel:satpsimpleasset:GetHTLCHashByContractId:*", + "policy": { + "type": "Signature", + "criteria": [] + } + }, + { + "pattern": "mychannel:satpsimpleasset:GetHTLCHashPreImage:*", + "policy": { + "type": "Signature", + "criteria": [] + } + }, + { + "pattern": "mychannel:satpsimpleasset:GetHTLCHashPreImageByContractId:*", + "policy": { + "type": "Signature", + "criteria": [] + } + } + ] +} diff --git a/weaver/samples/fabric/satpsimpleasset/.gitignore b/weaver/samples/fabric/satpsimpleasset/.gitignore new file mode 100644 index 00000000000..6e83e63f957 --- /dev/null +++ b/weaver/samples/fabric/satpsimpleasset/.gitignore @@ -0,0 +1,4 @@ +satpsimpleasset +asset-mgmt +mocks +vendor diff --git a/weaver/samples/fabric/satpsimpleasset/Makefile b/weaver/samples/fabric/satpsimpleasset/Makefile new file mode 100644 index 00000000000..0b11edb7ab9 --- /dev/null +++ b/weaver/samples/fabric/satpsimpleasset/Makefile @@ -0,0 +1,27 @@ +run-vendor: + go mod edit -replace github.com/hyperledger/cacti/weaver/common/protos-go/v2=../../../common/protos-go/ + go mod edit -replace github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/interfaces/asset-mgmt/v2=../../../core/network/fabric-interop-cc/interfaces/asset-mgmt/ + go mod edit -replace github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/libs/testutils=../../../core/network/fabric-interop-cc/libs/testutils/ + go mod vendor + +undo-vendor: + rm -rf vendor + go mod edit -dropreplace github.com/hyperledger/cacti/weaver/common/protos-go/v2 + go mod edit -dropreplace github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/interfaces/asset-mgmt/v2 + go mod edit -dropreplace github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/libs/testutils + +build-local: run-vendor build undo-vendor + +test-local: run-vendor test undo-vendor + +build: + go build -v . + +test: + go test -v . + +clean-vendor: + rm -rf vendor + +clean: clean-vendor + rm satpsimpleasset diff --git a/weaver/samples/fabric/satpsimpleasset/assetmgmt.go b/weaver/samples/fabric/satpsimpleasset/assetmgmt.go new file mode 100644 index 00000000000..ac626b514b9 --- /dev/null +++ b/weaver/samples/fabric/satpsimpleasset/assetmgmt.go @@ -0,0 +1,356 @@ +/* + * Copyright IBM Corp. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +package main + +import ( + "encoding/json" + + "github.com/golang/protobuf/proto" + "github.com/hyperledger/cacti/weaver/common/protos-go/v2/common" + "github.com/hyperledger/fabric-contract-api-go/contractapi" + log "github.com/sirupsen/logrus" +) + +// asset specific checks (ideally an asset in a different application might implement checks specific to that asset) +func (s *SmartContract) BondAssetSpecificChecks(ctx contractapi.TransactionContextInterface, assetType, id string, lockInfoSerializedProto64 string) error { + + lockInfo, err := s.amc.ValidateAndExtractLockInfo(lockInfoSerializedProto64) + if err != nil { + return err + } + lockInfoHTLC := &common.AssetLockHTLC{} + err = proto.Unmarshal(lockInfo.LockInfo, lockInfoHTLC) + if err != nil { + return logThenErrorf("unmarshal error: %+v", err) + } + // ReadAsset should check both the existence and ownership of the asset for the locker + bond, err := s.ReadAsset(ctx, assetType, id) + if err != nil { + return logThenErrorf("failed reading the bond asset: %+v", err) + } + log.Infof("bond: %+v", *bond) + log.Infof("lockInfoHTLC: %+v", *lockInfoHTLC) + + // Check if asset doesn't mature before locking period + if uint64(bond.MaturityDate.Unix()) < lockInfoHTLC.ExpiryTimeSecs { + return logThenErrorf("cannot lock bond asset as it will mature before locking period") + } + + return nil +} + +// Ledger transaction (invocation) functions + +func (s *SmartContract) LockAsset(ctx contractapi.TransactionContextInterface, assetExchangeAgreementSerializedProto64 string, lockInfoSerializedProto64 string) (string, error) { + + assetAgreement, err := s.amc.ValidateAndExtractAssetAgreement(assetExchangeAgreementSerializedProto64) + if err != nil { + return "", err + } + + contractId, err := s.amc.LockAsset(ctx, assetExchangeAgreementSerializedProto64, lockInfoSerializedProto64) + if err != nil { + return "", logThenErrorf(err.Error()) + } + + // write to the ledger the details needed at the time of unlock/claim + err = s.amc.ContractIdAssetsLookupMap(ctx, assetAgreement.AssetType, assetAgreement.Id, contractId) + if err != nil { + return "", logThenErrorf(err.Error()) + } + + return contractId, nil +} + +func (s *SmartContract) LockFungibleAsset(ctx contractapi.TransactionContextInterface, fungibleAssetExchangeAgreementSerializedProto64 string, lockInfoSerializedProto64 string) (string, error) { + + assetAgreement, err := s.amc.ValidateAndExtractFungibleAssetAgreement(fungibleAssetExchangeAgreementSerializedProto64) + if err != nil { + return "", err + } + lockInfo, err := s.amc.ValidateAndExtractLockInfo(lockInfoSerializedProto64) + if err != nil { + return "", err + } + lockInfoHTLC := &common.AssetLockHTLC{} + err = proto.Unmarshal(lockInfo.LockInfo, lockInfoHTLC) + if err != nil { + return "", logThenErrorf("unmarshal error: %+v", err) + } + + // Check if locker/transaction-creator has enough quantity of token assets to lock + lockerHasEnoughTokens, err := s.TokenAssetsExist(ctx, assetAgreement.AssetType, assetAgreement.NumUnits) + if err != nil { + return "", logThenErrorf(err.Error()) + } + if !lockerHasEnoughTokens { + return "", logThenErrorf("cannot lock token asset of type %s as there are not enough tokens", assetAgreement.AssetType) + } + + contractId, err := s.amc.LockFungibleAsset(ctx, fungibleAssetExchangeAgreementSerializedProto64, lockInfoSerializedProto64) + if err != nil { + return "", logThenErrorf(err.Error()) + } + + err = s.DeleteTokenAssets(ctx, assetAgreement.AssetType, assetAgreement.NumUnits) + if err != nil { + // not performing the operation UnlockFungibleAsset and let the TxCreator take care of it + return contractId, logThenErrorf(err.Error()) + } + + err = s.amc.ContractIdFungibleAssetsLookupMap(ctx, assetAgreement.AssetType, assetAgreement.NumUnits, contractId) + if err != nil { + return "", logThenErrorf(err.Error()) + } + + return contractId, nil +} + +// Check whether this asset has been locked by anyone (not just by caller) +func (s *SmartContract) IsAssetLocked(ctx contractapi.TransactionContextInterface, assetAgreementSerializedProto64 string) (bool, error) { + return s.amc.IsAssetLocked(ctx, assetAgreementSerializedProto64) +} + +// Check whether a bond asset has been locked using contractId by anyone (not just by caller) +func (s *SmartContract) IsAssetLockedQueryUsingContractId(ctx contractapi.TransactionContextInterface, contractId string) (bool, error) { + return s.amc.IsAssetLockedQueryUsingContractId(ctx, contractId) +} + +// Check whether a token asset has been locked using contractId by anyone (not just by caller) +func (s *SmartContract) IsFungibleAssetLocked(ctx contractapi.TransactionContextInterface, contractId string) (bool, error) { + return s.amc.IsFungibleAssetLocked(ctx, contractId) +} + +func (s *SmartContract) ClaimAsset(ctx contractapi.TransactionContextInterface, assetAgreementSerializedProto64 string, claimInfoSerializedProto64 string) (bool, error) { + assetAgreement, err := s.amc.ValidateAndExtractAssetAgreement(assetAgreementSerializedProto64) + if err != nil { + return false, err + } + claimed, err := s.amc.ClaimAsset(ctx, assetAgreementSerializedProto64, claimInfoSerializedProto64) + if err != nil { + return false, logThenErrorf(err.Error()) + } + if claimed { + // Change asset ownership to claimant + recipientECertBase64, err := getECertOfTxCreatorBase64(ctx) + if err != nil { + return false, logThenErrorf(err.Error()) + } + asset, err := getBondAsset(ctx, assetAgreement.AssetType, assetAgreement.Id) + if err != nil { + return false, logThenErrorf(err.Error()) + } + asset.Owner = string(recipientECertBase64) + assetJSON, err := json.Marshal(asset) + if err != nil { + return false, logThenErrorf(err.Error()) + } + err = ctx.GetStub().PutState(getBondAssetKey(assetAgreement.AssetType, assetAgreement.Id), assetJSON) + if err != nil { + return false, logThenErrorf(err.Error()) + } + + err = s.amc.DeleteAssetLookupMaps(ctx, assetAgreement.AssetType, assetAgreement.Id) + if err != nil { + return false, logThenErrorf("failed to delete bond asset lookup maps: %+v", err) + } + + return true, nil + } else { + return false, logThenErrorf("claim on bond asset type %s with asset id %s failed", assetAgreement.AssetType, assetAgreement.Id) + } +} + +func (s *SmartContract) AssignAsset(ctx contractapi.TransactionContextInterface, assetAgreementSerializedProto64 string, claimInfoSerializedProto64 string) (bool, error) { + assetAgreement, err := s.amc.ValidateAndExtractAssetAgreement(assetAgreementSerializedProto64) + if err != nil { + return false, err + } + + // Change asset ownership to claimant + recipientECertBase64, err := getECertOfTxCreatorBase64(ctx) + if err != nil { + return false, logThenErrorf(err.Error()) + } + asset, err := getBondAsset(ctx, assetAgreement.AssetType, assetAgreement.Id) + if err != nil { + return false, logThenErrorf(err.Error()) + } + asset.Owner = string(recipientECertBase64) + assetJSON, err := json.Marshal(asset) + if err != nil { + return false, logThenErrorf(err.Error()) + } + err = ctx.GetStub().PutState(getBondAssetKey(assetAgreement.AssetType, assetAgreement.Id), assetJSON) + if err != nil { + return false, logThenErrorf(err.Error()) + } + + return true, nil +} + +func (s *SmartContract) ClaimAssetUsingContractId(ctx contractapi.TransactionContextInterface, contractId, claimInfoSerializedProto64 string) (bool, error) { + claimed, err := s.amc.ClaimAssetUsingContractId(ctx, contractId, claimInfoSerializedProto64) + if err != nil { + return false, logThenErrorf(err.Error()) + } + if claimed { + // Change asset ownership to claimant + recipientECertBase64, err := getECertOfTxCreatorBase64(ctx) + if err != nil { + return false, logThenErrorf(err.Error()) + } + + // Fetch the contracted bond asset type and id from the ledger + assetType, assetId, err := s.amc.FetchFromContractIdAssetLookupMap(ctx, contractId) + if err != nil { + return false, logThenErrorf(err.Error()) + } + + asset, err := getBondAsset(ctx, assetType, assetId) + if err != nil { + return false, logThenErrorf(err.Error()) + } + asset.Owner = recipientECertBase64 + assetJSON, err := json.Marshal(asset) + if err != nil { + return false, logThenErrorf(err.Error()) + } + err = ctx.GetStub().PutState(getBondAssetKey(assetType, assetId), assetJSON) + if err != nil { + return false, logThenErrorf(err.Error()) + } + // delete the lookup maps + err = s.amc.DeleteAssetLookupMapsUsingContractId(ctx, assetType, assetId, contractId) + if err != nil { + return false, logThenErrorf(err.Error()) + } + + return true, nil + } else { + return false, logThenErrorf("claim on bond asset using contractId %s failed", contractId) + } +} + +func (s *SmartContract) ClaimFungibleAsset(ctx contractapi.TransactionContextInterface, contractId, claimInfoSerializedProto64 string) (bool, error) { + claimed, err := s.amc.ClaimFungibleAsset(ctx, contractId, claimInfoSerializedProto64) + if err != nil { + return false, logThenErrorf(err.Error()) + } + if claimed { + // Add the claimed tokens into the wallet of the claimant + recipientECertBase64, err := getECertOfTxCreatorBase64(ctx) + if err != nil { + return false, logThenErrorf(err.Error()) + } + + // Fetch the contracted token asset type and numUnits from the ledger + assetType, numUnits, err := s.amc.FetchFromContractIdFungibleAssetLookupMap(ctx, contractId) + if err != nil { + return false, logThenErrorf(err.Error()) + } + + err = s.IssueTokenAssets(ctx, assetType, numUnits, recipientECertBase64) + if err != nil { + return false, logThenErrorf(err.Error()) + } + err = s.amc.DeleteFungibleAssetLookupMap(ctx, contractId) + if err != nil { + return false, logThenErrorf(err.Error()) + } + return true, nil + } else { + return false, logThenErrorf("claim on token asset using contractId %s failed", contractId) + } +} + +func (s *SmartContract) UnlockAsset(ctx contractapi.TransactionContextInterface, assetAgreementSerializedProto64 string) (bool, error) { + assetAgreement, err := s.amc.ValidateAndExtractAssetAgreement(assetAgreementSerializedProto64) + if err != nil { + return false, err + } + + unlocked, err := s.amc.UnlockAsset(ctx, assetAgreementSerializedProto64) + if err != nil { + return false, logThenErrorf(err.Error()) + } + if unlocked { + err = s.amc.DeleteAssetLookupMaps(ctx, assetAgreement.AssetType, assetAgreement.Id) + if err != nil { + return false, logThenErrorf("failed to delete bond asset lookup maps: %+v", err) + } + } else { + return false, logThenErrorf("unlock on bond asset type %s with asset id %s failed", assetAgreement.AssetType, assetAgreement.Id) + } + + return true, nil +} + +func (s *SmartContract) UnlockAssetUsingContractId(ctx contractapi.TransactionContextInterface, contractId string) (bool, error) { + unlocked, err := s.amc.UnlockAssetUsingContractId(ctx, contractId) + if err != nil { + return false, logThenErrorf(err.Error()) + } + if unlocked { + // delete the lookup maps + err := s.amc.DeleteAssetLookupMapsOnlyUsingContractId(ctx, contractId) + if err != nil { + return false, logThenErrorf(err.Error()) + } + return true, nil + } else { + return false, logThenErrorf("unlock on bond asset using contractId %s failed", contractId) + } +} + +func (s *SmartContract) UnlockFungibleAsset(ctx contractapi.TransactionContextInterface, contractId string) (bool, error) { + unlocked, err := s.amc.UnlockFungibleAsset(ctx, contractId) + if err != nil { + return false, logThenErrorf(err.Error()) + } + if unlocked { + // Add the unlocked tokens into the wallet of the locker + lockerECertBase64, err := getECertOfTxCreatorBase64(ctx) + if err != nil { + return false, logThenErrorf(err.Error()) + } + + // Fetch the contracted token asset type and numUnits from the ledger + assetType, numUnits, err := s.amc.FetchFromContractIdFungibleAssetLookupMap(ctx, contractId) + if err != nil { + return false, logThenErrorf(err.Error()) + } + + err = s.IssueTokenAssets(ctx, assetType, numUnits, lockerECertBase64) + if err != nil { + return false, logThenErrorf(err.Error()) + } + err = s.amc.DeleteFungibleAssetLookupMap(ctx, contractId) + if err != nil { + return false, logThenErrorf(err.Error()) + } + return true, nil + } else { + return false, logThenErrorf("unlock on token asset using contractId %s failed", contractId) + } +} + +func (s *SmartContract) GetHTLCHash(ctx contractapi.TransactionContextInterface, assetAgreementBytesBase64 string) (string, error) { + return s.amc.GetHTLCHash(ctx, assetAgreementBytesBase64) +} + +func (s *SmartContract) GetHTLCHashByContractId(ctx contractapi.TransactionContextInterface, contractId string) (string, error) { + return s.amc.GetHTLCHashByContractId(ctx, contractId) +} + +func (s *SmartContract) GetHTLCHashPreImage(ctx contractapi.TransactionContextInterface, assetAgreementBytesBase64 string) (string, error) { + return s.amc.GetHTLCHashPreImage(ctx, assetAgreementBytesBase64) +} + +func (s *SmartContract) GetHTLCHashPreImageByContractId(ctx contractapi.TransactionContextInterface, contractId string) (string, error) { + return s.amc.GetHTLCHashPreImageByContractId(ctx, contractId) +} diff --git a/weaver/samples/fabric/satpsimpleasset/assetmgmt_test.go b/weaver/samples/fabric/satpsimpleasset/assetmgmt_test.go new file mode 100644 index 00000000000..83db59decd6 --- /dev/null +++ b/weaver/samples/fabric/satpsimpleasset/assetmgmt_test.go @@ -0,0 +1,232 @@ +package main_test + +import ( + "encoding/json" + "encoding/base64" + "crypto/sha256" + "fmt" + "testing" + "time" + + mspProtobuf "github.com/hyperledger/fabric-protos-go/msp" + "github.com/golang/protobuf/proto" + "github.com/hyperledger/fabric-chaincode-go/shim" + "github.com/stretchr/testify/require" + sa "github.com/hyperledger/cacti/weaver/samples/fabric/satpsimpleasset" + "github.com/hyperledger/cacti/weaver/common/protos-go/v2/common" + wtest "github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/libs/testutils" +) + +// function that supplies value that is to be returned by ctx.GetStub().GetCreator() in locker/recipient context +func getCreatorInContext(creator string) string { + serializedIdentity := &mspProtobuf.SerializedIdentity{} + var eCertBytes []byte + if creator == "locker" { + eCertBytes, _ = base64.StdEncoding.DecodeString(getLockerECertBase64()) + } else { + eCertBytes, _ = base64.StdEncoding.DecodeString(getRecipientECertBase64()) + } + serializedIdentity.IdBytes = eCertBytes + serializedIdentity.Mspid = "ca.org1.example.com" + serializedIdentityBytes, _ := proto.Marshal(serializedIdentity) + + return string(serializedIdentityBytes) +} + +// function that supplies the ECert in base64 for locker (e.g., Alice) +func getLockerECertBase64() string { + eCertBase64 := "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNyVENDQWxTZ0F3SUJBZ0lVSENXLzBtV0xhc2hISG9zd0xxVWhpK1FwREc4d0NnWUlLb1pJemowRUF3SXcKY2pFTE1Ba0dBMVVFQmhNQ1ZWTXhGekFWQmdOVkJBZ1REazV2Y25Sb0lFTmhjbTlzYVc1aE1ROHdEUVlEVlFRSApFd1pFZFhKb1lXMHhHakFZQmdOVkJBb1RFVzl5WnpFdWJtVjBkMjl5YXpFdVkyOXRNUjB3R3dZRFZRUURFeFJqCllTNXZjbWN4TG01bGRIZHZjbXN4TG1OdmJUQWVGdzB5TURBM01qa3dORE0yTURCYUZ3MHlNVEEzTWprd05EUXgKTURCYU1GMHhDekFKQmdOVkJBWVRBbFZUTVJjd0ZRWURWUVFJRXc1T2IzSjBhQ0JEWVhKdmJHbHVZVEVVTUJJRwpBMVVFQ2hNTFNIbHdaWEpzWldSblpYSXhEekFOQmdOVkJBc1RCbU5zYVdWdWRERU9NQXdHQTFVRUF4TUZkWE5sCmNqRXdXVEFUQmdjcWhrak9QUUlCQmdncWhrak9QUU1CQndOQ0FBU3VoL3JWQ2Y4T0R1dzBJaG5yTTJpaWYyYTcKc0dUOEJJVjFQRURVM1NucUNsbWgrUlYvM0p5S2wvVHl0aHpOL1pWbktFL3R2NWQzZ1ZXYk5zdGM5NytTbzRIYwpNSUhaTUE0R0ExVWREd0VCL3dRRUF3SUhnREFNQmdOVkhSTUJBZjhFQWpBQU1CMEdBMVVkRGdRV0JCUXgvaExZCkNORzRlekNxdmdUS0MvV3d1U1ZubURBZkJnTlZIU01FR0RBV2dCVFdENjArZUNIYkR5RDMzUFdiQ3hWdVFxTUEKcVRBZkJnTlZIUkVFR0RBV2doUnZZelV4TURNM05EY3pPREF1YVdKdExtTnZiVEJZQmdncUF3UUZCZ2NJQVFSTQpleUpoZEhSeWN5STZleUpvWmk1QlptWnBiR2xoZEdsdmJpSTZJaUlzSW1obUxrVnVjbTlzYkcxbGJuUkpSQ0k2CkluVnpaWEl4SWl3aWFHWXVWSGx3WlNJNkltTnNhV1Z1ZENKOWZUQUtCZ2dxaGtqT1BRUURBZ05IQURCRUFpQUYKbnNMNlV1eFRtSks5bmhkTU1QNWxWN3hueVlsMVd5RGl6RVFzZnd1T1p3SWdYY3duSE9hVURXWWpmWHRGU0k1eQp6WjltcjZQRWtSNER0VEhJUkZhTVYxOD0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ==" + + return eCertBase64 +} + +// function that supplies the ECert in base64 for recipient (e.g., Bob) +func getRecipientECertBase64() string { + eCertBase64 := "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNzekNDQWxxZ0F3SUJBZ0lVSjk3ZDJaWUNkRkNHbFo5L3hmZHRlcUdMc1Jvd0NnWUlLb1pJemowRUF3SXcKY2pFTE1Ba0dBMVVFQmhNQ1ZWTXhGekFWQmdOVkJBZ1REazV2Y25Sb0lFTmhjbTlzYVc1aE1ROHdEUVlEVlFRSApFd1pFZFhKb1lXMHhHakFZQmdOVkJBb1RFVzl5WnpFdWJtVjBkMjl5YXpFdVkyOXRNUjB3R3dZRFZRUURFeFJqCllTNXZjbWN4TG01bGRIZHZjbXN4TG1OdmJUQWVGdzB5TURBM01qa3dORE0yTURCYUZ3MHlNVEEzTWprd05EUXgKTURCYU1HQXhDekFKQmdOVkJBWVRBbFZUTVJjd0ZRWURWUVFJRXc1T2IzSjBhQ0JEWVhKdmJHbHVZVEVVTUJJRwpBMVVFQ2hNTFNIbHdaWEpzWldSblpYSXhEakFNQmdOVkJBc1RCV0ZrYldsdU1SSXdFQVlEVlFRREV3bHZjbWN4CllXUnRhVzR3V1RBVEJnY3Foa2pPUFFJQkJnZ3Foa2pPUFFNQkJ3TkNBQVFmbjRmVHRDclQ3WVMrZVI1WWRFVU8KMHRKWmJGaEtyYUdqeWVNM2tBTzNNN1VHdVBsUCtXcFdjNkNYUEx3bTNETHgrcjFhMUx6eW1KUWdaOVJjdXErcgpvNEhmTUlIY01BNEdBMVVkRHdFQi93UUVBd0lIZ0RBTUJnTlZIUk1CQWY4RUFqQUFNQjBHQTFVZERnUVdCQlM2ClkxR1FCMXAwUlNBeWxjTTRxQTlZS0JkU2hEQWZCZ05WSFNNRUdEQVdnQlRXRDYwK2VDSGJEeUQzM1BXYkN4VnUKUXFNQXFUQWZCZ05WSFJFRUdEQVdnaFJ2WXpVeE1ETTNORGN6T0RBdWFXSnRMbU52YlRCYkJnZ3FBd1FGQmdjSQpBUVJQZXlKaGRIUnljeUk2ZXlKb1ppNUJabVpwYkdsaGRHbHZiaUk2SWlJc0ltaG1Ma1Z1Y205c2JHMWxiblJKClJDSTZJbTl5WnpGaFpHMXBiaUlzSW1obUxsUjVjR1VpT2lKaFpHMXBiaUo5ZlRBS0JnZ3Foa2pPUFFRREFnTkgKQURCRUFpQkwrSzAzVGFFeWJaRkdWMmMzSS81ZXlpMFBveGc2elZOWDJkajJWRlk5WWdJZ0w5ZlhzcWhaUEU0VApBSkU4ZVZqdWZaOVJnNERJWWloTVVTKzBPbGpWL3pBPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0t" + return eCertBase64 +} + +// function to generate a "SHA256" hash in base64 format for a given preimage +func generateSHA256HashInBase64Form(preimage string) string { + hasher := sha256.New() + hasher.Write([]byte(preimage)) + shaHash := hasher.Sum(nil) + shaHashBase64 := base64.StdEncoding.EncodeToString(shaHash) + return shaHashBase64 +} + +type ContractedFungibleAsset struct { + Type string `json:"type"` + NumUnits uint64 `json:"id"` +} + +// test case for "asset exchange" happy path +func TestExchangeBondAssetWithTokenAsset(t *testing.T) { + ctx, chaincodeStub := wtest.PrepMockStub() + sc := sa.SmartContract{} + sc.ConfigureInterop("interopcc") + + bondLocker := getLockerECertBase64() + bondRecipient := getRecipientECertBase64() + bondType := "bond" + bondId := "b01" + bondIssuer := "network1" + bondFaceValue := 1 + currentTime := time.Now() + bondMaturityDate := currentTime.Add(time.Hour * 24) // maturity date is 1 day after current time + + tokenType := "cbdc" + tokenIssuer := "network2" + tokenValue := 1 + numTokens := uint64(10) + tokensLocker := getRecipientECertBase64() + tokensRecipient := getLockerECertBase64() + + + // Create bond asset + // let ctx.GetStub().GetState() return that the bond asset didn't exist before + chaincodeStub.GetStateReturnsOnCall(0, nil, nil) + err := sc.CreateAsset(ctx, bondType, bondId, bondLocker, bondIssuer, bondFaceValue, bondMaturityDate.Format(time.RFC822)) + require.NoError(t, err) + + + // Create token asset type + chaincodeStub.GetStateReturnsOnCall(1, nil, nil) + res, err := sc.CreateTokenAssetType(ctx, tokenType, tokenIssuer, tokenValue) + require.NoError(t, err) + require.Equal(t, res, true) + + + // Issue token assets for Bob + tokenAssetType := sa.TokenAssetType { + Issuer: tokenIssuer, + Value: tokenValue, + } + tokenAssetTypeBytes, _ := json.Marshal(tokenAssetType) + chaincodeStub.GetStateReturnsOnCall(2, tokenAssetTypeBytes, nil) + walletMap := make(map[string]uint64) + tokensWallet := &sa.TokenWallet{WalletMap: walletMap} + tokensWalletBytes, _ := json.Marshal(tokensWallet) + chaincodeStub.GetStateReturnsOnCall(3, tokensWalletBytes, nil) + err = sc.IssueTokenAssets(ctx, tokenType, numTokens, getRecipientECertBase64()) + require.NoError(t, err) + + + // Lock bond asset in network1 by Alice for Bob + fmt.Println("*** Lock bond asset in network1 by Alice ***") + preimage := "abcd" + hashBase64 := generateSHA256HashInBase64Form(preimage) + defaultTimeLockSecs := uint64(300) // set default locking period as 5 minutes + currentTimeSecs := uint64(time.Now().Unix()) + bondContractId := "bond-contract" + lockInfoHTLC := &common.AssetLockHTLC { + HashBase64: []byte(hashBase64), + ExpiryTimeSecs: currentTimeSecs + defaultTimeLockSecs, + TimeSpec: common.TimeSpec_EPOCH, + } + lockInfoHTLCBytes, _ := proto.Marshal(lockInfoHTLC) + lockInfo := &common.AssetLock{ + LockInfo: lockInfoHTLCBytes, + } + lockInfoBytes, _ := proto.Marshal(lockInfo) + bondAgreement := &common.AssetExchangeAgreement { + AssetType: bondType, + Id: bondId, + Locker: bondLocker, + Recipient: bondRecipient, + } + bondAgreementBytes, _ := proto.Marshal(bondAgreement) + bondAsset := sa.BondAsset { + Type: bondType, + ID: bondId, + Owner: bondLocker, + Issuer: bondIssuer, + FaceValue: bondFaceValue, + MaturityDate: bondMaturityDate, + } + bondAssetBytes, err := json.Marshal(bondAsset) + chaincodeStub.GetCreatorReturnsOnCall(0, []byte(getCreatorInContext("locker")), nil) + chaincodeStub.GetStateReturnsOnCall(4, bondAssetBytes, nil) + chaincodeStub.InvokeChaincodeReturnsOnCall(0, shim.Success([]byte("false"))) + chaincodeStub.InvokeChaincodeReturnsOnCall(1, shim.Success([]byte(bondContractId))) + bondContractId, err = sc.LockAsset(ctx, base64.StdEncoding.EncodeToString(bondAgreementBytes), base64.StdEncoding.EncodeToString(lockInfoBytes)) + require.NoError(t, err) + require.NotEmpty(t, bondContractId) + + + // Lock token asset in network2 by Bob for Alice + fmt.Println("*** Lock token asset in network2 by Bob ***") + tokensContractId := "tokens-contract" + tokensAgreement := &common.FungibleAssetExchangeAgreement { + AssetType: tokenType, + NumUnits: numTokens, + Locker: tokensLocker, + Recipient: tokensRecipient, + } + tokensAgreementBytes, _ := proto.Marshal(tokensAgreement) + chaincodeStub.GetCreatorReturnsOnCall(1, []byte(getCreatorInContext("recipient")), nil) + tokenAssetType = sa.TokenAssetType { + Issuer: tokenIssuer, + Value: tokenValue, + } + tokenAssetTypeBytes, _ = json.Marshal(tokenAssetType) + chaincodeStub.GetStateReturnsOnCall(5, tokenAssetTypeBytes, nil) + walletMap = make(map[string]uint64) + walletMap[tokenType] = numTokens + tokensWallet = &sa.TokenWallet{WalletMap: walletMap} + tokensWalletBytes, _ = json.Marshal(tokensWallet) + chaincodeStub.GetStateReturnsOnCall(6, tokensWalletBytes, nil) + chaincodeStub.InvokeChaincodeReturnsOnCall(2, shim.Success([]byte(tokensContractId))) + chaincodeStub.GetCreatorReturnsOnCall(2, []byte(getCreatorInContext("recipient")), nil) + chaincodeStub.GetStateReturnsOnCall(7, tokenAssetTypeBytes, nil) + chaincodeStub.GetStateReturnsOnCall(8, tokensWalletBytes, nil) + tokensContractId, err = sc.LockFungibleAsset(ctx, base64.StdEncoding.EncodeToString(tokensAgreementBytes), base64.StdEncoding.EncodeToString(lockInfoBytes)) + require.NoError(t, err) + require.NotEmpty(t, tokensContractId) + + + // Claim token asset in network2 by Alice + fmt.Println("*** Claim token asset in network2 by Alice ***") + preimageBase64 := base64.StdEncoding.EncodeToString([]byte(preimage)) + claimInfoHTLC := &common.AssetClaimHTLC { + HashPreimageBase64: []byte(preimageBase64), + } + claimInfoHTLCBytes, _ := proto.Marshal(claimInfoHTLC) + claimInfo := &common.AssetClaim{ + ClaimInfo: claimInfoHTLCBytes, + LockMechanism: common.LockMechanism_HTLC, + } + claimInfoBytes, _ := proto.Marshal(claimInfo) + chaincodeStub.InvokeChaincodeReturnsOnCall(3, shim.Success(nil)) + chaincodeStub.GetCreatorReturnsOnCall(3, []byte(getCreatorInContext("locker")), nil) + chaincodeStub.GetCreatorReturnsOnCall(4, []byte(getCreatorInContext("locker")), nil) + tokenAssetType = sa.TokenAssetType { + Issuer: tokenIssuer, + Value: tokenValue, + } + tokenAssetTypeBytes, _ = json.Marshal(tokenAssetType) + contractedTokenAsset := ContractedFungibleAsset{ + Type: tokenType, + NumUnits: numTokens, + } + + contractedTokenAssetBytes, _ := json.Marshal(contractedTokenAsset) + chaincodeStub.GetStateReturnsOnCall(9, tokenAssetTypeBytes, nil) + chaincodeStub.GetStateReturnsOnCall(10, contractedTokenAssetBytes, nil) + chaincodeStub.GetStateReturnsOnCall(11, nil, nil) + _, err = sc.ClaimFungibleAsset(ctx, base64.StdEncoding.EncodeToString(tokensAgreementBytes), base64.StdEncoding.EncodeToString(claimInfoBytes)) + require.NoError(t, err) + + + // Claim bond asset in network1 by Bob + fmt.Println("*** Claim bond asset in network1 by Bob ***") + chaincodeStub.InvokeChaincodeReturnsOnCall(4, shim.Success(nil)) + chaincodeStub.InvokeChaincodeReturnsOnCall(5, shim.Success([]byte("true"))) + chaincodeStub.InvokeChaincodeReturnsOnCall(6, shim.Success([]byte("true"))) + chaincodeStub.GetCreatorReturnsOnCall(5, []byte(getCreatorInContext("recipient")), nil) + chaincodeStub.GetStateReturnsOnCall(12, bondAssetBytes, nil) + chaincodeStub.GetStateReturnsOnCall(13, []byte(bondContractId), nil) + _, err = sc.ClaimAsset(ctx, base64.StdEncoding.EncodeToString(bondAgreementBytes), base64.StdEncoding.EncodeToString(claimInfoBytes)) + require.NoError(t, err) + +} diff --git a/weaver/samples/fabric/satpsimpleasset/bondasset.go b/weaver/samples/fabric/satpsimpleasset/bondasset.go new file mode 100644 index 00000000000..e5cb7cbf1f2 --- /dev/null +++ b/weaver/samples/fabric/satpsimpleasset/bondasset.go @@ -0,0 +1,327 @@ +package main + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "time" + + "github.com/golang/protobuf/proto" + "github.com/hyperledger/cacti/weaver/common/protos-go/v2/common" + "github.com/hyperledger/fabric-contract-api-go/contractapi" +) + + +type BondAsset struct { + Type string `json:"type"` + ID string `json:"id"` + Owner string `json:"owner"` + Issuer string `json:"issuer"` + FaceValue int `json:"facevalue"` + MaturityDate time.Time `json:"maturitydate"` +} + +func getBondAssetKey(assetType string, assetId string) string { + return assetType + assetId +} + +func getBondAsset(ctx contractapi.TransactionContextInterface, assetType, id string) (*BondAsset, error) { + assetJSON, err := ctx.GetStub().GetState(getBondAssetKey(assetType, id)) + if err != nil { + return nil, fmt.Errorf("failed to read asset record from world state: %v", err) + } + if assetJSON == nil { + return nil, fmt.Errorf("the asset %s does not exist", id) + } + + var asset BondAsset + err = json.Unmarshal(assetJSON, &asset) + if err != nil { + return nil, err + } + return &asset, nil +} + +// InitBondAssetLedger adds a base set of assets to the ledger +func (s *SmartContract) InitBondAssetLedger(ctx contractapi.TransactionContextInterface) error { + assets := []BondAsset{ + {Type: "t1", ID: "a01", Issuer: "Treasury" , Owner: "", FaceValue: 300, + MaturityDate: time.Date(2022, time.April, 1, 12, 0, 0, 0, time.UTC)}, + {Type: "t1", ID: "a02", Issuer: "Treasury" , Owner: "", FaceValue: 400, + MaturityDate: time.Date(2022, time.July, 1, 12, 0, 0, 0, time.UTC)}, + } + + for _, asset := range assets { + assetJSON, err := json.Marshal(asset) + if err != nil { + return err + } + + err = ctx.GetStub().PutState(getBondAssetKey(asset.Type, asset.ID), assetJSON) + if err != nil { + return fmt.Errorf("failed to put to world state. %v", err) + } + } + + return nil +} + +// CreateAsset issues a new asset to the world state with given details. +func (s *SmartContract) CreateAsset(ctx contractapi.TransactionContextInterface, assetType, id, owner, issuer string, faceValue int, maturityDate string) error { + if assetType == "" { + return fmt.Errorf("Asset type cannot be blank") + } + if id == "" { + return fmt.Errorf("Asset ID cannot be blank") + } + if owner == "" && issuer == "" { + return fmt.Errorf("Asset Owner and Issuer cannot both be blank") + } + exists, err := s.AssetExists(ctx, assetType, id) + if err != nil { + return err + } + if exists { + return fmt.Errorf("the asset %s already exists", id) + } + + md_time, err := time.Parse(time.RFC822, maturityDate) + if err != nil { + return fmt.Errorf("maturity date provided is not in correct format, please use this format: %s", time.RFC822) + } + + if md_time.Before(time.Now()) { + return fmt.Errorf("maturity date can not be in past.") + } + + asset := BondAsset{ + Type: assetType, + ID: id, + Owner: owner, + Issuer: issuer, + FaceValue: faceValue, + MaturityDate: md_time, + } + assetJSON, err := json.Marshal(asset) + if err != nil { + return err + } + + return ctx.GetStub().PutState(getBondAssetKey(assetType, id), assetJSON) +} + +// ReadAsset returns the asset stored in the world state with given id. +// This function is called with the parameter inUpdateOwnerContext value as false, except in the update-owner context +func (s *SmartContract) ReadAsset(ctx contractapi.TransactionContextInterface, assetType, id string) (*BondAsset, error) { + asset, err := getBondAsset(ctx, assetType, id) + if err != nil { + return nil, err + } + if !checkAccessToAsset(s, ctx, asset) { + return nil, fmt.Errorf("cannot access Bond Asset %s", id) + } + return asset, nil +} + +// DeleteAsset deletes an given asset from the world state. +func (s *SmartContract) DeleteAsset(ctx contractapi.TransactionContextInterface, assetType, id string) error { + + // Read the asset (which internally check access) + asset, err := s.ReadAsset(ctx, assetType, id) + if err != nil { + return err + } + return ctx.GetStub().DelState(getBondAssetKey(asset.Type, asset.ID)) +} + + +// isCallerAssetOwner returns true only if the invoker of the transaction is also the asset owner +func isCallerAssetOwner(ctx contractapi.TransactionContextInterface, asset *BondAsset) bool { + caller, err := getECertOfTxCreatorBase64(ctx) + if err != nil { + fmt.Println(err.Error()) + return false + } + return (asset.Owner == caller) +} + +// isBondAssetLocked returns true only if the asset is presently locked +func isBondAssetLocked(s *SmartContract, ctx contractapi.TransactionContextInterface, asset *BondAsset) bool { + bondAssetAgreement := &common.AssetExchangeAgreement{ + AssetType: asset.Type, + Id: asset.ID, + Recipient: "*", + Locker: asset.Owner, + } + bondAssetAgreementProtoSerialized, err := proto.Marshal(bondAssetAgreement) + if err != nil { + fmt.Println(err.Error()) + return false + } + bondAssetAgreementProto64 := base64.StdEncoding.EncodeToString(bondAssetAgreementProtoSerialized) + locked, err := s.IsAssetLocked(ctx, bondAssetAgreementProto64) + if err != nil { + fmt.Println(err.Error()) + return false + } + return locked +} + +// isBondAssetLockedForMe returns true only if the asset is presently locked for me +func isBondAssetLockedForMe(s *SmartContract, ctx contractapi.TransactionContextInterface, asset *BondAsset) bool { + bondAssetAgreement := &common.AssetExchangeAgreement{ + AssetType: asset.Type, + Id: asset.ID, + Recipient: "", + Locker: asset.Owner, + } + bondAssetAgreementProtoSerialized, err := proto.Marshal(bondAssetAgreement) + if err != nil { + fmt.Println(err.Error()) + return false + } + bondAssetAgreementProto64 := base64.StdEncoding.EncodeToString(bondAssetAgreementProtoSerialized) + locked, err := s.IsAssetLocked(ctx, bondAssetAgreementProto64) + if err != nil { + fmt.Println(err.Error()) + return false + } + return locked +} + +// checkAccessToAsset checks several conditions under which an asset can be put on hold (i.e., not available for regular business operation) +func checkAccessToAsset(s *SmartContract, ctx contractapi.TransactionContextInterface, asset *BondAsset) bool { + // Ensure that the client is the owner of the asset + if !isCallerAssetOwner(ctx, asset) { + fmt.Printf("Illegal update: caller is not owner of asset %s\n", asset.ID) + return false + } + + // Ensure that the asset is not locked + if isBondAssetLocked(s, ctx, asset) { + fmt.Printf("Cannot update attributes of locked asset %s\n", asset.ID) + return false + } + + return true +} + +// AssetExists returns true when asset with given ID exists in world state +func (s *SmartContract) AssetExists(ctx contractapi.TransactionContextInterface, assetType, id string) (bool, error) { + assetJSON, err := ctx.GetStub().GetState(getBondAssetKey(assetType, id)) + if err != nil { + return false, fmt.Errorf("failed to read asset record from world state: %v", err) + } + + return assetJSON != nil, nil +} + +// IsAssetReleased returns true if asset maturity date elapses +func (s *SmartContract) IsAssetReleased(ctx contractapi.TransactionContextInterface, assetType, id string) (bool, error) { + asset, err := s.ReadAsset(ctx, assetType, id) + if err != nil { + return false, err + } + currDate := time.Now() + if (currDate.After(asset.MaturityDate)) { + return true, nil + } + + return false, nil +} + +// UpdateOwner sets the owner of an asset to a new owner. +func (s *SmartContract) UpdateOwner(ctx contractapi.TransactionContextInterface, assetType, id string, newOwner string) error { + // Read asset (which internally checks access if it is free to modified) + asset, err := s.ReadAsset(ctx, assetType, id) + if err != nil { + return err + } + + asset.Owner = newOwner + assetJSON, err := json.Marshal(asset) + if err != nil { + return err + } + + return ctx.GetStub().PutState(getBondAssetKey(assetType, id), assetJSON) +} + +// UpdateMaturityDate sets the maturity date of the asset to an updated date as passed in the parameters. +func (s *SmartContract) UpdateMaturityDate(ctx contractapi.TransactionContextInterface, assetType, id string, newMaturityDate time.Time) error { + // Read asset (which internally checks access if it is free to modified) + asset, err := s.ReadAsset(ctx, assetType, id) + if err != nil { + return err + } + + asset.MaturityDate = newMaturityDate + assetJSON, err := json.Marshal(asset) + if err != nil { + return err + } + + return ctx.GetStub().PutState(getBondAssetKey(assetType, id), assetJSON) +} + +// UpdateFaceValue sets the face value of an asset to the new value passed. +func (s *SmartContract) UpdateFaceValue(ctx contractapi.TransactionContextInterface, assetType, id string, newFaceValue int) error { + // Read asset (which internally checks access if it is free to modified) + asset, err := s.ReadAsset(ctx, assetType, id) + if err != nil { + return err + } + + asset.FaceValue = newFaceValue + assetJSON, err := json.Marshal(asset) + if err != nil { + return err + } + + return ctx.GetStub().PutState(getBondAssetKey(assetType, id), assetJSON) +} + +// GetMyAssets returns the assets owner by the caller +func (s *SmartContract) GetMyAssets(ctx contractapi.TransactionContextInterface) ([]*BondAsset, error) { + assets, err := s.GetAllAssets(ctx) + if err != nil { + return nil, err + } + + var myassets []*BondAsset + + for _, asset := range assets { + if checkAccessToAsset(s, ctx, asset) { + myassets = append(myassets, asset) + } + } + return myassets, nil +} + +// GetAllAssets returns all assets found in world state +func (s *SmartContract) GetAllAssets(ctx contractapi.TransactionContextInterface) ([]*BondAsset, error) { + // range query with empty string for startKey and endKey does an + // open-ended query of all assets in the chaincode namespace. + resultsIterator, err := ctx.GetStub().GetStateByRange("", "") + if err != nil { + return nil, err + } + defer resultsIterator.Close() + + var assets []*BondAsset + for resultsIterator.HasNext() { + queryResponse, err := resultsIterator.Next() + if err != nil { + return nil, err + } + + var asset BondAsset + err = json.Unmarshal(queryResponse.Value, &asset) + if err != nil { + return nil, err + } + assets = append(assets, &asset) + } + + return assets, nil +} diff --git a/weaver/samples/fabric/satpsimpleasset/bondasset_test.go b/weaver/samples/fabric/satpsimpleasset/bondasset_test.go new file mode 100644 index 00000000000..b43170e23a1 --- /dev/null +++ b/weaver/samples/fabric/satpsimpleasset/bondasset_test.go @@ -0,0 +1,242 @@ +package main_test + +import ( + "encoding/json" + "fmt" + "testing" + "time" + + "github.com/hyperledger/fabric-protos-go/ledger/queryresult" + sa "github.com/hyperledger/cacti/weaver/samples/fabric/satpsimpleasset" + "github.com/stretchr/testify/require" + wtest "github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/libs/testutils" + wtestmocks "github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/libs/testutils/mocks" +) + +const ( + defaultAssetType = "BearerBonds" + defaultAssetId = "asset1" + defaultAssetOwner = "Alice" + defaultAssetIssuer = "Treasury" +) + +func TestInitBondAssetLedger(t *testing.T) { + transactionContext, chaincodeStub := wtest.PrepMockStub() + simpleAsset := sa.SmartContract{} + simpleAsset.ConfigureInterop("interopcc") + + err := simpleAsset.InitBondAssetLedger(transactionContext) + require.NoError(t, err) + + chaincodeStub.PutStateReturns(fmt.Errorf("failed inserting key")) + err = simpleAsset.InitBondAssetLedger(transactionContext) + require.EqualError(t, err, "failed to put to world state. failed inserting key") +} + +func TestCreateAsset(t *testing.T) { + transactionContext, chaincodeStub := wtest.PrepMockStub() + simpleAsset := sa.SmartContract{} + simpleAsset.ConfigureInterop("interopcc") + + err := simpleAsset.CreateAsset(transactionContext, "", "", "", "", 0, "02 Jan 26 15:04 MST") + require.Error(t, err) + + err = simpleAsset.CreateAsset(transactionContext, defaultAssetType, "", "", "", 0, "02 Jan 26 15:04 MST") + require.Error(t, err) + + err = simpleAsset.CreateAsset(transactionContext, defaultAssetType, defaultAssetId, "", "", 0, "02 Jan 26 15:04 MST") + require.Error(t, err) + + err = simpleAsset.CreateAsset(transactionContext, defaultAssetType, defaultAssetId, defaultAssetOwner, "", 0, "02 Jan 26 15:04 MST") + require.NoError(t, err) + + err = simpleAsset.CreateAsset(transactionContext, defaultAssetType, defaultAssetId, "", defaultAssetIssuer, 0, "02 Jan 26 15:04 MST") + require.NoError(t, err) + + err = simpleAsset.CreateAsset(transactionContext, defaultAssetType, defaultAssetId, defaultAssetOwner, "", 0, "02 Jan 06 15:04 MST") + require.EqualError(t, err, "maturity date can not be in past.") + + err = simpleAsset.CreateAsset(transactionContext, defaultAssetType, defaultAssetId, defaultAssetOwner, "", 0, "") + require.EqualError(t, err, "maturity date provided is not in correct format, please use this format: 02 Jan 06 15:04 MST") + + chaincodeStub.GetStateReturns([]byte{}, nil) + err = simpleAsset.CreateAsset(transactionContext, defaultAssetType, defaultAssetId, defaultAssetOwner, "", 0, "") + require.EqualError(t, err, "the asset asset1 already exists") + + chaincodeStub.GetStateReturns(nil, fmt.Errorf("unable to retrieve asset")) + err = simpleAsset.CreateAsset(transactionContext, defaultAssetType, defaultAssetId, defaultAssetOwner, "", 0, "") + require.EqualError(t, err, "failed to read asset record from world state: unable to retrieve asset") +} + +func TestReadAsset(t *testing.T) { + transactionContext, chaincodeStub := wtest.PrepMockStub() + simpleAsset := sa.SmartContract{} + simpleAsset.ConfigureInterop("interopcc") + + expectedAsset := &sa.BondAsset{ID: "asset1"} + bytes, err := json.Marshal(expectedAsset) + require.NoError(t, err) + + chaincodeStub.GetStateReturns(bytes, nil) + asset, err := simpleAsset.ReadAsset(transactionContext, "", "") + require.NoError(t, err) + require.Equal(t, expectedAsset, asset) + + chaincodeStub.GetStateReturns(nil, fmt.Errorf("unable to retrieve asset")) + _, err = simpleAsset.ReadAsset(transactionContext, "", "") + require.EqualError(t, err, "failed to read asset record from world state: unable to retrieve asset") + + chaincodeStub.GetStateReturns(nil, nil) + asset, err = simpleAsset.ReadAsset(transactionContext, "", "asset1") + require.EqualError(t, err, "the asset asset1 does not exist") + require.Nil(t, asset) +} + +func TestUpdateFaceValue(t *testing.T) { + transactionContext, chaincodeStub := wtest.PrepMockStub() + simpleAsset := sa.SmartContract{} + simpleAsset.ConfigureInterop("interopcc") + + expectedAsset := &sa.BondAsset{ID: "asset1"} + bytes, err := json.Marshal(expectedAsset) + require.NoError(t, err) + + chaincodeStub.GetStateReturns(bytes, nil) + err = simpleAsset.UpdateFaceValue(transactionContext, "", "", 0) + require.NoError(t, err) + + chaincodeStub.GetStateReturns(nil, nil) + err = simpleAsset.UpdateFaceValue(transactionContext, "", "asset1", 0) + require.EqualError(t, err, "the asset asset1 does not exist") + + chaincodeStub.GetStateReturns(nil, fmt.Errorf("unable to retrieve asset")) + err = simpleAsset.UpdateFaceValue(transactionContext, "", "asset1", 0) + require.EqualError(t, err, "failed to read asset record from world state: unable to retrieve asset") +} + +func TestUpdateMaturityDate(t *testing.T) { + transactionContext, chaincodeStub := wtest.PrepMockStub() + simpleAsset := sa.SmartContract{} + simpleAsset.ConfigureInterop("interopcc") + + expectedAsset := &sa.BondAsset{ID: "asset1"} + bytes, err := json.Marshal(expectedAsset) + require.NoError(t, err) + + chaincodeStub.GetStateReturns(bytes, nil) + err = simpleAsset.UpdateMaturityDate(transactionContext, "", "", time.Now()) + require.NoError(t, err) + + chaincodeStub.GetStateReturns(nil, nil) + err = simpleAsset.UpdateMaturityDate(transactionContext, "", "asset1", time.Now()) + require.EqualError(t, err, "the asset asset1 does not exist") + + chaincodeStub.GetStateReturns(nil, fmt.Errorf("unable to retrieve asset")) + err = simpleAsset.UpdateMaturityDate(transactionContext, "", "asset1", time.Now()) + require.EqualError(t, err, "failed to read asset record from world state: unable to retrieve asset") +} + +func TestDeleteAsset(t *testing.T) { + transactionContext, chaincodeStub := wtest.PrepMockStub() + simpleAsset := sa.SmartContract{} + simpleAsset.ConfigureInterop("interopcc") + + asset := &sa.BondAsset{ID: "asset1"} + bytes, err := json.Marshal(asset) + require.NoError(t, err) + + chaincodeStub.GetStateReturns(bytes, nil) + chaincodeStub.DelStateReturns(nil) + err = simpleAsset.DeleteAsset(transactionContext, "", "") + require.NoError(t, err) + + chaincodeStub.GetStateReturns(nil, nil) + err = simpleAsset.DeleteAsset(transactionContext, "", "asset1") + require.EqualError(t, err, "the asset asset1 does not exist") + + chaincodeStub.GetStateReturns(nil, fmt.Errorf("unable to retrieve asset")) + err = simpleAsset.DeleteAsset(transactionContext, "", "") + require.EqualError(t, err, "failed to read asset record from world state: unable to retrieve asset") +} + +func TestUpdateOwner(t *testing.T) { + transactionContext, chaincodeStub := wtest.PrepMockStub() + simpleAsset := sa.SmartContract{} + simpleAsset.ConfigureInterop("interopcc") + + asset := &sa.BondAsset{ID: "asset1"} + bytes, err := json.Marshal(asset) + require.NoError(t, err) + + chaincodeStub.GetStateReturns(bytes, nil) + err = simpleAsset.UpdateOwner(transactionContext, "", "", "") + require.NoError(t, err) + + chaincodeStub.GetStateReturns(nil, fmt.Errorf("unable to retrieve asset")) + err = simpleAsset.UpdateOwner(transactionContext, "", "", "") + require.EqualError(t, err, "failed to read asset record from world state: unable to retrieve asset") +} + +func TestGetMyAssets(t *testing.T) { + transactionContext, chaincodeStub := wtest.PrepMockStub() + simpleAsset := sa.SmartContract{} + simpleAsset.ConfigureInterop("interopcc") + iterator := &wtestmocks.StateQueryIterator{} + + asset := &sa.BondAsset{ID: "asset1", Owner: getTestTxCreatorECertBase64()} + bytes, err := json.Marshal(asset) + require.NoError(t, err) + + iterator.HasNextReturnsOnCall(0, true) + iterator.HasNextReturnsOnCall(1, false) + iterator.NextReturns(&queryresult.KV{Value: bytes}, nil) + + chaincodeStub.GetCreatorReturns([]byte(getCreator()), nil) + + chaincodeStub.GetStateByRangeReturns(iterator, nil) + assets, err := simpleAsset.GetAllAssets(transactionContext) + require.NoError(t, err) + require.Equal(t, []*sa.BondAsset{asset}, assets) + + iterator.HasNextReturns(true) + iterator.NextReturns(nil, fmt.Errorf("failed retrieving next item")) + assets, err = simpleAsset.GetAllAssets(transactionContext) + require.EqualError(t, err, "failed retrieving next item") + require.Nil(t, assets) + + chaincodeStub.GetStateByRangeReturns(nil, fmt.Errorf("failed retrieving all assets")) + assets, err = simpleAsset.GetAllAssets(transactionContext) + require.EqualError(t, err, "failed retrieving all assets") + require.Nil(t, assets) +} + +func TestGetAllAssets(t *testing.T) { + transactionContext, chaincodeStub := wtest.PrepMockStub() + simpleAsset := sa.SmartContract{} + simpleAsset.ConfigureInterop("interopcc") + iterator := &wtestmocks.StateQueryIterator{} + + asset := &sa.BondAsset{ID: "asset1"} + bytes, err := json.Marshal(asset) + require.NoError(t, err) + + iterator.HasNextReturnsOnCall(0, true) + iterator.HasNextReturnsOnCall(1, false) + iterator.NextReturns(&queryresult.KV{Value: bytes}, nil) + + chaincodeStub.GetStateByRangeReturns(iterator, nil) + assets, err := simpleAsset.GetAllAssets(transactionContext) + require.NoError(t, err) + require.Equal(t, []*sa.BondAsset{asset}, assets) + + iterator.HasNextReturns(true) + iterator.NextReturns(nil, fmt.Errorf("failed retrieving next item")) + assets, err = simpleAsset.GetAllAssets(transactionContext) + require.EqualError(t, err, "failed retrieving next item") + require.Nil(t, assets) + + chaincodeStub.GetStateByRangeReturns(nil, fmt.Errorf("failed retrieving all assets")) + assets, err = simpleAsset.GetAllAssets(transactionContext) + require.EqualError(t, err, "failed retrieving all assets") + require.Nil(t, assets) +} diff --git a/weaver/samples/fabric/satpsimpleasset/go.mod b/weaver/samples/fabric/satpsimpleasset/go.mod new file mode 100644 index 00000000000..eedb9f8ddb4 --- /dev/null +++ b/weaver/samples/fabric/satpsimpleasset/go.mod @@ -0,0 +1,42 @@ +module github.com/hyperledger/cacti/weaver/samples/fabric/satpsimpleasset + +go 1.20 + +require ( + github.com/golang/protobuf v1.5.3 + 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 + github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/libs/testutils v0.0.0-20230907062207-cd6eb2f89fb4 + github.com/hyperledger/fabric-chaincode-go v0.0.0-20230228194215-b84622ba6a7a + github.com/hyperledger/fabric-contract-api-go v1.2.1 + github.com/hyperledger/fabric-protos-go v0.3.0 + github.com/sirupsen/logrus v1.9.0 + github.com/stretchr/testify v1.8.2 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/go-openapi/jsonpointer v0.19.5 // indirect + github.com/go-openapi/jsonreference v0.20.0 // indirect + github.com/go-openapi/spec v0.20.8 // indirect + github.com/go-openapi/swag v0.21.1 // indirect + github.com/gobuffalo/envy v1.10.1 // indirect + github.com/gobuffalo/packd v1.0.1 // indirect + github.com/gobuffalo/packr v1.30.1 // indirect + github.com/joho/godotenv v1.4.0 // indirect + github.com/josharian/intern v1.0.0 // indirect + github.com/mailru/easyjson v0.7.7 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rogpeppe/go-internal v1.8.1 // indirect + github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect + github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect + github.com/xeipuuv/gojsonschema v1.2.0 // indirect + golang.org/x/net v0.8.0 // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect + google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f // indirect + google.golang.org/grpc v1.54.0 // indirect + google.golang.org/protobuf v1.30.0 // indirect + gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/weaver/samples/fabric/satpsimpleasset/go.sum b/weaver/samples/fabric/satpsimpleasset/go.sum new file mode 100644 index 00000000000..da4c985ffde --- /dev/null +++ b/weaver/samples/fabric/satpsimpleasset/go.sum @@ -0,0 +1,149 @@ +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= +github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY= +github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= +github.com/go-openapi/jsonreference v0.20.0 h1:MYlu0sBgChmCfJxxUKZ8g1cPWFOB37YSZqewK7OKeyA= +github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXymS4zJbYVCZmcgkasdo= +github.com/go-openapi/spec v0.20.8 h1:ubHmXNY3FCIOinT8RNrrPfGc9t7I1qhPtdOGoG2AxRU= +github.com/go-openapi/spec v0.20.8/go.mod h1:2OpW+JddWPrpXSCIX8eOx7lZ5iyuWj3RYR6VaaBKcWA= +github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= +github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU= +github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ= +github.com/gobuffalo/envy v1.7.0/go.mod h1:n7DRkBerg/aorDM8kbduw5dN3oXGswK5liaSCx4T5NI= +github.com/gobuffalo/envy v1.10.1 h1:ppDLoXv2feQ5nus4IcgtyMdHQkKng2lhJCIm33cblM0= +github.com/gobuffalo/envy v1.10.1/go.mod h1:AWx4++KnNOW3JOeEvhSaq+mvgAvnMYOY1XSIin4Mago= +github.com/gobuffalo/logger v1.0.0/go.mod h1:2zbswyIUa45I+c+FLXuWl9zSWEiVuthsk8ze5s8JvPs= +github.com/gobuffalo/packd v0.3.0/go.mod h1:zC7QkmNkYVGKPw4tHpBQ+ml7W/3tIebgeo1b36chA3Q= +github.com/gobuffalo/packd v1.0.1 h1:U2wXfRr4E9DH8IdsDLlRFwTZTK7hLfq9qT/QHXGVe/0= +github.com/gobuffalo/packd v1.0.1/go.mod h1:PP2POP3p3RXGz7Jh6eYEf93S7vA2za6xM7QT85L4+VY= +github.com/gobuffalo/packr v1.30.1 h1:hu1fuVR3fXEZR7rXNW3h8rqSML8EVAf6KNm0NKO/wKg= +github.com/gobuffalo/packr v1.30.1/go.mod h1:ljMyFO2EcrnzsHsN99cvbq055Y9OhRrIaviy289eRuk= +github.com/gobuffalo/packr/v2 v2.5.1/go.mod h1:8f9c96ITobJlPzI44jj+4tHnEKNt0xXWSVlXRN9X1Iw= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg= +github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/hyperledger/fabric-chaincode-go v0.0.0-20230228194215-b84622ba6a7a h1:HwSCxEeiBthwcazcAykGATQ36oG9M+HEQvGLvB7aLvA= +github.com/hyperledger/fabric-chaincode-go v0.0.0-20230228194215-b84622ba6a7a/go.mod h1:TDSu9gxURldEnaGSFbH1eMlfSQBWQcMQfnDBcpQv5lU= +github.com/hyperledger/fabric-contract-api-go v1.2.1 h1:Ww9cKH/qHl5s6WqF+Ts5ju5eaBxC/awB/BJE+rOsEkM= +github.com/hyperledger/fabric-contract-api-go v1.2.1/go.mod h1:BhWve0gz1iH+Xc+cO3rmeIZI7YaTWOQodka9CgeUOgo= +github.com/hyperledger/fabric-protos-go v0.3.0 h1:MXxy44WTMENOh5TI8+PCK2x6pMj47Go2vFRKDHB2PZs= +github.com/hyperledger/fabric-protos-go v0.3.0/go.mod h1:WWnyWP40P2roPmmvxsUXSvVI/CF6vwY1K1UFidnKBys= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg= +github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= +github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= +github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= +github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= +github.com/karrick/godirwalk v1.10.12/go.mod h1:RoGL9dQei4vP9ilrpETWE8CLOZ1kiN0LhBygSwrAsHA= +github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= +github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= +github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= +github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= +github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= +github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/rogpeppe/go-internal v1.8.1 h1:geMPLpDpQOgVyCg5z5GoRwLHepNdb71NXb67XFkP+Eg= +github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= +github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= +github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= +github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= +github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= +github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= +github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= +github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= +github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= +github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190515120540-06a5c4944438/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f h1:BWUVssLB0HVOSY78gIdvk1dTVYtT1y8SBWtPYuTJ/6w= +google.golang.org/genproto v0.0.0-20230110181048-76db0878b65f/go.mod h1:RGgjbofJ8xD9Sq1VVhDM1Vok1vRONV+rg+CjzG4SZKM= +google.golang.org/grpc v1.54.0 h1:EhTqbhiYeixwWQtAEZAxmV9MGqcjEU2mFx52xCzNyag= +google.golang.org/grpc v1.54.0/go.mod h1:PUSEXI6iWghWaB6lXM4knEgpJNu2qUcKfDtNci3EC2g= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= +google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= +gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/weaver/samples/fabric/satpsimpleasset/helper.go b/weaver/samples/fabric/satpsimpleasset/helper.go new file mode 100644 index 00000000000..efca833cc72 --- /dev/null +++ b/weaver/samples/fabric/satpsimpleasset/helper.go @@ -0,0 +1,53 @@ +/* + * Copyright IBM Corp. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +// helper contains miscelaneous helper functions used throughout the code +package main + +import ( + "fmt" + "errors" + "encoding/base64" + "bytes" + + "github.com/golang/protobuf/proto" + "github.com/hyperledger/fabric-contract-api-go/contractapi" + mspProtobuf "github.com/hyperledger/fabric-protos-go/msp" + log "github.com/sirupsen/logrus" +) + +// functions to log and return errors +func logThenErrorf(format string, args ...interface{}) error { + errorMsg := fmt.Sprintf(format, args...) + log.Error(errorMsg) + return errors.New(errorMsg) +} + +func getECertOfTxCreatorBase64(ctx contractapi.TransactionContextInterface) (string, error) { + + txCreatorBytes, err := ctx.GetStub().GetCreator() + if err != nil { + return "", fmt.Errorf("unable to get the transaction creator information: %+v", err) + } + + serializedIdentity := &mspProtobuf.SerializedIdentity{} + err = proto.Unmarshal(txCreatorBytes, serializedIdentity) + if err != nil { + return "", fmt.Errorf("getECertOfTxCreatorBase64: unmarshal error: %+v", err) + } + + eCertBytesBase64 := base64.StdEncoding.EncodeToString(serializedIdentity.IdBytes) + + return eCertBytesBase64, nil +} + +func createKeyValuePairs(m map[string]uint64) string { + b := new(bytes.Buffer) + for key, value := range m { + fmt.Fprintf(b, "%s=\"%d\"\n", key, value) + } + return b.String() +} diff --git a/weaver/samples/fabric/satpsimpleasset/main.go b/weaver/samples/fabric/satpsimpleasset/main.go new file mode 100644 index 00000000000..0b8c5b9d714 --- /dev/null +++ b/weaver/samples/fabric/satpsimpleasset/main.go @@ -0,0 +1,59 @@ +package main + +import ( + "fmt" + "os" + + "github.com/hyperledger/fabric-chaincode-go/shim" + "github.com/hyperledger/fabric-contract-api-go/contractapi" + am "github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/interfaces/asset-mgmt/v2" +) + +// SmartContract provides functions for managing an BondAsset and TokenAsset +type SmartContract struct { + contractapi.Contract + amc am.AssetManagementContract +} + +func (s *SmartContract) ConfigureInterop(interopChaincodeId string) { + s.amc.Configure(interopChaincodeId) +} + +func (s *SmartContract) InitLedger(ctx contractapi.TransactionContextInterface, ccType string, interopChaincodeId string) error { + s.ConfigureInterop(interopChaincodeId) + if ccType == "Bond" { + return s.InitBondAssetLedger(ctx) + } else if ccType == "Token" { + return s.InitTokenAssetLedger(ctx) + } + return fmt.Errorf("only Bond and Token are accepted as ccType.") +} + +func main() { + chaincode, err := contractapi.NewChaincode(new(SmartContract)) + + if err != nil { + fmt.Printf("Error creating chaincode: %s", err.Error()) + return + } + + _, ok := os.LookupEnv("EXTERNAL_SERVICE") + if ok { + server := &shim.ChaincodeServer{ + CCID: os.Getenv("CHAINCODE_CCID"), + Address: os.Getenv("CHAINCODE_ADDRESS"), + CC: chaincode, + TLSProps: shim.TLSProperties{ + Disabled: true, + }, + } + // Start the chaincode external server + err = server.Start() + } else { + err = chaincode.Start() + } + if err != nil { + fmt.Printf("Error starting chaincode: %s", err.Error()) + } + +} diff --git a/weaver/samples/fabric/satpsimpleasset/tokenasset.go b/weaver/samples/fabric/satpsimpleasset/tokenasset.go new file mode 100644 index 00000000000..972d90399a8 --- /dev/null +++ b/weaver/samples/fabric/satpsimpleasset/tokenasset.go @@ -0,0 +1,316 @@ +package main + +import ( + "encoding/json" + "fmt" + + "github.com/hyperledger/fabric-contract-api-go/contractapi" +) + +type TokenAssetType struct { + Issuer string `json:"issuer"` + Value int `json:"value"` +} +type TokenWallet struct { + WalletMap map[string]uint64 `json:"walletlist"` +} + + +// InitTokenAssetLedger adds a base set of assets to the ledger +func (s *SmartContract) InitTokenAssetLedger(ctx contractapi.TransactionContextInterface) error { + _, err := s.CreateTokenAssetType(ctx, "token1", "CentralBank", 1) + if err != nil { + return err + } + return err +} + +// CreateTokenAssetType issues a new token asset type to the world state with given details. +func (s *SmartContract) CreateTokenAssetType(ctx contractapi.TransactionContextInterface, tokenAssetType string, issuer string, value int) (bool, error) { + if tokenAssetType == "" { + return false, fmt.Errorf("Token asset type cannot be blank") + } + exists, err := s.TokenAssetTypeExists(ctx, tokenAssetType) + if err != nil { + return false, err + } + if exists { + return false, fmt.Errorf("the token asset type %s already exists.", tokenAssetType) + } + + asset := TokenAssetType{ + Issuer: issuer, + Value: value, + } + assetJSON, err := json.Marshal(asset) + if err != nil { + return false, err + } + id := getTokenAssetTypeId(tokenAssetType) + err = ctx.GetStub().PutState(id, assetJSON) + + if err != nil { + return false, fmt.Errorf("failed to create token asset type %s. %v", tokenAssetType, err) + } + return true, nil +} + +// ReadTokenAssetType returns the token asset type stored in the world state with given type. +func (s *SmartContract) ReadTokenAssetType(ctx contractapi.TransactionContextInterface, tokenAssetType string) (*TokenAssetType, error) { + id := getTokenAssetTypeId(tokenAssetType) + assetJSON, err := ctx.GetStub().GetState(id) + if err != nil { + return nil, fmt.Errorf("failed to read token asset type %s: %v", tokenAssetType, err) + } + if assetJSON == nil { + return nil, fmt.Errorf("the token asset type %s does not exist.", tokenAssetType) + } + + var fat TokenAssetType + err = json.Unmarshal(assetJSON, &fat) + if err != nil { + return nil, err + } + + return &fat, nil +} + +// DeleteTokenAssetType deletes an given token asset type from the world state. +func (s *SmartContract) DeleteTokenAssetType(ctx contractapi.TransactionContextInterface, tokenAssetType string) error { + exists, err := s.TokenAssetTypeExists(ctx, tokenAssetType) + if err != nil { + return err + } + if !exists { + return fmt.Errorf("the token asset type %s does not exist.", tokenAssetType) + } + + id := getTokenAssetTypeId(tokenAssetType) + err = ctx.GetStub().DelState(id) + if err != nil { + return fmt.Errorf("failed to delete token asset type %s: %v", tokenAssetType, err) + } + return nil +} + +// TokenAssetTypeExists returns true when token asset type with given ID exists in world state +func (s *SmartContract) TokenAssetTypeExists(ctx contractapi.TransactionContextInterface, tokenAssetType string) (bool, error) { + id := getTokenAssetTypeId(tokenAssetType) + assetJSON, err := ctx.GetStub().GetState(id) + if err != nil { + return false, fmt.Errorf("failed to read from world state: %v", err) + } + + return assetJSON != nil, nil +} + +// IssueTokenAssets issues new token assets to an owner. +func (s *SmartContract) IssueTokenAssets(ctx contractapi.TransactionContextInterface, tokenAssetType string, numUnits uint64, owner string) error { + if owner == "" { + return fmt.Errorf("Owner cannot be blank") + } + + exists, err := s.TokenAssetTypeExists(ctx, tokenAssetType) + if err != nil { + return err + } + if !exists { + return fmt.Errorf("cannot issue: the token asset type %s does not exist", tokenAssetType) + } + + id := getWalletId(owner) + return addTokenAssetsHelper(ctx, tokenAssetType, numUnits, id) +} + +// DeleteTokenAssets burns the token assets from an owner. +func (s *SmartContract) DeleteTokenAssets(ctx contractapi.TransactionContextInterface, tokenAssetType string, numUnits uint64) error { + owner, err := getECertOfTxCreatorBase64(ctx) + if err != nil { + return err + } + exists, err := s.TokenAssetTypeExists(ctx, tokenAssetType) + if err != nil { + return err + } + if !exists { + return fmt.Errorf("the token asset type %s does not exist", tokenAssetType) + } + + id := getWalletId(owner) + return subTokenAssetsHelper(ctx, tokenAssetType, numUnits, id) +} + +// TransferTokenAssets transfers the token assets from client's account to newOwner +func (s *SmartContract) TransferTokenAssets(ctx contractapi.TransactionContextInterface, tokenAssetType string, numUnits uint64, newOwner string) error { + exists, err := s.TokenAssetTypeExists(ctx, tokenAssetType) + if err != nil { + return err + } + if !exists { + return fmt.Errorf("the token asset type %s does not exist", tokenAssetType) + } + + if newOwner == "" { + return fmt.Errorf("New owner cannot be blank") + } + + owner, err := getECertOfTxCreatorBase64(ctx) + if err != nil { + return err + } + + ownerId := getWalletId(owner) + newOwnerId := getWalletId(newOwner) + + err = subTokenAssetsHelper(ctx, tokenAssetType, numUnits, ownerId) + if err != nil { + return err + } + return addTokenAssetsHelper(ctx, tokenAssetType, numUnits, newOwnerId) +} + +// GetBalance returns the amount of given token asset type owned by an owner. +func (s *SmartContract) GetBalance(ctx contractapi.TransactionContextInterface, tokenAssetType string, owner string) (uint64, error) { + exists, err := s.TokenAssetTypeExists(ctx, tokenAssetType) + if err != nil { + return 0, err + } + if !exists { + return 0, fmt.Errorf("the token asset type %s does not exist", tokenAssetType) + } + + id := getWalletId(owner) + walletJSON, err := ctx.GetStub().GetState(id) + if err != nil { + return 0, fmt.Errorf("failed to read owner's wallet from world state: %v", err) + } + if walletJSON == nil { + return 0, fmt.Errorf("owner does not have a wallet") + } + + var wallet TokenWallet + err = json.Unmarshal(walletJSON, &wallet) + if err != nil { + return 0, err + } + balance := wallet.WalletMap[tokenAssetType] + return balance, nil +} + +// GetMyWallet returns the available amount for each token asset type owned by an owner. +func (s *SmartContract) GetMyWallet(ctx contractapi.TransactionContextInterface) (string, error) { + owner, err := getECertOfTxCreatorBase64(ctx) + if err != nil { + return "", err + } + + id := getWalletId(owner) + walletJSON, err := ctx.GetStub().GetState(id) + if err != nil { + return "", fmt.Errorf("failed to read owner's wallet from world state: %v", err) + } + if walletJSON == nil { + return "", fmt.Errorf("owner does not have a wallet") + } + + var wallet TokenWallet + err = json.Unmarshal(walletJSON, &wallet) + if err != nil { + return "", err + } + return createKeyValuePairs(wallet.WalletMap), nil +} + +// Checks if owner has some given amount of token asset +func (s *SmartContract) TokenAssetsExist(ctx contractapi.TransactionContextInterface, tokenAssetType string, numUnits uint64) (bool, error) { + owner, err := getECertOfTxCreatorBase64(ctx) + if err != nil { + return false, err + } + balance, err := s.GetBalance(ctx, tokenAssetType, owner) + if err != nil { + return false, err + } + return balance >= numUnits, nil +} + +// Helper Functions for token asset +func addTokenAssetsHelper(ctx contractapi.TransactionContextInterface, tokenAssetType string, numUnits uint64, id string) error { + walletJSON, err := ctx.GetStub().GetState(id) + if err != nil { + return logThenErrorf("failed to retrieve entry from ledger: %+v", err) + } + var wallet TokenWallet + if walletJSON != nil { + err = json.Unmarshal(walletJSON, &wallet) + if err != nil { + return err + } + balance := wallet.WalletMap[tokenAssetType] + wallet.WalletMap[tokenAssetType] = balance + numUnits + } else { + walletMap := make(map[string]uint64) + walletMap[tokenAssetType] = numUnits + wallet = TokenWallet{ + WalletMap: walletMap, + } + } + + walletNewJSON, err := json.Marshal(wallet) + if err != nil { + return err + } + return ctx.GetStub().PutState(id, walletNewJSON) +} + +func subTokenAssetsHelper(ctx contractapi.TransactionContextInterface, tokenAssetType string, numUnits uint64, id string) error { + walletJSON, err := ctx.GetStub().GetState(id) + var wallet TokenWallet + if err != nil { + return err + } + if walletJSON == nil { + return fmt.Errorf("owner does not have a wallet") + } + + err = json.Unmarshal(walletJSON, &wallet) + if err != nil { + return err + } + + // Check if owner has sufficient amount of given type to delete + _, exists := wallet.WalletMap[tokenAssetType] + if !exists { + return fmt.Errorf("the owner does not possess any units of the token asset type %s", tokenAssetType) + } + if wallet.WalletMap[tokenAssetType] < numUnits { + return fmt.Errorf("the owner does not possess enough units of the token asset type %s", tokenAssetType) + } + + // Subtract after all checks + wallet.WalletMap[tokenAssetType] -= numUnits + + // Delete token asset type from map if num of units becomes zero + if wallet.WalletMap[tokenAssetType] == 0 { + delete(wallet.WalletMap, tokenAssetType) + } + + if len(wallet.WalletMap) == 0 { + // Delete the entry from State if wallet becomes empty + return ctx.GetStub().DelState(id) + } else { + // Update the new wallet object otherwise + walletNewJSON, err := json.Marshal(wallet) + if err != nil { + return err + } + return ctx.GetStub().PutState(id, walletNewJSON) + } +} + +func getTokenAssetTypeId(tokenAssetType string) string { + return "FAT_" + tokenAssetType +} +func getWalletId(owner string) string { + return "W_" + owner +} diff --git a/weaver/samples/fabric/satpsimpleasset/tokenasset_test.go b/weaver/samples/fabric/satpsimpleasset/tokenasset_test.go new file mode 100644 index 00000000000..facbfb393ff --- /dev/null +++ b/weaver/samples/fabric/satpsimpleasset/tokenasset_test.go @@ -0,0 +1,326 @@ +package main_test + +import ( + "encoding/json" + "fmt" + "testing" + "encoding/base64" + "bytes" + + "github.com/golang/protobuf/proto" + mspProtobuf "github.com/hyperledger/fabric-protos-go/msp" + sa "github.com/hyperledger/cacti/weaver/samples/fabric/satpsimpleasset" + "github.com/stretchr/testify/require" + wtest "github.com/hyperledger/cacti/weaver/core/network/fabric-interop-cc/libs/testutils" +) + +func TestInitTokenAssetLedger(t *testing.T) { + transactionContext, chaincodeStub := wtest.PrepMockStub() + simpleToken := sa.SmartContract{} + simpleToken.ConfigureInterop("interopcc") + + err := simpleToken.InitTokenAssetLedger(transactionContext) + require.NoError(t, err) + + chaincodeStub.PutStateReturns(fmt.Errorf("failed inserting key")) + err = simpleToken.InitTokenAssetLedger(transactionContext) + require.EqualError(t, err, "failed to create token asset type token1. failed inserting key") +} + +func TestCreateTokenAssetType(t *testing.T) { + transactionContext, chaincodeStub := wtest.PrepMockStub() + simpleToken := sa.SmartContract{} + simpleToken.ConfigureInterop("interopcc") + + // Should fail if token asset type is empty + res, err := simpleToken.CreateTokenAssetType(transactionContext, "", "", 0) + require.Error(t, err) + + // Successful Case + res, err = simpleToken.CreateTokenAssetType(transactionContext, "sometokentype", "", 0) + require.NoError(t, err) + require.Equal(t, res, true) + + // Check if tokenAssetType already exists + chaincodeStub.GetStateReturns([]byte{}, nil) + res, err = simpleToken.CreateTokenAssetType(transactionContext, "token1", "", 0) + require.EqualError(t, err, "the token asset type token1 already exists.") + require.Equal(t, res, false) + + // Check if PutState fails + chaincodeStub.GetStateReturns(nil, nil) + chaincodeStub.PutStateReturns(fmt.Errorf("failed to put state")) + res, err = simpleToken.CreateTokenAssetType(transactionContext, "token1", "", 0) + require.EqualError(t, err, "failed to create token asset type token1. failed to put state") + require.Equal(t, res, false) + + // Check if GetState fails + chaincodeStub.GetStateReturns(nil, fmt.Errorf("unable to retrieve asset")) + res, err = simpleToken.CreateTokenAssetType(transactionContext, "token1", "", 0) + require.EqualError(t, err, "failed to read from world state: unable to retrieve asset") + require.Equal(t, res, false) +} + +func TestReadTokenAssetType(t *testing.T) { + transactionContext, chaincodeStub := wtest.PrepMockStub() + simpleToken := sa.SmartContract{} + simpleToken.ConfigureInterop("interopcc") + + expectedAsset := &sa.TokenAssetType{Issuer: "CentralBank", Value: 10} + bytes, err := json.Marshal(expectedAsset) + require.NoError(t, err) + + // Successful Read + chaincodeStub.GetStateReturns(bytes, nil) + asset, err := simpleToken.ReadTokenAssetType(transactionContext, "") + require.NoError(t, err) + require.Equal(t, expectedAsset, asset) + + // GetState Fail case + chaincodeStub.GetStateReturns(nil, fmt.Errorf("unable to retrieve asset")) + _, err = simpleToken.ReadTokenAssetType(transactionContext, "") + require.EqualError(t, err, "failed to read token asset type : unable to retrieve asset") + + // token asset type does not exist + chaincodeStub.GetStateReturns(nil, nil) + asset, err = simpleToken.ReadTokenAssetType(transactionContext, "token1") + require.EqualError(t, err, "the token asset type token1 does not exist.") + require.Nil(t, asset) +} + +func TestDeleteTokenAssetType(t *testing.T) { + transactionContext, chaincodeStub := wtest.PrepMockStub() + simpleToken := sa.SmartContract{} + simpleToken.ConfigureInterop("interopcc") + + chaincodeStub.DelStateReturns(nil) + err := simpleToken.DeleteTokenAssetType(transactionContext, "") + require.EqualError(t, err, "the token asset type does not exist.") + + bytes, err := json.Marshal(true) + chaincodeStub.GetStateReturns(bytes, nil) + chaincodeStub.DelStateReturns(fmt.Errorf("unable to retrieve asset")) + err = simpleToken.DeleteTokenAssetType(transactionContext, "token1") + require.EqualError(t, err, "failed to delete token asset type token1: unable to retrieve asset") + + chaincodeStub.GetStateReturns(bytes, nil) + chaincodeStub.DelStateReturns(nil) + err = simpleToken.DeleteTokenAssetType(transactionContext, "token1") + require.NoError(t, err) +} + +func TestIssueTokenAssets(t *testing.T) { + transactionContext, chaincodeStub := wtest.PrepMockStub() + simpleToken := sa.SmartContract{} + simpleToken.ConfigureInterop("interopcc") + + walletMap := make(map[string]uint64) + expectedAsset := &sa.TokenWallet{WalletMap: walletMap} + bytes, err := json.Marshal(expectedAsset) + require.NoError(t, err) + + // Should fail of owner is blank + chaincodeStub.GetStateReturns(bytes, nil) + err = simpleToken.IssueTokenAssets(transactionContext, "", 0, "") + require.Error(t, err) + + // Checking succesful case + chaincodeStub.GetStateReturns(bytes, nil) + err = simpleToken.IssueTokenAssets(transactionContext, "", 0, "someowner") + require.NoError(t, err) + + // Check if writing state after issuing fails + chaincodeStub.GetStateReturns(bytes, nil) + chaincodeStub.PutStateReturns(fmt.Errorf("failed to put state")) + err = simpleToken.IssueTokenAssets(transactionContext, "", 0, "someowner") + require.EqualError(t, err, "failed to put state") + + // Error check + chaincodeStub.GetStateReturns(nil, fmt.Errorf("failed to read state")) + err = simpleToken.IssueTokenAssets(transactionContext, "", 0, "someowner") + require.EqualError(t, err, "failed to read from world state: failed to read state") + + // Check if given token asset type doesn't exist + chaincodeStub.GetStateReturns(nil, nil) + err = simpleToken.IssueTokenAssets(transactionContext, "token1", 0, "someowner") + require.EqualError(t, err, "cannot issue: the token asset type token1 does not exist") +} + +func TestDeleteTokenAssets(t *testing.T) { + transactionContext, chaincodeStub := wtest.PrepMockStub() + simpleToken := sa.SmartContract{} + simpleToken.ConfigureInterop("interopcc") + + walletMap := make(map[string]uint64) + walletMap["token1"] = 5 + expectedAsset := &sa.TokenWallet{WalletMap: walletMap} + bytes, err := json.Marshal(expectedAsset) + require.NoError(t, err) + + // Successful delete case + chaincodeStub.GetStateReturns(bytes, nil) + err = simpleToken.DeleteTokenAssets(transactionContext, "token1", 2) + require.NoError(t, err) + + // Trying to delete more than owner hass + chaincodeStub.GetStateReturns(bytes, nil) + err = simpleToken.DeleteTokenAssets(transactionContext, "token1", 10) + require.EqualError(t, err, "the owner does not possess enough units of the token asset type token1") + + // Trying to delete token that owner doesn't possess + chaincodeStub.GetStateReturns(bytes, nil) + err = simpleToken.DeleteTokenAssets(transactionContext, "token2", 2) + require.EqualError(t, err, "the owner does not possess any units of the token asset type token2") + + // Error Check + chaincodeStub.GetStateReturns(nil, fmt.Errorf("Failed to read state")) + err = simpleToken.DeleteTokenAssets(transactionContext, "", 0) + require.EqualError(t, err, "failed to read from world state: Failed to read state") + + // check if it tries to delete wallet entry when wallet list is empty + chaincodeStub.GetStateReturns(bytes, nil) + chaincodeStub.DelStateReturns(fmt.Errorf("Failed to delete state")) + err = simpleToken.DeleteTokenAssets(transactionContext, "token1", 5) + require.EqualError(t, err, "Failed to delete state") + +} +func TestTransferTokenAssets(t *testing.T) { + transactionContext, chaincodeStub := wtest.PrepMockStub() + simpleToken := sa.SmartContract{} + simpleToken.ConfigureInterop("interopcc") + + walletMap := make(map[string]uint64) + walletMap["token1"] = 5 + expectedAsset := &sa.TokenWallet{WalletMap: walletMap} + bytes, err := json.Marshal(expectedAsset) + require.NoError(t, err) + + chaincodeStub.GetStateReturns(bytes, nil) + err = simpleToken.TransferTokenAssets(transactionContext, "token1", 2, "") + require.Error(t, err) + + chaincodeStub.GetStateReturns(bytes, nil) + err = simpleToken.TransferTokenAssets(transactionContext, "token1", 2, "newowner") + require.NoError(t, err) + + chaincodeStub.GetStateReturns(bytes, nil) + err = simpleToken.TransferTokenAssets(transactionContext, "token1", 10, "newowner") + require.EqualError(t, err, "the owner does not possess enough units of the token asset type token1") + + chaincodeStub.GetStateReturns(nil, fmt.Errorf("Failed to read state")) + err = simpleToken.DeleteTokenAssets(transactionContext, "", 0) + require.EqualError(t, err, "failed to read from world state: Failed to read state") +} +func TestGetBalance(t *testing.T) { + transactionContext, chaincodeStub := wtest.PrepMockStub() + simpleToken := sa.SmartContract{} + simpleToken.ConfigureInterop("interopcc") + + walletMap := make(map[string]uint64) + walletMap["token1"] = 5 + expectedAsset := &sa.TokenWallet{WalletMap: walletMap} + bytes, err := json.Marshal(expectedAsset) + require.NoError(t, err) + + // Successful GetBalance case + chaincodeStub.GetStateReturnsOnCall(0, bytes, nil) + chaincodeStub.GetStateReturnsOnCall(1, bytes, nil) + bal, err := simpleToken.GetBalance(transactionContext, "token1", "") + require.NoError(t, err) + require.Equal(t, bal, uint64(5)) + + // GetState Fails + chaincodeStub.GetStateReturnsOnCall(2, nil, fmt.Errorf("Failed to read state")) + bal, err = simpleToken.GetBalance(transactionContext, "", "") + require.EqualError(t, err, "failed to read from world state: Failed to read state") + + chaincodeStub.GetStateReturnsOnCall(3, bytes, nil) + chaincodeStub.GetStateReturnsOnCall(4, nil, fmt.Errorf("Failed to read state")) + bal, err = simpleToken.GetBalance(transactionContext, "", "") + require.EqualError(t, err, "failed to read owner's wallet from world state: Failed to read state") +} + +func TestGetMyWallet(t *testing.T) { + transactionContext, chaincodeStub := wtest.PrepMockStub() + simpleToken := sa.SmartContract{} + simpleToken.ConfigureInterop("interopcc") + + walletMap := make(map[string]uint64) + walletMap["token1"] = 5 + expectedRes := createKeyValuePairs(walletMap) + expectedAsset := &sa.TokenWallet{WalletMap: walletMap} + bytes, err := json.Marshal(expectedAsset) + require.NoError(t, err) + + chaincodeStub.GetCreatorReturns([]byte(getCreator()), nil) + + // Successful GetBalance case + chaincodeStub.GetStateReturnsOnCall(0, bytes, nil) + bal, err := simpleToken.GetMyWallet(transactionContext) + require.NoError(t, err) + require.Equal(t, bal, expectedRes) + + chaincodeStub.GetStateReturnsOnCall(1, nil, fmt.Errorf("Failed to read state")) + bal, err = simpleToken.GetMyWallet(transactionContext) + require.EqualError(t, err, "failed to read owner's wallet from world state: Failed to read state") + + // Owner doesn't have a wallet + chaincodeStub.GetStateReturnsOnCall(2, nil, nil) + bal, err = simpleToken.GetMyWallet(transactionContext) + require.EqualError(t, err, "owner does not have a wallet") +} + +func TestTokenAssetsExist(t *testing.T) { + transactionContext, chaincodeStub := wtest.PrepMockStub() + simpleToken := sa.SmartContract{} + simpleToken.ConfigureInterop("interopcc") + + walletMap := make(map[string]uint64) + walletMap["token1"] = 5 + expectedAsset := &sa.TokenWallet{WalletMap: walletMap} + bytes, err := json.Marshal(expectedAsset) + require.NoError(t, err) + + // Token Assets exist case + chaincodeStub.GetStateReturns(bytes, nil) + res, err := simpleToken.TokenAssetsExist(transactionContext, "token1", 4) + require.NoError(t, err) + require.Equal(t, res, true) + + // Token Assets doesn't exist case + chaincodeStub.GetStateReturns(bytes, nil) + res, err = simpleToken.TokenAssetsExist(transactionContext, "token1", 6) + require.NoError(t, err) + require.Equal(t, res, false) + + chaincodeStub.GetStateReturns(nil, fmt.Errorf("Failed to read state")) + res, err = simpleToken.TokenAssetsExist(transactionContext, "", 0) + require.EqualError(t, err, "failed to read from world state: Failed to read state") + require.Equal(t, res, false) +} + +// function that supplies value that is to be returned by ctx.GetStub().GetCreator() +func getCreator() string { + serializedIdentity := &mspProtobuf.SerializedIdentity{} + eCertBytes, _ := base64.StdEncoding.DecodeString(getTestTxCreatorECertBase64()) + serializedIdentity.IdBytes = []byte(eCertBytes) + serializedIdentity.Mspid = "ca.org1.example.com" + serializedIdentityBytes, _ := proto.Marshal(serializedIdentity) + + return string(serializedIdentityBytes) +} + +// function that supplies the ECert in base64 for the transaction creator +func getTestTxCreatorECertBase64() string { + eCertBase64 := "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUNVVENDQWZpZ0F3SUJBZ0lSQU5qaWdnVHRhSERGRmtIaUI3VnhPN013Q2dZSUtvWkl6ajBFQXdJd2N6RUxNQWtHQTFVRUJoTUNWVk14RXpBUkJnTlZCQWdUQ2tOaGJHbG1iM0p1YVdFeEZqQVVCZ05WQkFjVERWTmhiaUJHY21GdVkybHpZMjh4R1RBWEJnTlZCQW9URUc5eVp6RXVaWGhoYlhCc1pTNWpiMjB4SERBYUJnTlZCQU1URTJOaExtOXlaekV1WlhoaGJYQnNaUzVqYjIwd0hoY05NVGt3TkRBeE1EZzBOVEF3V2hjTk1qa3dNekk1TURnME5UQXdXakJ6TVFzd0NRWURWUVFHRXdKVlV6RVRNQkVHQTFVRUNCTUtRMkZzYVdadmNtNXBZVEVXTUJRR0ExVUVCeE1OVTJGdUlFWnlZVzVqYVhOamJ6RVpNQmNHQTFVRUNoTVFiM0puTVM1bGVHRnRjR3hsTG1OdmJURWNNQm9HQTFVRUF4TVRZMkV1YjNKbk1TNWxlR0Z0Y0d4bExtTnZiVEJaTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEEwSUFCT2VlYTRCNlM5ZTlyLzZUWGZFZUFmZ3FrNVdpcHZZaEdveGg1ZEZuK1g0bTN2UXZTQlhuVFdLVzczZVNnS0lzUHc5dExDVytwZW9yVnMxMWdieXdiY0dqYlRCck1BNEdBMVVkRHdFQi93UUVBd0lCcGpBZEJnTlZIU1VFRmpBVUJnZ3JCZ0VGQlFjREFnWUlLd1lCQlFVSEF3RXdEd1lEVlIwVEFRSC9CQVV3QXdFQi96QXBCZ05WSFE0RUlnUWcxYzJHZmJTa3hUWkxIM2VzUFd3c2llVkU1QWhZNHNPQjVGOGEvaHM5WjhVd0NnWUlLb1pJemowRUF3SURSd0F3UkFJZ1JkZ1krNW9iMDNqVjJLSzFWdjZiZE5xM2NLWHc0cHhNVXY5MFZOc0tHdTBDSUE4Q0lMa3ZEZWg3NEFCRDB6QUNkbitBTkMyVVQ2Sk5UNnd6VHNLN3BYdUwKLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ==" + + return eCertBase64 +} + +func createKeyValuePairs(m map[string]uint64) string { + b := new(bytes.Buffer) + for key, value := range m { + fmt.Fprintf(b, "%s=\"%d\"\n", key, value) + } + return b.String() +} diff --git a/weaver/sdks/fabric/interoperation-node-sdk/index.js b/weaver/sdks/fabric/interoperation-node-sdk/index.js index 34293f16e72..53d21b54550 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/index.js +++ b/weaver/sdks/fabric/interoperation-node-sdk/index.js @@ -15,6 +15,7 @@ module.exports.RelayHelper = require("./src/Relay.js"); module.exports.InteroperableHelper = require("./src/InteroperableHelper.js"); module.exports.AssetManager = require("./src/AssetManager.js"); +module.exports.SatpAssetManager = require("./src/SatpAssetManager.js"); module.exports.HashFunctions = require("./src/HashFunctions.js"); module.exports.EventsManager = require("./src/EventsManager.js"); module.exports.MembershipManager = require("./src/MembershipManager.js"); diff --git a/weaver/sdks/fabric/interoperation-node-sdk/src/SatpAssetManager.ts b/weaver/sdks/fabric/interoperation-node-sdk/src/SatpAssetManager.ts new file mode 100644 index 00000000000..313c995765e --- /dev/null +++ b/weaver/sdks/fabric/interoperation-node-sdk/src/SatpAssetManager.ts @@ -0,0 +1,1111 @@ +/* + * Copyright IBM Corp. All Rights Reserved. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +/** + * This file provides helper functions for interoperability operations. + **/ +/** End file docs */ + +import log4js from "log4js"; +import crypto from "crypto"; +import fabproto6 from "fabric-protos"; +import * as helpers from "./helpers"; +import assetLocksPb from "@hyperledger/cacti-weaver-protos-js/common/asset_locks_pb"; +import { Contract, ContractListener } from "fabric-network"; +import { Hash, SHA256, SHA512 } from "./HashFunctions" +const logger = log4js.getLogger("InteroperableHelper"); + + +// Create an asset exchange agreement structure +function createAssetExchangeAgreementSerialized(assetType, assetID, recipientECert, lockerECert) +{ + const assetExchangeAgreement = new assetLocksPb.AssetExchangeAgreement(); + assetExchangeAgreement.setAssettype(assetType); + assetExchangeAgreement.setId(assetID); + assetExchangeAgreement.setRecipient(recipientECert); + assetExchangeAgreement.setLocker(lockerECert); + return Buffer.from(assetExchangeAgreement.serializeBinary()).toString('base64'); +} + +// Create a fungible asset exchange agreement structure +function createFungibleAssetExchangeAgreementSerialized(assetType, numUnits, recipientECert, lockerECert) +{ + const assetExchangeAgreement = new assetLocksPb.FungibleAssetExchangeAgreement(); + assetExchangeAgreement.setAssettype(assetType); + assetExchangeAgreement.setNumunits(numUnits); + assetExchangeAgreement.setRecipient(recipientECert); + assetExchangeAgreement.setLocker(lockerECert); + return Buffer.from(assetExchangeAgreement.serializeBinary()).toString('base64'); +} + +// Create an asset lock structure +function createAssetLockInfoSerialized(hash, expiryTimeSecs) +{ + const lockInfoHTLC = new assetLocksPb.AssetLockHTLC(); + lockInfoHTLC.setHashmechanism(hash.HASH_MECHANISM); + lockInfoHTLC.setHashbase64(Buffer.from(hash.getSerializedHashBase64())); + lockInfoHTLC.setExpirytimesecs(expiryTimeSecs); + lockInfoHTLC.setTimespec(assetLocksPb.TimeSpec.EPOCH); + const lockInfoHTLCSerialized = lockInfoHTLC.serializeBinary(); + const lockInfo = new assetLocksPb.AssetLock(); + lockInfo.setLockmechanism(assetLocksPb.LockMechanism.HTLC); + lockInfo.setLockinfo(lockInfoHTLCSerialized); + return Buffer.from(lockInfo.serializeBinary()).toString('base64'); +} + +// Create an asset claim structure +function createAssetClaimInfoSerialized(hash) +{ + const claimInfoHTLC = new assetLocksPb.AssetClaimHTLC(); + claimInfoHTLC.setHashmechanism(hash.HASH_MECHANISM); + claimInfoHTLC.setHashpreimagebase64(Buffer.from(hash.getSerializedPreimageBase64())); + const claimInfoHTLCSerialized = claimInfoHTLC.serializeBinary(); + const claimInfo = new assetLocksPb.AssetClaim(); + claimInfo.setLockmechanism(assetLocksPb.LockMechanism.HTLC); + claimInfo.setClaiminfo(claimInfoHTLCSerialized); + return Buffer.from(claimInfo.serializeBinary()).toString('base64'); +} + +/** + * First/second step of a Hashed Time Lock Contract + * - Lock a unique asset instance using a hash + * + * Byzantine Swaps: Call StartHTLCAssetLockListener within here while passing new callback + * parameter as newly defined function: assetLockExpirationCallback is passed as localCallback + **/ +const createHTLC = async ( + contract: Contract, + assetType: string, + assetID: string, + recipientECert: string, + hash: Hash, + expiryTimeSecs: number, + timeoutCallback: (c: Contract, t: string, i: string, r: string, h: Hash) => any, + endorsingOrgs: Array = [], +): Promise<{ hash: Hash; result: any }> => { + + if (!contract) + { + logger.error("Contract handle not supplied"); + return { hash: null, result: false }; + } + if (!assetType) + { + logger.error("Asset type not supplied"); + return { hash: null, result: false }; + } + if (!assetID) + { + logger.error("Asset ID not supplied"); + return { hash: null, result: false }; + } + if (!recipientECert) + { + logger.error("Recipient ECert not supplied"); + return { hash: null, result: false }; + } + const currTimeSecs = Math.floor(Date.now()/1000); // Convert epoch milliseconds to seconds + if (expiryTimeSecs <= currTimeSecs) + { + logger.error("Supplied expiry time invalid or in the past: %s; current time: %s", new Date(expiryTimeSecs).toISOString(), new Date(currTimeSecs).toISOString()); + return { hash: null, result: false }; + } + + if (hash == null) { + hash = new SHA256() + } + if (hash.hash64 == null) { + hash.generateRandomPreimage(22); + } + + const assetExchangeAgreementStr = createAssetExchangeAgreementSerialized(assetType, assetID, recipientECert, ""); + const lockInfoStr = createAssetLockInfoSerialized(hash, expiryTimeSecs); + + //If timeoutCallback is not defined, start automated listener + if (!timeoutCallback) + { + StartHTLCAssetLockListener(contract, "", assetType, assetID, recipientECert, "", assetLockExpirationCallback, endorsingOrgs); + } + + const tx = contract.createTransaction("LockAsset") + const ccArgs = [assetExchangeAgreementStr, lockInfoStr] + if (endorsingOrgs && endorsingOrgs.length > 0) { + tx.setEndorsingOrganizations(...endorsingOrgs) + } + // Normal invoke function + const [result, submitError] = await helpers.handlePromise( + tx.submit(...ccArgs) + ); + if (submitError) { + throw new Error(`LockAsset submitTransaction Error: ${submitError}`); + } + + if (timeoutCallback) + { + // Start timer for lock expiration + setTimeout(timeoutCallback, (expiryTimeSecs * 1000) - Date.now(), contract, assetType, assetID, recipientECert, hash); + } + + return { hash: hash, result: result }; +}; + +/** + * First/second step of a Hashed Time Lock Contract + * - Lock a set of fungible assets using a hash + **/ +const createFungibleHTLC = async ( + contract: Contract, + assetType: string, + numUnits: number, + recipientECert: string, + hash: Hash, + expiryTimeSecs: number, + timeoutCallback: (c: Contract, i: string, t: string, n: number, r: string, h: Hash) => any, + endorsingOrgs: Array = [], +): Promise<{ hash: Hash; result: any }> => { + + if (!contract) + { + logger.error("Contract handle not supplied"); + return { hash: null, result: "" }; + } + if (!assetType) + { + logger.error("Asset type not supplied"); + return { hash: null, result: "" }; + } + if (numUnits <= 0) + { + logger.error("Asset count must be a positive integer"); + return { hash: null, result: "" }; + } + if (!recipientECert) + { + logger.error("Recipient ECert not supplied"); + return { hash: null, result: "" }; + } + const currTimeSecs = Math.floor(Date.now()/1000); // Convert epoch milliseconds to seconds + if (expiryTimeSecs <= currTimeSecs) + { + logger.error("Supplied expiry time invalid or in the past: %s; current time: %s", new Date(expiryTimeSecs).toISOString(), new Date(currTimeSecs).toISOString()); + return { hash: null, result: "" }; + } + + if (!hash) { + hash = new SHA256() + } + if (hash.hash64 == null) { + hash.generateRandomPreimage(22); + } + + const assetExchangeAgreementStr = createFungibleAssetExchangeAgreementSerialized(assetType, numUnits, recipientECert, ""); + const lockInfoStr = createAssetLockInfoSerialized(hash, expiryTimeSecs); + + //If timeoutCallback is not defined, start automated listener + if (!timeoutCallback) + { + StartHTLCFungibleAssetLockListener(contract, "", assetType, numUnits, recipientECert, "", fungibleAssetLockExpirationCallback, endorsingOrgs); + } + + const tx = contract.createTransaction("LockFungibleAsset") + const ccArgs = [assetExchangeAgreementStr, lockInfoStr] + if (endorsingOrgs && endorsingOrgs.length > 0) { + tx.setEndorsingOrganizations(...endorsingOrgs) + } + // Normal invoke function + const [contractId, submitError] = await helpers.handlePromise( + tx.submit(...ccArgs) + ); + if (submitError) { + throw new Error(`LockFungibleAsset submitTransaction Error: ${submitError}`); + } + + if (timeoutCallback) + { + // Start timer for lock expiration + setTimeout(timeoutCallback, (expiryTimeSecs * 1000) - Date.now(), contract, contractId, assetType, numUnits, recipientECert, hash); + } + + return { hash: hash, result: contractId }; +}; + +/** + * Latter step of a Hashed Time Lock Contract + * - Claim a unique asset instance using a hash preimage + **/ +const claimAssetInHTLC = async ( + contract: Contract, + assetType: string, + assetID: string, + lockerECert: string, + hash: Hash, + endorsingOrgs: Array = [] +): Promise => { + + if (!contract) + { + logger.error("Contract handle not supplied"); + return false; + } + if (!assetType) + { + logger.error("Asset type not supplied"); + return false; + } + if (!assetID) + { + logger.error("Asset ID not supplied"); + return false; + } + if (!lockerECert) + { + logger.error("Locker ECert not supplied"); + return false; + } + if (!hash) + { + logger.error("Instance of Hash interface not supplied") + return false + } + if (!hash.preimage) + { + logger.error("Hash Preimage not supplied"); + return false; + } + + const assetExchangeAgreementStr = createAssetExchangeAgreementSerialized(assetType, assetID, "", lockerECert); + const claimInfoStr = createAssetClaimInfoSerialized(hash); + + // Normal invoke function + const tx = contract.createTransaction("ClaimAsset") + const ccArgs = [assetExchangeAgreementStr, claimInfoStr] + if (endorsingOrgs && endorsingOrgs.length > 0) { + tx.setEndorsingOrganizations(...endorsingOrgs) + } + const [result, submitError] = await helpers.handlePromise( + tx.submit(...ccArgs) + ); + if (submitError) { + throw new Error(`ClaimAsset submitTransaction Error: ${submitError}`); + } + return result; +}; + +const assignAsset = async ( + contract: Contract, + assetType: string, + assetID: string, + lockerECert: string, + hash: Hash, + endorsingOrgs: Array = [] +): Promise => { + + if (!contract) + { + logger.error("Contract handle not supplied"); + return false; + } + if (!assetType) + { + logger.error("Asset type not supplied"); + return false; + } + if (!assetID) + { + logger.error("Asset ID not supplied"); + return false; + } + if (!lockerECert) + { + logger.error("Locker ECert not supplied"); + return false; + } + if (!hash) + { + logger.error("Instance of Hash interface not supplied") + return false + } + if (!hash.preimage) + { + logger.error("Hash Preimage not supplied"); + return false; + } + + const assetExchangeAgreementStr = createAssetExchangeAgreementSerialized(assetType, assetID, "", lockerECert); + const claimInfoStr = createAssetClaimInfoSerialized(hash); + + // Normal invoke function + const tx = contract.createTransaction("AssignAsset") + const ccArgs = [assetExchangeAgreementStr, claimInfoStr] + if (endorsingOrgs && endorsingOrgs.length > 0) { + tx.setEndorsingOrganizations(...endorsingOrgs) + } + const [result, submitError] = await helpers.handlePromise( + tx.submit(...ccArgs) + ); + if (submitError) { + throw new Error(`AssignAsset submitTransaction Error: ${submitError}`); + } + return result; +}; + +/** + * Latter step of a Hashed Time Lock Contract + * - Claim a unique asset instance using a hash preimage and contractId + **/ +const claimAssetInHTLCusingContractId = async ( + contract: Contract, + contractId: string, + hash: Hash, + endorsingOrgs: Array = [] +): Promise => { + + if (!contract) + { + logger.error("Contract handle not supplied"); + return false; + } + if (!contractId) + { + logger.error("contract ID not supplied"); + return false; + } + if (!hash) + { + logger.error("Instance of Hash interface not supplied") + return false + } + if (!hash.preimage) + { + logger.error("Hash Preimage not supplied"); + return false; + } + + const claimInfoStr = createAssetClaimInfoSerialized(hash); + + // Normal invoke function + const tx = contract.createTransaction("ClaimAssetUsingContractId") + const ccArgs = [contractId, claimInfoStr] + if (endorsingOrgs && endorsingOrgs.length > 0) { + tx.setEndorsingOrganizations(...endorsingOrgs) + } + const [result, submitError] = await helpers.handlePromise( + tx.submit(...ccArgs) + ); + if (submitError) { + throw new Error(`ClaimAssetUsingContractId submitTransaction Error: ${submitError}`); + } + return result; +}; + + +/** + * Latter step of a Hashed Time Lock Contract + * - Claim a set of fungible assets using a hash preimage + **/ +const claimFungibleAssetInHTLC = async ( + contract: Contract, + contractId: string, + hash: Hash, + endorsingOrgs: Array = [] +): Promise => { + + if (!contract) + { + logger.error("Contract handle not supplied"); + return false; + } + if (!contractId) + { + logger.error("contract ID not supplied"); + return false; + } + if (!hash) + { + logger.error("Instance of Hash interface not supplied") + return false + } + if (!hash.preimage) + { + logger.error("Hash Preimage not supplied"); + return false; + } + + const claimInfoStr = createAssetClaimInfoSerialized(hash); + + // Normal invoke function + const tx = contract.createTransaction("ClaimFungibleAsset") + const ccArgs = [contractId, claimInfoStr] + if (endorsingOrgs && endorsingOrgs.length > 0) { + tx.setEndorsingOrganizations(...endorsingOrgs) + } + const [result, submitError] = await helpers.handlePromise( + tx.submit(...ccArgs) + ); + if (submitError) { + throw new Error(`ClaimFungibleAsset submitTransaction Error: ${submitError}`); + } + return result; +}; + +/** + * Rollback step of a Hashed Time Lock Contract + * - Reclaim a unique asset instance + **/ +const reclaimAssetInHTLC = async ( + contract: Contract, + assetType: string, + assetID: string, + recipientECert: string, + endorsingOrgs: Array = [] +): Promise => { + + if (!contract) + { + logger.error("Contract handle not supplied"); + return false; + } + if (!assetType) + { + logger.error("Asset type not supplied"); + return false; + } + if (!assetID) + { + logger.error("Asset ID not supplied"); + return false; + } + if (!recipientECert) + { + logger.error("Recipient ECert not supplied"); + return false; + } + + const assetExchangeAgreementStr = createAssetExchangeAgreementSerialized(assetType, assetID, recipientECert, ""); + + // Normal invoke function + const tx = contract.createTransaction("UnlockAsset") + const ccArgs = [assetExchangeAgreementStr] + if (endorsingOrgs && endorsingOrgs.length > 0) { + tx.setEndorsingOrganizations(...endorsingOrgs) + } + const [result, submitError] = await helpers.handlePromise( + tx.submit(...ccArgs) + ); + if (submitError) { + throw new Error(`UnlockAsset submitTransaction Error: ${submitError}`); + } + return result; +}; + +/** + * Rollback step of a Hashed Time Lock Contract + * - Reclaim a unique asset instance using contractId + **/ +const reclaimAssetInHTLCusingContractId = async ( + contract: Contract, + contractId: string, + endorsingOrgs: Array = [] +): Promise => { + + if (!contract) + { + logger.error("Contract handle not supplied"); + return false; + } + if (!contractId) + { + logger.error("contract ID not supplied"); + return false; + } + + // Normal invoke function + const tx = contract.createTransaction("UnlockAssetUsingContractId") + const ccArgs = [contractId] + if (endorsingOrgs && endorsingOrgs.length > 0) { + tx.setEndorsingOrganizations(...endorsingOrgs) + } + const [result, submitError] = await helpers.handlePromise( + tx.submit(...ccArgs) + ); + if (submitError) { + throw new Error(`UnlockAssetUsingContractId submitTransaction Error: ${submitError}`); + } + return result; +}; + +/** + * Rollback step of a Hashed Time Lock Contract + * - Reclaim a set of fungible assets + **/ +const reclaimFungibleAssetInHTLC = async ( + contract: Contract, + contractId: string, + endorsingOrgs: Array = [] +): Promise => { + + if (!contract) + { + logger.error("Contract handle not supplied"); + return false; + } + if (!contractId) + { + logger.error("contract ID not supplied"); + return false; + } + + // Normal invoke function + const tx = contract.createTransaction("UnlockFungibleAsset") + const ccArgs = [contractId] + if (endorsingOrgs && endorsingOrgs.length > 0) { + tx.setEndorsingOrganizations(...endorsingOrgs) + } + const [result, submitError] = await helpers.handlePromise( + tx.submit(...ccArgs) + ); + if (submitError) { + throw new Error(`UnlockFungibleAsset submitTransaction Error: ${submitError}`); + } + return result; +}; + +/** + * Query the state of a Hashed Time Lock Contract + * - Determine if a unique asset instance is locked by a given party for another given party + **/ +const isAssetLockedInHTLC = async ( + contract: Contract, + assetType: string, + assetID: string, + recipientECert: string, + lockerECert: string, +): Promise => { + + if (!contract) + { + logger.error("Contract handle not supplied"); + return false; + } + if (!assetType) + { + logger.error("Asset type not supplied"); + return false; + } + if (!assetID) + { + logger.error("Asset ID not supplied"); + return false; + } + if (!recipientECert) + { + logger.error("Recipient ECert not supplied"); + return false; + } + if (!lockerECert) + { + logger.error("Locker ECert not supplied"); + return false; + } + + const assetExchangeAgreementStr = createAssetExchangeAgreementSerialized(assetType, assetID, recipientECert, lockerECert); + + // Normal invoke function + const [result, evaluateError] = await helpers.handlePromise( + contract.evaluateTransaction("IsAssetLocked", assetExchangeAgreementStr), + ); + if (evaluateError) { + throw new Error(`IsAssetLocked evaluateTransaction Error: ${evaluateError}`); + } + return result.toString() === "true"; +}; + +/** + * Query the state of a Hashed Time Lock Contract using contractId + * - Determine if a unique asset instance is locked by a given party for another given party + **/ +const isAssetLockedInHTLCqueryUsingContractId = async ( + contract: Contract, + contractId: string, +): Promise => { + + if (!contract) + { + logger.error("Contract handle not supplied"); + return false; + } + if (!contractId) + { + logger.error("contract ID not supplied"); + return false; + } + + // Normal invoke function + const [result, evaluateError] = await helpers.handlePromise( + contract.evaluateTransaction("IsAssetLockedQueryUsingContractId", contractId), + ); + if (evaluateError) { + throw new Error(`IsAssetLockedQueryUsingContractId evaluateTransaction Error: ${evaluateError}`); + } + return result.toString() === "true"; +}; + +/** + * Query the state of a Hashed Time Lock Contract + * - Determine if a set of fungible assets is locked by a given party for another given party + **/ +const isFungibleAssetLockedInHTLC = async ( + contract: Contract, + contractId: string, +): Promise => { + + if (!contract) + { + logger.error("Contract handle not supplied"); + return false; + } + if (!contractId) + { + logger.error("contract ID not supplied"); + return false; + } + + // Normal invoke function + const [result, evaluateError] = await helpers.handlePromise( + contract.evaluateTransaction("IsFungibleAssetLocked", contractId), + ); + if (evaluateError) { + throw new Error(`IsFungibleAssetLocked evaluateTransaction Error: ${evaluateError}`); + } + return result.toString() === "true"; +}; + + +/** + * HTLC Lifecycle Events + * - Developers should note that event emission and actions in response occur on a best effort basis. + * - Also, there is no guarantee that a particular event (lock, claim, reclaim) will ever get emitted + * - Therefore, the calling (or listening) logic should incorporate suitable fallbacks and timeouts. + **/ + +/** + * The below functions trigger callbacks passed as arguments when a matching event is received from the contract layer + **/ +const StartHTLCEventListener = ( + contract: Contract, + eventName: string, + contractId: string, + assetType: string, + assetId: string, + numUnits: number, + recipientECert: string, + lockerECert: string, + eventCallback: Function, + endorsingOrgs: Array = [], +): void => { + const listener: ContractListener = async (event) => { + if (event.eventName === eventName) { + let assetLockContractInfo; + + if (eventName.includes('Fungible')) { + const eventInfo: assetLocksPb.FungibleAssetContractHTLC = assetLocksPb.FungibleAssetContractHTLC.deserializeBinary(event.payload); + assetLockContractInfo = eventInfo; + } + else { + const eventInfo: assetLocksPb.AssetContractHTLC = assetLocksPb.AssetContractHTLC.deserializeBinary(event.payload); + assetLockContractInfo = eventInfo; + } + const infoContractId = assetLockContractInfo.getContractid(); + if (contractId && contractId.length > 0) { + if (infoContractId.length > 0 && infoContractId !== contractId) { + return; + } + } + const infoAssetType = assetLockContractInfo.getAgreement().getAssettype(); + if (assetType && assetType.length > 0) { + if (infoAssetType.length > 0 && infoAssetType !== assetType) { + return; + } + } + let infoNumUnits: number, infoAssetId: string; + if (eventName.includes('Fungible')) { + infoNumUnits = assetLockContractInfo.getAgreement().getNumunits(); + if (infoNumUnits != numUnits) { + return; + } + } + else { + infoAssetId = assetLockContractInfo.getAgreement().getId(); + if (assetId && assetId.length > 0) { + if (infoAssetId.length > 0 && infoAssetId !== assetId) { + return; + } + } + } + const infoRecipient = assetLockContractInfo.getAgreement().getRecipient(); + if (recipientECert && recipientECert.length > 0) { + if (infoRecipient.length > 0 && infoRecipient !== recipientECert) { + return; + } + } + const infoLocker = assetLockContractInfo.getAgreement().getLocker(); + if (lockerECert && lockerECert.length > 0) { + if (infoLocker.length > 0 && infoLocker !== lockerECert) { + return; + } + } + // All filters passed + if (eventName === 'LockAsset' || eventName === 'LockFungibleAsset') { + const timeout = assetLockContractInfo.getLock().getExpirytimesecs(); + const hashBase64 = assetLockContractInfo.getLock().getHashbase64(); + let hash: Hash; + + const hashMechanism = assetLockContractInfo.getLock().getHashmechanism(); + if (hashMechanism === assetLocksPb.HashMechanism.SHA256) { + hash = new SHA256(); + } + else if (hashMechanism === assetLocksPb.HashMechanism.SHA512) { + hash = new SHA512(); + } + else { + throw new Error(`Hash Mechanism not supported`); + } + hash.setSerializedHashBase64(hashBase64); + // We only care about timeouts for locking the asset, not for the unlock itself + if (eventName === 'LockAsset') { + eventCallback(contract, infoContractId, infoAssetType, infoAssetId, infoRecipient, infoLocker, hash, timeout, endorsingOrgs); + } + else { + eventCallback(contract, infoContractId, infoAssetType, infoNumUnits, infoRecipient, infoLocker, hash, timeout, endorsingOrgs); + } + } else if (eventName === 'ClaimAsset' || eventName === 'ClaimFungibleAsset') { + const hashPreimageBase64 = assetLockContractInfo.getClaim().getHashpreimagebase64(); + const hashPreimage: string = Buffer.from(hashPreimageBase64.toString(), 'base64').toString('utf8'); + if (eventName === 'ClaimAsset') { + eventCallback(contract, infoContractId, infoAssetType, infoAssetId, infoRecipient, infoLocker, hashPreimage); + } + else { + eventCallback(contract, infoContractId, infoAssetType, infoNumUnits, infoRecipient, infoLocker, hashPreimage); + } + } + else if (eventName === 'UnlockAsset') { + eventCallback(contract, infoContractId, infoAssetType, infoAssetId, infoRecipient, infoLocker); + } + else if (eventName === 'UnlockFungibleAsset') { + eventCallback(contract, infoContractId, infoAssetType, infoNumUnits, infoRecipient, infoLocker); + } + } + }; + contract.addContractListener(listener); +} + +const StartHTLCAssetLockListener = ( + contract: Contract, + contractId: string, + assetType: string, + assetId: string, + recipientECert: string, + lockerECert: string, + lockCallback: (c: Contract, d: string, t: string, i: string, r: string, l: string, v: Hash, timeout: number, eOrgs: Array) => any, + endorsingOrgs: Array = [], +): void => { + StartHTLCEventListener(contract, 'LockAsset', contractId, assetType, assetId, -1, recipientECert, lockerECert, lockCallback, endorsingOrgs); +} + +// NOTE: For Nonfungible Assets +// Byzantine Swaps: Timed counterpart for timed AssetLockListener for reversion +const assetLockExpirationCallback = ( + contract: Contract, + contractID: string, + assetType: string, + assetID: string, + recipientECert: string, + lockerECert: string, + hash: Hash, + expiryTime: number, + endorsingOrgs: Array = [] +): void => { + // Compare expiryTimeSec with currentTimeSec, which is number of milliseconds since epoch (L174) + const currTimeSecs = Math.floor(Date.now()/1000); + const reclaimCallback = async (contract: Contract, contractID: string) => { + // Check if asset hasn't been claimed yet. If true, do nothing. If false, either do the following cases: + const [islocked, isLockedQueryError] = await helpers.handlePromise(isAssetLockedInHTLCqueryUsingContractId(contract, contractID)); + if (islocked === false) { + // CASE #1: Check GetHTLCHashPreImageByContractId(contractId) + const [result, evaluateError] = await helpers.handlePromise( + contract.evaluateTransaction("GetHTLCHashPreImageByContractId", contractID), + ); + + // CASE #2: If the function above returns ANY error, call reclaimAssetInHTLC + if (evaluateError) { + // Put retry logic in event of failure. Retry 3x and then give up if unsuccessful (temp solution for now; requires CORE changes) + // If it fails, retry for i (arbitrarily defined) more attempts until you quit + let i = 0; + do { + let [retryReclaimResult, retryReclaimableQueryError] = await helpers.handlePromise(reclaimAssetInHTLCusingContractId(contract, contractID, endorsingOrgs)); + if (!retryReclaimableQueryError) { + console.log("Nonfungible Asset unlocked successfully"); + break; + } + + i++; + } while (i < 3); + } + } + } + + // If you have time remaining, call setTimeout with reclaimCallback + if (expiryTime - currTimeSecs > 0) { + setTimeout(reclaimCallback, 1000 * (expiryTime - currTimeSecs), contract, contractID); + } else { + // If no time remaining, call the reclaim callback immediately + reclaimCallback(contract, contractID); + } +} + +//NOTE: FUNGIBLE counterpart +// Byzantine Swaps: Timed counterpart for timed AssetLockListener for reversion +const fungibleAssetLockExpirationCallback = ( + contract: Contract, + contractID: string, + assetType: string, + numUnits: number, + recipientECert: string, + lockerECert: string, + hash: Hash, + expiryTime: number, + endorsingOrgs: Array = [] +): void => { + // Compare expiryTimeSec with currentTimeSec, which is number of milliseconds since epoch (L174) + const currTimeSecs = Math.floor(Date.now()/1000); + const reclaimCallback = async (contract: Contract, contractID: string) => { + // Check if asset hasn't been claimed yet. If true, do nothing. If false, either do the following cases: + const [islocked, isLockedQueryError] = await helpers.handlePromise(isFungibleAssetLockedInHTLC(contract, contractID)); + + if (islocked === false) { + // CASE #1: Check GetHTLCHashPreImageByContractId(contractId) + const [result, evaluateError] = await helpers.handlePromise( + contract.evaluateTransaction("GetHTLCHashPreImageByContractId", contractID), + ); + + // CASE #2: If the function above returns ANY error, call reclaimAssetInHTLC + if (evaluateError) { + // Put retry logic in event of failure. Retry 3x and then give up if unsuccessful (temp solution for now; requires CORE changes) + // If it fails, retry for i (arbitrarily defined) more attempts until you quit + let i = 0; + do { + let [retryReclaimResult, retryReclaimableQueryError] = await helpers.handlePromise(reclaimFungibleAssetInHTLC(contract, contractID, endorsingOrgs)); + if (!retryReclaimableQueryError) { + console.log("Fungible Asset unlocked successfully"); + break; + } + + i++; + } while (i < 3); + } + } + } + + // If you have time remaining, call setTimeout with reclaimCallback + if (expiryTime - currTimeSecs > 0) { + setTimeout(reclaimCallback, 1000 * (expiryTime - currTimeSecs), contract, contractID); + } else { + // If no time remaining, call the reclaim callback immediately + reclaimCallback(contract, contractID); + } +} + +const StartHTLCAssetClaimListener = ( + contract: Contract, + contractId: string, + assetType: string, + assetId: string, + recipientECert: string, + lockerECert: string, + claimCallback: (c: Contract, d: string, t: string, i: string, r: string, l: string, p: string) => any, +): void => { + StartHTLCEventListener(contract, 'ClaimAsset', contractId, assetType, assetId, -1, recipientECert, lockerECert, claimCallback); +} + +const StartHTLCAssetUnlockListener = ( + contract: Contract, + contractId: string, + assetType: string, + assetId: string, + recipientECert: string, + lockerECert: string, + unlockCallback: (c: Contract, d: string, t: string, i: string, r: string, l: string) => any, +): void => { + StartHTLCEventListener(contract, 'UnlockAsset', contractId, assetType, assetId, -1, recipientECert, lockerECert, unlockCallback); +} + +const StartHTLCFungibleAssetLockListener = ( + contract: Contract, + contractId: string, + assetType: string, + numUnits: number, + recipientECert: string, + lockerECert: string, + lockCallback: (c: Contract, d: string, t: string, n: number, r: string, l: string, v: Hash, timeout: number, eOrgs: Array) => any, + endorsingOrgs: Array = [], +): void => { + StartHTLCEventListener(contract, 'LockFungibleAsset', contractId, assetType, "", numUnits, recipientECert, lockerECert, lockCallback, endorsingOrgs); +} + +const StartHTLCFungibleAssetClaimListener = ( + contract: Contract, + contractId: string, + assetType: string, + numUnits: number, + recipientECert: string, + lockerECert: string, + claimCallback: (c: Contract, d: string, t: string, n: number, r: string, l: string, p: string) => any, +): void => { + StartHTLCEventListener(contract, 'ClaimFungibleAsset', contractId, assetType, "", numUnits, recipientECert, lockerECert, claimCallback); +} + +const StartHTLCFungibleAssetUnlockListener = ( + contract: Contract, + contractId: string, + assetType: string, + numUnits: number, + recipientECert: string, + lockerECert: string, + unlockCallback: (c: Contract, d: string, t: string, n: number, r: string, l: string) => any, +): void => { + StartHTLCEventListener(contract, 'UnlockFungibleAsset', contractId, assetType, "", numUnits, recipientECert, lockerECert, unlockCallback); +} + +/** + * The below functions return promises for HTLC events. + * Developers can use 'await' to synchronously manage asset swapping logic. + **/ + const HTLCAssetLocked = async ( + contract: Contract, + contractId: string, + assetType: string, + assetId: string, + recipientECert: string, + lockerECert: string, +): Promise => { + return new Promise((resolve, reject) => { + const waitForLock = (contract, contractId, assetType, assetId, recipientECert, lockerECert, hashValue) => { + resolve(hashValue); + }; + StartHTLCAssetLockListener(contract, contractId, assetType, assetId, recipientECert, lockerECert, waitForLock); + }); +} + +const HTLCAssetClaimed = async ( + contract: Contract, + contractId: string, + assetType: string, + assetId: string, + recipientECert: string, + lockerECert: string, +): Promise => { + return new Promise((resolve, reject) => { + const waitForClaim = (contract, contractId, assetType, assetId, recipientECert, lockerECert, hashPreimage) => { + resolve(hashPreimage); + }; + StartHTLCAssetClaimListener(contract, contractId, assetType, assetId, recipientECert, lockerECert, waitForClaim); + }); +} + +const HTLCAssetUnlocked = async ( + contract: Contract, + contractId: string, + assetType: string, + assetId: string, + recipientECert: string, + lockerECert: string, +): Promise => { + return new Promise((resolve, reject) => { + const waitForUnlock = (contract, contractId, assetType, assetId, recipientECert, lockerECert) => { + resolve(); + }; + StartHTLCAssetUnlockListener(contract, contractId, assetType, assetId, recipientECert, lockerECert, waitForUnlock); + }); +} + +const HTLCFungibleAssetLocked = async ( + contract: Contract, + contractId: string, + assetType: string, + numUnits: number, + recipientECert: string, + lockerECert: string, +): Promise => { + return new Promise((resolve, reject) => { + const waitForLock = (contract, contractId, assetType, numUnits, recipientECert, lockerECert, hashValue) => { + resolve(hashValue); + }; + StartHTLCFungibleAssetLockListener(contract, contractId, assetType, numUnits, recipientECert, lockerECert, waitForLock); + }); +} + +const HTLCFungibleAssetClaimed = async ( + contract: Contract, + contractId: string, + assetType: string, + numUnits: number, + recipientECert: string, + lockerECert: string, +): Promise => { + return new Promise((resolve, reject) => { + const waitForClaim = (contract, contractId, assetType, numUnits, recipientECert, lockerECert, hashPreimage) => { + resolve(hashPreimage); + }; + StartHTLCFungibleAssetClaimListener(contract, contractId, assetType, numUnits, recipientECert, lockerECert, waitForClaim); + }); +} + +const HTLCFungibleAssetUnlocked = async ( + contract: Contract, + contractId: string, + assetType: string, + numUnits: number, + recipientECert: string, + lockerECert: string, +): Promise => { + return new Promise((resolve, reject) => { + const waitForUnlock = (contract, contractId, assetType, numUnits, recipientECert, lockerECert) => { + resolve(); + }; + StartHTLCFungibleAssetUnlockListener(contract, contractId, assetType, numUnits, recipientECert, lockerECert, waitForUnlock); + }); +} + +export { + createAssetExchangeAgreementSerialized, + createFungibleAssetExchangeAgreementSerialized, + createAssetLockInfoSerialized, + createAssetClaimInfoSerialized, + createHTLC, + createFungibleHTLC, + claimAssetInHTLC, + claimAssetInHTLCusingContractId, + claimFungibleAssetInHTLC, + reclaimAssetInHTLC, + reclaimAssetInHTLCusingContractId, + reclaimFungibleAssetInHTLC, + assignAsset, + isAssetLockedInHTLC, + isAssetLockedInHTLCqueryUsingContractId, + isFungibleAssetLockedInHTLC, + StartHTLCAssetLockListener, + StartHTLCAssetClaimListener, + StartHTLCAssetUnlockListener, + StartHTLCFungibleAssetLockListener, + StartHTLCFungibleAssetClaimListener, + StartHTLCFungibleAssetUnlockListener, + HTLCAssetLocked, + HTLCAssetClaimed, + HTLCAssetUnlocked, + HTLCFungibleAssetLocked, + HTLCFungibleAssetClaimed, + HTLCFungibleAssetUnlocked, +}; diff --git a/weaver/sdks/fabric/interoperation-node-sdk/types/index.d.ts b/weaver/sdks/fabric/interoperation-node-sdk/types/index.d.ts index 4ec78c0f11f..f965212e3e0 100644 --- a/weaver/sdks/fabric/interoperation-node-sdk/types/index.d.ts +++ b/weaver/sdks/fabric/interoperation-node-sdk/types/index.d.ts @@ -14,6 +14,8 @@ import * as RelayHelper from "../src/Relay"; export { RelayHelper }; import * as AssetManager from "../src/AssetManager"; export { AssetManager }; +import * as SatpAssetManager from "../src/SatpAssetManager"; +export { SatpAssetManager }; import * as HashFunctions from "../src/HashFunctions"; export { HashFunctions }; import * as EventsManager from "../src/EventsManager"; diff --git a/weaver/tests/network-setups/fabric/dev/scripts/deployCC.sh b/weaver/tests/network-setups/fabric/dev/scripts/deployCC.sh index 21dc1bbbe5c..216dc5e7dea 100755 --- a/weaver/tests/network-setups/fabric/dev/scripts/deployCC.sh +++ b/weaver/tests/network-setups/fabric/dev/scripts/deployCC.sh @@ -302,6 +302,10 @@ chaincodeInvokeInit() { peer chaincode invoke -o localhost:${ORD_P} --ordererTLSHostnameOverride orderer.$NW_NAME.com --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n $CC_CHAIN_CODE $PEER_CONN_PARMS --isInit -c '{"function":"initLedger","Args":["Bond", "interop"]}' >&log.txt elif [ "$CC_CHAIN_CODE" = "simpleasset" ] && [ "$NW_NAME" = "network2" ]; then peer chaincode invoke -o localhost:${ORD_P} --ordererTLSHostnameOverride orderer.$NW_NAME.com --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n $CC_CHAIN_CODE $PEER_CONN_PARMS --isInit -c '{"function":"initLedger","Args":["Token", "interop"]}' >&log.txt + elif [ "$CC_CHAIN_CODE" = "satpsimpleasset" ] && [ "$NW_NAME" = "network1" ]; then + peer chaincode invoke -o localhost:${ORD_P} --ordererTLSHostnameOverride orderer.$NW_NAME.com --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n $CC_CHAIN_CODE $PEER_CONN_PARMS --isInit -c '{"function":"initLedger","Args":["Bond", "interop"]}' >&log.txt + elif [ "$CC_CHAIN_CODE" = "satpsimpleasset" ] && [ "$NW_NAME" = "network2" ]; then + peer chaincode invoke -o localhost:${ORD_P} --ordererTLSHostnameOverride orderer.$NW_NAME.com --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n $CC_CHAIN_CODE $PEER_CONN_PARMS --isInit -c '{"function":"initLedger","Args":["Token", "interop"]}' >&log.txt elif [ "$CC_CHAIN_CODE" = "simpleassettransfer" ] && [ "$NW_NAME" = "network1" ]; then peer chaincode invoke -o localhost:${ORD_P} --ordererTLSHostnameOverride orderer.$NW_NAME.com --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n $CC_CHAIN_CODE $PEER_CONN_PARMS --isInit -c '{"function":"initLedger","Args":["interop", "network1"]}' >&log.txt elif [ "$CC_CHAIN_CODE" = "simpleassettransfer" ] && [ "$NW_NAME" = "network2" ]; then