@fairmint/canton-node-sdk
Version:
Canton Node SDK
481 lines (478 loc) • 21 kB
YAML
# Copyright (c) 2024 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved.
# SPDX-License-Identifier: Apache-2.0
{{- $appIdentifier := "sv-app" }}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ $appIdentifier }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "splice-util-lib.default-labels" (set . "app" $appIdentifier) | nindent 4 }}
migration: {{ .Values.migration.id | quote }}
spec:
replicas: 1
selector:
matchLabels:
app: {{ $appIdentifier }}
strategy:
type: "Recreate"
template:
metadata:
annotations:
{{- toYaml .Values.pod.annotations | nindent 8 }}
labels:
{{- include "splice-util-lib.default-labels" (set . "app" $appIdentifier) | nindent 8 }}
migration: {{ .Values.migration.id | quote }}
spec:
{{- include "splice-util-lib.service-account" .Values | nindent 6 }}
securityContext:
runAsUser: 1001
runAsGroup: 1001
fsGroup: 1001
containers:
- name: sv-app
image: "{{ .Values.imageRepo }}/sv-app:{{ .Chart.AppVersion }}{{ ((.Values.imageDigests).sv_app) }}"
{{- with .Values.imagePullPolicy }}
imagePullPolicy: {{ . }}
{{- end }}
env:
- name: JAVA_TOOL_OPTIONS
value: {{ .Values.defaultJvmOptions }} {{ .Values.additionalJvmOptions }}
{{- include "splice-util-lib.auth0-env-vars" (dict "appName" "sv" "keyName" "sv" "fixedTokens" .Values.cluster.fixedTokens) | indent 12}}
{{- include "splice-util-lib.auth0-user-env-var" (dict "appName" "validator" "keyName" "validator") | indent 12}}
- name: SPLICE_APP_SV_PARTICIPANT_ADDRESS
value: {{ .Values.participantAddress | quote }}
{{- if .Values.migration.migrating }}
- name: ADDITIONAL_CONFIG_SV_ONBOARDING
value: |
_onboarding {
type = "domain-migration"
dump-file-path = "/domain-upgrade-dump/domain_migration_dump.json"
}
{{- else if .Values.joinWithKeyOnboarding }}
- name: ADDITIONAL_CONFIG_SV_ONBOARDING
value: |
_onboarding {
type = "join-with-key"
sv-client.admin-api.url = "{{ .Values.joinWithKeyOnboarding.sponsorApiUrl }}"
}
- name: SPLICE_APP_SV_PUBLIC_KEY
valueFrom:
secretKeyRef:
key: public
name: "splice-app-sv-key"
optional: false
- name: SPLICE_APP_SV_PRIVATE_KEY
valueFrom:
secretKeyRef:
key: private
name: "splice-app-sv-key"
optional: false
{{- else }}
{{- if eq .Values.onboardingType "found-dso" }}
- name: SPLICE_APP_SV_IS_DEV_NET
value: {{ .Values.isDevNet | quote }}
{{- if .Values.initialAmuletPrice }}
- name: SPLICE_APP_SV_INITIAL_AMULET_PRICE
value: {{ .Values.initialAmuletPrice | quote }}
{{- end }}
{{- end }}
{{ if .Values.onboardingType }}
- name: SPLICE_APP_SV_ONBOARDING_TYPE
value: {{ .Values.onboardingType }}
{{- end }}
{{- end }}
{{- if .Values.onboardingName }}
- name: SPLICE_APP_SV_ONBOARDING_NAME
value: {{ .Values.onboardingName }}
{{- end }}
{{- if .Values.onboardingFoundingSvRewardWeightBps }}
- name: SPLICE_APP_SV_SV1_REWARD_WEIGHT
value: {{ .Values.onboardingFoundingSvRewardWeightBps | quote }}
{{- end }}
{{- if .Values.onboardingRoundZeroDuration }}
- name: SPLICE_APP_SV_ROUND_ZERO_DURATION
value: {{ .Values.onboardingRoundZeroDuration | quote }}
{{- end }}
{{- if .Values.initialRound }}
- name: SPLICE_APP_SV_INITIAL_ROUND
value: {{ .Values.initialRound | quote }}
{{- end }}
{{- if .Values.initialTickDuration }}
- name: SPLICE_APP_SV_INITIAL_TICK_DURATION
value: {{ .Values.initialTickDuration | quote }}
{{- end }}
{{- if .Values.initialHoldingFee }}
- name: SPLICE_APP_SV_INITIAL_HOLDING_FEE
value: {{ .Values.initialHoldingFee | quote }}
{{- end }}
{{- if .Values.initialAmuletPrice }}
- name: SPLICE_APP_SV_INITIAL_AMULET_PRICE_VOTE
value: {{ .Values.initialAmuletPrice | quote }}
{{- end }}
- name: SPLICE_APP_SV_AUTH_AUDIENCE
value: {{ .Values.auth.audience | quote }}
- name: SPLICE_APP_SV_AUTH_JWKS_URL
value: {{ .Values.auth.jwksUrl | quote }}
{{ if (.Values.auth.jwks).connectionTimeout }}
- name: SPLICE_APP_VALIDATOR_AUTH_JWKS_CONNECTION_TIMEOUT
value: {{ .Values.auth.jwks.connectionTimeout | quote }}
{{ end }}
{{ if (.Values.auth.jwks).readTimeout }}
- name: SPLICE_APP_VALIDATOR_AUTH_JWKS_READ_TIMEOUT
value: {{ .Values.auth.jwks.readTimeout | quote }}
{{ end }}
{{ if .Values.disableIngestUpdateHistoryFromParticipantBegin }}
- name: ADDITIONAL_CONFIG_UPDATE_HISTORY_INGESTION
value: |
canton.sv-apps.sv.ingest-update-history-from-participant-begin = false
{{ end }}
{{- with .Values.persistence }}
- name: ADDITIONAL_CONFIG_PERSISTENCE
value: |
canton.sv-apps.sv.storage {
config {
properties = {
databaseName = "{{ .databaseName }}"
currentSchema = "{{ .schema }}"
serverName = "{{ .host }}"
portNumber = {{ .port }}
user = "{{ .user }}"
password = ${SPLICE_APP_POSTGRES_PASSWORD}
}
}
}
- name: SPLICE_APP_POSTGRES_PASSWORD
valueFrom:
secretKeyRef:
name: {{ $.Values.persistence.secretName }}
key: postgresPassword
{{- end }}
- name: ADDITIONAL_CONFIG_MIGRATION_ID
value: |
canton.sv-apps.sv {
domain-migration-id = {{ .Values.migration.id }}
}
{{ if hasKey .Values.migration "legacyId" }}
- name: ADDITIONAL_CONFIG_LEGACY_MIGRATION_ID
value: |
canton.sv-apps.sv {
legacy-migration-id = {{ .Values.migration.legacyId }}
}
{{ end }}
- name: ADDITIONAL_CONFIG_GLOBAL_DOMAIN_UPGRADE_DUMP_PATH
value: |
canton.sv-apps.sv.domain-migration-dump-path = "/domain-upgrade-dump/domain_migration_dump.json"
{{- with .Values.domain }}
- name: ADDITIONAL_CONFIG_SV_DOMAIN
#TODO(#930) - switch to port 443 https://github.com/DACH-NY/canton/issues/23835
value: |
canton.sv-apps.sv.local-synchronizer-node {
sequencer {
{{- if .enableBftSequencer }}
is-bft-sequencer = true
{{- end }}
admin-api {
address = {{ .sequencerAddress | quote }}
port = 5009
}
internal-api {
address = {{ .sequencerAddress | quote }}
port = 5008
}
external-public-api-url = {{ .sequencerPublicUrl | quote }}
{{- if .sequencerPruningConfig.enabled }}
pruning {
pruning-interval = {{ .sequencerPruningConfig.pruningInterval | quote }}
retention-period = {{ .sequencerPruningConfig.retentionPeriod | quote }}
}
{{- end }}
}
mediator {
admin-api {
address = {{ .mediatorAddress | quote }}
port = 5007
}
}
}
{{- end }}
{{- if .Values.decentralizedSynchronizerUrl }}
- name: SPLICE_APP_SV_GLOBAL_DOMAIN_URL
value: {{ .Values.decentralizedSynchronizerUrl | quote }}
{{- end }}
{{- if (.Values.cometBFT).enabled }}
- name: SPLICE_APP_SV_COMETBFT_ENABLED
value: {{ (.Values.cometBFT).enabled | quote }}
{{- end }}
{{- if (.Values.cometBFT).connectionUri }}
- name: SPLICE_APP_SV_COMETBFT_CONNECTION_URI
value: {{ (.Values.cometBFT).connectionUri }}
{{- end }}
{{- if (.Values.cometBFT).externalGovernanceKey }}
- name: ADDITIONAL_CONFIG_SV_COMETBFT_GOVERNANCE_KEY
value: |
_comet_bft_config {
governance-key {
public-key = ${?SPLICE_APP_SV_COMETBFT_GOVERNANCE_PUBLIC_KEY}
private-key = ${?SPLICE_APP_SV_COMETBFT_GOVERNANCE_PRIVATE_KEY}
}
}
- name: SPLICE_APP_SV_COMETBFT_GOVERNANCE_PUBLIC_KEY
valueFrom:
secretKeyRef:
key: public
name: "splice-app-sv-cometbft-governance-key"
optional: false
- name: SPLICE_APP_SV_COMETBFT_GOVERNANCE_PRIVATE_KEY
valueFrom:
secretKeyRef:
key: private
name: "splice-app-sv-cometbft-governance-key"
optional: false
{{- end }}
- name: SPLICE_APP_UI_NETWORK_NAME
value: {{ .Values.spliceInstanceNames.networkName | quote }}
- name: SPLICE_APP_UI_NETWORK_FAVICON_URL
value: {{ .Values.spliceInstanceNames.networkFaviconUrl | quote }}
- name: SPLICE_APP_UI_AMULET_NAME
value: {{ .Values.spliceInstanceNames.amuletName | quote }}
- name: SPLICE_APP_UI_AMULET_NAME_ACRONYM
value: {{ .Values.spliceInstanceNames.amuletNameAcronym | quote }}
- name: SPLICE_APP_UI_NAME_SERVICE_NAME
value: {{ .Values.spliceInstanceNames.nameServiceName | quote }}
- name: SPLICE_APP_UI_NAME_SERVICE_NAME_ACRONYM
value: {{ .Values.spliceInstanceNames.nameServiceNameAcronym | quote }}
{{- range $ii, $onboarding := .Values.expectedValidatorOnboardings }}
- name: ADDITIONAL_CONFIG_VALIDATOR_ONBOARDING_{{ $ii }}
value: |
canton.sv-apps.sv.expected-validator-onboardings.{{ $ii }} = {
secret = ${SPLICE_APP_VALIDATOR_ONBOARDING_SECRET_{{ $ii }}}
expires-in = {{ $onboarding.expiresIn }}
}
- name: SPLICE_APP_VALIDATOR_ONBOARDING_SECRET_{{ $ii }}
valueFrom: {{ $onboarding.secretFrom | toYaml | nindent 16 }}
{{- end }}
{{- range $ii, $sv := .Values.approvedSvIdentities }}
- name: ADDITIONAL_CONFIG_APPROVED_SV_IDENTITY_{{ $ii }}
value: |
canton.sv-apps.sv.approved-sv-identities.{{ $ii }} = {
name = {{ $sv.name | quote }}
public-key = {{ $sv.publicKey | quote }}
reward-weight-bps = {{ $sv.rewardWeightBps | quote }}
}
{{- end }}
{{- with .Values.identitiesExport }}
- name: ADDITIONAL_CONFIG_SPLICE_APP_SV_IDENTITIES_EXPORT
value: |
canton.sv-apps.sv.identities-dump = {
type = gcp
bucket {
project-id = {{ .bucket.projectId }}
bucket-name = {{ .bucket.bucketName }}
credentials {
type = service-account
json-credentials = ${SPLICE_APP_SV_IDS_BACKUP_BUCKET_SERVICE_ACCOUNT_CREDENTIALS}
}
}
prefix = {{ .prefix | quote }}
}
- name: SPLICE_APP_SV_IDS_BACKUP_BUCKET_SERVICE_ACCOUNT_CREDENTIALS
valueFrom:
secretKeyRef:
key: "json-credentials"
name: {{ .bucket.secretName }}
{{- end }}
{{- with .Values.participantIdentitiesDumpImport }}
- name: ADDITIONAL_CONFIG_SPLICE_APP_SV_PARTICIPANT_IDENTITIES_DUMP_IMPORT
value: |
canton.sv-apps.sv.participant-bootstrapping-dump {
type = file
file = /participant-bootstrapping-dump/content
}
{{- end }}
- name: ADDITIONAL_CONFIG_SCAN_PUBLIC_URL
value: |
canton.sv-apps.sv.scan.public-url = {{ .Values.scan.publicUrl | quote }}
canton.sv-apps.sv.scan.internal-url = {{ .Values.scan.internalUrl | quote }}
{{- if .Values.disableOnboardingParticipantPromotionDelay }}
- name: ADDITIONAL_CONFIG_DISABLE_ONBOARDING_PARTICIPANT_PROMOTION_DELAY
value: |
canton.sv-apps.sv.enable-onboarding-participant-promotion-delay = false
{{- end }}
{{- range $ii, $sv := .Values.extraBeneficiaries }}
- name: ADDITIONAL_CONFIG_BENEFICIARIES_{{ $ii }}
value: |
canton.sv-apps.sv.extra-beneficiaries.{{ $ii }} = {
beneficiary = {{ $sv.beneficiary | quote }}
weight = {{ $sv.weight }}
}
{{- end }}
{{- with .Values.onboardingPollingInterval }}
- name: ADDITIONAL_CONFIG_ONBOARDING_POLLING_INTERVAL
value: |
canton.sv-apps.sv.onboarding-polling-interval = {{ . }}
{{- end }}
{{- with .Values.initialSynchronizerFeesConfig }}
- name: ADDITIONAL_CONFIG_DOMAIN_FEES
value: |
canton.sv-apps.sv.onboarding.initial-synchronizer-fees-config {
extra-traffic-price = {{ printf "%f" .extraTrafficPrice }}
min-topup-amount = {{ printf "%.0f" .minTopupAmount }}
base-rate-burst-amount = {{ printf "%.0f" .baseRateBurstAmount }}
base-rate-burst-window = {{ printf "%.0fm" .baseRateBurstWindowMins | quote }}
read-vs-write-scaling-factor = {{ printf "%.0f" .readVsWriteScalingFactor }}
}
{{- end }}
{{- if .Values.initialPackageConfigJson }}
- name: ADDITIONAL_CONFIG_INITIAL_PACKAGE_CONFIG
value: |
canton.sv-apps.sv.onboarding.initial-package-config = {{ .Values.initialPackageConfigJson | quote }}
{{- end }}
- name: FAIL_ON_APP_VERSION_MISMATCH
value: {{ .Values.failOnAppVersionMismatch | quote }}
{{- include "splice-util-lib.additional-env-vars" .Values.additionalEnvVars | indent 12}}
{{- include "splice-util-lib.log-level" .Values | indent 12}}
- name: SPLICE_APP_CONTACT_POINT
value: {{ .Values.contactPoint | default "" | quote }}
- name: SPLICE_APP_SV_PARTICIPANT_IDENTIFIER
value: {{ .Values.nodeIdentifier | quote }}
- name: SPLICE_APP_SV_SEQUENCER_IDENTIFIER
value: {{ .Values.nodeIdentifier | quote }}
- name: SPLICE_APP_SV_MEDIATOR_IDENTIFIER
value: {{ .Values.nodeIdentifier | quote }}
{{- if .Values.delegatelessAutomationExpectedTaskDuration }}
- name: SPLICE_APP_EXPECTED_TASK_DURATION
value: {{ .Values.delegatelessAutomationExpectedTaskDuration | quote }}
{{- end }}
{{- if .Values.delegatelessAutomationExpiredRewardCouponBatchSize }}
- name: SPLICE_APP_EXPIRED_REWARD_COUPON_BATCH_SIZE
value: {{ .Values.delegatelessAutomationExpiredRewardCouponBatchSize | quote }}
{{- end }}
{{- if .Values.domain.skipInitialization }}
- name: ADDITIONAL_CONFIG_SYNCHRONIZER_INITIALIZATION
value: canton.sv-apps.sv.skip-synchronizer-initialization = true
{{- end }}
{{- with .Values.maxVettingDelay }}
- name: ADDITIONAL_CONFIG_MAX_VETTING_DELAY
value: canton.sv-apps.sv.max-vetting-delay = "{{ . }}"
{{- end }}
ports:
- name: sv-api
containerPort: 5014
protocol: TCP
livenessProbe:
httpGet:
path: /api/sv/livez
port: 5014
initialDelaySeconds: {{ .Values.livenessProbeInitialDelaySeconds | default 60 }}
periodSeconds: 60
failureThreshold: 5
timeoutSeconds: 10
readinessProbe:
httpGet:
path: /api/sv/readyz
port: 5014
initialDelaySeconds: 5
periodSeconds: 5
failureThreshold: 5
timeoutSeconds: 10
{{- if or .Values.participantIdentitiesDumpImport .Values.migration.attachPvc }}
volumeMounts:
{{- with .Values.participantIdentitiesDumpImport }}
- name: participant-bootstrapping-dump-volume
mountPath: /participant-bootstrapping-dump
readOnly: true
{{- end }}
{{- if .Values.migration.attachPvc }}
- name: domain-upgrade-dump-volume
mountPath: /domain-upgrade-dump
{{- end }}
{{- end }}
{{- with .Values.resources }}
resources: {{- toYaml . | nindent 12 }}
{{- end }}
initContainers:
- name: {{ .Release.Name }}-init
image: postgres:14
env:
- name: PGPASSWORD
valueFrom:
secretKeyRef:
key: postgresPassword
name: {{ .Values.persistence.secretName }}
command:
- 'bash'
- '-c'
- |
until errmsg=$(psql -h {{ .Values.persistence.host }} -p {{ .Values.persistence.port }} --username=cnadmin --dbname=cantonnet -c 'create database {{ .Values.persistence.databaseName }}' 2>&1); do
if [[ $errmsg == *"already exists"* ]]; then
echo "Database {{ .Values.persistence.databaseName }} already exists. Done."
break
fi
echo "trying to create postgres database {{ .Values.persistence.databaseName }}, last error: $errmsg";
sleep 2;
done
volumes:
{{- with .Values.participantIdentitiesDumpImport }}
- name: participant-bootstrapping-dump-volume
secret:
secretName: {{ .secretName }}
{{- end }}
{{- if .Values.migration.attachPvc }}
- name: domain-upgrade-dump-volume
persistentVolumeClaim:
claimName: {{ .Values.pvc.volumeName }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
apiVersion: v1
kind: Service
metadata:
name: {{ $appIdentifier }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "splice-util-lib.default-labels" (set . "app" $appIdentifier) | nindent 4 }}
migration: {{ .Values.migration.id | quote }}
spec:
selector:
app: {{ $appIdentifier }}
ports:
- name: sv-api
port: 5014
protocol: TCP
- name: metrics
port: 10013
protocol: TCP
{{- if .Values.migration.attachPvc }}
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: {{ .Values.pvc.volumeName }}
namespace: {{ $.Release.Namespace }}
annotations:
helm.sh/resource-policy: keep
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20G
storageClassName: {{ .Values.pvc.volumeStorageClass }}
{{- end }}
{{- if .Values.enablePostgresMetrics }}
{{- include "splice-util-lib.postgres-metrics" (dict "persistence" .Values.persistence "namespace" .Release.Namespace "nodeSelector" .Values.nodeSelector "affinity" .Values.affinity "tolerations" .Values.tolerations ) }}
{{- end}}