@distrohelena/canton-typescript-sdk 0.1.5 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +333 -1
- package/dist/client/canton-client-options.d.ts +3 -0
- package/dist/client/canton-client-options.js +2 -0
- package/dist/client/service-registry.js +3 -2
- package/dist/core/errors/grpc-transport-error.d.ts +14 -0
- package/dist/core/errors/grpc-transport-error.js +76 -0
- package/dist/core/signing/command-signer.interface.d.ts +2 -0
- package/dist/core/transports/transport.interface.d.ts +2 -2
- package/dist/core/types/canton-hash-purpose.d.ts +2 -1
- package/dist/core/types/canton-hash-purpose.js +1 -0
- package/dist/core/types/daml-numeric.d.ts +6 -0
- package/dist/core/types/daml-numeric.js +14 -0
- package/dist/core/types/daml-party.d.ts +6 -0
- package/dist/core/types/daml-party.js +14 -0
- package/dist/core/types/disclosed-contract.d.ts +13 -0
- package/dist/core/types/disclosed-contract.js +15 -0
- package/dist/core/types/requests/create-decentralized-party-request.d.ts +41 -0
- package/dist/core/types/requests/create-decentralized-party-request.js +82 -0
- package/dist/core/types/requests/create-external-party-request.d.ts +42 -0
- package/dist/core/types/requests/create-external-party-request.js +47 -0
- package/dist/core/types/requests/finalize-decentralized-party-request.d.ts +39 -0
- package/dist/core/types/requests/finalize-decentralized-party-request.js +42 -0
- package/dist/core/types/requests/get-active-contracts-page-request.d.ts +15 -2
- package/dist/core/types/requests/get-active-contracts-page-request.js +4 -0
- package/dist/core/types/requests/submit-command-request.d.ts +5 -0
- package/dist/core/types/requests/submit-command-request.js +4 -0
- package/dist/core/types/topology/topology-signature-format.d.ts +2 -1
- package/dist/core/types/topology/topology-signature-format.js +1 -0
- package/dist/daml-lf/container/dar-archive-entry.d.ts +8 -0
- package/dist/daml-lf/container/dar-archive-entry.js +8 -0
- package/dist/daml-lf/container/dar-archive-loader.js +14 -0
- package/dist/daml-lf/container/dar-archive.d.ts +6 -0
- package/dist/daml-lf/container/dar-archive.js +4 -0
- package/dist/daml-lf/container/dar-source-bundle-loader.d.ts +5 -0
- package/dist/daml-lf/container/dar-source-bundle-loader.js +33 -0
- package/dist/daml-lf/container/dar-source-bundle.d.ts +45 -0
- package/dist/daml-lf/container/dar-source-bundle.js +11 -0
- package/dist/daml-lf/container/dar-source-file-entry.d.ts +8 -0
- package/dist/daml-lf/container/dar-source-file-entry.js +8 -0
- package/dist/daml-lf/daml-lf-compilation.d.ts +12 -0
- package/dist/daml-lf/daml-lf-compilation.js +35 -0
- package/dist/daml-lf/index.d.ts +11 -0
- package/dist/daml-lf/index.js +10 -0
- package/dist/daml-lf/interpreter/daml-lf-builtin-dispatch.d.ts +43 -0
- package/dist/daml-lf/interpreter/daml-lf-builtin-dispatch.js +933 -0
- package/dist/daml-lf/interpreter/daml-lf-evaluator.d.ts +95 -0
- package/dist/daml-lf/interpreter/daml-lf-evaluator.js +1131 -0
- package/dist/daml-lf/interpreter/daml-lf-interpreter-scaffold.d.ts +3 -0
- package/dist/daml-lf/interpreter/daml-lf-interpreter-scaffold.js +6 -1
- package/dist/daml-lf/interpreter/daml-lf-lexical-scope.d.ts +13 -0
- package/dist/daml-lf/interpreter/daml-lf-lexical-scope.js +46 -0
- package/dist/daml-lf/interpreter/daml-lf-runtime-frame.d.ts +16 -0
- package/dist/daml-lf/interpreter/daml-lf-runtime-frame.js +15 -0
- package/dist/daml-lf/interpreter/daml-lf-runtime-value.d.ts +21 -0
- package/dist/daml-lf/interpreter/daml-lf-runtime-value.js +4 -1
- package/dist/daml-lf/interpreter/daml-lf-step-kind.d.ts +7 -0
- package/dist/daml-lf/interpreter/daml-lf-step-kind.js +8 -0
- package/dist/daml-lf/interpreter/daml-lf-trace-sink.interface.d.ts +30 -0
- package/dist/daml-lf/interpreter/daml-lf-trace-sink.interface.js +1 -0
- package/dist/daml-lf/model/daml-lf-builtin-type.d.ts +3 -0
- package/dist/daml-lf/model/daml-lf-builtin-type.js +3 -0
- package/dist/daml-lf/model/daml-lf-choice.d.ts +5 -0
- package/dist/daml-lf/model/daml-lf-choice.js +4 -0
- package/dist/daml-lf/model/daml-lf-expression-path.d.ts +2 -0
- package/dist/daml-lf/model/daml-lf-expression-path.js +81 -0
- package/dist/daml-lf/model/daml-lf-expression.d.ts +146 -0
- package/dist/daml-lf/model/daml-lf-expression.js +71 -0
- package/dist/daml-lf/model/daml-lf-template.d.ts +2 -0
- package/dist/daml-lf/model/daml-lf-template.js +2 -0
- package/dist/daml-lf/model/daml-lf-type.d.ts +2 -0
- package/dist/daml-lf/model/daml-lf-type.js +4 -0
- package/dist/daml-lf/model/lf-2-model-mapper.d.ts +5 -0
- package/dist/daml-lf/model/lf-2-model-mapper.js +445 -12
- package/dist/debugger/errors/replay-determinism.exception.d.ts +3 -0
- package/dist/debugger/errors/replay-determinism.exception.js +3 -0
- package/dist/debugger/errors/replay-missing-package.exception.d.ts +3 -0
- package/dist/debugger/errors/replay-missing-package.exception.js +3 -0
- package/dist/debugger/errors/replay-missing-source.exception.d.ts +3 -0
- package/dist/debugger/errors/replay-missing-source.exception.js +3 -0
- package/dist/debugger/errors/replay-source-map.exception.d.ts +3 -0
- package/dist/debugger/errors/replay-source-map.exception.js +3 -0
- package/dist/debugger/errors/replay-state-hydration.exception.d.ts +3 -0
- package/dist/debugger/errors/replay-state-hydration.exception.js +3 -0
- package/dist/debugger/errors/replay-unsupported-lf-construct.exception.d.ts +3 -0
- package/dist/debugger/errors/replay-unsupported-lf-construct.exception.js +3 -0
- package/dist/debugger/errors/replay-unsupported-update.exception.d.ts +3 -0
- package/dist/debugger/errors/replay-unsupported-update.exception.js +3 -0
- package/dist/debugger/index.d.ts +31 -0
- package/dist/debugger/index.js +31 -0
- package/dist/debugger/ledger-replay-debugger-client.d.ts +31 -0
- package/dist/debugger/ledger-replay-debugger-client.js +53 -0
- package/dist/debugger/replay/ledger-replay-environment-builder.d.ts +95 -0
- package/dist/debugger/replay/ledger-replay-environment-builder.js +249 -0
- package/dist/debugger/replay/ledger-replay-session-loader.d.ts +78 -0
- package/dist/debugger/replay/ledger-replay-session-loader.js +565 -0
- package/dist/debugger/replay/replay-artifact-resolver.d.ts +30 -0
- package/dist/debugger/replay/replay-artifact-resolver.js +210 -0
- package/dist/debugger/replay/replay-determinism-validator.d.ts +12 -0
- package/dist/debugger/replay/replay-determinism-validator.js +161 -0
- package/dist/debugger/replay/replay-entrypoint-definition-resolver.d.ts +40 -0
- package/dist/debugger/replay/replay-entrypoint-definition-resolver.js +337 -0
- package/dist/debugger/replay/replay-entrypoint.d.ts +22 -0
- package/dist/debugger/replay/replay-entrypoint.js +14 -0
- package/dist/debugger/replay/replay-ledger-value-normalizer.d.ts +7 -0
- package/dist/debugger/replay/replay-ledger-value-normalizer.js +194 -0
- package/dist/debugger/replay/replay-update-loader.d.ts +24 -0
- package/dist/debugger/replay/replay-update-loader.js +94 -0
- package/dist/debugger/replay/replay-update-visibility-validator.d.ts +19 -0
- package/dist/debugger/replay/replay-update-visibility-validator.js +19 -0
- package/dist/debugger/session/in-memory-replay-session-store.d.ts +27 -0
- package/dist/debugger/session/in-memory-replay-session-store.js +109 -0
- package/dist/debugger/session/replay-phase.d.ts +7 -0
- package/dist/debugger/session/replay-phase.js +8 -0
- package/dist/debugger/session/replay-scope.d.ts +10 -0
- package/dist/debugger/session/replay-scope.js +10 -0
- package/dist/debugger/session/replay-session-metadata.d.ts +10 -0
- package/dist/debugger/session/replay-session-metadata.js +10 -0
- package/dist/debugger/session/replay-session-request.d.ts +6 -0
- package/dist/debugger/session/replay-session-request.js +10 -0
- package/dist/debugger/session/replay-session.d.ts +12 -0
- package/dist/debugger/session/replay-session.js +10 -0
- package/dist/debugger/session/replay-source-location.d.ts +17 -0
- package/dist/debugger/session/replay-source-location.js +16 -0
- package/dist/debugger/session/replay-stack-frame.d.ts +8 -0
- package/dist/debugger/session/replay-stack-frame.js +8 -0
- package/dist/debugger/session/replay-state-delta.d.ts +29 -0
- package/dist/debugger/session/replay-state-delta.js +24 -0
- package/dist/debugger/session/replay-step-advance-result.d.ts +24 -0
- package/dist/debugger/session/replay-step-advance-result.js +16 -0
- package/dist/debugger/session/replay-step.d.ts +30 -0
- package/dist/debugger/session/replay-step.js +24 -0
- package/dist/debugger/session/replay-value-preview.d.ts +8 -0
- package/dist/debugger/session/replay-value-preview.js +15 -0
- package/dist/debugger/source/daml-source-mapper.d.ts +12 -0
- package/dist/debugger/source/daml-source-mapper.js +21 -0
- package/dist/debugger/source/dar-source-map-metadata.d.ts +26 -0
- package/dist/debugger/source/dar-source-map-metadata.js +10 -0
- package/dist/debugger/source/source-coverage-validator.d.ts +8 -0
- package/dist/debugger/source/source-coverage-validator.js +16 -0
- package/dist/debugger/source/source-indexed-compilation.d.ts +45 -0
- package/dist/debugger/source/source-indexed-compilation.js +110 -0
- package/dist/debugger/source/source-mapping-precision.d.ts +5 -0
- package/dist/debugger/source/source-mapping-precision.js +4 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.js +13 -0
- package/dist/query/cache/memory-query-cache.d.ts +9 -0
- package/dist/query/cache/memory-query-cache.js +24 -0
- package/dist/query/cache/query-cache-store.d.ts +5 -0
- package/dist/query/cache/query-cache-store.js +1 -0
- package/dist/query/canton-manager-options.d.ts +17 -0
- package/dist/query/canton-manager-options.js +1 -0
- package/dist/query/canton-manager.d.ts +11 -0
- package/dist/query/canton-manager.js +42 -0
- package/dist/query/errors/pqs-query-error.d.ts +10 -0
- package/dist/query/errors/pqs-query-error.js +11 -0
- package/dist/query/errors/pqs-schema-profile-error.d.ts +3 -0
- package/dist/query/errors/pqs-schema-profile-error.js +3 -0
- package/dist/query/errors/query-capability-error.d.ts +7 -0
- package/dist/query/errors/query-capability-error.js +10 -0
- package/dist/query/grpc/grpc-contract-query-client.d.ts +32 -0
- package/dist/query/grpc/grpc-contract-query-client.js +126 -0
- package/dist/query/model-types.d.ts +258 -0
- package/dist/query/model-types.js +14 -0
- package/dist/query/pqs/pqs-pool.d.ts +13 -0
- package/dist/query/pqs/pqs-pool.js +18 -0
- package/dist/query/pqs/pqs-query-client.d.ts +49 -0
- package/dist/query/pqs/pqs-query-client.js +324 -0
- package/dist/query/pqs/pqs-schema-profile.d.ts +25 -0
- package/dist/query/pqs/pqs-schema-profile.js +120 -0
- package/dist/query/pqs/pqs-sql-compiler.d.ts +7 -0
- package/dist/query/pqs/pqs-sql-compiler.js +132 -0
- package/dist/query/pqs/read-only-sql.d.ts +1 -0
- package/dist/query/pqs/read-only-sql.js +35 -0
- package/dist/query/query-client.d.ts +61 -0
- package/dist/query/query-client.js +1 -0
- package/dist/query/query-source.d.ts +4 -0
- package/dist/query/query-source.js +5 -0
- package/dist/services/command/command-service-client.d.ts +2 -2
- package/dist/services/commands/command-submission-pipeline.d.ts +2 -2
- package/dist/services/party-management/decentralized-party-lifecycle.d.ts +6 -0
- package/dist/services/party-management/decentralized-party-lifecycle.js +82 -0
- package/dist/services/party-management/party-management-service-client.d.ts +16 -1
- package/dist/services/party-management/party-management-service-client.js +142 -1
- package/dist/services/topology-manager-write/topology-signed-transaction-assembler.js +4 -0
- package/dist/testing/campaign/campaign-artifact.d.ts +20 -0
- package/dist/testing/campaign/campaign-artifact.js +147 -0
- package/dist/testing/campaign/campaign-definition.d.ts +9 -0
- package/dist/testing/campaign/campaign-definition.js +78 -0
- package/dist/testing/campaign/campaign-metrics.d.ts +32 -0
- package/dist/testing/campaign/campaign-metrics.js +26 -0
- package/dist/testing/campaign/campaign-model.d.ts +11 -0
- package/dist/testing/campaign/campaign-model.js +21 -0
- package/dist/testing/campaign/campaign-runner.d.ts +99 -0
- package/dist/testing/campaign/campaign-runner.js +194 -0
- package/dist/testing/campaign/campaign-scheduler.d.ts +40 -0
- package/dist/testing/campaign/campaign-scheduler.js +75 -0
- package/dist/testing/campaign/campaign-types.d.ts +52 -0
- package/dist/testing/campaign/campaign-types.js +11 -0
- package/dist/testing/daml/daml-action-arbitrary.d.ts +13 -0
- package/dist/testing/daml/daml-action-arbitrary.js +24 -0
- package/dist/testing/daml/daml-choice-action-arbitrary.d.ts +18 -0
- package/dist/testing/daml/daml-choice-action-arbitrary.js +27 -0
- package/dist/testing/daml/daml-create-action-arbitrary.d.ts +19 -0
- package/dist/testing/daml/daml-create-action-arbitrary.js +34 -0
- package/dist/testing/daml/daml-testing-catalog.d.ts +38 -0
- package/dist/testing/daml/daml-testing-catalog.js +40 -0
- package/dist/testing/daml/daml-value-arbitrary.d.ts +8 -0
- package/dist/testing/daml/daml-value-arbitrary.js +43 -0
- package/dist/testing/daml/declarative-campaign-arbitrary.d.ts +15 -0
- package/dist/testing/daml/declarative-campaign-arbitrary.js +30 -0
- package/dist/testing/errors/invariant-campaign-failure.d.ts +24 -0
- package/dist/testing/errors/invariant-campaign-failure.js +37 -0
- package/dist/testing/errors/testing-configuration-error.d.ts +3 -0
- package/dist/testing/errors/testing-configuration-error.js +6 -0
- package/dist/testing/handlers/handler.d.ts +19 -0
- package/dist/testing/handlers/handler.js +31 -0
- package/dist/testing/index.d.ts +22 -0
- package/dist/testing/index.js +22 -0
- package/dist/testing/runtime/campaign-isolation.d.ts +14 -0
- package/dist/testing/runtime/campaign-isolation.js +23 -0
- package/dist/testing/runtime/canton-test-runtime.d.ts +58 -0
- package/dist/testing/runtime/canton-test-runtime.js +138 -0
- package/dist/testing/runtime/declarative-action-executor.d.ts +16 -0
- package/dist/testing/runtime/declarative-action-executor.js +41 -0
- package/dist/testing/targets/target.d.ts +49 -0
- package/dist/testing/targets/target.js +121 -0
- package/dist/transports/grpc/grpc-channel-factory.js +31 -1
- package/dist/transports/grpc/grpc-transport.d.ts +2 -2
- package/dist/transports/grpc/grpc-transport.js +11 -8
- package/dist/transports/grpc/mappers/commands-mapper.js +23 -2
- package/dist/transports/grpc/mappers/contracts-mapper.d.ts +3 -1
- package/dist/transports/grpc/mappers/contracts-mapper.js +16 -3
- package/dist/transports/grpc/mappers/interactive-command-mapper.d.ts +4 -1
- package/dist/transports/grpc/mappers/interactive-command-mapper.js +3 -8
- package/dist/transports/grpc/mappers/topology-manager-write-mapper.js +59 -1
- package/dist/transports/json/mappers/commands-mapper.js +20 -6
- package/node/.generated/start-local/additional-config.extra-participants.conf +37 -0
- package/node/.generated/start-local/additional-config.extra-validators.conf +35 -0
- package/node/.generated/start-local/compose-extra-participants.yaml +147 -0
- package/node/.generated/start-local/extra-participants.env +30 -0
- package/node/es256-jwt.mjs +177 -0
- package/node/start-local.sh +886 -0
- package/node/stop-local.sh +200 -0
- package/node/test-start-local.sh +354 -0
- package/node/test-stop-local.sh +112 -0
- package/package.json +21 -2
|
@@ -0,0 +1,886 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
set -euo pipefail
|
|
3
|
+
|
|
4
|
+
SCRIPT_DIR="$(cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)"
|
|
5
|
+
REPO_ROOT="$(cd -- "$SCRIPT_DIR/.." && pwd)"
|
|
6
|
+
DOCKER_COMPOSE_CMD=()
|
|
7
|
+
|
|
8
|
+
load_repo_root_env() {
|
|
9
|
+
local env_file="$REPO_ROOT/.env"
|
|
10
|
+
if [[ -f "$env_file" ]]; then
|
|
11
|
+
local existing_cn_quickstart_dir="${CN_QUICKSTART_DIR:-}"
|
|
12
|
+
set -a
|
|
13
|
+
# shellcheck disable=SC1090
|
|
14
|
+
source "$env_file"
|
|
15
|
+
set +a
|
|
16
|
+
if [[ -n "$existing_cn_quickstart_dir" ]]; then
|
|
17
|
+
CN_QUICKSTART_DIR="$existing_cn_quickstart_dir"
|
|
18
|
+
fi
|
|
19
|
+
fi
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
normalize_quickstart_dir_candidate() {
|
|
23
|
+
local candidate="$1"
|
|
24
|
+
|
|
25
|
+
if [[ -z "$candidate" ]]; then
|
|
26
|
+
return 1
|
|
27
|
+
fi
|
|
28
|
+
|
|
29
|
+
if [[ -d "$candidate/quickstart" ]]; then
|
|
30
|
+
candidate="$candidate/quickstart"
|
|
31
|
+
fi
|
|
32
|
+
|
|
33
|
+
if [[ -f "$candidate/compose.yaml" && -d "$candidate/docker/modules" ]]; then
|
|
34
|
+
cd -- "$candidate" && pwd
|
|
35
|
+
return 0
|
|
36
|
+
fi
|
|
37
|
+
|
|
38
|
+
return 1
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
resolve_quickstart_dir() {
|
|
42
|
+
local candidate
|
|
43
|
+
for candidate in \
|
|
44
|
+
"${CN_QUICKSTART_DIR:-}" \
|
|
45
|
+
"$SCRIPT_DIR/../cn-quickstart/quickstart" \
|
|
46
|
+
"$SCRIPT_DIR/../../cn-quickstart/quickstart"
|
|
47
|
+
do
|
|
48
|
+
if normalize_quickstart_dir_candidate "$candidate"; then
|
|
49
|
+
return 0
|
|
50
|
+
fi
|
|
51
|
+
done
|
|
52
|
+
|
|
53
|
+
echo "Unable to locate CN Quickstart. Set CN_QUICKSTART_DIR in $REPO_ROOT/.env or place the checkout in a supported location." >&2
|
|
54
|
+
return 1
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
make_target_exists() {
|
|
58
|
+
local target="$1"
|
|
59
|
+
make -qp 2>/dev/null | grep -Eq "^${target}:"
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
read_env_value_from_files() {
|
|
63
|
+
local key="$1"
|
|
64
|
+
shift
|
|
65
|
+
|
|
66
|
+
local file
|
|
67
|
+
for file in "$@"; do
|
|
68
|
+
if [[ -f "$file" ]]; then
|
|
69
|
+
local line
|
|
70
|
+
line="$(grep -E "^${key}=" "$file" | tail -n 1 || true)"
|
|
71
|
+
if [[ -n "$line" ]]; then
|
|
72
|
+
printf '%s\n' "${line#*=}"
|
|
73
|
+
return 0
|
|
74
|
+
fi
|
|
75
|
+
fi
|
|
76
|
+
done
|
|
77
|
+
return 1
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
read_env_value() {
|
|
81
|
+
read_env_value_from_files "$1" .env.local .env
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
generated_dir() {
|
|
85
|
+
printf '%s\n' "${START_LOCAL_GENERATED_DIR:-$SCRIPT_DIR/.generated/start-local}"
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
resolve_es256_enabled() {
|
|
89
|
+
local value="${LOCALNET_ES256_JWT:-0}"
|
|
90
|
+
if [[ "$value" != "0" && "$value" != "1" ]]; then
|
|
91
|
+
echo "LOCALNET_ES256_JWT must be 0 or 1." >&2
|
|
92
|
+
return 1
|
|
93
|
+
fi
|
|
94
|
+
printf '%s\n' "$value"
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
es256_runtime_dir() {
|
|
98
|
+
printf '%s\n' "${START_LOCAL_ES256_RUNTIME_DIR:-$REPO_ROOT/.generated/localnet-es256}"
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
prepare_es256_runtime_files() {
|
|
102
|
+
local runtime_dir
|
|
103
|
+
runtime_dir="$(es256_runtime_dir)"
|
|
104
|
+
local enabled
|
|
105
|
+
enabled="$(resolve_es256_enabled)"
|
|
106
|
+
if [[ "$enabled" != "1" ]]; then
|
|
107
|
+
return 0
|
|
108
|
+
fi
|
|
109
|
+
|
|
110
|
+
local private_key_path="$runtime_dir/es256-private-key.pem"
|
|
111
|
+
local certificate_path="$runtime_dir/es256-certificate.pem"
|
|
112
|
+
local token_path="$runtime_dir/ledger-api-user.token"
|
|
113
|
+
local compose_file="$runtime_dir/compose-es256.yaml"
|
|
114
|
+
local canton_config_file="$runtime_dir/canton-es256.conf"
|
|
115
|
+
local subject="${LOCALNET_ES256_SUBJECT:-ledger-api-user}"
|
|
116
|
+
local ttl_seconds="${LOCALNET_ES256_TOKEN_TTL_SECONDS:-600}"
|
|
117
|
+
|
|
118
|
+
if [[ -n "${LOCALNET_ES256_PRIVATE_KEY_PATH:-}" || -n "${LOCALNET_ES256_CERTIFICATE_PATH:-}" ]]; then
|
|
119
|
+
if [[ -z "${LOCALNET_ES256_PRIVATE_KEY_PATH:-}" || -z "${LOCALNET_ES256_CERTIFICATE_PATH:-}" ]]; then
|
|
120
|
+
echo "LOCALNET_ES256_PRIVATE_KEY_PATH and LOCALNET_ES256_CERTIFICATE_PATH must be set together." >&2
|
|
121
|
+
return 1
|
|
122
|
+
fi
|
|
123
|
+
private_key_path="$LOCALNET_ES256_PRIVATE_KEY_PATH"
|
|
124
|
+
certificate_path="$LOCALNET_ES256_CERTIFICATE_PATH"
|
|
125
|
+
if [[ ! -r "$private_key_path" || ! -r "$certificate_path" ]]; then
|
|
126
|
+
echo "Supplied ES256 private key or certificate is not readable." >&2
|
|
127
|
+
return 1
|
|
128
|
+
fi
|
|
129
|
+
else
|
|
130
|
+
if [[ "${LOCALNET_ES256_ROTATE:-0}" == "1" ]]; then
|
|
131
|
+
rm -f "$private_key_path" "$certificate_path"
|
|
132
|
+
fi
|
|
133
|
+
if [[ ! -f "$private_key_path" ]]; then
|
|
134
|
+
mkdir -p "$runtime_dir"
|
|
135
|
+
node "$SCRIPT_DIR/es256-jwt.mjs" init --runtime-dir "$runtime_dir" >/dev/null
|
|
136
|
+
fi
|
|
137
|
+
if [[ ! -f "$certificate_path" ]]; then
|
|
138
|
+
openssl req -x509 -new -sha256 -days 3650 -key "$private_key_path" -subj "/CN=localnet-es256" -out "$certificate_path" >/dev/null 2>&1
|
|
139
|
+
fi
|
|
140
|
+
fi
|
|
141
|
+
|
|
142
|
+
mkdir -p "$runtime_dir"
|
|
143
|
+
node "$SCRIPT_DIR/es256-jwt.mjs" mint \
|
|
144
|
+
--private-key-path "$private_key_path" \
|
|
145
|
+
--subject "$subject" \
|
|
146
|
+
--audience "https://canton.network.global/es256" \
|
|
147
|
+
--ttl-seconds "$ttl_seconds" > "$token_path"
|
|
148
|
+
chmod 600 "$token_path"
|
|
149
|
+
|
|
150
|
+
cat > "$canton_config_file" <<EOF
|
|
151
|
+
include file("/app/base-app.conf")
|
|
152
|
+
|
|
153
|
+
EOF
|
|
154
|
+
local participant profile
|
|
155
|
+
for participant in app-provider app-user sv; do
|
|
156
|
+
case "$participant" in
|
|
157
|
+
app-provider) profile="$APP_PROVIDER_PROFILE" ;;
|
|
158
|
+
app-user) profile="$APP_USER_PROFILE" ;;
|
|
159
|
+
sv) profile="$SV_PROFILE" ;;
|
|
160
|
+
esac
|
|
161
|
+
if [[ "$profile" != "off" ]]; then
|
|
162
|
+
cat >> "$canton_config_file" <<EOF
|
|
163
|
+
canton.participants.${participant}.ledger-api.auth-services = [
|
|
164
|
+
{
|
|
165
|
+
type = unsafe-jwt-hmac-256
|
|
166
|
+
target-audience = "https://canton.network.global"
|
|
167
|
+
secret = "unsafe"
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
type = jwt-es-256-crt
|
|
171
|
+
certificate = "/app/es256-certificate.pem"
|
|
172
|
+
target-audience = "https://canton.network.global/es256"
|
|
173
|
+
}
|
|
174
|
+
]
|
|
175
|
+
EOF
|
|
176
|
+
fi
|
|
177
|
+
done
|
|
178
|
+
|
|
179
|
+
cat > "$compose_file" <<EOF
|
|
180
|
+
services:
|
|
181
|
+
canton:
|
|
182
|
+
volumes:
|
|
183
|
+
- "${LOCALNET_DIR}/conf/canton/app.conf:/app/base-app.conf:ro"
|
|
184
|
+
- "$canton_config_file:/app/app.conf:ro"
|
|
185
|
+
- "$certificate_path:/app/es256-certificate.pem:ro"
|
|
186
|
+
EOF
|
|
187
|
+
export LOCALNET_ES256_COMPOSE_FILE="$compose_file"
|
|
188
|
+
export LOCALNET_ES256_TOKEN_PATH="$token_path"
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
append_es256_args() {
|
|
192
|
+
local -n compose_args_ref="$1"
|
|
193
|
+
if [[ "$(resolve_es256_enabled)" == "1" ]]; then
|
|
194
|
+
compose_args_ref+=( -f "$LOCALNET_ES256_COMPOSE_FILE" )
|
|
195
|
+
fi
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
resolve_docker_compose_cmd() {
|
|
199
|
+
if (( ${#DOCKER_COMPOSE_CMD[@]} > 0 )); then
|
|
200
|
+
return 0
|
|
201
|
+
fi
|
|
202
|
+
|
|
203
|
+
if docker compose version >/dev/null 2>&1; then
|
|
204
|
+
DOCKER_COMPOSE_CMD=(docker compose)
|
|
205
|
+
return 0
|
|
206
|
+
fi
|
|
207
|
+
|
|
208
|
+
if docker-compose version >/dev/null 2>&1; then
|
|
209
|
+
DOCKER_COMPOSE_CMD=(docker-compose)
|
|
210
|
+
return 0
|
|
211
|
+
fi
|
|
212
|
+
|
|
213
|
+
echo "Unable to find a working Docker Compose command. Install 'docker compose' or 'docker-compose'." >&2
|
|
214
|
+
return 1
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
docker_compose() {
|
|
218
|
+
resolve_docker_compose_cmd
|
|
219
|
+
"${DOCKER_COMPOSE_CMD[@]}" "$@"
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
resolve_extra_participants() {
|
|
223
|
+
local value="${EXTRA_PARTICIPANTS:-0}"
|
|
224
|
+
if [[ ! "$value" =~ ^[0-9]+$ ]]; then
|
|
225
|
+
echo "EXTRA_PARTICIPANTS must be a non-negative integer." >&2
|
|
226
|
+
return 1
|
|
227
|
+
fi
|
|
228
|
+
if [[ "$value" == "0" ]]; then
|
|
229
|
+
printf '0\n'
|
|
230
|
+
return 0
|
|
231
|
+
fi
|
|
232
|
+
printf '%s\n' "$value"
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
load_localnet_common_env() {
|
|
236
|
+
local common_env_file="$1"
|
|
237
|
+
set -a
|
|
238
|
+
# shellcheck disable=SC1090
|
|
239
|
+
source "$common_env_file"
|
|
240
|
+
set +a
|
|
241
|
+
PARTICIPANT_LEDGER_API_PORT_SUFFIX="${PARTICIPANT_LEDGER_API_PORT_SUFFIX:-901}"
|
|
242
|
+
PARTICIPANT_ADMIN_API_PORT_SUFFIX="${PARTICIPANT_ADMIN_API_PORT_SUFFIX:-902}"
|
|
243
|
+
PARTICIPANT_JSON_API_PORT_SUFFIX="${PARTICIPANT_JSON_API_PORT_SUFFIX:-975}"
|
|
244
|
+
VALIDATOR_ADMIN_API_PORT_SUFFIX="${VALIDATOR_ADMIN_API_PORT_SUFFIX:-903}"
|
|
245
|
+
CANTON_HTTP_HEALTHCHECK_PORT_SUFFIX="${CANTON_HTTP_HEALTHCHECK_PORT_SUFFIX:-900}"
|
|
246
|
+
CANTON_GRPC_HEALTHCHECK_PORT_SUFFIX="${CANTON_GRPC_HEALTHCHECK_PORT_SUFFIX:-961}"
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
participant_port() {
|
|
250
|
+
local prefix="$1"
|
|
251
|
+
local suffix="$2"
|
|
252
|
+
printf '%s%s\n' "$prefix" "$suffix"
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
published_port() {
|
|
256
|
+
local container_port="$1"
|
|
257
|
+
local test_port
|
|
258
|
+
test_port="${TEST_PORT:-$(read_env_value TEST_PORT || true)}"
|
|
259
|
+
if [[ -n "$test_port" ]]; then
|
|
260
|
+
printf '%s%s\n' "$test_port" "$container_port"
|
|
261
|
+
return 0
|
|
262
|
+
fi
|
|
263
|
+
printf '%s\n' "$container_port"
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
extra_pqs_postgres_port() {
|
|
267
|
+
local index="$1"
|
|
268
|
+
printf '554%s\n' "$index"
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
resolve_party_hint_base() {
|
|
272
|
+
local compose_env_file="$1"
|
|
273
|
+
|
|
274
|
+
(
|
|
275
|
+
set -a
|
|
276
|
+
if [[ -f .env ]]; then
|
|
277
|
+
# shellcheck disable=SC1091
|
|
278
|
+
source .env
|
|
279
|
+
fi
|
|
280
|
+
if [[ -f .env.local ]]; then
|
|
281
|
+
# shellcheck disable=SC1091
|
|
282
|
+
source .env.local
|
|
283
|
+
fi
|
|
284
|
+
# shellcheck disable=SC1090
|
|
285
|
+
source "$compose_env_file"
|
|
286
|
+
set +a
|
|
287
|
+
printf '%s\n' "${PARTY_HINT:-${DOCKER_NETWORK:-localnet}-localparty-1}"
|
|
288
|
+
)
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
write_extra_participant_runtime_files() {
|
|
292
|
+
local count="$1"
|
|
293
|
+
local output_dir="$2"
|
|
294
|
+
local party_hint_base="$3"
|
|
295
|
+
local auth_mode="$4"
|
|
296
|
+
mkdir -p "$output_dir"
|
|
297
|
+
|
|
298
|
+
local env_file="$output_dir/extra-participants.env"
|
|
299
|
+
local canton_config_file="$output_dir/additional-config.extra-participants.conf"
|
|
300
|
+
local splice_config_file="$output_dir/additional-config.extra-validators.conf"
|
|
301
|
+
local compose_file="$output_dir/compose-extra-participants.yaml"
|
|
302
|
+
|
|
303
|
+
{
|
|
304
|
+
printf 'START_LOCAL_GENERATED_DIR=%s\n' "$output_dir"
|
|
305
|
+
local index
|
|
306
|
+
for ((index = 1; index <= count; index++)); do
|
|
307
|
+
local prefix=$((index + 4))
|
|
308
|
+
local name="extra-${index}"
|
|
309
|
+
local database="participant-${name}"
|
|
310
|
+
local party_hint="extra_${index}_${party_hint_base}"
|
|
311
|
+
local pqs_database="pqs-${name}"
|
|
312
|
+
local pqs_name="pqs-${name}"
|
|
313
|
+
local pqs_user_name="${name}-pqs-user"
|
|
314
|
+
local pqs_postgres_name="postgres-pqs-${name}"
|
|
315
|
+
local pqs_postgres_published_port
|
|
316
|
+
local validator_database="validator-${name}"
|
|
317
|
+
local validator_party_hint="validator_${index}_${party_hint_base}"
|
|
318
|
+
local validator_onboarding_secret="${name}-validator-onboarding-secret"
|
|
319
|
+
local validator_user_name="ledger-api-user"
|
|
320
|
+
local wallet_admin_user_name="$name"
|
|
321
|
+
local auth_audience="https://canton.network.global"
|
|
322
|
+
local ledger_port admin_port json_port validator_admin_port http_health_port grpc_health_port
|
|
323
|
+
local published_ledger_port published_admin_port published_json_port published_validator_admin_port
|
|
324
|
+
ledger_port="$(participant_port "$prefix" "$PARTICIPANT_LEDGER_API_PORT_SUFFIX")"
|
|
325
|
+
admin_port="$(participant_port "$prefix" "$PARTICIPANT_ADMIN_API_PORT_SUFFIX")"
|
|
326
|
+
json_port="$(participant_port "$prefix" "$PARTICIPANT_JSON_API_PORT_SUFFIX")"
|
|
327
|
+
validator_admin_port="$(participant_port "$prefix" "$VALIDATOR_ADMIN_API_PORT_SUFFIX")"
|
|
328
|
+
http_health_port="$(participant_port "$prefix" "$CANTON_HTTP_HEALTHCHECK_PORT_SUFFIX")"
|
|
329
|
+
grpc_health_port="$(participant_port "$prefix" "$CANTON_GRPC_HEALTHCHECK_PORT_SUFFIX")"
|
|
330
|
+
pqs_postgres_published_port="$(extra_pqs_postgres_port "$index")"
|
|
331
|
+
published_ledger_port="$(published_port "$ledger_port")"
|
|
332
|
+
published_admin_port="$(published_port "$admin_port")"
|
|
333
|
+
published_json_port="$(published_port "$json_port")"
|
|
334
|
+
published_validator_admin_port="$(published_port "$validator_admin_port")"
|
|
335
|
+
|
|
336
|
+
printf 'CREATE_DATABASE_EXTRA_%s=%s\n' "$index" "$database"
|
|
337
|
+
printf 'CREATE_DATABASE_EXTRA_VALIDATOR_%s=%s\n' "$index" "$validator_database"
|
|
338
|
+
printf 'CREATE_DATABASE_EXTRA_PQS_%s=%s\n' "$index" "$pqs_database"
|
|
339
|
+
printf 'EXTRA_PARTICIPANT_%s_NAME=%s\n' "$index" "$name"
|
|
340
|
+
printf 'EXTRA_PARTICIPANT_%s_DB=%s\n' "$index" "$database"
|
|
341
|
+
printf 'EXTRA_PARTICIPANT_%s_PARTY_HINT=%s\n' "$index" "$party_hint"
|
|
342
|
+
printf 'EXTRA_PARTICIPANT_%s_LEDGER_API_PORT=%s\n' "$index" "$ledger_port"
|
|
343
|
+
printf 'EXTRA_PARTICIPANT_%s_ADMIN_API_PORT=%s\n' "$index" "$admin_port"
|
|
344
|
+
printf 'EXTRA_PARTICIPANT_%s_JSON_API_PORT=%s\n' "$index" "$json_port"
|
|
345
|
+
printf 'EXTRA_PARTICIPANT_%s_HTTP_HEALTHCHECK_PORT=%s\n' "$index" "$http_health_port"
|
|
346
|
+
printf 'EXTRA_PARTICIPANT_%s_GRPC_HEALTHCHECK_PORT=%s\n' "$index" "$grpc_health_port"
|
|
347
|
+
printf 'EXTRA_PARTICIPANT_%s_LEDGER_API_PUBLISHED_PORT=%s\n' "$index" "$published_ledger_port"
|
|
348
|
+
printf 'EXTRA_PARTICIPANT_%s_ADMIN_API_PUBLISHED_PORT=%s\n' "$index" "$published_admin_port"
|
|
349
|
+
printf 'EXTRA_PARTICIPANT_%s_JSON_API_PUBLISHED_PORT=%s\n' "$index" "$published_json_port"
|
|
350
|
+
printf 'EXTRA_VALIDATOR_%s_DB=%s\n' "$index" "$validator_database"
|
|
351
|
+
printf 'EXTRA_VALIDATOR_%s_PARTY_HINT=%s\n' "$index" "$validator_party_hint"
|
|
352
|
+
printf 'EXTRA_VALIDATOR_%s_ONBOARDING_SECRET=%s\n' "$index" "$validator_onboarding_secret"
|
|
353
|
+
printf 'EXTRA_VALIDATOR_%s_ADMIN_API_PORT=%s\n' "$index" "$validator_admin_port"
|
|
354
|
+
printf 'EXTRA_VALIDATOR_%s_ADMIN_API_PUBLISHED_PORT=%s\n' "$index" "$published_validator_admin_port"
|
|
355
|
+
printf 'EXTRA_VALIDATOR_%s_USER_NAME=%s\n' "$index" "$validator_user_name"
|
|
356
|
+
printf 'EXTRA_VALIDATOR_%s_WALLET_ADMIN_USER_NAME=%s\n' "$index" "$wallet_admin_user_name"
|
|
357
|
+
printf 'EXTRA_VALIDATOR_%s_AUTH_AUDIENCE=%s\n' "$index" "$auth_audience"
|
|
358
|
+
printf 'EXTRA_VALIDATOR_%s_AUTH_MODE=%s\n' "$index" "$auth_mode"
|
|
359
|
+
printf 'EXTRA_PQS_%s_NAME=%s\n' "$index" "$pqs_name"
|
|
360
|
+
printf 'EXTRA_PQS_%s_USER_NAME=%s\n' "$index" "$pqs_user_name"
|
|
361
|
+
printf 'EXTRA_PQS_%s_POSTGRES_NAME=%s\n' "$index" "$pqs_postgres_name"
|
|
362
|
+
printf 'EXTRA_PQS_%s_POSTGRES_DB=%s\n' "$index" "$pqs_database"
|
|
363
|
+
printf 'EXTRA_PQS_%s_POSTGRES_PUBLISHED_PORT=%s\n' "$index" "$pqs_postgres_published_port"
|
|
364
|
+
printf 'EXTRA_PQS_%s_CONFIG_FILE=%s-pqs.conf\n' "$index" "$name"
|
|
365
|
+
done
|
|
366
|
+
} > "$env_file"
|
|
367
|
+
|
|
368
|
+
{
|
|
369
|
+
local index
|
|
370
|
+
for ((index = 1; index <= count; index++)); do
|
|
371
|
+
cat <<EOF
|
|
372
|
+
canton.participants.extra-${index} = \$\${_participant} {
|
|
373
|
+
storage.config.properties.databaseName = "participant-extra-${index}"
|
|
374
|
+
init {
|
|
375
|
+
generate-topology-transactions-and-keys = true
|
|
376
|
+
identity.type = auto
|
|
377
|
+
}
|
|
378
|
+
monitoring {
|
|
379
|
+
http-health-server.port = \${EXTRA_PARTICIPANT_${index}_HTTP_HEALTHCHECK_PORT}
|
|
380
|
+
grpc-health-server.port = \${EXTRA_PARTICIPANT_${index}_GRPC_HEALTHCHECK_PORT}
|
|
381
|
+
}
|
|
382
|
+
http-ledger-api.port = \${EXTRA_PARTICIPANT_${index}_JSON_API_PORT}
|
|
383
|
+
admin-api.port = \${EXTRA_PARTICIPANT_${index}_ADMIN_API_PORT}
|
|
384
|
+
ledger-api.port = \${EXTRA_PARTICIPANT_${index}_LEDGER_API_PORT}
|
|
385
|
+
ledger-api {
|
|
386
|
+
auth-services = [{
|
|
387
|
+
type = unsafe-jwt-hmac-256
|
|
388
|
+
target-audience = "\${EXTRA_VALIDATOR_${index}_AUTH_AUDIENCE}"
|
|
389
|
+
secret = "unsafe"
|
|
390
|
+
}]
|
|
391
|
+
|
|
392
|
+
user-management-service.additional-admin-user-id = "\${EXTRA_VALIDATOR_${index}_USER_NAME}"
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
EOF
|
|
397
|
+
done
|
|
398
|
+
} > "$canton_config_file"
|
|
399
|
+
|
|
400
|
+
if [[ "$(resolve_es256_enabled)" == "1" ]]; then
|
|
401
|
+
local index
|
|
402
|
+
for ((index = 1; index <= count; index++)); do
|
|
403
|
+
cat >> "$canton_config_file" <<EOF
|
|
404
|
+
canton.participants.extra-${index}.ledger-api.auth-services = [
|
|
405
|
+
{
|
|
406
|
+
type = unsafe-jwt-hmac-256
|
|
407
|
+
target-audience = "https://canton.network.global"
|
|
408
|
+
secret = "unsafe"
|
|
409
|
+
},
|
|
410
|
+
{
|
|
411
|
+
type = jwt-es-256-crt
|
|
412
|
+
certificate = "/app/es256-certificate.pem"
|
|
413
|
+
target-audience = "https://canton.network.global/es256"
|
|
414
|
+
}
|
|
415
|
+
]
|
|
416
|
+
|
|
417
|
+
EOF
|
|
418
|
+
done
|
|
419
|
+
fi
|
|
420
|
+
|
|
421
|
+
{
|
|
422
|
+
local index
|
|
423
|
+
for ((index = 1; index <= count; index++)); do
|
|
424
|
+
local validator_backend_ref='$${_validator_backend}'
|
|
425
|
+
cat <<EOF
|
|
426
|
+
canton.validator-apps.extra-${index}-validator_backend = ${validator_backend_ref} {
|
|
427
|
+
onboarding.secret = "\${EXTRA_VALIDATOR_${index}_ONBOARDING_SECRET}"
|
|
428
|
+
domain-migration-dump-path = "/domain-upgrade-dump/domain_migration_dump-extra-${index}.json"
|
|
429
|
+
storage.config.properties.databaseName = "\${EXTRA_VALIDATOR_${index}_DB}"
|
|
430
|
+
admin-api.port = \${EXTRA_VALIDATOR_${index}_ADMIN_API_PORT}
|
|
431
|
+
canton-identifier-config.participant = extra-${index}
|
|
432
|
+
participant-client {
|
|
433
|
+
admin-api.port = \${EXTRA_PARTICIPANT_${index}_ADMIN_API_PORT}
|
|
434
|
+
ledger-api {
|
|
435
|
+
client-config.port = \${EXTRA_PARTICIPANT_${index}_LEDGER_API_PORT}
|
|
436
|
+
auth-config = {
|
|
437
|
+
type = "self-signed"
|
|
438
|
+
user = "\${EXTRA_VALIDATOR_${index}_USER_NAME}"
|
|
439
|
+
audience = "\${EXTRA_VALIDATOR_${index}_AUTH_AUDIENCE}"
|
|
440
|
+
secret = "unsafe"
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
auth = {
|
|
445
|
+
algorithm = "hs-256-unsafe"
|
|
446
|
+
audience = "\${EXTRA_VALIDATOR_${index}_AUTH_AUDIENCE}"
|
|
447
|
+
secret = "unsafe"
|
|
448
|
+
}
|
|
449
|
+
ledger-api-user = "\${EXTRA_VALIDATOR_${index}_USER_NAME}"
|
|
450
|
+
validator-wallet-users.0 = "\${EXTRA_VALIDATOR_${index}_WALLET_ADMIN_USER_NAME}"
|
|
451
|
+
validator-party-hint = "\${EXTRA_VALIDATOR_${index}_PARTY_HINT}"
|
|
452
|
+
|
|
453
|
+
domains.global.buy-extra-traffic {
|
|
454
|
+
min-topup-interval = \${?MIN_TRAFFIC_TOPUP_INTERVAL}
|
|
455
|
+
target-throughput = \${?TARGET_TRAFFIC_THROUGHPUT}
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
canton.sv-apps.sv.expected-validator-onboardings += { secret = "\${EXTRA_VALIDATOR_${index}_ONBOARDING_SECRET}" }
|
|
460
|
+
|
|
461
|
+
EOF
|
|
462
|
+
done
|
|
463
|
+
} > "$splice_config_file"
|
|
464
|
+
|
|
465
|
+
{
|
|
466
|
+
cat <<'EOF'
|
|
467
|
+
volumes:
|
|
468
|
+
EOF
|
|
469
|
+
local index
|
|
470
|
+
for ((index = 1; index <= count; index++)); do
|
|
471
|
+
cat <<EOF
|
|
472
|
+
postgres-pqs-extra-${index}:
|
|
473
|
+
EOF
|
|
474
|
+
done
|
|
475
|
+
cat <<'EOF'
|
|
476
|
+
|
|
477
|
+
services:
|
|
478
|
+
postgres:
|
|
479
|
+
env_file:
|
|
480
|
+
- ${START_LOCAL_GENERATED_DIR}/extra-participants.env
|
|
481
|
+
canton:
|
|
482
|
+
env_file:
|
|
483
|
+
- ${START_LOCAL_GENERATED_DIR}/extra-participants.env
|
|
484
|
+
environment:
|
|
485
|
+
ADDITIONAL_CONFIG_EXTRA_PARTICIPANTS: |
|
|
486
|
+
EOF
|
|
487
|
+
sed 's/^/ /' "$canton_config_file"
|
|
488
|
+
cat <<'EOF'
|
|
489
|
+
ports:
|
|
490
|
+
EOF
|
|
491
|
+
for ((index = 1; index <= count; index++)); do
|
|
492
|
+
cat <<EOF
|
|
493
|
+
- "\${EXTRA_PARTICIPANT_${index}_LEDGER_API_PUBLISHED_PORT}:\${EXTRA_PARTICIPANT_${index}_LEDGER_API_PORT}"
|
|
494
|
+
- "\${EXTRA_PARTICIPANT_${index}_ADMIN_API_PUBLISHED_PORT}:\${EXTRA_PARTICIPANT_${index}_ADMIN_API_PORT}"
|
|
495
|
+
- "\${EXTRA_PARTICIPANT_${index}_JSON_API_PUBLISHED_PORT}:\${EXTRA_PARTICIPANT_${index}_JSON_API_PORT}"
|
|
496
|
+
EOF
|
|
497
|
+
done
|
|
498
|
+
cat <<'EOF'
|
|
499
|
+
splice:
|
|
500
|
+
env_file:
|
|
501
|
+
- ${START_LOCAL_GENERATED_DIR}/extra-participants.env
|
|
502
|
+
environment:
|
|
503
|
+
ADDITIONAL_CONFIG_EXTRA_VALIDATORS: |
|
|
504
|
+
EOF
|
|
505
|
+
sed -e 's/\${?/\$\${?/g' -e 's/^/ /' "$splice_config_file"
|
|
506
|
+
cat <<'EOF'
|
|
507
|
+
ports:
|
|
508
|
+
EOF
|
|
509
|
+
for ((index = 1; index <= count; index++)); do
|
|
510
|
+
cat <<EOF
|
|
511
|
+
- "\${EXTRA_VALIDATOR_${index}_ADMIN_API_PUBLISHED_PORT}:\${EXTRA_VALIDATOR_${index}_ADMIN_API_PORT}"
|
|
512
|
+
EOF
|
|
513
|
+
done
|
|
514
|
+
for ((index = 1; index <= count; index++)); do
|
|
515
|
+
cat <<EOF
|
|
516
|
+
postgres-pqs-extra-${index}:
|
|
517
|
+
image: "postgres:\${POSTGRES_VERSION}"
|
|
518
|
+
container_name: postgres-pqs-extra-${index}
|
|
519
|
+
volumes:
|
|
520
|
+
- postgres-pqs-extra-${index}:/var/lib/postgresql/data
|
|
521
|
+
- \${LOCALNET_DIR}/docker/postgres/postgres-entrypoint.sh:/postgres-entrypoint.sh
|
|
522
|
+
environment:
|
|
523
|
+
POSTGRES_USER: \${DB_USER}
|
|
524
|
+
POSTGRES_PASSWORD: \${DB_PASSWORD}
|
|
525
|
+
POSTGRES_DB: postgres
|
|
526
|
+
CREATE_DATABASE_EXTRA_PQS_${index}: \${EXTRA_PQS_${index}_POSTGRES_DB}
|
|
527
|
+
ports:
|
|
528
|
+
- "\${EXTRA_PQS_${index}_POSTGRES_PUBLISHED_PORT}:5432"
|
|
529
|
+
entrypoint: /postgres-entrypoint.sh
|
|
530
|
+
healthcheck:
|
|
531
|
+
test: "pg_isready -U \${DB_USER} -d postgres"
|
|
532
|
+
interval: 10s
|
|
533
|
+
timeout: 3s
|
|
534
|
+
retries: 3
|
|
535
|
+
start_period: 30s
|
|
536
|
+
user: "postgres"
|
|
537
|
+
command:
|
|
538
|
+
- postgres
|
|
539
|
+
- -c
|
|
540
|
+
- max_connections=1000
|
|
541
|
+
pqs-extra-${index}:
|
|
542
|
+
image: \${SCRIBE_IMAGE}:\${SCRIBE_VERSION}
|
|
543
|
+
container_name: pqs-extra-${index}
|
|
544
|
+
environment:
|
|
545
|
+
SCRIBE_SOURCE_LEDGER_HOST: canton
|
|
546
|
+
SCRIBE_SOURCE_LEDGER_PORT: \${EXTRA_PARTICIPANT_${index}_LEDGER_API_PORT}
|
|
547
|
+
SCRIBE_SOURCE_LEDGER_AUTH: OAuth
|
|
548
|
+
SCRIBE_TARGET_POSTGRES_HOST: postgres-pqs-extra-${index}
|
|
549
|
+
SCRIBE_TARGET_POSTGRES_PORT: 5432
|
|
550
|
+
SCRIBE_TARGET_POSTGRES_DATABASE: \${EXTRA_PQS_${index}_POSTGRES_DB}
|
|
551
|
+
SCRIBE_TARGET_POSTGRES_USERNAME: \${DB_USER}
|
|
552
|
+
SCRIBE_TARGET_POSTGRES_PASSWORD: \${DB_PASSWORD}
|
|
553
|
+
SCRIBE_CONFIG: /onboarding/extra-${index}-pqs.conf
|
|
554
|
+
volumes:
|
|
555
|
+
- onboarding:/onboarding
|
|
556
|
+
command:
|
|
557
|
+
- pipeline
|
|
558
|
+
- ledger
|
|
559
|
+
- postgres-document
|
|
560
|
+
depends_on:
|
|
561
|
+
canton:
|
|
562
|
+
condition: service_healthy
|
|
563
|
+
splice-onboarding:
|
|
564
|
+
condition: service_healthy
|
|
565
|
+
postgres-pqs-extra-${index}:
|
|
566
|
+
condition: service_healthy
|
|
567
|
+
restart: on-failure:100
|
|
568
|
+
EOF
|
|
569
|
+
done
|
|
570
|
+
} > "$compose_file"
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
append_extra_participant_args() {
|
|
574
|
+
local count="$1"
|
|
575
|
+
local auth_mode="$2"
|
|
576
|
+
local -n compose_args_ref="$3"
|
|
577
|
+
local output_dir
|
|
578
|
+
output_dir="$(generated_dir)"
|
|
579
|
+
|
|
580
|
+
if (( count == 0 )); then
|
|
581
|
+
rm -rf "$output_dir"
|
|
582
|
+
return 0
|
|
583
|
+
fi
|
|
584
|
+
|
|
585
|
+
write_extra_participant_runtime_files "$count" "$output_dir" "$PARTY_HINT_BASE" "$auth_mode"
|
|
586
|
+
compose_args_ref+=(
|
|
587
|
+
-f "$output_dir/compose-extra-participants.yaml"
|
|
588
|
+
--env-file "$output_dir/extra-participants.env"
|
|
589
|
+
)
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
extra_participants_healthy() {
|
|
593
|
+
local count="$1"
|
|
594
|
+
if (( count == 0 )); then
|
|
595
|
+
return 0
|
|
596
|
+
fi
|
|
597
|
+
|
|
598
|
+
local checks=()
|
|
599
|
+
local index
|
|
600
|
+
for ((index = 1; index <= count; index++)); do
|
|
601
|
+
local prefix=$((index + 4))
|
|
602
|
+
local health_port
|
|
603
|
+
health_port="$(participant_port "$prefix" "$CANTON_HTTP_HEALTHCHECK_PORT_SUFFIX")"
|
|
604
|
+
checks+=("curl -sf --max-time 2 http://localhost:${health_port}/health > /dev/null")
|
|
605
|
+
done
|
|
606
|
+
|
|
607
|
+
local joined_checks
|
|
608
|
+
joined_checks="$(printf '%s && ' "${checks[@]}")"
|
|
609
|
+
joined_checks="${joined_checks% && }"
|
|
610
|
+
docker exec canton bash -lc "$joined_checks" >/dev/null 2>&1
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
prerequisite_services() {
|
|
614
|
+
local auth_mode="$1"
|
|
615
|
+
local services=(postgres canton)
|
|
616
|
+
if [[ "$auth_mode" == "oauth2" ]]; then
|
|
617
|
+
services=(keycloak nginx-keycloak "${services[@]}")
|
|
618
|
+
fi
|
|
619
|
+
printf '%s\n' "${services[@]}"
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
dependent_services() {
|
|
623
|
+
printf '%s\n' splice splice-onboarding pqs-app-provider pqs-sv
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
extra_pqs_services() {
|
|
627
|
+
local count="$1"
|
|
628
|
+
local index
|
|
629
|
+
for ((index = 1; index <= count; index++)); do
|
|
630
|
+
printf 'pqs-extra-%s\n' "$index"
|
|
631
|
+
done
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
wait_for_container_health() {
|
|
635
|
+
local container="$1"
|
|
636
|
+
local attempts="${2:-30}"
|
|
637
|
+
local delay_seconds="${3:-2}"
|
|
638
|
+
local status
|
|
639
|
+
|
|
640
|
+
for ((i = 1; i <= attempts; i++)); do
|
|
641
|
+
status="$(docker inspect --format '{{.State.Health.Status}}' "$container" 2>/dev/null | tail -n 1 || true)"
|
|
642
|
+
if [[ "$status" == "healthy" ]]; then
|
|
643
|
+
return 0
|
|
644
|
+
fi
|
|
645
|
+
sleep "$delay_seconds"
|
|
646
|
+
done
|
|
647
|
+
|
|
648
|
+
echo "$container did not become healthy after $((attempts * delay_seconds)) seconds." >&2
|
|
649
|
+
return 1
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
wait_for_canton_health() {
|
|
653
|
+
local extra_participants="${1:-0}"
|
|
654
|
+
local attempts=30
|
|
655
|
+
local delay_seconds=2
|
|
656
|
+
local status
|
|
657
|
+
|
|
658
|
+
for ((i = 1; i <= attempts; i++)); do
|
|
659
|
+
status="$(docker inspect --format '{{.State.Health.Status}}' canton 2>/dev/null | tail -n 1 || true)"
|
|
660
|
+
if [[ "$status" == "healthy" ]] && extra_participants_healthy "$extra_participants"; then
|
|
661
|
+
return 0
|
|
662
|
+
fi
|
|
663
|
+
sleep "$delay_seconds"
|
|
664
|
+
done
|
|
665
|
+
|
|
666
|
+
echo "canton did not become healthy after $((attempts * delay_seconds)) seconds." >&2
|
|
667
|
+
return 1
|
|
668
|
+
}
|
|
669
|
+
|
|
670
|
+
provision_extra_pqs() {
|
|
671
|
+
local count="$1"
|
|
672
|
+
if (( count == 0 )); then
|
|
673
|
+
return 0
|
|
674
|
+
fi
|
|
675
|
+
|
|
676
|
+
local index
|
|
677
|
+
for ((index = 1; index <= count; index++)); do
|
|
678
|
+
local name="extra-${index}"
|
|
679
|
+
local json_port
|
|
680
|
+
json_port="$(published_port "$(participant_port "$((index + 4))" "$PARTICIPANT_JSON_API_PORT_SUFFIX")")"
|
|
681
|
+
|
|
682
|
+
docker exec \
|
|
683
|
+
-e EXTRA_PARTICIPANT_NAME="$name" \
|
|
684
|
+
-e EXTRA_PARTICIPANT_JSON_API_PORT="$json_port" \
|
|
685
|
+
-e EXTRA_PARTICIPANT_PARTY_HINT="extra_${index}_${PARTY_HINT_BASE}" \
|
|
686
|
+
-e EXTRA_PQS_USER_NAME="${name}-pqs-user" \
|
|
687
|
+
-e EXTRA_PQS_CONFIG_FILE="${name}-pqs.conf" \
|
|
688
|
+
splice-onboarding \
|
|
689
|
+
bash -lc '
|
|
690
|
+
set -euo pipefail
|
|
691
|
+
source /app/utils.sh
|
|
692
|
+
participant="canton:${EXTRA_PARTICIPANT_JSON_API_PORT}"
|
|
693
|
+
admin_token="$(generate_jwt "participant_admin" "$AUTH_APP_PROVIDER_AUDIENCE")"
|
|
694
|
+
party="$(allocate_party "$admin_token" "$EXTRA_PARTICIPANT_PARTY_HINT" "$participant")"
|
|
695
|
+
create_user "$admin_token" "$EXTRA_PQS_USER_NAME" "$EXTRA_PQS_USER_NAME" "$party" "$participant"
|
|
696
|
+
grant_rights "$admin_token" "$EXTRA_PQS_USER_NAME" "$party" "ReadAs" "$participant"
|
|
697
|
+
pqs_user_token="$(generate_jwt "$EXTRA_PQS_USER_NAME" "$AUTH_APP_PROVIDER_AUDIENCE")"
|
|
698
|
+
share_file "$EXTRA_PQS_CONFIG_FILE" <<EOF
|
|
699
|
+
pipeline.datasource=TransactionTreeStream
|
|
700
|
+
pipeline.ledger.start=Oldest
|
|
701
|
+
pipeline.oauth.accessToken="${pqs_user_token}"
|
|
702
|
+
EOF
|
|
703
|
+
'
|
|
704
|
+
|
|
705
|
+
grant_user_read_as_any_party_right \
|
|
706
|
+
"${name}-pqs-user" \
|
|
707
|
+
"https://canton.network.global" \
|
|
708
|
+
"$json_port"
|
|
709
|
+
done
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
grant_validator_read_as_any_party_right() {
|
|
713
|
+
local validator_user_name="$1"
|
|
714
|
+
local auth_audience="$2"
|
|
715
|
+
local participant_json_port="$3"
|
|
716
|
+
|
|
717
|
+
docker exec \
|
|
718
|
+
-e VALIDATOR_USER_NAME="$validator_user_name" \
|
|
719
|
+
-e VALIDATOR_AUTH_AUDIENCE="$auth_audience" \
|
|
720
|
+
-e PARTICIPANT_JSON_API_PORT="$participant_json_port" \
|
|
721
|
+
splice-onboarding \
|
|
722
|
+
bash -lc '
|
|
723
|
+
set -euo pipefail
|
|
724
|
+
source /app/utils.sh
|
|
725
|
+
participant="canton:${PARTICIPANT_JSON_API_PORT}"
|
|
726
|
+
validator_token="$(generate_jwt "$VALIDATOR_USER_NAME" "$VALIDATOR_AUTH_AUDIENCE")"
|
|
727
|
+
payload="$(cat <<EOF
|
|
728
|
+
{
|
|
729
|
+
"userId": "${VALIDATOR_USER_NAME}",
|
|
730
|
+
"identityProviderId": "",
|
|
731
|
+
"rights": [
|
|
732
|
+
{"kind":{"CanReadAsAnyParty":{"value":{}}}}
|
|
733
|
+
]
|
|
734
|
+
}
|
|
735
|
+
EOF
|
|
736
|
+
)"
|
|
737
|
+
curl_check "http://$participant/v2/users/$VALIDATOR_USER_NAME/rights" "$validator_token" "application/json" \
|
|
738
|
+
--data-raw "$payload" >/dev/null
|
|
739
|
+
'
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
grant_user_read_as_any_party_right() {
|
|
743
|
+
local user_name="$1"
|
|
744
|
+
local auth_audience="$2"
|
|
745
|
+
local participant_json_port="$3"
|
|
746
|
+
|
|
747
|
+
docker exec \
|
|
748
|
+
-e TARGET_USER_NAME="$user_name" \
|
|
749
|
+
-e TARGET_AUTH_AUDIENCE="$auth_audience" \
|
|
750
|
+
-e PARTICIPANT_JSON_API_PORT="$participant_json_port" \
|
|
751
|
+
splice-onboarding \
|
|
752
|
+
bash -lc '
|
|
753
|
+
set -euo pipefail
|
|
754
|
+
source /app/utils.sh
|
|
755
|
+
participant="canton:${PARTICIPANT_JSON_API_PORT}"
|
|
756
|
+
admin_token="$(generate_jwt "participant_admin" "$TARGET_AUTH_AUDIENCE")"
|
|
757
|
+
payload="$(cat <<EOF
|
|
758
|
+
{
|
|
759
|
+
"userId": "${TARGET_USER_NAME}",
|
|
760
|
+
"identityProviderId": "",
|
|
761
|
+
"rights": [
|
|
762
|
+
{"kind":{"CanReadAsAnyParty":{"value":{}}}}
|
|
763
|
+
]
|
|
764
|
+
}
|
|
765
|
+
EOF
|
|
766
|
+
)"
|
|
767
|
+
curl_check "http://$participant/v2/users/$TARGET_USER_NAME/rights" "$admin_token" "application/json" \
|
|
768
|
+
--data-raw "$payload" >/dev/null
|
|
769
|
+
'
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
grant_localnet_validator_read_rights() {
|
|
773
|
+
local extra_participants="${1:-0}"
|
|
774
|
+
local validator_user_name="ledger-api-user"
|
|
775
|
+
local auth_audience="https://canton.network.global"
|
|
776
|
+
|
|
777
|
+
grant_validator_read_as_any_party_right \
|
|
778
|
+
"$validator_user_name" \
|
|
779
|
+
"$auth_audience" \
|
|
780
|
+
"$(published_port "$(participant_port 3 "$PARTICIPANT_JSON_API_PORT_SUFFIX")")"
|
|
781
|
+
|
|
782
|
+
grant_validator_read_as_any_party_right \
|
|
783
|
+
"$validator_user_name" \
|
|
784
|
+
"$auth_audience" \
|
|
785
|
+
"$(published_port "$(participant_port 4 "$PARTICIPANT_JSON_API_PORT_SUFFIX")")"
|
|
786
|
+
|
|
787
|
+
local index
|
|
788
|
+
for ((index = 1; index <= extra_participants; index++)); do
|
|
789
|
+
grant_validator_read_as_any_party_right \
|
|
790
|
+
"$validator_user_name" \
|
|
791
|
+
"$auth_audience" \
|
|
792
|
+
"$(published_port "$(participant_port "$((index + 4))" "$PARTICIPANT_JSON_API_PORT_SUFFIX")")"
|
|
793
|
+
done
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
start_ledger_stack() {
|
|
797
|
+
local auth_mode="${1:-shared-secret}"
|
|
798
|
+
local modules_dir="$QUICKSTART_DIR/docker/modules"
|
|
799
|
+
local localnet_dir="$modules_dir/localnet"
|
|
800
|
+
local splice_version
|
|
801
|
+
splice_version="$(read_env_value SPLICE_VERSION || true)"
|
|
802
|
+
export MODULES_DIR="$modules_dir"
|
|
803
|
+
export LOCALNET_DIR="$localnet_dir"
|
|
804
|
+
export LOCALNET_ENV_DIR="$localnet_dir/env"
|
|
805
|
+
export IMAGE_TAG="${IMAGE_TAG:-$splice_version}"
|
|
806
|
+
export APP_PROVIDER_PROFILE=on
|
|
807
|
+
export APP_USER_PROFILE=off
|
|
808
|
+
export SV_PROFILE=on
|
|
809
|
+
export PQS_SV_PROFILE=on
|
|
810
|
+
load_localnet_common_env "$localnet_dir/env/common.env"
|
|
811
|
+
prepare_es256_runtime_files
|
|
812
|
+
local extra_participants
|
|
813
|
+
extra_participants="$(resolve_extra_participants)"
|
|
814
|
+
if (( extra_participants > 0 )) && [[ "$auth_mode" != "shared-secret" ]]; then
|
|
815
|
+
echo "EXTRA_PARTICIPANTS with extra PQS currently supports AUTH_MODE=shared-secret only." >&2
|
|
816
|
+
return 1
|
|
817
|
+
fi
|
|
818
|
+
PARTY_HINT_BASE="$(resolve_party_hint_base "$localnet_dir/compose.env")"
|
|
819
|
+
export PARTY_HINT_BASE
|
|
820
|
+
local compose_args=(
|
|
821
|
+
-f compose.yaml
|
|
822
|
+
-f "$localnet_dir/compose.yaml"
|
|
823
|
+
-f "$modules_dir/splice-onboarding/compose.yaml"
|
|
824
|
+
-f "$modules_dir/pqs/compose.yaml"
|
|
825
|
+
--env-file .env
|
|
826
|
+
--env-file .env.local
|
|
827
|
+
--env-file "$localnet_dir/compose.env"
|
|
828
|
+
--env-file "$localnet_dir/env/common.env"
|
|
829
|
+
--env-file "$modules_dir/pqs/compose.env"
|
|
830
|
+
--profile app-provider
|
|
831
|
+
--profile pqs-app-provider
|
|
832
|
+
--profile pqs-sv
|
|
833
|
+
)
|
|
834
|
+
|
|
835
|
+
if [[ "$auth_mode" == "oauth2" ]]; then
|
|
836
|
+
compose_args+=(
|
|
837
|
+
-f "$modules_dir/keycloak/compose.yaml"
|
|
838
|
+
--env-file "$modules_dir/keycloak/compose.env"
|
|
839
|
+
--profile keycloak
|
|
840
|
+
)
|
|
841
|
+
fi
|
|
842
|
+
|
|
843
|
+
append_extra_participant_args "$extra_participants" "$auth_mode" compose_args
|
|
844
|
+
append_es256_args compose_args
|
|
845
|
+
docker_compose "${compose_args[@]}" down -v --remove-orphans
|
|
846
|
+
mapfile -t startup_services < <(prerequisite_services "$auth_mode")
|
|
847
|
+
mapfile -t followup_services < <(dependent_services)
|
|
848
|
+
|
|
849
|
+
docker_compose "${compose_args[@]}" up -d --no-recreate "${startup_services[@]}"
|
|
850
|
+
wait_for_canton_health "$extra_participants"
|
|
851
|
+
|
|
852
|
+
docker_compose "${compose_args[@]}" up -d --no-recreate "${followup_services[@]}"
|
|
853
|
+
|
|
854
|
+
if (( extra_participants > 0 )); then
|
|
855
|
+
wait_for_container_health splice 60 2
|
|
856
|
+
wait_for_container_health splice-onboarding 60 2
|
|
857
|
+
if [[ "$auth_mode" == "shared-secret" ]]; then
|
|
858
|
+
grant_localnet_validator_read_rights "$extra_participants"
|
|
859
|
+
fi
|
|
860
|
+
provision_extra_pqs "$extra_participants"
|
|
861
|
+
local extra_pqs_services_list=()
|
|
862
|
+
mapfile -t extra_pqs_services_list < <(extra_pqs_services "$extra_participants")
|
|
863
|
+
docker_compose "${compose_args[@]}" up -d --no-recreate "${extra_pqs_services_list[@]}"
|
|
864
|
+
fi
|
|
865
|
+
}
|
|
866
|
+
|
|
867
|
+
load_repo_root_env
|
|
868
|
+
QUICKSTART_DIR="$(resolve_quickstart_dir)"
|
|
869
|
+
cd "$QUICKSTART_DIR"
|
|
870
|
+
|
|
871
|
+
if [[ ! -f .env.local ]]; then
|
|
872
|
+
echo ".env.local not found. Bootstrapping Quickstart with 'make setup'."
|
|
873
|
+
make setup
|
|
874
|
+
fi
|
|
875
|
+
|
|
876
|
+
if [[ "$(resolve_es256_enabled)" != "1" ]] && make_target_exists start-local-ledger; then
|
|
877
|
+
make start-local-ledger
|
|
878
|
+
else
|
|
879
|
+
auth_mode="$(read_env_value AUTH_MODE || true)"
|
|
880
|
+
auth_mode="${auth_mode:-shared-secret}"
|
|
881
|
+
echo "start-local-ledger target not found. Starting ledger-only compose stack directly."
|
|
882
|
+
start_ledger_stack "$auth_mode"
|
|
883
|
+
if [[ "$(resolve_es256_enabled)" == "1" ]]; then
|
|
884
|
+
echo "ES256 bearer token written to $LOCALNET_ES256_TOKEN_PATH"
|
|
885
|
+
fi
|
|
886
|
+
fi
|