From 5988691a2f0aef3e340ccd787762d307d992e7b2 Mon Sep 17 00:00:00 2001 From: Steve Degosserie <723552+stiiifff@users.noreply.github.com> Date: Tue, 21 Oct 2025 23:18:50 +0300 Subject: [PATCH 01/12] =?UTF-8?q?feat:=20=E2=9C=A8=20Add=20deployment=20ch?= =?UTF-8?q?arts=20for=20StorageHub=20MSP,=20BSP=20&=20Indexer=20nodes=20(L?= =?UTF-8?q?ocal=20&=20Stagenet=20envs)=20(#160)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Summary This PR adds comprehensive Kubernetes deployment infrastructure for StorageHub components, enabling deployment of the full StorageHub network stack (MSP, BSP, Indexer, and Fisherman nodes) alongside DataHaven nodes in both local and stagenet environments. ### What's Added **1. New Helm Chart: StorageHub MSP Backend API** (`deploy/charts/backend/`) - REST API service for StorageHub operations - Connects to PostgreSQL database for indexed blockchain data - Connects to RPC nodes for real-time blockchain queries - Configurable via TOML configuration file - Supports environment-specific overrides - Includes comprehensive documentation **2. StorageHub Node Deployment Charts** (`deploy/charts/node/storagehub/`) - **MSP Node** (`sh-mspnode`): Main Service Provider nodes with charging capabilities - **BSP Node** (`sh-bspnode`): Backup Service Provider nodes for redundancy - **Indexer Node** (`sh-idxnode`): Full indexing node with PostgreSQL integration - **Fisherman Node** (`sh-fisherman`): Network monitoring and verification node **3. Environment Configurations** - **Local environment** (`deploy/environments/local/`): Development setup with hostpath storage - **Stagenet environment** (`deploy/environments/stagenet/`): Production-like setup with AWS EBS - PostgreSQL database configurations for Indexer and Fisherman nodes - Proper service discovery and network configuration **4. Enhanced CLI Tooling** (`test/cli/`) - New `deploy storagehub` command for deploying StorageHub components - Updated `launch storagehub` command for local testing - Interactive deployment with environment selection - Automatic database provisioning via Bitnami PostgreSQL charts **5. Node Configuration Improvements** - Fork-aware transaction pool for DH boot & validator nodes - Unsafe RPC methods exposed on MSP nodes (for provider operations) - JWT secret support for MSP Backend authentication - ECDSA key scheme for StorageHub BCSV keys (DataHaven compatibility) ### Architecture ``` StorageHub Stack: ├── MSP Nodes (2 replicas) → Storage providers with charging ├── BSP Nodes (2 replicas) → Backup storage providers ├── Indexer Node → Database indexing + PostgreSQL ├── Fisherman Node → Monitoring + PostgreSQL (shared with Indexer) └── MSP Backend API → REST API for StorageHub operations ``` ### Testing **Local Testing**: ```bash cd test bun cli launch storagehub # Interactive launcher # or bun cli deploy storagehub # Deploy via Helm ``` **Stagenet Deployment**: ```bash cd deploy helm install sh-mspnode ./charts/node \ -f ./charts/node/storagehub/sh-mspnode.yaml \ -f ./environments/stagenet/sh-mspnode.yaml \ -n datahaven-stagenet ``` ### Breaking Changes None - This is purely additive infrastructure. ### Migration Notes For existing deployments: 1. DataHaven nodes now use `--pool-type fork-aware` flag 2. Bootnode and validator node configs updated accordingly 3. No action required for existing DataHaven-only deployments --- deploy/charts/backend/Chart.yaml | 9 + deploy/charts/backend/README.md | 270 ++++++++++++++++++ .../backend/storagehub/sh-mspbackend.yaml | 64 +++++ deploy/charts/backend/templates/_helpers.tpl | 60 ++++ .../charts/backend/templates/configmap.yaml | 48 ++++ .../charts/backend/templates/deployment.yaml | 80 ++++++ deploy/charts/backend/templates/ingress.yaml | 61 ++++ deploy/charts/backend/templates/secret.yaml | 13 + deploy/charts/backend/templates/service.yaml | 22 ++ .../backend/templates/serviceaccount.yaml | 12 + deploy/charts/backend/values.yaml | 122 ++++++++ deploy/charts/node/datahaven/dh-bootnode.yaml | 1 + .../charts/node/datahaven/dh-validator.yaml | 1 + deploy/charts/node/storagehub/sh-bspnode.yaml | 47 +++ .../charts/node/storagehub/sh-fisherman.yaml | 44 +++ deploy/charts/node/storagehub/sh-idxnode.yaml | 38 +++ deploy/charts/node/storagehub/sh-mspnode.yaml | 49 ++++ deploy/environments/local/dh-bootnode.yaml | 2 +- deploy/environments/local/sh-bspnode.yaml | 44 +++ deploy/environments/local/sh-fisherman.yaml | 44 +++ deploy/environments/local/sh-idxnode-db.yaml | 21 ++ deploy/environments/local/sh-idxnode.yaml | 33 +++ deploy/environments/local/sh-mspbackend.yaml | 73 +++++ deploy/environments/local/sh-mspnode.yaml | 44 +++ deploy/environments/stagenet/dh-bootnode.yaml | 2 +- .../environments/stagenet/dh-validator.yaml | 2 +- deploy/environments/stagenet/sh-bspnode.yaml | 51 ++++ .../environments/stagenet/sh-fisherman.yaml | 51 ++++ .../environments/stagenet/sh-idxnode-db.yaml | 22 ++ deploy/environments/stagenet/sh-idxnode.yaml | 28 ++ .../environments/stagenet/sh-mspbackend.yaml | 71 +++++ deploy/environments/stagenet/sh-mspnode.yaml | 51 ++++ operator/Dockerfile.local | 25 ++ test/cli/handlers/deploy/index.ts | 4 + test/cli/handlers/deploy/storagehub.ts | 216 ++++++++++++++ test/cli/handlers/launch/index.ts | 13 +- test/cli/handlers/launch/storagehub.ts | 36 +++ test/cli/index.ts | 9 +- 38 files changed, 1775 insertions(+), 8 deletions(-) create mode 100644 deploy/charts/backend/Chart.yaml create mode 100644 deploy/charts/backend/README.md create mode 100644 deploy/charts/backend/storagehub/sh-mspbackend.yaml create mode 100644 deploy/charts/backend/templates/_helpers.tpl create mode 100644 deploy/charts/backend/templates/configmap.yaml create mode 100644 deploy/charts/backend/templates/deployment.yaml create mode 100644 deploy/charts/backend/templates/ingress.yaml create mode 100644 deploy/charts/backend/templates/secret.yaml create mode 100644 deploy/charts/backend/templates/service.yaml create mode 100644 deploy/charts/backend/templates/serviceaccount.yaml create mode 100644 deploy/charts/backend/values.yaml create mode 100644 deploy/charts/node/storagehub/sh-bspnode.yaml create mode 100644 deploy/charts/node/storagehub/sh-fisherman.yaml create mode 100644 deploy/charts/node/storagehub/sh-idxnode.yaml create mode 100644 deploy/charts/node/storagehub/sh-mspnode.yaml create mode 100644 deploy/environments/local/sh-bspnode.yaml create mode 100644 deploy/environments/local/sh-fisherman.yaml create mode 100644 deploy/environments/local/sh-idxnode-db.yaml create mode 100644 deploy/environments/local/sh-idxnode.yaml create mode 100644 deploy/environments/local/sh-mspbackend.yaml create mode 100644 deploy/environments/local/sh-mspnode.yaml create mode 100644 deploy/environments/stagenet/sh-bspnode.yaml create mode 100644 deploy/environments/stagenet/sh-fisherman.yaml create mode 100644 deploy/environments/stagenet/sh-idxnode-db.yaml create mode 100644 deploy/environments/stagenet/sh-idxnode.yaml create mode 100644 deploy/environments/stagenet/sh-mspbackend.yaml create mode 100644 deploy/environments/stagenet/sh-mspnode.yaml create mode 100644 operator/Dockerfile.local create mode 100644 test/cli/handlers/deploy/storagehub.ts create mode 100644 test/cli/handlers/launch/storagehub.ts diff --git a/deploy/charts/backend/Chart.yaml b/deploy/charts/backend/Chart.yaml new file mode 100644 index 00000000..b2fd66b4 --- /dev/null +++ b/deploy/charts/backend/Chart.yaml @@ -0,0 +1,9 @@ +apiVersion: v2 +name: sh-mspbackend +description: A Helm chart for StorageHub MSP Backend API +type: application +version: 0.1.0 +appVersion: "1.0.0" +maintainers: +- name: StorageHub Team + email: team@storagehub.io \ No newline at end of file diff --git a/deploy/charts/backend/README.md b/deploy/charts/backend/README.md new file mode 100644 index 00000000..efedff2d --- /dev/null +++ b/deploy/charts/backend/README.md @@ -0,0 +1,270 @@ +# StorageHub MSP Backend Helm Chart + +This Helm chart deploys the StorageHub MSP Backend API service that provides REST API access to the StorageHub network data. + +## Overview + +The StorageHub MSP Backend API: +- Connects to a StorageHub Indexer's database for indexed blockchain data +- Connects to a StorageHub MSP node for real-time blockchain queries +- Provides REST API endpoints for StorageHub operations + +## Prerequisites + +- Kubernetes 1.19+ +- Helm 3.2.0+ +- Running StorageHub Indexer database (PostgreSQL) +- Running StorageHub MSP node + +## Installation + +### Using base configuration + +```bash +helm install sh-mspbackend ./charts/backend \ + -f ./charts/backend/storagehub/sh-mspbackend.yaml +``` + +### For Local environment + +```bash +helm install sh-mspbackend ./charts/backend \ + -f ./charts/backend/storagehub/sh-mspbackend.yaml \ + -f ./environments/local/sh-mspbackend.yaml \ + -n kt-datahaven-local +``` + +### For Stagenet environment + +```bash +helm install sh-mspbackend ./charts/backend \ + -f ./charts/backend/storagehub/sh-mspbackend.yaml \ + -f ./environments/stagenet/sh-mspbackend.yaml \ + -n datahaven-stagenet +``` + +## Configuration + +### Key Parameters + +| Parameter | Description | Default | +|-----------|-------------|---------| +| `image.repository` | Container image repository | `moonsonglabs/storage-hub-msp-backend` | +| `image.tag` | Container image tag | `latest` | +| `replicaCount` | Number of replicas | `1` | +| `service.type` | Kubernetes service type | `ClusterIP` | +| `service.port` | Service port | `8080` | +| `service.targetPort` | Service target port | `80` | +| `backend.port` | Backend application port | `8080` | +| `backend.database.url` | PostgreSQL connection URL | `postgresql://storagehub:storagehub@sh-indexer-db:5432/storagehub` | +| `backend.rpc.endpoint` | WebSocket RPC endpoint | `ws://sh-idxnode:9944` | +| `backend.api.defaultPageSize` | Default page size for API results | `20` | +| `backend.api.maxPageSize` | Maximum page size for API results | `100` | +| `ingress.enabled` | Enable ingress | `false` | + +### Configuration File + +The backend uses a TOML configuration file passed via the `--config` CLI argument. This file is automatically generated from the Helm values and mounted as a ConfigMap at `/configs/config.toml`. + +#### Basic Configuration: +```yaml +backend: + port: 8080 + + database: + url: postgresql://indexer:indexer@sh-idxnode-db-postgresql:5432/datahaven + + rpc: + endpoint: ws://sh-mspnode-0:9955 + + api: + defaultPageSize: 20 + maxPageSize: 100 + + auth: + jwtSecret: "your-secret-here" + + args: + - "--config" + - "/configs/config.toml" + +configMap: + enabled: true +``` + +#### Alternative: Building Database URL from Components +The chart can also construct the database URL from separate components: +```yaml +backend: + database: + host: sh-idxnode-db-postgresql + port: 5432 + name: datahaven + user: indexer + password: production_password +``` + +**Note:** For production deployments, consider using Kubernetes Secrets or external secret management solutions for sensitive values like database passwords and JWT secrets. + +### Environment Variables + +Additional environment variables can be configured: + +```yaml +backend: + env: + NODE_ENV: production + LOG_LEVEL: info +``` + +### Additional ConfigMap Data + +You can add extra files to the ConfigMap: + +```yaml +configMap: + enabled: true + data: + custom-config.yaml: | + # Your custom configuration here + key: value +``` + +### CLI Arguments + +Additional CLI arguments can be specified to pass to the backend application: + +```yaml +backend: + args: + - "--config" + - "/configs/config.toml" + - "--log-level" + - "debug" +``` + +### Using Environment Variables from ConfigMaps or Secrets + +You can inject environment variables from existing ConfigMaps or Secrets: + +```yaml +backend: + envFrom: + - configMapRef: + name: my-config + - secretRef: + name: my-secret +``` + +## Accessing the Service + +### Local Environment + +When deployed with `NodePort` service type: +```bash +# Access via NodePort (configured as 30300 in local environment) +curl http://localhost:30300/ + +# Or via ingress if enabled +curl http://sh-mspbackend.datahaven.local/ +``` + +### Stagenet Environment + +```bash +# Access via ingress +curl https://sh-mspbackend.datahaven-kt.xyz/ +``` + +## Generated Configuration + +The chart automatically generates a `config.toml` file with the following structure: + +```toml +host = "0.0.0.0" +port = 8080 + +[api] +default_page_size = 20 +max_page_size = 100 + +[storage_hub] +rpc_url = "ws://sh-mspnode-0:9955" +msp_callback_url = "http://sh-mspbackend:8080" +timeout_secs = 30 +max_concurrent_requests = 100 +verify_tls = true +mock_mode = false + +[auth] +jwt_secret = "your-secret-here" + +[database] +url = "postgresql://indexer:indexer@sh-idxnode-db-postgresql:5432/datahaven" +mock_mode = false +``` + +## Troubleshooting + +### Check pod status +```bash +kubectl get pods -l app.kubernetes.io/name=sh-mspbackend -n +``` + +### View logs +```bash +kubectl logs -l app.kubernetes.io/name=sh-mspbackend -n +``` + +### Verify database connection +For local environment: +```bash +kubectl exec -it deployment/sh-mspbackend -n kt-datahaven-local -- nc -zv sh-idxnode-db-postgresql 5432 +``` + +For stagenet environment: +```bash +kubectl exec -it deployment/sh-mspbackend -n datahaven-stagenet -- nc -zv sh-idxnode-db-postgresql 5432 +``` + +### Verify RPC connection +For local environment: +```bash +kubectl exec -it deployment/sh-mspbackend -n kt-datahaven-local -- nc -zv sh-mspnode-0 9955 +``` + +For stagenet environment: +```bash +kubectl exec -it deployment/sh-mspbackend -n datahaven-stagenet -- nc -zv sh-mspnode-0 9955 +``` + +### View generated configuration +```bash +kubectl get configmap sh-mspbackend-config -n -o yaml +``` + +## Uninstallation + +```bash +# For local environment +helm uninstall sh-mspbackend -n kt-datahaven-local + +# For stagenet environment +helm uninstall sh-mspbackend -n datahaven-stagenet +``` + +## Environment-Specific Examples + +### Local Environment Values +See `environments/local/sh-mspbackend.yaml` for the complete local configuration, which includes: +- NodePort service on port 30300 +- Debug logging +- Traefik ingress at `sh-mspbackend.datahaven.local` +- Minimal resource requests for development + +### Stagenet Environment Values +See `environments/stagenet/sh-mspbackend.yaml` for the complete stagenet configuration, which includes: +- ClusterIP service with AWS NLB annotations +- Production logging levels +- ALB ingress with SSL at `sh-mspbackend.datahaven-kt.xyz` +- Production-level resource requests and limits \ No newline at end of file diff --git a/deploy/charts/backend/storagehub/sh-mspbackend.yaml b/deploy/charts/backend/storagehub/sh-mspbackend.yaml new file mode 100644 index 00000000..8f8de5e0 --- /dev/null +++ b/deploy/charts/backend/storagehub/sh-mspbackend.yaml @@ -0,0 +1,64 @@ +# StorageHub MSP Backend API base configuration +# This file contains the base configuration for the StorageHub MSP Backend API + +# Chart metadata +fullnameOverride: sh-mspbackend + +# Container image +image: + repository: moonsonglabs/storage-hub-msp-backend + tag: latest + pullPolicy: Always + +# Service configuration +service: + type: ClusterIP + port: 8080 + targetPort: 80 + +# Backend API configuration +backend: + port: 8080 + + # Database connection to StorageHub Indexer PostgreSQL + database: + url: postgresql://indexer:indexer@sh-idxnode-db-postgresql:5432/datahaven + + # RPC connection to StorageHub Indexer node + rpc: + endpoint: ws://sh-mspnode-0:9955 + + # Authentication (set in environment-specific values) + # auth: + # jwtSecret: "set-in-environment-values" + + # CLI arguments for the backend application + args: + - "--config" + - "/configs/config.toml" + +# Resource limits +resources: + requests: + memory: "256Mi" + cpu: "100m" + limits: + memory: "512Mi" + cpu: "500m" + +# Service account +serviceAccount: + create: true + name: sh-mspbackend + +# Security context +securityContext: + runAsNonRoot: true + runAsUser: 1000 + capabilities: + drop: + - ALL + +# Ingress configuration (disabled by default, enabled per environment) +ingress: + enabled: false diff --git a/deploy/charts/backend/templates/_helpers.tpl b/deploy/charts/backend/templates/_helpers.tpl new file mode 100644 index 00000000..d9930293 --- /dev/null +++ b/deploy/charts/backend/templates/_helpers.tpl @@ -0,0 +1,60 @@ +{{/* +Expand the name of the chart. +*/}} +{{- define "backend.name" -}} +{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Create a default fully qualified app name. +*/}} +{{- define "backend.fullname" -}} +{{- if .Values.fullnameOverride }} +{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- $name := default .Chart.Name .Values.nameOverride }} +{{- if contains $name .Release.Name }} +{{- .Release.Name | trunc 63 | trimSuffix "-" }} +{{- else }} +{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }} +{{- end }} +{{- end }} +{{- end }} + +{{/* +Create chart name and version as used by the chart label. +*/}} +{{- define "backend.chart" -}} +{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }} +{{- end }} + +{{/* +Common labels +*/}} +{{- define "backend.labels" -}} +helm.sh/chart: {{ include "backend.chart" . }} +{{ include "backend.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + +{{/* +Selector labels +*/}} +{{- define "backend.selectorLabels" -}} +app.kubernetes.io/name: {{ include "backend.name" . }} +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + +{{/* +Create the name of the service account to use +*/}} +{{- define "backend.serviceAccountName" -}} +{{- if .Values.serviceAccount.create }} +{{- default (include "backend.fullname" .) .Values.serviceAccount.name }} +{{- else }} +{{- default "default" .Values.serviceAccount.name }} +{{- end }} +{{- end }} \ No newline at end of file diff --git a/deploy/charts/backend/templates/configmap.yaml b/deploy/charts/backend/templates/configmap.yaml new file mode 100644 index 00000000..22afaa07 --- /dev/null +++ b/deploy/charts/backend/templates/configmap.yaml @@ -0,0 +1,48 @@ +{{- if .Values.configMap.enabled -}} +apiVersion: v1 +kind: ConfigMap +metadata: + name: {{ include "backend.fullname" . }}-config + labels: + {{- include "backend.labels" . | nindent 4 }} +data: + config.toml: | + # StorageHub Backend Configuration + host = "0.0.0.0" + port = {{ .Values.backend.port }} + + [api] + default_page_size = {{ .Values.backend.api.defaultPageSize | default 20 }} + max_page_size = {{ .Values.backend.api.maxPageSize | default 100 }} + + [storage_hub] + {{- if .Values.backend.rpc.endpoint }} + rpc_url = {{ .Values.backend.rpc.endpoint | quote }} + {{- end }} + + msp_callback_url = "http://{{ include "backend.fullname" . }}:8080" + + timeout_secs = 30 + max_concurrent_requests = 100 + verify_tls = true + mock_mode = false + + [auth] + {{- if .Values.backend.auth.jwtSecret }} + jwt_secret = {{ .Values.backend.auth.jwtSecret | quote }} + {{- end }} + + [database] + {{- if .Values.backend.database.url }} + url = {{ .Values.backend.database.url | quote }} + {{- else if .Values.backend.database.host }} + url = "postgresql://{{ .Values.backend.database.user | default "indexer" }}:{{ .Values.backend.database.password | default "password" }}@{{ .Values.backend.database.host }}:{{ .Values.backend.database.port | default 5432 }}/{{ .Values.backend.database.name | default "storagehub" }}" + {{- else }} + url = "postgresql://indexer:password@sh-indexer-db:5432/storagehub" + {{- end }} + + mock_mode = false + {{- range $key, $value := .Values.configMap.data }} + {{ $key }}: {{ $value | quote }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/deploy/charts/backend/templates/deployment.yaml b/deploy/charts/backend/templates/deployment.yaml new file mode 100644 index 00000000..c998e2eb --- /dev/null +++ b/deploy/charts/backend/templates/deployment.yaml @@ -0,0 +1,80 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: {{ include "backend.fullname" . }} + labels: + {{- include "backend.labels" . | nindent 4 }} +spec: + replicas: {{ .Values.replicaCount }} + selector: + matchLabels: + {{- include "backend.selectorLabels" . | nindent 6 }} + template: + metadata: + annotations: + checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} + {{- with .Values.podAnnotations }} + {{- toYaml . | nindent 8 }} + {{- end }} + labels: + {{- include "backend.selectorLabels" . | nindent 8 }} + spec: + {{- with .Values.imagePullSecrets }} + imagePullSecrets: + {{- toYaml . | nindent 8 }} + {{- end }} + serviceAccountName: {{ include "backend.serviceAccountName" . }} + securityContext: + {{- toYaml .Values.podSecurityContext | nindent 8 }} + containers: + - name: {{ .Chart.Name }} + securityContext: + {{- toYaml .Values.securityContext | nindent 12 }} + image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}" + imagePullPolicy: {{ .Values.image.pullPolicy }} + ports: + - name: http + containerPort: {{ .Values.backend.port }} + protocol: TCP + env: + - name: PORT + value: {{ .Values.backend.port | quote }} + {{- range $key, $value := .Values.backend.env }} + - name: {{ $key }} + value: {{ $value | quote }} + {{- end }} + {{- with .Values.backend.envFrom }} + envFrom: + {{- toYaml . | nindent 12 }} + {{- end }} + {{- if .Values.backend.args }} + args: + {{- toYaml .Values.backend.args | nindent 12 }} + {{- end }} + resources: + {{- toYaml .Values.resources | nindent 12 }} + {{- if .Values.configMap.enabled }} + volumeMounts: + - name: config + mountPath: "/configs/config.toml" + subPath: "config.toml" + readOnly: true + {{- end }} + {{- if .Values.configMap.enabled }} + volumes: + - name: config + configMap: + name: {{ include "backend.fullname" . }}-config + {{- 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 }} \ No newline at end of file diff --git a/deploy/charts/backend/templates/ingress.yaml b/deploy/charts/backend/templates/ingress.yaml new file mode 100644 index 00000000..ca8849a5 --- /dev/null +++ b/deploy/charts/backend/templates/ingress.yaml @@ -0,0 +1,61 @@ +{{- if .Values.ingress.enabled -}} +{{- $fullName := include "backend.fullname" . -}} +{{- $svcPort := .Values.service.port -}} +{{- if and .Values.ingress.className (not (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion)) }} + {{- if not (hasKey .Values.ingress.annotations "kubernetes.io/ingress.class") }} + {{- $_ := set .Values.ingress.annotations "kubernetes.io/ingress.class" .Values.ingress.className}} + {{- end }} +{{- end }} +{{- if semverCompare ">=1.19-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1 +{{- else if semverCompare ">=1.14-0" .Capabilities.KubeVersion.GitVersion -}} +apiVersion: networking.k8s.io/v1beta1 +{{- else -}} +apiVersion: extensions/v1beta1 +{{- end }} +kind: Ingress +metadata: + name: {{ $fullName }} + labels: + {{- include "backend.labels" . | nindent 4 }} + {{- with .Values.ingress.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + {{- if and .Values.ingress.className (semverCompare ">=1.18-0" .Capabilities.KubeVersion.GitVersion) }} + ingressClassName: {{ .Values.ingress.className }} + {{- end }} + {{- if .Values.ingress.tls }} + tls: + {{- range .Values.ingress.tls }} + - hosts: + {{- range .hosts }} + - {{ . | quote }} + {{- end }} + secretName: {{ .secretName }} + {{- end }} + {{- end }} + rules: + {{- range .Values.ingress.hosts }} + - host: {{ .host | quote }} + http: + paths: + {{- range .paths }} + - path: {{ .path }} + {{- if and .pathType (semverCompare ">=1.18-0" $.Capabilities.KubeVersion.GitVersion) }} + pathType: {{ .pathType }} + {{- end }} + backend: + {{- if semverCompare ">=1.19-0" $.Capabilities.KubeVersion.GitVersion }} + service: + name: {{ $fullName }} + port: + number: {{ $svcPort }} + {{- else }} + serviceName: {{ $fullName }} + servicePort: {{ $svcPort }} + {{- end }} + {{- end }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/deploy/charts/backend/templates/secret.yaml b/deploy/charts/backend/templates/secret.yaml new file mode 100644 index 00000000..812e46ef --- /dev/null +++ b/deploy/charts/backend/templates/secret.yaml @@ -0,0 +1,13 @@ +{{- if .Values.secrets.enabled -}} +apiVersion: v1 +kind: Secret +metadata: + name: {{ include "backend.fullname" . }}-custom + labels: + {{- include "backend.labels" . | nindent 4 }} +type: Opaque +data: + {{- range $key, $value := .Values.secrets.data }} + {{ $key }}: {{ $value | b64enc | quote }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/deploy/charts/backend/templates/service.yaml b/deploy/charts/backend/templates/service.yaml new file mode 100644 index 00000000..8d65dcbb --- /dev/null +++ b/deploy/charts/backend/templates/service.yaml @@ -0,0 +1,22 @@ +apiVersion: v1 +kind: Service +metadata: + name: {{ include "backend.fullname" . }} + labels: + {{- include "backend.labels" . | nindent 4 }} + {{- with .Values.service.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +spec: + type: {{ .Values.service.type }} + ports: + - port: {{ .Values.service.port }} + targetPort: http + protocol: TCP + name: http + {{- if and (eq .Values.service.type "NodePort") .Values.service.nodePort }} + nodePort: {{ .Values.service.nodePort }} + {{- end }} + selector: + {{- include "backend.selectorLabels" . | nindent 4 }} \ No newline at end of file diff --git a/deploy/charts/backend/templates/serviceaccount.yaml b/deploy/charts/backend/templates/serviceaccount.yaml new file mode 100644 index 00000000..56355387 --- /dev/null +++ b/deploy/charts/backend/templates/serviceaccount.yaml @@ -0,0 +1,12 @@ +{{- if .Values.serviceAccount.create -}} +apiVersion: v1 +kind: ServiceAccount +metadata: + name: {{ include "backend.serviceAccountName" . }} + labels: + {{- include "backend.labels" . | nindent 4 }} + {{- with .Values.serviceAccount.annotations }} + annotations: + {{- toYaml . | nindent 4 }} + {{- end }} +{{- end }} \ No newline at end of file diff --git a/deploy/charts/backend/values.yaml b/deploy/charts/backend/values.yaml new file mode 100644 index 00000000..61ff0885 --- /dev/null +++ b/deploy/charts/backend/values.yaml @@ -0,0 +1,122 @@ +# Default values for backend. +# This is a YAML-formatted file. +# Declare variables to be passed into your templates. + +replicaCount: 1 + +image: + repository: storagehub/backend + pullPolicy: IfNotPresent + tag: "latest" + +imagePullSecrets: [] +nameOverride: "" +fullnameOverride: "" + +serviceAccount: + create: true + annotations: {} + name: "" + +podAnnotations: {} + +podSecurityContext: {} + # fsGroup: 2000 + +securityContext: {} + # capabilities: + # drop: + # - ALL + # readOnlyRootFilesystem: true + # runAsNonRoot: true + # runAsUser: 1000 + +service: + type: ClusterIP + port: 3000 + targetPort: 3000 + annotations: {} + +ingress: + enabled: false + className: "" + annotations: {} + hosts: + - host: api.storagehub.local + paths: + - path: / + pathType: Prefix + tls: [] + +resources: + limits: + cpu: 500m + memory: 512Mi + requests: + cpu: 250m + memory: 256Mi + +nodeSelector: {} + +tolerations: [] + +affinity: {} + +# Backend API Configuration +backend: + # Port the backend listens on + port: 3000 + + # Database configuration + database: + # Full database connection URL + url: "postgresql://storagehub:storagehub@sh-indexer-db:5432/storagehub" + # Use existing secret for database URL + existingSecret: "" + # Key in the secret containing the DATABASE_URL + existingSecretUrlKey: "database-url" + + # RPC Node configuration + rpc: + endpoint: "ws://sh-idxnode:9944" + # Alternative HTTP endpoint if needed + httpEndpoint: "http://sh-idxnode:9933" + + # API configuration + api: + defaultPageSize: 20 + maxPageSize: 100 + + # Authentication configuration + auth: + jwtSecret: "" + + # Environment variables + env: + NODE_ENV: "production" + LOG_LEVEL: "info" + + # Additional environment variables from ConfigMap or Secret + envFrom: [] + + # CLI arguments to pass to the backend application + args: [] + # Example: + # args: + # - "--config" + # - "/app/config.toml" + # - "--log-level" + # - "debug" + +# ConfigMap for configuration files +configMap: + enabled: true + # Additional configuration to merge into config.json + extraConfig: {} + # Additional files to add to ConfigMap + data: {} + +# Secrets for sensitive data +secrets: + enabled: false + data: {} \ No newline at end of file diff --git a/deploy/charts/node/datahaven/dh-bootnode.yaml b/deploy/charts/node/datahaven/dh-bootnode.yaml index 4d537199..3da23587 100644 --- a/deploy/charts/node/datahaven/dh-bootnode.yaml +++ b/deploy/charts/node/datahaven/dh-bootnode.yaml @@ -26,6 +26,7 @@ node: - "--allow-private-ipv4" - "--discover-local" - "--network-backend libp2p" + - "--pool-type fork-aware" ingress: enabled: false diff --git a/deploy/charts/node/datahaven/dh-validator.yaml b/deploy/charts/node/datahaven/dh-validator.yaml index 9822a469..dc9a2356 100644 --- a/deploy/charts/node/datahaven/dh-validator.yaml +++ b/deploy/charts/node/datahaven/dh-validator.yaml @@ -43,6 +43,7 @@ node: persistGeneratedNodeKey: true flags: - "--network-backend libp2p" + - "--pool-type fork-aware" # Note: Bootnode discovery will happen automatically via the chainspec downloaded from customChainspecUrl enableOffchainIndexing: true diff --git a/deploy/charts/node/storagehub/sh-bspnode.yaml b/deploy/charts/node/storagehub/sh-bspnode.yaml new file mode 100644 index 00000000..56697db8 --- /dev/null +++ b/deploy/charts/node/storagehub/sh-bspnode.yaml @@ -0,0 +1,47 @@ +name: sh-bspnode +description: Datahaven BSP node +fullnameOverride: sh-bspnode + +image: + repository: datahavenxyz/datahaven + tag: main + pullPolicy: Always + +imagePullSecrets: + - name: datahaven-dockerhub + +node: + command: datahaven-node + customChainspecUrl: http://dh-bootnode:8080/chainspec.json + forceDownloadChainspec: true + role: full + replicas: 2 + chainData: + pruning: 1000 + storageClass: "gp2" + chainKeystore: + storageClass: "gp2" + keys: + # This is Alice seed. To generate new seed run: docker run --rm datahavenxyz/datahaven:latest key generate + - seed: "bottom drive obey lake curtain smoke basket hold race lonely fit walk" + type: bcsv + scheme: ecdsa + # ${HOSTNAME##*-} will be evaluated as the pod index, pod-0: //Eve, pod-1: //Ferdie + extraDerivation: '$([ "${HOSTNAME##*-}" = "0" ] && echo "//Eve" || echo "//Ferdie")' + persistGeneratedNodeKey: true + flags: + - "--allow-private-ipv4" + - "--discover-local" + - "--network-backend libp2p" + - "--provider" + - "--provider-type bsp" + - "--max-storage-capacity 10737418240" # 10 GiB + - "--jump-capacity=1073741824" # 1 GiB + +ingress: + enabled: false + perReplica: true + wildcardDomain: datahaven.local + # If enabled, this would generate: + # - sh-bspnode-0.datahaven.local + # - sh-bspnode-1.datahaven.local diff --git a/deploy/charts/node/storagehub/sh-fisherman.yaml b/deploy/charts/node/storagehub/sh-fisherman.yaml new file mode 100644 index 00000000..612584fd --- /dev/null +++ b/deploy/charts/node/storagehub/sh-fisherman.yaml @@ -0,0 +1,44 @@ +name: sh-fisherman +description: Datahaven Fisherman node +fullnameOverride: sh-fisherman + +image: + repository: datahavenxyz/datahaven + tag: main + pullPolicy: Always + +imagePullSecrets: + - name: datahaven-dockerhub + +node: + command: datahaven-node + customChainspecUrl: http://dh-bootnode:8080/chainspec.json + forceDownloadChainspec: true + role: full + replicas: 1 + chainData: + pruning: 1000 + storageClass: "gp2" + chainKeystore: + storageClass: "gp2" + keys: + # This is Alice seed. To generate new seed run: docker run --rm datahavenxyz/datahaven:latest key generate + - seed: "bottom drive obey lake curtain smoke basket hold race lonely fit walk" + type: bcsv + scheme: ecdsa + # ${HOSTNAME##*-} will be evaluated as the pod index, pod-0: //Gustavo, pod-1: //Hermano + extraDerivation: '$([ "${HOSTNAME##*-}" = "0" ] && echo "//Gustavo" || echo "//Hermano")' + persistGeneratedNodeKey: true + flags: + - "--allow-private-ipv4" + - "--discover-local" + - "--network-backend libp2p" + - "--fisherman" + - "--fisherman-database-url postgresql://indexer:indexer@sh-idxnode-db-postgresql:5432/datahaven" + +ingress: + enabled: false + perReplica: false + wildcardDomain: datahaven.local + # If enabled, this would generate: + # - sh-fisherman-0.datahaven.local diff --git a/deploy/charts/node/storagehub/sh-idxnode.yaml b/deploy/charts/node/storagehub/sh-idxnode.yaml new file mode 100644 index 00000000..8a606ab5 --- /dev/null +++ b/deploy/charts/node/storagehub/sh-idxnode.yaml @@ -0,0 +1,38 @@ +name: sh-idxnode +description: Datahaven Indexer node +fullnameOverride: sh-idxnode + +image: + repository: datahavenxyz/datahaven + tag: main + pullPolicy: Always + +imagePullSecrets: + - name: datahaven-dockerhub + +node: + command: datahaven-node + customChainspecUrl: http://dh-bootnode:8080/chainspec.json + forceDownloadChainspec: true + role: full + replicas: 1 + chainData: + pruning: 1000 + storageClass: "gp2" + chainKeystore: + storageClass: "gp2" + persistGeneratedNodeKey: true + flags: + - "--allow-private-ipv4" + - "--discover-local" + - "--network-backend libp2p" + - "--indexer" + - "--indexer-mode full" + - "--indexer-database-url postgresql://indexer:indexer@sh-idxnode-db-postgresql:5432/datahaven" + +ingress: + enabled: false + perReplica: false + wildcardDomain: datahaven.local + # If enabled, this would generate: + # - sh-idxnode-0.datahaven.local diff --git a/deploy/charts/node/storagehub/sh-mspnode.yaml b/deploy/charts/node/storagehub/sh-mspnode.yaml new file mode 100644 index 00000000..34f6de6a --- /dev/null +++ b/deploy/charts/node/storagehub/sh-mspnode.yaml @@ -0,0 +1,49 @@ +name: sh-mspnode +description: Datahaven MSP node +fullnameOverride: sh-mspnode + +image: + repository: datahavenxyz/datahaven + tag: main + pullPolicy: Always + +imagePullSecrets: + - name: datahaven-dockerhub + +node: + command: datahaven-node + customChainspecUrl: http://dh-bootnode:8080/chainspec.json + forceDownloadChainspec: true + role: full + replicas: 2 + chainData: + pruning: 1000 + storageClass: "gp2" + chainKeystore: + storageClass: "gp2" + keys: + # This is Alice seed. To generate new seed run: docker run --rm datahavenxyz/datahaven:latest key generate + - seed: "bottom drive obey lake curtain smoke basket hold race lonely fit walk" + type: bcsv + scheme: ecdsa + # ${HOSTNAME##*-} will be evaluated as the pod index, pod-0: //Charlie, pod-1: //Dave + extraDerivation: '$([ "${HOSTNAME##*-}" = "0" ] && echo "//Charlie" || echo "//Dave")' + persistGeneratedNodeKey: true + allowUnsafeRpcMethods: true + flags: + - "--allow-private-ipv4" + - "--discover-local" + - "--network-backend libp2p" + - "--provider" + - "--provider-type msp" + - "--msp-charging-period 100" # in blocks, 100 blocks = 10 minutes + - "--max-storage-capacity 10737418240" # 10 GiB + - "--jump-capacity=1073741824" # 1 GiB + +ingress: + enabled: false + perReplica: true + wildcardDomain: datahaven.local + # If enabled, this would generate: + # - sh-mspnode-0.datahaven.local + # - sh-mspnode-1.datahaven.local diff --git a/deploy/environments/local/dh-bootnode.yaml b/deploy/environments/local/dh-bootnode.yaml index de46dd2e..245db825 100644 --- a/deploy/environments/local/dh-bootnode.yaml +++ b/deploy/environments/local/dh-bootnode.yaml @@ -15,7 +15,7 @@ imagePullSecrets: ingress: enabled: false ingressClassName: traefik - host: dh-bootnode-0.datahaven-kt.local + host: dh-bootnode-0.datahaven.local node: chain: local diff --git a/deploy/environments/local/sh-bspnode.yaml b/deploy/environments/local/sh-bspnode.yaml new file mode 100644 index 00000000..db3339f3 --- /dev/null +++ b/deploy/environments/local/sh-bspnode.yaml @@ -0,0 +1,44 @@ +# BSP-specific settings for Local environment + +global: + environment: local + namespace: kt-datahaven-local + +image: + tag: local + pullPolicy: IfNotPresent + +imagePullSecrets: + - name: datahaven-dockerhub + +# Ingress disabled for local (can be enabled for testing) +ingress: + enabled: false + ingressClassName: traefik + perReplica: true + wildcardDomain: datahaven.local + # If enabled, this would generate: + # - sh-bspnode-0.datahaven.local + # - sh-bspnode-1.datahaven.local + +node: + chain: local + customChainspecUrl: + forceDownloadChainspec: false + chainData: + storageClass: "hostpath" + persistence: + size: 10Gi + chainKeystore: + storageClass: "hostpath" + resources: + requests: + memory: "256Mi" + cpu: "100m" + limits: + memory: "512Mi" + cpu: "200m" + perNodeServices: + apiService: + enabled: true + type: NodePort diff --git a/deploy/environments/local/sh-fisherman.yaml b/deploy/environments/local/sh-fisherman.yaml new file mode 100644 index 00000000..1f544a8d --- /dev/null +++ b/deploy/environments/local/sh-fisherman.yaml @@ -0,0 +1,44 @@ +# Fisherman-specific settings for Local environment + +global: + environment: local + namespace: kt-datahaven-local + +image: + tag: local + pullPolicy: IfNotPresent + +imagePullSecrets: + - name: datahaven-dockerhub + +# Ingress disabled for local (can be enabled for testing) +ingress: + enabled: false + ingressClassName: traefik + perReplica: true + wildcardDomain: datahaven.local + # If enabled, this would generate: + # - sh-fisherman-0.datahaven.local + # - sh-fisherman-1.datahaven.local + +node: + chain: local + customChainspecUrl: + forceDownloadChainspec: false + chainData: + storageClass: "hostpath" + persistence: + size: 10Gi + chainKeystore: + storageClass: "hostpath" + resources: + requests: + memory: "256Mi" + cpu: "100m" + limits: + memory: "512Mi" + cpu: "200m" + perNodeServices: + apiService: + enabled: true + type: NodePort diff --git a/deploy/environments/local/sh-idxnode-db.yaml b/deploy/environments/local/sh-idxnode-db.yaml new file mode 100644 index 00000000..c66998cd --- /dev/null +++ b/deploy/environments/local/sh-idxnode-db.yaml @@ -0,0 +1,21 @@ +# Install PostgreSQL into local k8S cluster +# helm repo add bitnami https://charts.bitnami.com/bitnami +# helm repo update +# helm install sh-idxnode-db bitnami/postgresql -f ./deploy/environments/local/sh-idxnode-db.yaml -n datahaven-local + +auth: + username: indexer + password: indexer + database: datahaven + postgresPassword: postgres +primary: + persistence: + enabled: true + size: 10Gi # requires a default StorageClass + resources: + requests: { cpu: "100m", memory: "256Mi" } + limits: { cpu: "500m", memory: "512Mi" } +volumePermissions: + enabled: true # helps with FS perms on some storage classes +metrics: + enabled: true # optional: Prometheus exporter diff --git a/deploy/environments/local/sh-idxnode.yaml b/deploy/environments/local/sh-idxnode.yaml new file mode 100644 index 00000000..a3aeda52 --- /dev/null +++ b/deploy/environments/local/sh-idxnode.yaml @@ -0,0 +1,33 @@ +# Indexer-specific settings for Local environment + +global: + environment: local + namespace: kt-datahaven-local + +image: + tag: local + pullPolicy: IfNotPresent + +imagePullSecrets: + - name: datahaven-dockerhub + +ingress: + enabled: false + +node: + chain: local + customChainspecUrl: + forceDownloadChainspec: false + chainData: + storageClass: "hostpath" + persistence: + size: 10Gi + chainKeystore: + storageClass: "hostpath" + resources: + requests: + memory: "256Mi" + cpu: "100m" + limits: + memory: "512Mi" + cpu: "200m" diff --git a/deploy/environments/local/sh-mspbackend.yaml b/deploy/environments/local/sh-mspbackend.yaml new file mode 100644 index 00000000..ae5006dc --- /dev/null +++ b/deploy/environments/local/sh-mspbackend.yaml @@ -0,0 +1,73 @@ +# StorageHub MSP Backend API configuration for Local environment + +global: + environment: local + namespace: kt-datahaven-local + +# Use local image +image: + repository: moonsonglabs/storage-hub-msp-backend + tag: latest + pullPolicy: Always + +imagePullSecrets: + - name: datahaven-dockerhub + +# Single replica for local development +replicaCount: 1 + +# Service configuration for local access +service: + type: NodePort + port: 8080 + nodePort: 30300 # Fixed NodePort for local access + +# Backend configuration for local environment +backend: + database: + url: postgresql://indexer:indexer@sh-idxnode-db-postgresql:5432/datahaven + + rpc: + url: ws://sh-idxnode:9944 + + auth: + jwtSecret: "local-development-secret" + + env: + LOG_LEVEL: debug + + # CLI arguments for local development + args: + - "--config" + - "/app/config/config.toml" + +# Minimal resources for local development +resources: + requests: + memory: "128Mi" + cpu: "50m" + limits: + memory: "256Mi" + cpu: "200m" + +# Enable ingress for local development with Traefik +ingress: + enabled: true + className: traefik + annotations: + traefik.ingress.kubernetes.io/router.entrypoints: web + hosts: + - host: sh-mspbackend.datahaven.local + paths: + - path: / + pathType: Prefix + +# ConfigMap for local environment +configMap: + enabled: true + extraConfig: + environment: "local" + features: + debug: true + swagger: true + metrics: true \ No newline at end of file diff --git a/deploy/environments/local/sh-mspnode.yaml b/deploy/environments/local/sh-mspnode.yaml new file mode 100644 index 00000000..b4bdb88c --- /dev/null +++ b/deploy/environments/local/sh-mspnode.yaml @@ -0,0 +1,44 @@ +# MSP-specific settings for Local environment + +global: + environment: local + namespace: kt-datahaven-local + +image: + tag: local + pullPolicy: IfNotPresent + +imagePullSecrets: + - name: datahaven-dockerhub + +# Ingress disabled for local (can be enabled for testing) +ingress: + enabled: false + ingressClassName: traefik + perReplica: true + wildcardDomain: datahaven.local + # If enabled, this would generate: + # - sh-mspnode-0.datahaven.local + # - sh-mspnode-1.datahaven.local + +node: + chain: local + customChainspecUrl: + forceDownloadChainspec: false + chainData: + storageClass: "hostpath" + persistence: + size: 10Gi + chainKeystore: + storageClass: "hostpath" + resources: + requests: + memory: "256Mi" + cpu: "100m" + limits: + memory: "512Mi" + cpu: "200m" + perNodeServices: + apiService: + enabled: true + type: NodePort diff --git a/deploy/environments/stagenet/dh-bootnode.yaml b/deploy/environments/stagenet/dh-bootnode.yaml index d03787dd..b3f41d40 100644 --- a/deploy/environments/stagenet/dh-bootnode.yaml +++ b/deploy/environments/stagenet/dh-bootnode.yaml @@ -5,7 +5,7 @@ global: namespace: kt-datahaven-stagenet image: - tag: main + tag: latest pullPolicy: Always imagePullSecrets: diff --git a/deploy/environments/stagenet/dh-validator.yaml b/deploy/environments/stagenet/dh-validator.yaml index 5deca490..66af0a42 100644 --- a/deploy/environments/stagenet/dh-validator.yaml +++ b/deploy/environments/stagenet/dh-validator.yaml @@ -5,7 +5,7 @@ global: namespace: kt-datahaven-stagenet image: - tag: main + tag: latest pullPolicy: Always imagePullSecrets: diff --git a/deploy/environments/stagenet/sh-bspnode.yaml b/deploy/environments/stagenet/sh-bspnode.yaml new file mode 100644 index 00000000..fa0ef078 --- /dev/null +++ b/deploy/environments/stagenet/sh-bspnode.yaml @@ -0,0 +1,51 @@ +# BSP-specific settings for stagenet + +global: + environment: stagenet + namespace: kt-datahaven-stagenet + +image: + tag: latest + pullPolicy: Always + +imagePullSecrets: + - name: datahaven-dockerhub + +ingress: + enabled: true + perReplica: true + wildcardDomain: datahaven-kt.xyz + # This will generate: + # - sh-bspnode-0.datahaven-kt.xyz + # - sh-bspnode-1.datahaven-kt.xyz + # (based on replica count) + annotations: + kubernetes.io/ingress.class: alb + alb.ingress.kubernetes.io/scheme: internet-facing + alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]' + alb.ingress.kubernetes.io/load-balancer-name: sh-bspnode + alb.ingress.kubernetes.io/target-type: ip + alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS-1-2-2017-01 + alb.ingress.kubernetes.io/load-balancer-attributes: idle_timeout.timeout_seconds=120 + alb.ingress.kubernetes.io/target-group-attributes: deregistration_delay.timeout_seconds=30 + alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-east-1:601766312530:certificate/61c2fc57-4ce4-4a80-90b8-2810c1221f09 + external-dns.alpha.kubernetes.io/hostname: sh-bspnode.datahaven-kt.xyz + meta.helm.sh/release-name: sh-bspnode + meta.helm.sh/release-namespace: kt-datahaven-stagenet + +node: + chain: stagenet-local + chainData: + persistence: + size: 20Gi + resources: + requests: + memory: "512Mi" + cpu: "200m" + limits: + memory: "1Gi" + cpu: "500m" + perNodeServices: + apiService: + enabled: true + type: NodePort diff --git a/deploy/environments/stagenet/sh-fisherman.yaml b/deploy/environments/stagenet/sh-fisherman.yaml new file mode 100644 index 00000000..2d82b49e --- /dev/null +++ b/deploy/environments/stagenet/sh-fisherman.yaml @@ -0,0 +1,51 @@ +# Fisherman-specific settings for stagenet + +global: + environment: stagenet + namespace: kt-datahaven-stagenet + +image: + tag: latest + pullPolicy: Always + +imagePullSecrets: + - name: datahaven-dockerhub + +ingress: + enabled: true + perReplica: true + wildcardDomain: datahaven-kt.xyz + # This will generate: + # - sh-fisherman-0.datahaven-kt.xyz + # - sh-fisherman-1.datahaven-kt.xyz + # (based on replica count) + annotations: + kubernetes.io/ingress.class: alb + alb.ingress.kubernetes.io/scheme: internet-facing + alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]' + alb.ingress.kubernetes.io/load-balancer-name: sh-fisherman + alb.ingress.kubernetes.io/target-type: ip + alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS-1-2-2017-01 + alb.ingress.kubernetes.io/load-balancer-attributes: idle_timeout.timeout_seconds=120 + alb.ingress.kubernetes.io/target-group-attributes: deregistration_delay.timeout_seconds=30 + alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-east-1:601766312530:certificate/61c2fc57-4ce4-4a80-90b8-2810c1221f09 + external-dns.alpha.kubernetes.io/hostname: sh-fisherman.datahaven-kt.xyz + meta.helm.sh/release-name: sh-fisherman + meta.helm.sh/release-namespace: kt-datahaven-stagenet + +node: + chain: stagenet-local + chainData: + persistence: + size: 20Gi + resources: + requests: + memory: "512Mi" + cpu: "200m" + limits: + memory: "1Gi" + cpu: "500m" + perNodeServices: + apiService: + enabled: true + type: NodePort diff --git a/deploy/environments/stagenet/sh-idxnode-db.yaml b/deploy/environments/stagenet/sh-idxnode-db.yaml new file mode 100644 index 00000000..1845defa --- /dev/null +++ b/deploy/environments/stagenet/sh-idxnode-db.yaml @@ -0,0 +1,22 @@ +# Install PostgreSQL into local k8S cluster +# helm repo add bitnami https://charts.bitnami.com/bitnami +# helm repo update +# helm install sh-idxnode-db bitnami/postgresql -f ./deploy/environments/local/sh-idxnode-db.yaml -n kt-datahaven-stagenet + +auth: + username: indexer + password: indexer + database: datahaven + postgresPassword: postgres +primary: + persistence: + enabled: true + size: 10Gi # requires a default StorageClass + storageClass: "gp2" + resources: + requests: { cpu: "100m", memory: "256Mi" } + limits: { cpu: "500m", memory: "512Mi" } +volumePermissions: + enabled: true # helps with FS perms on some storage classes +metrics: + enabled: true # optional: Prometheus exporter diff --git a/deploy/environments/stagenet/sh-idxnode.yaml b/deploy/environments/stagenet/sh-idxnode.yaml new file mode 100644 index 00000000..1e713ea2 --- /dev/null +++ b/deploy/environments/stagenet/sh-idxnode.yaml @@ -0,0 +1,28 @@ +# Indexer-specific settings for stagenet + +global: + environment: stagenet + namespace: kt-datahaven-stagenet + +image: + tag: latest + pullPolicy: Always + +imagePullSecrets: + - name: datahaven-dockerhub + +ingress: + enabled: false + +node: + chain: stagenet-local + chainData: + persistence: + size: 20Gi + resources: + requests: + memory: "512Mi" + cpu: "200m" + limits: + memory: "1Gi" + cpu: "500m" diff --git a/deploy/environments/stagenet/sh-mspbackend.yaml b/deploy/environments/stagenet/sh-mspbackend.yaml new file mode 100644 index 00000000..cf93b1d7 --- /dev/null +++ b/deploy/environments/stagenet/sh-mspbackend.yaml @@ -0,0 +1,71 @@ +# StorageHub MSP Backend API configuration for Stagenet environment + +global: + environment: stagenet + namespace: datahaven-stagenet + +# Stagenet image configuration +image: + repository: moonsonglabs/storage-hub-msp-backend + tag: latest + pullPolicy: Always + +imagePullSecrets: + - name: datahaven-dockerhub + +replicaCount: 1 + +# Service configuration +service: + type: ClusterIP + port: 8080 + annotations: + service.beta.kubernetes.io/aws-load-balancer-type: "nlb" + +# Backend configuration for stagenet +backend: + database: + url: postgresql://indexer:indexer@sh-idxnode-db-postgresql:5432/datahaven + + rpc: + endpoint: ws://sh-mspnode-0:9955 + + auth: + jwtSecret: "0xdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeefdeadbeef" + + # CLI arguments for production + args: + - "--config" + - "/configs/config.toml" + +# Production-ready resources +resources: + requests: + memory: "512Mi" + cpu: "250m" + limits: + memory: "1Gi" + cpu: "1000m" + +# Enable ingress with SSL +ingress: + enabled: true + host: sh-mspbackend.datahaven-kt.xyz + annotations: + kubernetes.io/ingress.class: alb + alb.ingress.kubernetes.io/scheme: internet-facing + alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]' + alb.ingress.kubernetes.io/load-balancer-name: sh-mspbackend + alb.ingress.kubernetes.io/target-type: ip + alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS-1-2-2017-01 + alb.ingress.kubernetes.io/load-balancer-attributes: idle_timeout.timeout_seconds=120 + alb.ingress.kubernetes.io/target-group-attributes: deregistration_delay.timeout_seconds=30 + alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-east-1:601766312530:certificate/61c2fc57-4ce4-4a80-90b8-2810c1221f09 + external-dns.alpha.kubernetes.io/hostname: sh-mspbackend.datahaven-kt.xyz + meta.helm.sh/release-name: sh-mspbackend + meta.helm.sh/release-namespace: kt-datahaven-stagenet + hosts: + - host: sh-mspbackend.datahaven-kt.xyz + paths: + - path: / + pathType: Prefix diff --git a/deploy/environments/stagenet/sh-mspnode.yaml b/deploy/environments/stagenet/sh-mspnode.yaml new file mode 100644 index 00000000..6bf28aee --- /dev/null +++ b/deploy/environments/stagenet/sh-mspnode.yaml @@ -0,0 +1,51 @@ +# MSP-specific settings for stagenet + +global: + environment: stagenet + namespace: kt-datahaven-stagenet + +image: + tag: latest + pullPolicy: Always + +imagePullSecrets: + - name: datahaven-dockerhub + +ingress: + enabled: true + perReplica: true + wildcardDomain: datahaven-kt.xyz + # This will generate: + # - sh-mspnode-0.datahaven-kt.xyz + # - sh-mspnode-1.datahaven-kt.xyz + # (based on replica count) + annotations: + kubernetes.io/ingress.class: alb + alb.ingress.kubernetes.io/scheme: internet-facing + alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]' + alb.ingress.kubernetes.io/load-balancer-name: sh-mspnode + alb.ingress.kubernetes.io/target-type: ip + alb.ingress.kubernetes.io/ssl-policy: ELBSecurityPolicy-TLS-1-2-2017-01 + alb.ingress.kubernetes.io/load-balancer-attributes: idle_timeout.timeout_seconds=120 + alb.ingress.kubernetes.io/target-group-attributes: deregistration_delay.timeout_seconds=30 + alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-east-1:601766312530:certificate/61c2fc57-4ce4-4a80-90b8-2810c1221f09 + external-dns.alpha.kubernetes.io/hostname: sh-mspnode.datahaven-kt.xyz + meta.helm.sh/release-name: sh-mspnode + meta.helm.sh/release-namespace: kt-datahaven-stagenet + +node: + chain: stagenet-local + chainData: + persistence: + size: 20Gi + resources: + requests: + memory: "512Mi" + cpu: "200m" + limits: + memory: "1Gi" + cpu: "500m" + perNodeServices: + apiService: + enabled: true + type: NodePort diff --git a/operator/Dockerfile.local b/operator/Dockerfile.local new file mode 100644 index 00000000..f1f226b9 --- /dev/null +++ b/operator/Dockerfile.local @@ -0,0 +1,25 @@ +# Dockerfile.local - Fast local image build using pre-built binary +# Usage: docker build -f Dockerfile.local -t datahaven:local . +# Prerequisite: cargo build --release (or --release --features fast-runtime) + +FROM docker.io/parity/base-bin:latest + +# Copy the pre-built binary from local target directory +COPY ./target/release/datahaven-node /usr/local/bin/datahaven-node + +# Make sure binary is executable +RUN chmod +x /usr/local/bin/datahaven-node + +USER root +RUN useradd -m -u 1001 -U -s /bin/sh -d /datahaven datahaven && \ + mkdir -p /data /datahaven/.local/share && \ + chown -R datahaven:datahaven /data && \ + ln -s /data /datahaven/.local/share/datahaven && \ + /usr/local/bin/datahaven-node --version + +USER datahaven + +EXPOSE 30333 9933 9944 9615 +VOLUME ["/data"] + +ENTRYPOINT ["/usr/local/bin/datahaven-node"] diff --git a/test/cli/handlers/deploy/index.ts b/test/cli/handlers/deploy/index.ts index c6fea896..ca88ce32 100644 --- a/test/cli/handlers/deploy/index.ts +++ b/test/cli/handlers/deploy/index.ts @@ -9,6 +9,7 @@ import { deployDataHavenSolochain } from "./datahaven"; import { deployKurtosis } from "./kurtosis"; import { setParametersFromCollection } from "./parameters"; import { deployRelayers } from "./relayer"; +import { deployStorageHubComponents } from "./storagehub"; import { performValidatorOperations } from "./validator"; // Non-optional properties determined by having default values @@ -39,6 +40,7 @@ export interface DeployOptions { skipValidatorOperations: boolean; skipSetParameters: boolean; skipRelayers: boolean; + skipStorageHub: boolean; } const deployFunction = async (options: DeployOptions, launchedNetwork: LaunchedNetwork) => { @@ -82,6 +84,8 @@ const deployFunction = async (options: DeployOptions, launchedNetwork: LaunchedN await deployRelayers(options, launchedNetwork); + await deployStorageHubComponents(options, launchedNetwork); + // Cleaning up the port forwarding for the validator. await validatorPortForwardCleanup(); diff --git a/test/cli/handlers/deploy/storagehub.ts b/test/cli/handlers/deploy/storagehub.ts new file mode 100644 index 00000000..9422268d --- /dev/null +++ b/test/cli/handlers/deploy/storagehub.ts @@ -0,0 +1,216 @@ +import path from "node:path"; +import { $ } from "bun"; +import invariant from "tiny-invariant"; +import { logger, printDivider, printHeader } from "utils"; +import { waitFor } from "utils/waits"; +import { isNetworkReady } from "../../../launcher/datahaven"; +import type { LaunchedNetwork } from "../../../launcher/types/launchedNetwork"; +import { forwardPort } from "../common/kubernetes"; +import type { DeployOptions } from "."; + +/** + * Deploys StorageHub components (MSP, BSP, Indexer, Fisherman nodes and databases) in a Kubernetes namespace. + * + * @param options - Configuration options for launching the network. + * @param launchedNetwork - An instance of LaunchedNetwork to track the network's state. + * @returns A promise that resolves when all StorageHub components are deployed. + */ +export const deployStorageHubComponents = async ( + options: DeployOptions, + launchedNetwork: LaunchedNetwork +): Promise => { + if (options.skipStorageHub) { + logger.info("🏳️ Skipping StorageHub components deployment"); + printDivider(); + return; + } + + printHeader("Deploying StorageHub Components"); + + invariant(options.datahavenImageTag, "❌ DataHaven image tag not defined"); + + if (!options.dockerUsername) { + await checkTagExists(options.datahavenImageTag); + } + + // Deploy StorageHub Indexer database first (Indexer PostgreSQL database) + await deployStorageHubDatabase(options, launchedNetwork); + + // Deploy StorageHub nodes (MSP, BSP, Indexer, Fisherman) + await deployStorageHubNodes(options, launchedNetwork); + + // Deploy StorageHub MSP Backend API + await deployStorageHubBackend(options, launchedNetwork); + + await registerStorageHubNodes(launchedNetwork); + + printDivider(); +}; + +/** + * Deploys StorageHub PostgreSQL databases for Indexer and Fisherman nodes. + */ +const deployStorageHubDatabase = async ( + options: DeployOptions, + launchedNetwork: LaunchedNetwork +): Promise => { + logger.info("🗄️ Deploying StorageHub PostgreSQL database..."); + + const deployDatabase = async (name: string, component: string) => { + const timeout = "3m"; + const args = [ + "upgrade", + "--install", + name, + "oci://registry-1.docker.io/bitnamicharts/postgresql", + "-f", + `environments/${options.environment}/${component}-db.yaml`, + "-n", + launchedNetwork.kubeNamespace, + "--wait", + "--timeout", + timeout + ]; + + logger.info(`📦 Deploying ${name} database...`); + logger.debug(await $`helm ${args}`.cwd(path.join(process.cwd(), "../deploy")).text()); + logger.success(`${name} database deployed successfully`); + }; + + // Deploy Indexer database + await deployDatabase("sh-indexer-db", "sh-idxnode"); +}; + +/** + * Deploys StorageHub nodes (MSP, BSP, Indexer, Fisherman). + */ +const deployStorageHubNodes = async ( + options: DeployOptions, + launchedNetwork: LaunchedNetwork +): Promise => { + logger.info("🚀 Deploying StorageHub nodes..."); + + const deployNode = async (name: string, component: string) => { + const timeout = "5m"; + const args = [ + "upgrade", + "--install", + name, + "charts/node", + "-f", + `charts/node/storagehub/${component}.yaml`, + "-f", + `environments/${options.environment}/${component}.yaml`, + "-n", + launchedNetwork.kubeNamespace, + "--wait", + "--timeout", + timeout + ]; + + logger.info(`🏗️ Deploying ${name}...`); + logger.debug(await $`helm ${args}`.cwd(path.join(process.cwd(), "../deploy")).text()); + logger.success(`${name} deployed successfully`); + }; + + // Deploy StorageHub nodes in dependency order + await deployNode("sh-mspnode", "sh-mspnode"); + await deployNode("sh-bspnode", "sh-bspnode"); + await deployNode("sh-idxnode", "sh-idxnode"); + await deployNode("sh-fisherman", "sh-fisherman"); +}; + +/** + * Deploys StorageHub MSP Backend API. + */ +const deployStorageHubBackend = async ( + options: DeployOptions, + launchedNetwork: LaunchedNetwork +): Promise => { + logger.info("🚀 Deploying StorageHub MSP Backend API..."); + + const timeout = "3m"; + const args = [ + "upgrade", + "--install", + "sh-mspbackend", + "charts/backend", + "-f", + "charts/backend/storagehub/sh-mspbackend.yaml", + "-f", + `environments/${options.environment}/sh-mspbackend.yaml`, + "-n", + launchedNetwork.kubeNamespace, + "--wait", + "--timeout", + timeout + ]; + + logger.debug(await $`helm ${args}`.cwd(path.join(process.cwd(), "../deploy")).text()); + logger.success("StorageHub MSP Backend API deployed successfully"); +}; + +/** + * Waits for StorageHub Indexer node to be ready and registers nodes in LaunchedNetwork. + */ +const registerStorageHubNodes = async (launchedNetwork: LaunchedNetwork): Promise => { + // Forward port from indexer node to localhost for health checks + const indexerPort = 9944; + const { cleanup: indexerPortForwardCleanup } = await forwardPort( + "sh-idxnode-0", + indexerPort, + indexerPort + 100, // Use different local port to avoid conflicts + launchedNetwork + ); + + // Wait for the StorageHub Indexer to start + logger.info("⌛️ Waiting for StorageHub Indexer to start..."); + const timeoutMs = 5000; // 5 second timeout + const delayMs = 5000; // 5 second delay between iterations + await waitFor({ + lambda: async () => { + logger.info(`📡 Checking if StorageHub Indexer is ready (timeout: ${timeoutMs / 1000}s)...`); + const isReady = await isNetworkReady(indexerPort + 100, timeoutMs); + if (!isReady) { + logger.info( + `⌛️ StorageHub Indexer not ready, waiting ${delayMs / 1000}s to check again...` + ); + } + return isReady; + }, + iterations: 12, // 12 iterations of 5 + 5 = 2 minutes + delay: delayMs, + errorMessage: "StorageHub Indexer not ready" + }); + + logger.success("StorageHub Indexer is ready"); + + // Clean up the port forwarding + await indexerPortForwardCleanup(); + + // Register StorageHub nodes in LaunchedNetwork + launchedNetwork.addContainer("sh-mspnode-0", { ws: 9944 }); + launchedNetwork.addContainer("sh-bspnode-0", { ws: 9944 }); + launchedNetwork.addContainer("sh-idxnode-0", { ws: 9944 }); + launchedNetwork.addContainer("sh-fisherman-0", { ws: 9944 }); + + logger.info("📝 StorageHub nodes successfully registered in launchedNetwork."); +}; + +/** + * Checks if an image exists in Docker Hub. + * + * @param tag - The tag of the image to check. + * @returns A promise that resolves when the image is found. + */ +const checkTagExists = async (tag: string) => { + const cleanTag = tag.trim(); + logger.debug(`Checking if image ${cleanTag} is available on Docker Hub`); + const result = await $`docker manifest inspect ${cleanTag}`.nothrow().quiet(); + invariant( + result.exitCode === 0, + `❌ Image ${tag} not found.\n Does this image exist?\n Are you logged and have access to the repository?` + ); + + logger.success(`Image ${cleanTag} found on Docker Hub`); +}; diff --git a/test/cli/handlers/launch/index.ts b/test/cli/handlers/launch/index.ts index 307fcabf..4d0e79a0 100644 --- a/test/cli/handlers/launch/index.ts +++ b/test/cli/handlers/launch/index.ts @@ -10,6 +10,7 @@ import { launchDataHavenSolochain } from "./datahaven"; import { launchKurtosis } from "./kurtosis"; import { setParametersFromCollection } from "./parameters"; import { launchRelayers } from "./relayer"; +import { launchStorageHubComponents } from "./storagehub"; import { performSummaryOperations } from "./summary"; import { performValidatorOperations } from "./validator"; @@ -44,6 +45,7 @@ export interface LaunchOptions { setParameters?: boolean; relayer?: boolean; relayerImageTag: string; + storagehub?: boolean; cleanNetwork?: boolean; } @@ -94,6 +96,8 @@ const launchFunction = async (options: LaunchOptions, launchedNetwork: LaunchedN await launchRelayers(options, launchedNetwork); + await launchStorageHubComponents(options, launchedNetwork); + await performSummaryOperations(options, launchedNetwork); const fullEnd = performance.now(); const fullMinutes = ((fullEnd - timeStart) / (1000 * 60)).toFixed(1); @@ -119,7 +123,8 @@ export const launchPreActionHook = ( buildDatahaven, launchKurtosis, relayer, - setParameters + setParameters, + storagehub } = thisCmd.opts(); // Check for conflicts with --all flag @@ -132,10 +137,11 @@ export const launchPreActionHook = ( fundValidators === false || setupValidators === false || setParameters === false || - relayer === false) + relayer === false || + storagehub === false) ) { thisCmd.error( - "--all cannot be used with --no-datahaven, --no-build-datahaven, --no-launch-kurtosis, --no-deploy-contracts, --no-fund-validators, --no-setup-validators, --no-update-validator-set, --no-set-parameters, or --no-relayer" + "--all cannot be used with --no-datahaven, --no-build-datahaven, --no-launch-kurtosis, --no-deploy-contracts, --no-fund-validators, --no-setup-validators, --no-update-validator-set, --no-set-parameters, --no-relayer, or --no-storagehub" ); } @@ -149,6 +155,7 @@ export const launchPreActionHook = ( thisCmd.setOptionValue("setupValidators", true); thisCmd.setOptionValue("setParameters", true); thisCmd.setOptionValue("relayer", true); + thisCmd.setOptionValue("storagehub", true); thisCmd.setOptionValue("cleanNetwork", true); } diff --git a/test/cli/handlers/launch/storagehub.ts b/test/cli/handlers/launch/storagehub.ts new file mode 100644 index 00000000..13d8ff46 --- /dev/null +++ b/test/cli/handlers/launch/storagehub.ts @@ -0,0 +1,36 @@ +import { logger, printHeader } from "utils"; +import type { LaunchedNetwork } from "../../../launcher/types/launchedNetwork"; +import { deployStorageHubComponents } from "../deploy/storagehub"; +import type { LaunchOptions } from "."; + +/** + * Launches StorageHub components by delegating to the deploy function. + * + * @param options - Launch options. + * @param launchedNetwork - The launched network instance. + * @returns A promise that resolves when StorageHub components are launched. + */ +export const launchStorageHubComponents = async ( + options: LaunchOptions, + launchedNetwork: LaunchedNetwork +): Promise => { + // Convert launch options to deploy options format + const deployOptions = { + environment: "local" as const, // Launch is typically used for local development + skipStorageHub: !options.storagehub, + datahavenImageTag: options.datahavenImageTag, + dockerUsername: undefined, + dockerPassword: undefined, + dockerEmail: undefined + }; + + printHeader("Launching StorageHub Components"); + logger.info( + "🚀 Launching StorageHub components (MSP, BSP, Indexer, Fisherman nodes and databases)..." + ); + + // Reuse the deploy StorageHub function + await deployStorageHubComponents(deployOptions as any, launchedNetwork); + + logger.success("StorageHub components launched successfully"); +}; diff --git a/test/cli/index.ts b/test/cli/index.ts index 68f708c8..c3f44174 100644 --- a/test/cli/index.ts +++ b/test/cli/index.ts @@ -49,7 +49,7 @@ program `🫎 DataHaven: Network Deployer CLI for deploying a full DataHaven network stack to a Kubernetes cluster It will deploy: - DataHaven solochain validators (all envs), - - Storage providers (all envs) (TODO), + - StorageHub components: MSP, BSP, Indexer, Fisherman nodes and databases (local & stagenet envs), - Kurtosis Ethereum private network (stagenet env), - Snowbridge Relayers (all envs) ` @@ -98,6 +98,11 @@ program .option("--skip-validator-operations", "Skip performing validator operations", false) .option("--skip-set-parameters", "Skip setting DataHaven runtime parameters", false) .option("--skip-relayers", "Skip deploying Snowbridge Relayers", false) + .option( + "--skip-storage-hub", + "Skip deploying StorageHub components (MSP, BSP, Indexer, Fisherman, databases)", + false + ) .hook("preAction", deployPreActionHook) .action(deploy); @@ -109,7 +114,7 @@ program `🫎 DataHaven: Network Launcher CLI for launching a full DataHaven network. Complete with: - Solo-chain validators, - - Storage providers (TODO), + - StorageHub components: MSP, BSP, Indexer, Fisherman nodes and databases, - Ethereum Private network, - Snowbridge Relayers ` From eced179b095a8c4128e104977cc09758089bb407 Mon Sep 17 00:00:00 2001 From: undercover-cactus Date: Wed, 22 Oct 2025 13:36:30 +0200 Subject: [PATCH 02/12] misc: simplify Dockerfile to speed up build (#216) This PR remove the `cargo chef` step used to build the docker image used in deployment. We noticed that `cargo chef` was adding more time to the build and that removing it was saving us 40min. Also in this PR, we removed the base image from parity which was really heavy and was filling the rest of the disk space. This broke the build. After some investigation it doesn't seem to add a lot to the build. It has been replace with the official rust image as a base to build our node. The image used to run the image has been replaced with `debian:trixie-slim`. In the end those changed **should not** break any of the current behavior and makes save a bit of CI time. --- .github/workflows/CI.yml | 2 +- contracts/src/DataHavenServiceManager.sol | 4 +- docker/datahaven-build.Dockerfile | 55 +++-------------------- 3 files changed, 8 insertions(+), 53 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 8f5b4925..d05c6cee 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -69,4 +69,4 @@ jobs: uses: ./.github/workflows/task-e2e.yml secrets: inherit with: - image-tag: ${{ needs.docker-build-ci.outputs.image-tag }} \ No newline at end of file + image-tag: ${{ needs.docker-build-ci.outputs.image-tag }} diff --git a/contracts/src/DataHavenServiceManager.sol b/contracts/src/DataHavenServiceManager.sol index 31445ca5..be5e695c 100644 --- a/contracts/src/DataHavenServiceManager.sol +++ b/contracts/src/DataHavenServiceManager.sol @@ -99,9 +99,7 @@ contract DataHavenServiceManager is ServiceManagerBase, IDataHavenServiceManager ) external payable onlyOwner { // Send the new validator set message to the Snowbridge Gateway bytes memory message = buildNewValidatorSetMessage(); - _snowbridgeGateway.v2_sendMessage{ - value: msg.value - }( + _snowbridgeGateway.v2_sendMessage{value: msg.value}( message, new bytes[](0), // No assets to send bytes(""), // No claimer diff --git a/docker/datahaven-build.Dockerfile b/docker/datahaven-build.Dockerfile index d93614ec..5fc55325 100644 --- a/docker/datahaven-build.Dockerfile +++ b/docker/datahaven-build.Dockerfile @@ -1,5 +1,5 @@ # --- Setup Build Environment --- -FROM docker.io/paritytech/ci-unified:bullseye-1.88.0 AS base +FROM rust:latest AS base ARG MOLD_VERSION=2.40.4 ARG PROTOC_VER=21.12 @@ -10,42 +10,18 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ xz-utils \ clang \ libpq-dev \ - && echo "Installing mold v${MOLD_VERSION}..." \ - && curl -Lo mold.tar.gz "https://github.com/rui314/mold/releases/download/v${MOLD_VERSION}/mold-${MOLD_VERSION}-x86_64-linux.tar.gz" \ - && tar -xf mold.tar.gz --strip-components=1 -C /usr/local \ - && rm mold.tar.gz \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* \ && echo "Installing protoc v${PROTOC_VER}..." \ && curl -Lo protoc.zip "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VER}/protoc-${PROTOC_VER}-linux-x86_64.zip" \ && unzip -q protoc.zip -d /usr/local/ \ - && rm protoc.zip \ - && echo "Installing sccache v${SCCACHE_VERSION}..." \ - && curl -Lo sccache.tar.gz "https://github.com/mozilla/sccache/releases/download/v${SCCACHE_VERSION}/sccache-v${SCCACHE_VERSION}-x86_64-unknown-linux-musl.tar.gz" \ - && tar -xf sccache.tar.gz --strip-components=1 -C /usr/local/bin sccache-v${SCCACHE_VERSION}-x86_64-unknown-linux-musl/sccache \ - && rm sccache.tar.gz - -RUN cargo install cargo-chef --version 0.1.72 --locked - -ENV RUSTC_WRAPPER=sccache \ - SCCACHE_DIR=/usr/local/sccache \ - SCCACHE_CACHE_SIZE=25G \ - RUSTFLAGS="-Clinker=clang -Clink-arg=-fuse-ld=/usr/local/bin/mold" - -# --- Prepare build plan with cargo-chef --- -FROM base AS planner -WORKDIR /datahaven -COPY . . -RUN cargo chef prepare --recipe-path recipe.json + && rm protoc.zip # --- Build dependencies using cargo-chef --- FROM base AS builder WORKDIR /datahaven -COPY --from=planner /datahaven/recipe.json recipe.json -RUN --mount=type=cache,target=/usr/local/cargo/registry \ - --mount=type=cache,target=/usr/local/cargo/git \ - cargo chef cook --recipe-path recipe.json --release -COPY . . + +COPY . /datahaven RUN --mount=type=cache,target=/usr/local/cargo/registry \ --mount=type=cache,target=/usr/local/cargo/git \ if [ "$FAST_RUNTIME" = "TRUE" ]; then \ @@ -55,30 +31,11 @@ RUN --mount=type=cache,target=/usr/local/cargo/registry \ fi # --- Create final lightweight runtime image --- -FROM docker.io/parity/base-bin:latest - -# Copy CA certificates and shared libraries from builder -COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt -COPY --from=builder \ - /lib/x86_64-linux-gnu/libpq.so.5 \ - /lib/x86_64-linux-gnu/libssl.so.3 \ - /lib/x86_64-linux-gnu/libcrypto.so.3 \ - /lib/x86_64-linux-gnu/libgssapi_krb5.so.2 \ - /lib/x86_64-linux-gnu/libldap.so.2 \ - /lib/x86_64-linux-gnu/libz.so.1 \ - /lib/x86_64-linux-gnu/libzstd.so.1 \ - /lib/x86_64-linux-gnu/libkrb5.so.3 \ - /lib/x86_64-linux-gnu/libk5crypto.so.3 \ - /lib/x86_64-linux-gnu/libcom_err.so.2 \ - /lib/x86_64-linux-gnu/libkrb5support.so.0 \ - /lib/x86_64-linux-gnu/liblber.so.2 \ - /lib/x86_64-linux-gnu/libsasl2.so.2 \ - /lib/x86_64-linux-gnu/libkeyutils.so.1 \ - /lib/x86_64-linux-gnu/ - +FROM debian:trixie-slim COPY --from=builder /datahaven/target/release/datahaven-node /usr/local/bin USER root +RUN apt-get update && apt-get install -y gcc libc6-dev libpq-dev && rm -rf /var/lib/apt/lists/* RUN useradd -m -u 1001 -U -s /bin/sh -d /datahaven datahaven && \ mkdir -p /data /datahaven/.local/share && \ chown -R datahaven:datahaven /data && \ From 22d7ee4b943b45fa406053b383e7aaff4c6be114 Mon Sep 17 00:00:00 2001 From: Steve Degosserie <723552+stiiifff@users.noreply.github.com> Date: Thu, 23 Oct 2025 13:35:23 +0300 Subject: [PATCH 03/12] =?UTF-8?q?fix:=20=F0=9F=94=A7=20Bump=20SH=20storage?= =?UTF-8?q?=20providers=20pallet's=20MaxMultiAddressSize=20parameter=20to?= =?UTF-8?q?=20200=20(#244)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../mainnet/src/configs/storagehub/mod.rs | 2 +- .../stagenet/src/configs/storagehub/mod.rs | 2 +- .../testnet/src/configs/storagehub/mod.rs | 2 +- test/.papi/metadata/datahaven.scale | Bin 617005 -> 617151 bytes 4 files changed, 3 insertions(+), 3 deletions(-) diff --git a/operator/runtime/mainnet/src/configs/storagehub/mod.rs b/operator/runtime/mainnet/src/configs/storagehub/mod.rs index f2bf1bb3..3c15214d 100644 --- a/operator/runtime/mainnet/src/configs/storagehub/mod.rs +++ b/operator/runtime/mainnet/src/configs/storagehub/mod.rs @@ -184,7 +184,7 @@ impl pallet_storage_providers::Config for Runtime { type SpMinCapacity = ConstU64<2>; type DepositPerData = ConstU128<2>; type MaxFileSize = ConstU64<{ u64::MAX }>; - type MaxMultiAddressSize = ConstU32<100>; + type MaxMultiAddressSize = ConstU32<200>; type MaxMultiAddressAmount = ConstU32<5>; type MaxProtocols = ConstU32<100>; type BucketDeposit = BucketDeposit; diff --git a/operator/runtime/stagenet/src/configs/storagehub/mod.rs b/operator/runtime/stagenet/src/configs/storagehub/mod.rs index f2bf1bb3..3c15214d 100644 --- a/operator/runtime/stagenet/src/configs/storagehub/mod.rs +++ b/operator/runtime/stagenet/src/configs/storagehub/mod.rs @@ -184,7 +184,7 @@ impl pallet_storage_providers::Config for Runtime { type SpMinCapacity = ConstU64<2>; type DepositPerData = ConstU128<2>; type MaxFileSize = ConstU64<{ u64::MAX }>; - type MaxMultiAddressSize = ConstU32<100>; + type MaxMultiAddressSize = ConstU32<200>; type MaxMultiAddressAmount = ConstU32<5>; type MaxProtocols = ConstU32<100>; type BucketDeposit = BucketDeposit; diff --git a/operator/runtime/testnet/src/configs/storagehub/mod.rs b/operator/runtime/testnet/src/configs/storagehub/mod.rs index f2bf1bb3..3c15214d 100644 --- a/operator/runtime/testnet/src/configs/storagehub/mod.rs +++ b/operator/runtime/testnet/src/configs/storagehub/mod.rs @@ -184,7 +184,7 @@ impl pallet_storage_providers::Config for Runtime { type SpMinCapacity = ConstU64<2>; type DepositPerData = ConstU128<2>; type MaxFileSize = ConstU64<{ u64::MAX }>; - type MaxMultiAddressSize = ConstU32<100>; + type MaxMultiAddressSize = ConstU32<200>; type MaxMultiAddressAmount = ConstU32<5>; type MaxProtocols = ConstU32<100>; type BucketDeposit = BucketDeposit; diff --git a/test/.papi/metadata/datahaven.scale b/test/.papi/metadata/datahaven.scale index e3e44a66f6b433620b4d06fe9f8d97a8cfb2ac7e..2c9e630da36eb7ca594bd4dff43394b544130262 100644 GIT binary patch delta 14751 zcmaib3s_ZE_W0S4bMHC#p`f6=1qB2J1qGD^6%~sNc^HA%InW5CO z8?GF6iuySd78wSMxE%5GCJ)wwu$P5Hsd8mDxVo$oYvRm^=|516KsA=eY8W#ppk zqG$o|bWVp_l7tu^3+(qPISCl1` zWVu#Y<|?^HQd(gvEp_Eu0$lf7Ldbg8aZ4WGWJGzK&#~#Qnbvr2Gm;l!m&U?f+pS^5 z?gDE9aX#~!_4zwU!!r#Hsf0ARe14bm%(uVs(;pw#8(f!vcc`Ju$JO@WM%UqoW2kI!RXniS71~?8)ANr^id}l?eou z(qQfQ8u~FM`@zS-vtcloMv*2k=h5lp2+YZ&?~rCqT}w4iPD0mBG=}uTg`4PSI=mlz zdNbWgPHH9VDfZ!{HgpU94;k|=4_0iZQ}M+uo9Rpg>4U>tX^H3kb9Q=&csCue(`#UD zF`bVXzb&Rkg5+lo>Q7;9DNQGPp|X+&3#k_%joebY0!76lF|<+UYbA+G2W1kl&R&>$ z;}QvD&5eBz`tVq0V$kX=#ZC@G>Gz=zI(xv1qWLMG%c%zDjz@AFF4@XSs$iLmA zqqZ?R>H}L9-R##dlcZISQhRoVy~-x~E=m2mz@G~$mv+(saNfm?T5L64PRO8ET0`GA z@<6cluxRZvXM8DoiW62OaxsygsACh_a@*At{_AFb4!dH_dzK&d!af~jZ#L~qd zQPo{EgmggkE;`>&yrP$734an-k`R1YhCkfRf*|vHV%F~8MQiKi%|Bb5)HrYa@z+J$H79!e6mJ2ZL|BPrVHztE*JNz*32NPP^%UkiVQE-?~c z4Jk}ElXMt(hD92PWt+V&10p`4(;%&%#%hD-=mh>VZ#8_|LA_sSh_;NgOap-j%`8G| z_=vt|C81i;SAuhv_J3c~OhVQ}`uB9M7CKC4$Yi~Sl|V}D?YFRflsL2tlzk_>H{ z;9HrkApU@oPJw&_n@vKY-oWN#ll!&LF>VbBG~l=-kd-USOH1vAVgjtS*VH)5iX|yf z2QwJiF2r=BJZNOgNCfm5+5MBF3?w15#_sgMS4&ca4s^f5vPje@k14S_kGL_=k`${0 z+;@!2kf5>*60bMht+M>sM8nvnm~0rg6q60^rI@VagqYZ^Bt?IAnOH#3c-hhrf%-`4 z0>~fUF)=&I5YuJ_$<*;sTffUMLAWDLis22h7%Lw*@ zr4Gg5NGut{wdkpxU?V1Ns=X_stRqc=%Iv7F5(*ig^_FqTIJtHGT}#BMR5?`jAV0s z5Jw@A73I}61&*?<<@>=mibc>P1}J@l1i%eZY#nKaN2Ay;u$UIjVv~*f2pRez!*XQVVjz*?jk}7>QO?`#RW)4dfSu7SU{a^&{VH3HtyE$X+WS97vz2J- zKaFP3lU8_aCfk5!o5i3aS|J9D&^80NtSG-jSp9Y}Rq;=9|H%}|qCf#qAH)36N*{<} zHzBFdW7yQ7HiK9-ccjj&u0g|D7#Ch$Q?*2J?1E{rY!>>j>tos51a0H=*=!9unabJh z2hyWe#<9%=P4$_0mP>lI>2ug!l=d26x0NPBZvtC_j?piXC14@U+LV6JWE}W$GNOsr z!L`mrc9vKMP+r<^kOmEwEg~?2>RZ?(?dAFGaZZM`ibZG^*+qi|Y%94x{QepSRz+0!U^gzs ziEl6??6`$(!|>$eTNqkPJsvTISJ>@U1&*TXCRnqDJwZCPZ?~}PJ>klHs4HY&p&c(R z!j&ATy-~z&=eqw3*BlPkE<%xM+t|O*ezH==Mj{g}*vXbzNuRcH2m6>)s}a)8EFs3% zs4sYbY@#pq1%`2eL+I-P)657+oHTw_P*fvu5U9~>`O#~P(XQ6?KD{0aA% zVw6(gl}21|X>g&Dg$1V@$#pkYIqZ3MXZh{+tXeT8(U;@mOoJJBqs>o;o9;#H}*kpiqb~A!~+0N?7ChfN8*hE5X+76AqNr)ZRbg=)S1I+jf zdk-CAIGj#hNZ3APcf=pj)wz&9sYG;J^n8|dmJ{)-xol7$46l~*}!rHw|yZ2%g1oqjnLlBY(In02eGd+8|~M7 zG=IR;|G_a`8gTbN!ABYteZ$(2(Gn-Noc5Z6TWz-Q?C;D)=*2Or^uOdGH9UsY zB^c;of$+mAw%UBzNJ8@Lw(9b-YIv`Q1w%y-n{FBwJT4iftGYmN??0F_K~_dB98p~5 zWGW2zu#Kv$ATUuR6@1@gQ(QTVgZ-_FJ|>A{P^^&fCQA(PRYI2AN^NC@b`pTDU2zoo z;(ullEc*xZ$MEysH(4lzpT_y*59z1b0ul(PPP0^Ky~?Me<;3SK9--i#JUtsDm*g`n zgheR?Y@hMTP<)1k^H_!a4ldn^fot;_7KE|k^Jmc5`NIciSP~6XT#4I*AmJ>Fp`l}* zBNX9Yf`lhC!ilr&8XBd*z;29$(aB_!SSWadT}$H?ck~3qXV?Td{RW$)CW^jW6)D-> zcX(=mh4^{;o<64UDSF@2#`QgIOyAQ)-;+)0f@F#!Whky}{~+y?H`!8#k!H->tYUH& zzT?V$sZy@{A<0L||554gO$-{jkwMVwo8T|!SQzA>9%CB%uz$*{MkQLoQM>l`7p&wMwc~3v1uOZ9tv2`yEzD$S%R=8VEhljG^^oI$AGC zJSH``@q8q-OzG#@VGIu6JI@ZFU#;zDMQABoU>5;Sfg2er-bv8xpA#>N4bhGCrO zfY9U&|D$6l9~G2SC>o4U2G~aw1F)Wt*dJ({;tKz4D*Sp71Htwm`<~X}8HBDe6tHc~ zCcP6i|C3F6C$d0m&?za>m^?LC_;GgmmkjSeK=3HROLH!62mtR(8udGD_V=qFfF)rL@ zuNi<{7ci_Fgy%1?)wEx6k!hh2{V7|LFrc&QSENBNUIXKK2~Yw{zhFsl-|xsIa#5^> zK<&SuvfUKpxSG$|CUP0x_?(qvF*1GT4SQ60b&Lv!-AsMzFjB)OidCYDxe_3&lB~J| zB7HBd>XkIB>WPljQQLuSW5&T(9j6;#q=~xmg>_%DUzz-|My;w8=q9-wZ9w!T4EZA9 z{!6SNAW9`GF(-1nqsU&B>M<-hv!g)$iWOU8g>)9lCrXv#wVhwF45KO0EwHo*m+aq% z*`ILlSA7MILCP5EajX8p6}Fkvbk)^XFa_5AfRif&T7O`TG*gH3^U?d2HYT#pYTC&^ zC%LeV@DMD1hwhu^tFHQjF!+veA6%MN%4g9{s_R=@5a7DDXa$tdW)_=UB)b|Q*>&pv z4v*TLW7Ot=cV)ic&neX5P^C&YQY|9YdXVZoNV~=$)xk*vzf;{Mkm^*aUc14_GbwFQ z;l+9q1Z^s>0ZcPo3#BIBO82X19Ycg@R&Ax3zd&h|M=c_5r3Zid+H%A#gw#Q#W)*jY z)8H0gzJ?ryW4^fW>x3_T`8;}5f3so|UxxdiUr*xK;X>`1#HV5Y=HetCNn3OtF|8i? z+s4S>>So|`mPl=)3s`Lzfb38n zix_pGd^)Df4u|q+s18G)bv~3|OZwr4Fg`POz-w&{j$d1Y*h5@fgHRL3YvvDmfnOXC zeo+S(1y_8|Ntbjrrd;-@ad?axFY7=7(l9<%KEBpJwbbks17$Ke3I zJdK}-P))>dMJ>jr80$J6Wd+r>6&2-GHKWb&Lj?DSj&OcDz-l7ls~p?yMVSkdFsR*L zP`-6*wY|m)4@dARlf2$iNwS(?-~UK(*eD9dp}r*NC7LiTRWp-6h8d~Q7#=Vy7A0L?T3+r%`+`vPq(O=`DdF~-l3PXV$U82@ zLqQDpx5Oh56WUg!M7S#kM=u$U#qbC$PQ~CLCc_soI9rlIjpZArjZ!B*rRBxdQ6>^D zveGw{7o$N-fnUb*nM=}4B;Y!`4UL^d5^Ab!W!0GQ#qC;k2EOp*ut`9<(`m1&&NPuY z(WJv8jWqaoEPoP%nFF)<0aH3E;yR&-bXYK(&z_zkx}k_mTscURB%8K7j&GpUZi3^VkVyDp4qt+MsU>rHK5@bWbNQ0U zN)wvu+FMH#;Q*RgVEW@?bTLOvaN=Xscz7x=Gc{v3=uwk& z)TAecx>Nb}Xm$P4_)^+pay#fLttQ=fwT(_0snr92Dve*Owh1DwCaE2om!OeZzJzZ^ zTaC|s$nzIV`P*pP*DmAN@-CAnYxLYQejKw^Thn<1J84qjE-Q_K$;Oy%O@-Ssc#gRbo48_^ zeelG=-FiNQ?<51Teie_S1MYq0^a;`cL1$l}wX>3THX7vY8L`2zTxXqd8^ zC-F-rvIS1>R{WuGHTv$$aMx-+3nQaM+-hj2R`Vi)ZCJ@8!|>}Y9_`6jQE6BQ8O-80 z6KoXlP>{{PH4(EAFeynGynA?J81ZbwRP&F^R8kQJlU$P3?B085xc9hsD)lvseMd0V zm2eR-a%u>7uE1{JCnkITGXG(cJP4-lrPHxvl^n-spaiOO` zS{dJf1+rL4)7)V09h4C|m*KqS<$P1HHQgKtu3MJq=u2DosD-$rZQEz`8x!~C>~ z)|uh=hj1TjdXbwn=bv~Rp}SBUA{8~ig}3|H3qBZ^`bZ6Kj*^em=zbrLTcxmLd@9}R z0l)qjPo(=j6+H2nKB37RnO;$WA+N2p8Z$62Vq5elw~ ze9_|J5cC8up{a8v7N zoo1=i1NB5J-)8P|w+FNk+>d!pg0R`$KOOz<5xH?Xh|E0Fmky)EJsyIOKFQO_CKz}U z=jwV$Jbk(EQvqbV3vl=;v8nS7WO>vz#NTPWD*fC1>X-OoAL{D?p>JXk<_~k<IPtAGkQ3zL zSO3JICLaEXg@3YzEE2&-#&&d)Wz~*CoKNx4|4+WvfZgO65M}oARhZ*O%)&|Trc|Vq zY(Z_sTQJ;_-$Kuo203r>*mdcau@*1QGS1?qAsP;I2EvUVKApimNG8I%&z{Z*IrXEb zOdU8APQQhFkt_&!8^z9r#cyLQmL(de!yRw)53$Mpyz?B-#(eUrb36)X%U9>nGpvWu zJ{}OT2?B}{%{%ivQ)_qS$#Zja=rx*Im=4yRra!)m3X9tMnxz1&py5&!RaMx zrDd$Fm4dFfu$4OM#&`Hri)+2KQ8!*2b%>AJ5Cz?3k?@C-rPeA^JzV=Pug1XpukZ4$ zxRscG9$lNewhDUAb0h0B5=eWU1;#dd@z^__$6lSsUI^^xsptgO^`m;4U}rxL*Fi7j zrt!#4I`R=O9VDR&nn#8U!_pBAH0!|4u;qP@&g4D**zTiVhzVm66UHI7cmcNxP5;QI z6>0y3k7(jbo2A1dwc#Uew@B?4Wo30mfzw%4P*LS@I-vZ0Jb7OHK99t(2&Gzp@esVv z(>HYrgaoO}i{rCn89qCX-$?`>y*ko8URm8p6i2fgl0U#5^ijC|16=z(7FXtlm9)v? zy7$6rQJlXJ3Hv|fk#Oe#cjET)vjJQ_eX#IDJ})Q> zgX3`qb(}$1{xANU%|qk5+&*&ZJEqIxbQHUC(TlbK{7J;;fx9HsiO-iI`Xhb~#$L9M z_{=$1y;u<|s<+g$$cc4Sy`^qe1a^MRLw!>vKN4rhv)_U$cdok`KKh792Fq3wl3#5v zy4F@Lk+?hDhb8V~X4MLxe$0b?qD*7=V6qj~4D!XXs&(v;S*_#bx1t=_Pb)k<$Y&B8 zgnZ0H45c`8YHaY`AZ9+?O%Y3NKTXK`BIQv7=0CP?{^R=QFZwnI6Q+-U%%lFlecA2Z zmq4#Rq>PWcQ}n1i)C(?aJe=4jVqYV?;Bv>q?H2n;1dPIda7&;y)EZ%xV!g2P$LAmN zF@=Cg@d8N+6ex*^GOD6*9Q|Y*0Jn_~A07Q$Hn}{uZazJ3JJ3wS0wduS8h)AFZ`Y_`{(~ z!WVU3jCKj_)sJx6B~UyruU==h%gsuA^CE6qNWIQ?))#zjVuKf*!$_uagp7#tJX9KW zDvegfa~kyW7yOkud%bYQ(C;6?9W(U%b=>{1?>}e{-~E!8B{X><#v2jy;0UHTX&+&G zP)9weqaMD*cg#8Bh3a;5BbZ|p+^i!u>xji)@q#%=y%2@4EhC6ygl*9gTXe*!|KXW) zTE`)_{S0E8j)?aV|HF@jwR_=QG9kB)5u{5d;Fme3p#IBKZ|+3EQHO>1Jbr4uaZ4-K zY?l|oS{VtR93fbXSM^3Tc2XDPBn*7RXF}R#p6%D|h1$#zwFe%)%>9%e9k@pa{?}!m zKIg0#um}cvN7#%B26}bGULCRSe>`VS-#EnnpF!-`5&Lz-u&;S;$bc837?;5jL?1}~ z1{L-4*Zjr>Lx_pjT%?O$-~kAJX#_lAR1KGOK6o}O)KL2kPffV&h3H<-!y}ku*YmKB zIxJ9~iC4#CkqI6PITnjx<_m|3On}|PxPg@?xZ`@)Qm%r}6+EtJfru-ZvK)fdS8$(@ z0o$+eYq(t@kBJM-n1H{+#htOwukg8e1uX1a+?*VQ>~9gY1$K&}4O&EFH@x#LPsE&y zA7@x*`pI}9x&sFN<@KaXTRKG!;wZ(2AbE$O&&VYOlhHvkZXbi>Uyy#S zDp)=wu69ibmoFPoE&(roF_NSc(5G4NS-3DB`!>n zAH`#}cT?n9qPvF0at`+Xrp2O5yWn)1+(8<&#wGI2WLl%5N|^n{D=rl_kp^}@g!rw+ zdr5X8?LDvzmAzlPW|_Q0WJ=pt$Uc-FR9yGU{%}4+UPF#(vscM)GmMMa^|BK$qE}uo zr^%#6JDx4yNm#4$6bw)~4mRe>>7%t%x$-+WW&f0iTX<{bVu~~P>3lgF z0@lg1fUd*-^g-Y{Ib~w5GNf=^Km(L~AfYO4>*Sd@#Et9ZenRn%TFK4w-zgr1Ca;%2 zV1a5V1Z_#P{(Pt0L~(7dsmEOBS@^hKUV&Pe^-K9H zj+gyHe=9#qamjWyB66ca!e#qiqdXsT3<-D3Eto2N=WeWJ!GwF{bevl`_sE;&BM6oc z&)g#~4O?$Q4X36T7M5eSVJ%*Hvf&LJLKI3jnUd}jazv;knUgL=v1!-rk?|g#UAucP zt_9g)%6nA)?WKLPc4?pCR0({LEt}wluMG=-{>_;!%GnH{MX_6i8xkigg@Jq zW5TQ?9tzZU-KxwGHvpOomFH0*n~RiXIKLh$Qt(rVcKA)P5<$*tj}D!b);4S>JZA!2_gwl4yzHQ1pB-XV}d4%GbSW~_4W~W5TUl&k#C%ozvQe2z@UkXe&otkoe8H$}*1p@PRB&tUOW1jk}qyKetS&$5N*zTk1K_Qsm6`a zH&LzCI$D*BzGyQ3bV5N38KwDjDKi+Zilmp7jTBeK{#TS|D9O|^y75v3UOeo3UHLyw za^w(kNC(Y zQzI62p&VFizEO%7 zgVG2KC#z0*KQiR7c(R%d?@d;N(9#c2R+I3a%N##-HfuL`z(zlHK2D+g{L~aYN_pK+ z?ZxTyu)ms$qtWlLCg5tCFhva%pZDZyv!|$N=+DBdL24petl=Pa4Ql1OVEk4J4~y># zQ7h3*e-)x`C5qEPY$)ZBwk1q8;Fm{GJWV|zz6i2wv%=Lm9BteBNHq$(u{%;t5?=>7 zL5o!P?7n0!!Ek?o)U(Ux$m>>=*bBGeXD=Jbsx0zxsK7vKQ z#SS&I)Qf%&i&C>a-V%cc!G+rjN|1AsQ>&e=o@W>zI^^)}+_7DFy)u_P#jzJH1q0 zfVm*UGBul~;Vu3g_k^ihroJ+v&Ekir1La#gEL|4A|H3=V)gWz4y1I>+$Gp+rTCScT zIJpk2RPlo)_;jV(%`p}AXUHi~{oquFTJGk%WR-dw4d}6?;>Rfk<#&|fwQ4tUl*tmF z2I;HRIPJ6R)I-$ZZrP-_bgWiWJ<|T3X!m8SI|#~d&P8o2@fJ&|z0Bt zMS}fn)iBtTr>+-HBo9$~HQQSJzK;xOzrIm5V+r@=t8r)vJM-0<<{?XrorEv1b(9u? z&&_IpW?ZM9CTKt3zDX@$=z$jAq8`C>JFR!4dV#QE%T;)3vwFM#u*KIZB^B0IiM(uq zd%UDT$SP3hqEFgYpr&z5WgOPk@J4|e9)byrW%iLQcEMIhX^p*#TejC!C*!1;utnX3 z6RC8I`U*?7#B0em^&bR%IxkdLplQ3V&^^KG3)N*fqh1n4KCmJ+9-Vb!k(!2=kIReH z8MvNYML6l4aH0s;XB~W9q~_t=xZbW_#5i!#R&^d0+qSBiVNF))x?;TYSy&=YD9VcM z1=aYK1NRZv#e9yy8(VRm9))kVs;6*NPZq0ln{*8w2EKd4lx+ E0D(DHYXATM delta 14808 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 From 06574a4cf878dfb1b71c5788f08a2105a1d08518 Mon Sep 17 00:00:00 2001 From: Steve Degosserie <723552+stiiifff@users.noreply.github.com> Date: Thu, 23 Oct 2025 14:14:30 +0300 Subject: [PATCH 04/12] =?UTF-8?q?fix:=20=F0=9F=94=A7=20Lower=20StorageHub?= =?UTF-8?q?=20replication=20targets=20for=20the=20Testnet=20environment=20?= =?UTF-8?q?(#245)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We initially use the same values as for Stagenet. --- operator/runtime/testnet/src/configs/runtime_params.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/operator/runtime/testnet/src/configs/runtime_params.rs b/operator/runtime/testnet/src/configs/runtime_params.rs index ac0c23b8..1a48f2fc 100644 --- a/operator/runtime/testnet/src/configs/runtime_params.rs +++ b/operator/runtime/testnet/src/configs/runtime_params.rs @@ -205,7 +205,7 @@ pub mod dynamic_params { /// volunteered BSPs is ~1%. #[codec(index = 23)] #[allow(non_upper_case_globals)] - pub static BasicReplicationTarget: ReplicationTargetType = 7; + pub static BasicReplicationTarget: ReplicationTargetType = 1; /// The amount of BSPs that a standard security storage request should use as the replication target. /// @@ -214,7 +214,7 @@ pub mod dynamic_params { /// volunteered BSPs is ~0.1%. #[codec(index = 24)] #[allow(non_upper_case_globals)] - pub static StandardReplicationTarget: ReplicationTargetType = 12; + pub static StandardReplicationTarget: ReplicationTargetType = 2; /// The amount of BSPs that a high security storage request should use as the replication target. /// @@ -223,7 +223,7 @@ pub mod dynamic_params { /// volunteered BSPs is ~0.01%. #[codec(index = 25)] #[allow(non_upper_case_globals)] - pub static HighSecurityReplicationTarget: ReplicationTargetType = 17; + pub static HighSecurityReplicationTarget: ReplicationTargetType = 3; /// The amount of BSPs that a super high security storage request should use as the replication target. /// @@ -232,7 +232,7 @@ pub mod dynamic_params { /// volunteered BSPs is ~0.001%. #[codec(index = 26)] #[allow(non_upper_case_globals)] - pub static SuperHighSecurityReplicationTarget: ReplicationTargetType = 22; + pub static SuperHighSecurityReplicationTarget: ReplicationTargetType = 4; /// The amount of BSPs that an ultra high security storage request should use as the replication target. /// @@ -241,7 +241,7 @@ pub mod dynamic_params { /// volunteered BSPs is ~0.0001%. #[codec(index = 27)] #[allow(non_upper_case_globals)] - pub static UltraHighSecurityReplicationTarget: ReplicationTargetType = 26; + pub static UltraHighSecurityReplicationTarget: ReplicationTargetType = 5; /// The maximum amount of BSPs that a user can require a storage request to use as the replication target. /// From 908a2a7ed58f8dd6e90adf2bcbca75fa10f53aff Mon Sep 17 00:00:00 2001 From: undercover-cactus Date: Thu, 23 Oct 2025 16:02:36 +0200 Subject: [PATCH 05/12] ci: remove unused volumes after e2e tests and remove logs collection (#246) In this PR, we fix the ci error indicating we reached the number of volumes allow by deleting automatically after tests the volumes. We also remove the step that collect logs because the container that are interesting to us to debug are being removed entirely. Therefore the logs from the nodes are not being collected in this step. --- .github/workflows/task-e2e.yml | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) diff --git a/.github/workflows/task-e2e.yml b/.github/workflows/task-e2e.yml index c3037945..135835fe 100644 --- a/.github/workflows/task-e2e.yml +++ b/.github/workflows/task-e2e.yml @@ -139,16 +139,6 @@ jobs: - name: Run E2E tests run: bun test:e2e - # Try to collect all docker logs and upload it - - name: Collect docker logs + - name: Delete volumes not used if: always() - run: | - mkdir ./logs - for name in `docker ps -a --format '{{.Names}}'`; do docker logs $name > ./logs/$name.log 2>&1; done - - name: Upload logs to GitHub - if: always() - uses: actions/upload-artifact@v4 - with: - name: logs - path: logs/ - retention-days: 1 + run: podman system prune --volumes -f \ No newline at end of file From 4eca4675148029fb5d8f68e1992610ab6fdb30b2 Mon Sep 17 00:00:00 2001 From: undercover-cactus Date: Thu, 23 Oct 2025 16:33:27 +0200 Subject: [PATCH 06/12] ci: pin forge version when installing it (#243) In this PR, we pin the forge version use in the linter task. When forge make a new release it brokes the linter task. In the future we can update the forge version explicitly. --------- Co-authored-by: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com> --- .github/workflows/task-foundry-tests.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/task-foundry-tests.yml b/.github/workflows/task-foundry-tests.yml index 41fffc94..a988d8fe 100644 --- a/.github/workflows/task-foundry-tests.yml +++ b/.github/workflows/task-foundry-tests.yml @@ -31,6 +31,8 @@ jobs: - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 + with: + version: v1.4.3 - name: Cache Foundry libraries uses: actions/cache@v4 From 48f8add3c489f13fc11c9b083ac3fc3bf1f0d6f0 Mon Sep 17 00:00:00 2001 From: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com> Date: Fri, 24 Oct 2025 12:31:17 +0200 Subject: [PATCH 07/12] ci: fix fetch submodule (#248) This PR fixes the E2E checkout failure by fetching full history instead of a depth-1 clone so the Snowbridge forge-std submodule can resolve its pinned commit. --- .github/workflows/task-e2e.yml | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/.github/workflows/task-e2e.yml b/.github/workflows/task-e2e.yml index 135835fe..ec5856a9 100644 --- a/.github/workflows/task-e2e.yml +++ b/.github/workflows/task-e2e.yml @@ -46,6 +46,7 @@ jobs: - uses: actions/checkout@v4 with: submodules: recursive + fetch-depth: 0 - uses: oven-sh/setup-bun@v2 - name: Install Foundry uses: foundry-rs/foundry-toolchain@v1 @@ -129,16 +130,16 @@ jobs: chmod +x tmp/bin/snowbridge-relay docker rm -fv temp tmp/bin/snowbridge-relay --help - - - name: Pull DataHaven node image + + - name: Pull DataHaven node image run: | docker pull ghcr.io/datahaven-xyz/datahaven/datahaven:${{ inputs.image-tag }} docker tag ghcr.io/datahaven-xyz/datahaven/datahaven:${{ inputs.image-tag }} datahavenxyz/datahaven:local - + - run: bun install - name: Run E2E tests run: bun test:e2e - + - name: Delete volumes not used if: always() - run: podman system prune --volumes -f \ No newline at end of file + run: podman system prune --volumes -f From 911aca1c6f41dd6803e50149c01fa70b1399d119 Mon Sep 17 00:00:00 2001 From: Ahmad Kaouk <56095276+ahmadkaouk@users.noreply.github.com> Date: Fri, 24 Oct 2025 15:07:30 +0200 Subject: [PATCH 08/12] test: remove redundant E2E test suites (#247) Remove 4 test suites that only tested basic infrastructure/connectivity: - cross-chain.test.ts: Only basic chain queries, no actual cross-chain testing - ethereum-basic.test.ts: Tests Ethereum RPC itself, not DataHaven features - contracts.test.ts: Trivial deployment address checks - datahaven-substrate.test.ts: Redundant Substrate RPC connectivity tests Keep 3 comprehensive test suites covering core DataHaven functionality: - validator-set-update.test.ts: Validator onboarding and cross-chain updates - native-token-transfer.test.ts: Bidirectional token bridging - rewards-message.test.ts: Era transitions and reward distribution --- test/suites/contracts.test.ts | 105 -------------- test/suites/cross-chain.test.ts | 108 --------------- test/suites/datahaven-substrate.test.ts | 93 ------------- test/suites/ethereum-basic.test.ts | 173 ------------------------ 4 files changed, 479 deletions(-) delete mode 100644 test/suites/contracts.test.ts delete mode 100644 test/suites/cross-chain.test.ts delete mode 100644 test/suites/datahaven-substrate.test.ts delete mode 100644 test/suites/ethereum-basic.test.ts diff --git a/test/suites/contracts.test.ts b/test/suites/contracts.test.ts deleted file mode 100644 index 68324ddd..00000000 --- a/test/suites/contracts.test.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { describe, expect, it } from "bun:test"; -import { logger, parseDeploymentsFile } from "utils"; -import { BaseTestSuite } from "../framework"; - -class ContractsTestSuite extends BaseTestSuite { - constructor() { - super({ - suiteName: "contracts" - }); - - this.setupHooks(); - } -} - -// Create the test suite instance -const suite = new ContractsTestSuite(); - -describe("Smart Contract Interactions", () => { - it("should query contract deployment addresses", async () => { - const _connectors = suite.getTestConnectors(); - const deployments = await parseDeploymentsFile(); - - // Check that we have basic contract addresses - expect(deployments.BeefyClient).toBeDefined(); - expect(deployments.Gateway).toBeDefined(); - expect(deployments.ServiceManager).toBeDefined(); - - logger.info(`BeefyClient deployed at: ${deployments.BeefyClient}`); - logger.info(`Gateway deployed at: ${deployments.Gateway}`); - logger.info(`ServiceManager deployed at: ${deployments.ServiceManager}`); - }); - - it("should check contract code exists", async () => { - const connectors = suite.getTestConnectors(); - const deployments = await parseDeploymentsFile(); - - // Get deployment transaction receipt for BeefyClient - const code = await connectors.publicClient.getCode({ - address: deployments.BeefyClient as `0x${string}` - }); - - expect(code).toBeDefined(); - expect(code?.length).toBeGreaterThan(2); // More than just "0x" - - logger.info(`BeefyClient contract code size: ${code?.length} bytes`); - }); - - it("should check contract balances", async () => { - const connectors = suite.getTestConnectors(); - const deployments = await parseDeploymentsFile(); - - // Check ETH balance of contracts - const beefyBalance = await connectors.publicClient.getBalance({ - address: deployments.BeefyClient as `0x${string}` - }); - - const serviceManagerBalance = await connectors.publicClient.getBalance({ - address: deployments.ServiceManager as `0x${string}` - }); - - logger.info(`BeefyClient ETH balance: ${beefyBalance}`); - logger.info(`ServiceManager ETH balance: ${serviceManagerBalance}`); - - // Contracts typically start with 0 balance - expect(beefyBalance).toBeGreaterThanOrEqual(0n); - expect(serviceManagerBalance).toBeGreaterThanOrEqual(0n); - }); - - it("should verify contract addresses are valid", async () => { - const connectors = suite.getTestConnectors(); - const deployments = await parseDeploymentsFile(); - - // List of expected contracts - const expectedContracts = [ - "BeefyClient", - "ServiceManager", - "RewardsRegistry", - "AVSDirectory", - "DelegationManager", - "StrategyManager" - ]; - - for (const contractName of expectedContracts) { - const address = deployments[contractName as keyof typeof deployments]; - - if (address && typeof address === "string") { - // Verify it's a valid address format - expect(address.startsWith("0x")).toBeTrue(); - expect(address.length).toBe(42); - - // Verify contract exists (has code) - const code = await connectors.publicClient.getCode({ - address: address as `0x${string}` - }); - - expect(code).toBeDefined(); - expect(code?.length).toBeGreaterThan(2); - - logger.info(`✓ ${contractName} deployed at ${address}`); - } else { - logger.warn(`⚠️ ${contractName} not found in deployments`); - } - } - }); -}); diff --git a/test/suites/cross-chain.test.ts b/test/suites/cross-chain.test.ts deleted file mode 100644 index 65e782bb..00000000 --- a/test/suites/cross-chain.test.ts +++ /dev/null @@ -1,108 +0,0 @@ -import { beforeAll, describe, expect, it } from "bun:test"; -import type { PolkadotSigner } from "polkadot-api"; -import { getPapiSigner, logger, SUBSTRATE_FUNDED_ACCOUNTS } from "utils"; -import { BaseTestSuite } from "../framework"; - -class CrossChainTestSuite extends BaseTestSuite { - constructor() { - super({ - suiteName: "cross-chain" - }); - - this.setupHooks(); - } - - override async onSetup(): Promise { - // Relayers initialization is handled by the network setup - logger.info("Cross-chain test setup complete"); - } -} - -// Create the test suite instance -const suite = new CrossChainTestSuite(); - -describe("Cross-Chain Communication", () => { - let _signer: PolkadotSigner; - - beforeAll(() => { - _signer = getPapiSigner(); - }); - - it("should query Ethereum client state on DataHaven", async () => { - const connectors = suite.getTestConnectors(); - - // Check basic chain connectivity - const blockNumber = await connectors.papiClient.getBlockHeader(); - - logger.info(`Connected to DataHaven at block: ${blockNumber.number}`); - expect(blockNumber.number).toBeGreaterThan(0); - }); - - it("should check beacon relayer status", async () => { - const connectors = suite.getTestConnectors(); - - // Check if we can access chain state - try { - const blockHash = await connectors.papiClient.getFinalizedBlock(); - logger.info(`Finalized block hash: ${blockHash}`); - expect(blockHash).toBeDefined(); - } catch (_error) { - logger.warn("Unable to get finalized block - relayers may still be syncing"); - } - }); - - it("should verify validator registry connection", async () => { - const connectors = suite.getTestConnectors(); - - // For now, just check that we can connect - // The specific storage items depend on the runtime configuration - const blockNumber = await connectors.papiClient.getBlockHeader(); - - logger.info(`Current block number: ${blockNumber.number}`); - expect(blockNumber.number).toBeGreaterThan(0); - }); - - it("should check system information", async () => { - const connectors = suite.getTestConnectors(); - - // Query basic system information - const blockNumber = await connectors.dhApi.query.System.Number.getValue(); - const parentHash = await connectors.dhApi.query.System.ParentHash.getValue(); - - logger.info(`Current block: ${blockNumber}`); - logger.info(`Parent hash: ${parentHash}`); - - expect(blockNumber).toBeGreaterThan(0); - expect(parentHash).toBeDefined(); - }); - - it("should query ethereum client pallet", async () => { - const connectors = suite.getTestConnectors(); - - // Check if we can access account info - const accountInfo = await connectors.dhApi.query.System.Account.getValue( - SUBSTRATE_FUNDED_ACCOUNTS.ALITH.publicKey - ); - - logger.info(`Account nonce: ${accountInfo.nonce}`); - logger.info(`Account providers: ${accountInfo.providers}`); - - expect(accountInfo.providers).toBeGreaterThan(0); - }); - - it("should check BEEFY consensus status", async () => { - const connectors = suite.getTestConnectors(); - - // Query BEEFY validator set - const validatorSet = await connectors.papiClient.getUnsafeApi().apis.BeefyApi.validator_set(); - - if (validatorSet) { - logger.info(`BEEFY validator set ID: ${validatorSet.id}`); - logger.info(`BEEFY validator count: ${validatorSet.validators.length}`); - - expect(validatorSet.validators.length).toBeGreaterThan(0); - } else { - logger.warn("BEEFY validator set not yet available"); - } - }); -}); diff --git a/test/suites/datahaven-substrate.test.ts b/test/suites/datahaven-substrate.test.ts deleted file mode 100644 index 85040065..00000000 --- a/test/suites/datahaven-substrate.test.ts +++ /dev/null @@ -1,93 +0,0 @@ -import { beforeAll, describe, expect, it } from "bun:test"; -import type { PolkadotSigner } from "polkadot-api"; -import { - getPapiSigner, - isValidatorNodeRunning, - launchDatahavenValidator, - logger, - SUBSTRATE_FUNDED_ACCOUNTS, - TestAccounts -} from "utils"; -import { isAddress } from "viem"; -import { BaseTestSuite } from "../framework"; - -class DataHavenSubstrateTestSuite extends BaseTestSuite { - constructor() { - super({ - suiteName: "datahaven-substrate" - }); - - this.setupHooks(); - } - - override async onSetup(): Promise { - await launchDatahavenValidator(TestAccounts.Charlie, { - launchedNetwork: this.getConnectors().launchedNetwork - }); - } - - public getNetworkId(): string { - return this.getConnectors().launchedNetwork.networkId; - } -} - -// Create the test suite instance -const suite = new DataHavenSubstrateTestSuite(); - -describe("DataHaven Substrate Operations", () => { - let _signer: PolkadotSigner; - - beforeAll(() => { - _signer = getPapiSigner(); - }); - - it("should query runtime API", async () => { - const connectors = suite.getTestConnectors(); - const address = await connectors.dhApi.apis.EthereumRuntimeRPCApi.author(); - - logger.info(`Author address: ${address.asHex()}`); - expect(isAddress(address.asHex())).toBeTrue(); - }); - - it("should lookup account balance", async () => { - const connectors = suite.getTestConnectors(); - const { - data: { free: freeBalance } - } = await connectors.dhApi.query.System.Account.getValue( - SUBSTRATE_FUNDED_ACCOUNTS.ALITH.publicKey - ); - - logger.info(`Balance of ALITH: ${freeBalance}`); - expect(freeBalance).toBeGreaterThan(0n); - }); - - it("should listen to events", async () => { - const connectors = suite.getTestConnectors(); - - // Pull next ExtrinsicSuccess event - const event = await connectors.dhApi.event.System.ExtrinsicSuccess.pull(); - - expect(event).not.toBeEmpty(); - expect(event[0].payload.dispatch_info.weight.ref_time).toBeGreaterThan(0n); - - logger.info( - `Caught ExtrinsicSuccess event with weight: ${event[0].payload.dispatch_info.weight.ref_time}` - ); - }); - - it("should query block information", async () => { - const connectors = suite.getTestConnectors(); - - // Get current block - const blockHeader = await connectors.papiClient.getBlockHeader(); - - expect(blockHeader.number).toBeGreaterThan(0); - - logger.info(`Current block #${blockHeader.number}`); - }); - - it("should see Charlie running", async () => { - const isRunning = await isValidatorNodeRunning(TestAccounts.Charlie, suite.getNetworkId()); - expect(isRunning).toBe(true); - }); -}); diff --git a/test/suites/ethereum-basic.test.ts b/test/suites/ethereum-basic.test.ts deleted file mode 100644 index fcad80a4..00000000 --- a/test/suites/ethereum-basic.test.ts +++ /dev/null @@ -1,173 +0,0 @@ -import { describe, expect, it } from "bun:test"; -import { ANVIL_FUNDED_ACCOUNTS, generateRandomAccount, logger } from "utils"; -import { parseEther } from "viem"; -import { BaseTestSuite } from "../framework"; - -class EthereumBasicTestSuite extends BaseTestSuite { - constructor() { - super({ - suiteName: "ethereum-basic" - }); - - // Set up hooks in constructor - this.setupHooks(); - } -} - -// Create the test suite instance -const suite = new EthereumBasicTestSuite(); - -describe("Ethereum Basic Operations", () => { - it("should query block number", async () => { - const connectors = suite.getTestConnectors(); - const blockNumber = await connectors.publicClient.getBlockNumber(); - - expect(blockNumber).toBeGreaterThan(0n); - logger.info(`Current block number: ${blockNumber}`); - }); - - it("should check funded account balance", async () => { - const connectors = suite.getTestConnectors(); - const balance = await connectors.publicClient.getBalance({ - address: ANVIL_FUNDED_ACCOUNTS[0].publicKey - }); - - expect(balance).toBeGreaterThan(parseEther("1")); - logger.info(`Account balance: ${balance} wei`); - }); - - it("should send ETH transaction", async () => { - const connectors = suite.getTestConnectors(); - const amount = parseEther("1"); - const randomAccount = generateRandomAccount(); - - // Check initial balance - const balanceBefore = await connectors.publicClient.getBalance({ - address: randomAccount.address - }); - expect(balanceBefore).toBe(0n); - - // Check balance of the sender - const balance = await connectors.publicClient.getBalance({ - address: connectors.walletClient.account.address - }); - expect(balance).toBeGreaterThan(amount); - - // Send transaction - if (!connectors.walletClient.account) { - throw new Error("Wallet client account not available"); - } - const hash = await connectors.walletClient.sendTransaction({ - account: connectors.walletClient.account, - chain: null, - to: randomAccount.address as `0x${string}`, - value: amount - }); - - // Wait for receipt - const receipt = await connectors.publicClient.waitForTransactionReceipt({ hash }); - expect(receipt.status).toBe("success"); - - // Check final balance - const balanceAfter = await connectors.publicClient.getBalance({ - address: randomAccount.address - }); - expect(balanceAfter).toBe(amount); - - logger.info(`Successfully sent ${amount} wei to ${randomAccount.address}`); - }); - - it("should interact with multiple accounts", async () => { - const connectors = suite.getTestConnectors(); - const factory = suite.getConnectorFactory(); - - // Create wallet clients for multiple accounts - const wallet1 = factory.createWalletClient(ANVIL_FUNDED_ACCOUNTS[1].privateKey); - const wallet2 = factory.createWalletClient(ANVIL_FUNDED_ACCOUNTS[2].privateKey); - - const recipient = generateRandomAccount(); - const amount = parseEther("0.5"); - - // Fund wallet1 and wallet2 with 1ETH to successfully send transaction - const initialAmount = parseEther("1"); - - // Give 1ETH to wallet1 - const hashInit1 = await connectors.walletClient.sendTransaction({ - account: connectors.walletClient.account, - chain: null, - to: wallet1.account.address as `0x${string}`, - value: initialAmount - }); - - // Wait for receipt - const receiptInit1 = await connectors.publicClient.waitForTransactionReceipt({ - hash: hashInit1 - }); - expect(receiptInit1.status).toBe("success"); - - const balance1 = await connectors.publicClient.getBalance({ - address: wallet1.account.address - }); - expect(balance1).toBeGreaterThan(parseEther("1")); - - // Give 1ETH to wallet2 - const hashInit2 = await connectors.walletClient.sendTransaction({ - account: connectors.walletClient.account, - chain: null, - to: wallet2.account.address as `0x${string}`, - value: initialAmount - }); - - // Wait for receipt - const receiptInit2 = await connectors.publicClient.waitForTransactionReceipt({ - hash: hashInit2 - }); - expect(receiptInit2.status).toBe("success"); - - const balance2 = await connectors.publicClient.getBalance({ - address: wallet2.account.address - }); - expect(balance2).toBeGreaterThan(parseEther("1")); - - // Send from account 1 - if (!wallet1.account) { - throw new Error("Wallet1 account not available"); - } - - const hash1 = await wallet1.sendTransaction({ - account: wallet1.account, - chain: null, - to: recipient.address as `0x${string}`, - value: amount - }); - - // Send from account 2 - if (!wallet2.account) { - throw new Error("Wallet2 account not available"); - } - - const hash2 = await wallet2.sendTransaction({ - account: wallet2.account, - chain: null, - to: recipient.address as `0x${string}`, - value: amount - }); - - // Wait for both transactions - const [receipt1, receipt2] = await Promise.all([ - connectors.publicClient.waitForTransactionReceipt({ hash: hash1 }), - connectors.publicClient.waitForTransactionReceipt({ hash: hash2 }) - ]); - - expect(receipt1.status).toBe("success"); - expect(receipt2.status).toBe("success"); - - // Check final balance - const finalBalance = await connectors.publicClient.getBalance({ - address: recipient.address - }); - expect(finalBalance).toBe(amount * 2n); - - logger.info(`Received total of ${finalBalance} wei from multiple accounts`); - }, 20_000); -}); From 879be715b5b314e9ba2c17c8eef617ee960034ba Mon Sep 17 00:00:00 2001 From: Steve Degosserie <723552+stiiifff@users.noreply.github.com> Date: Fri, 24 Oct 2025 19:57:07 +0300 Subject: [PATCH 09/12] =?UTF-8?q?feat:=20=E2=9C=A8=20Bump=20client=20versi?= =?UTF-8?q?on=20to=20v0.3.1=20&=20runtime=20spec=5Fversion=20to=20310=20(#?= =?UTF-8?q?250)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- operator/Cargo.lock | 112 +++++++++++++-------------- operator/Cargo.toml | 2 +- operator/runtime/mainnet/src/lib.rs | 2 +- operator/runtime/stagenet/src/lib.rs | 2 +- operator/runtime/testnet/src/lib.rs | 2 +- test/.papi/metadata/datahaven.scale | Bin 617151 -> 617151 bytes 6 files changed, 60 insertions(+), 60 deletions(-) diff --git a/operator/Cargo.lock b/operator/Cargo.lock index e1059289..8cf9bf09 100644 --- a/operator/Cargo.lock +++ b/operator/Cargo.lock @@ -1517,7 +1517,7 @@ dependencies = [ "pallet-message-queue", "parity-scale-codec", "scale-info", - "snowbridge-core 0.3.0", + "snowbridge-core 0.3.1", "sp-core", "sp-runtime", "sp-std", @@ -2902,7 +2902,7 @@ dependencies = [ [[package]] name = "datahaven-mainnet-runtime" -version = "0.3.0" +version = "0.3.1" dependencies = [ "bridge-hub-common 0.13.1", "datahaven-runtime-common", @@ -3006,8 +3006,8 @@ dependencies = [ "shp-traits", "shp-treasury-funding", "smallvec", - "snowbridge-beacon-primitives 0.3.0", - "snowbridge-core 0.3.0", + "snowbridge-beacon-primitives 0.3.1", + "snowbridge-core 0.3.1", "snowbridge-inbound-queue-primitives", "snowbridge-merkle-tree", "snowbridge-outbound-queue-primitives", @@ -3049,7 +3049,7 @@ dependencies = [ [[package]] name = "datahaven-node" -version = "0.3.0" +version = "0.3.1" dependencies = [ "async-channel 1.9.0", "clap", @@ -3159,7 +3159,7 @@ dependencies = [ [[package]] name = "datahaven-runtime-common" -version = "0.3.0" +version = "0.3.1" dependencies = [ "fp-account", "frame-support", @@ -3188,7 +3188,7 @@ dependencies = [ [[package]] name = "datahaven-stagenet-runtime" -version = "0.3.0" +version = "0.3.1" dependencies = [ "bridge-hub-common 0.13.1", "datahaven-runtime-common", @@ -3292,8 +3292,8 @@ dependencies = [ "shp-traits", "shp-treasury-funding", "smallvec", - "snowbridge-beacon-primitives 0.3.0", - "snowbridge-core 0.3.0", + "snowbridge-beacon-primitives 0.3.1", + "snowbridge-core 0.3.1", "snowbridge-inbound-queue-primitives", "snowbridge-merkle-tree", "snowbridge-outbound-queue-primitives", @@ -3335,7 +3335,7 @@ dependencies = [ [[package]] name = "datahaven-testnet-runtime" -version = "0.3.0" +version = "0.3.1" dependencies = [ "bridge-hub-common 0.13.1", "datahaven-runtime-common", @@ -3439,8 +3439,8 @@ dependencies = [ "shp-traits", "shp-treasury-funding", "smallvec", - "snowbridge-beacon-primitives 0.3.0", - "snowbridge-core 0.3.0", + "snowbridge-beacon-primitives 0.3.1", + "snowbridge-core 0.3.1", "snowbridge-inbound-queue-primitives", "snowbridge-merkle-tree", "snowbridge-outbound-queue-primitives", @@ -3631,7 +3631,7 @@ dependencies = [ [[package]] name = "dhp-bridge" -version = "0.3.0" +version = "0.3.1" dependencies = [ "frame-support", "frame-system", @@ -3639,7 +3639,7 @@ dependencies = [ "pallet-datahaven-native-transfer", "pallet-external-validators", "parity-scale-codec", - "snowbridge-core 0.3.0", + "snowbridge-core 0.3.1", "snowbridge-inbound-queue-primitives", "sp-core", "sp-std", @@ -9058,7 +9058,7 @@ dependencies = [ [[package]] name = "pallet-datahaven-native-transfer" -version = "0.3.0" +version = "0.3.1" dependencies = [ "frame-benchmarking", "frame-support", @@ -9066,7 +9066,7 @@ dependencies = [ "pallet-balances", "parity-scale-codec", "scale-info", - "snowbridge-core 0.3.0", + "snowbridge-core 0.3.1", "snowbridge-outbound-queue-primitives", "sp-core", "sp-io", @@ -9170,7 +9170,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-balances-erc20" -version = "0.3.0" +version = "0.3.1" dependencies = [ "fp-evm", "frame-support", @@ -9193,7 +9193,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-batch" -version = "0.3.0" +version = "0.3.1" dependencies = [ "evm", "fp-evm", @@ -9232,7 +9232,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-call-permit" -version = "0.3.0" +version = "0.3.1" dependencies = [ "evm", "fp-evm", @@ -9366,7 +9366,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-proxy" -version = "0.3.0" +version = "0.3.1" dependencies = [ "evm", "fp-evm", @@ -9410,7 +9410,7 @@ dependencies = [ [[package]] name = "pallet-evm-precompile-registry" -version = "0.3.0" +version = "0.3.1" dependencies = [ "fp-evm", "frame-support", @@ -9447,7 +9447,7 @@ dependencies = [ [[package]] name = "pallet-external-validators" -version = "0.3.0" +version = "0.3.1" dependencies = [ "frame-benchmarking", "frame-support", @@ -9469,7 +9469,7 @@ dependencies = [ [[package]] name = "pallet-external-validators-rewards" -version = "0.3.0" +version = "0.3.1" dependencies = [ "cumulus-primitives-core", "frame-benchmarking", @@ -9484,7 +9484,7 @@ dependencies = [ "polkadot-primitives", "polkadot-runtime-parachains", "scale-info", - "snowbridge-core 0.3.0", + "snowbridge-core 0.3.1", "snowbridge-merkle-tree", "snowbridge-outbound-queue-primitives", "sp-core", @@ -9496,7 +9496,7 @@ dependencies = [ [[package]] name = "pallet-external-validators-rewards-runtime-api" -version = "0.3.0" +version = "0.3.1" dependencies = [ "parity-scale-codec", "snowbridge-merkle-tree", @@ -9719,7 +9719,7 @@ dependencies = [ [[package]] name = "pallet-outbound-commitment-store" -version = "0.3.0" +version = "0.3.1" dependencies = [ "frame-support", "frame-system", @@ -16042,7 +16042,7 @@ dependencies = [ [[package]] name = "snowbridge-beacon-primitives" -version = "0.3.0" +version = "0.3.1" dependencies = [ "byte-slice-cast", "frame-support", @@ -16086,7 +16086,7 @@ dependencies = [ [[package]] name = "snowbridge-core" -version = "0.3.0" +version = "0.3.1" dependencies = [ "bp-relayers", "ethabi-decode", @@ -16186,8 +16186,8 @@ dependencies = [ "log", "parity-scale-codec", "scale-info", - "snowbridge-beacon-primitives 0.3.0", - "snowbridge-core 0.3.0", + "snowbridge-beacon-primitives 0.3.1", + "snowbridge-core 0.3.1", "snowbridge-verification-primitives", "sp-core", "sp-io", @@ -16200,7 +16200,7 @@ dependencies = [ [[package]] name = "snowbridge-merkle-tree" -version = "0.3.0" +version = "0.3.1" dependencies = [ "array-bytes", "hex", @@ -16241,7 +16241,7 @@ dependencies = [ [[package]] name = "snowbridge-outbound-queue-primitives" -version = "0.3.0" +version = "0.3.1" dependencies = [ "alloy-core", "ethabi-decode", @@ -16253,7 +16253,7 @@ dependencies = [ "parity-scale-codec", "polkadot-parachain-primitives", "scale-info", - "snowbridge-core 0.3.0", + "snowbridge-core 0.3.1", "snowbridge-verification-primitives", "sp-arithmetic", "sp-core", @@ -16267,12 +16267,12 @@ dependencies = [ [[package]] name = "snowbridge-outbound-queue-v2-runtime-api" -version = "0.3.0" +version = "0.3.1" dependencies = [ "frame-support", "parity-scale-codec", "scale-info", - "snowbridge-core 0.3.0", + "snowbridge-core 0.3.1", "snowbridge-merkle-tree", "snowbridge-outbound-queue-primitives", "sp-api", @@ -16282,7 +16282,7 @@ dependencies = [ [[package]] name = "snowbridge-pallet-ethereum-client" -version = "0.3.0" +version = "0.3.1" dependencies = [ "frame-benchmarking", "frame-support", @@ -16295,8 +16295,8 @@ dependencies = [ "scale-info", "serde", "serde_json", - "snowbridge-beacon-primitives 0.3.0", - "snowbridge-core 0.3.0", + "snowbridge-beacon-primitives 0.3.1", + "snowbridge-core 0.3.1", "snowbridge-ethereum 0.3.0", "snowbridge-inbound-queue-primitives", "snowbridge-pallet-ethereum-client-fixtures", @@ -16312,8 +16312,8 @@ name = "snowbridge-pallet-ethereum-client-fixtures" version = "0.9.0" dependencies = [ "hex-literal 0.3.4", - "snowbridge-beacon-primitives 0.3.0", - "snowbridge-core 0.3.0", + "snowbridge-beacon-primitives 0.3.1", + "snowbridge-core 0.3.1", "snowbridge-inbound-queue-primitives", "sp-core", "sp-std", @@ -16321,7 +16321,7 @@ dependencies = [ [[package]] name = "snowbridge-pallet-inbound-queue-v2" -version = "0.3.0" +version = "0.3.1" dependencies = [ "alloy-core", "bp-relayers", @@ -16335,8 +16335,8 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "snowbridge-beacon-primitives 0.3.0", - "snowbridge-core 0.3.0", + "snowbridge-beacon-primitives 0.3.1", + "snowbridge-core 0.3.1", "snowbridge-inbound-queue-primitives", "snowbridge-pallet-ethereum-client", "snowbridge-pallet-inbound-queue-v2-fixtures", @@ -16357,8 +16357,8 @@ name = "snowbridge-pallet-inbound-queue-v2-fixtures" version = "0.10.0" dependencies = [ "hex-literal 0.3.4", - "snowbridge-beacon-primitives 0.3.0", - "snowbridge-core 0.3.0", + "snowbridge-beacon-primitives 0.3.1", + "snowbridge-core 0.3.1", "snowbridge-inbound-queue-primitives", "sp-core", "sp-std", @@ -16388,7 +16388,7 @@ dependencies = [ [[package]] name = "snowbridge-pallet-outbound-queue-v2" -version = "0.3.0" +version = "0.3.1" dependencies = [ "alloy-core", "bp-relayers", @@ -16402,8 +16402,8 @@ dependencies = [ "parity-scale-codec", "scale-info", "serde", - "snowbridge-beacon-primitives 0.3.0", - "snowbridge-core 0.3.0", + "snowbridge-beacon-primitives 0.3.1", + "snowbridge-core 0.3.1", "snowbridge-inbound-queue-primitives", "snowbridge-merkle-tree", "snowbridge-outbound-queue-primitives", @@ -16434,7 +16434,7 @@ dependencies = [ "parity-scale-codec", "polkadot-primitives", "scale-info", - "snowbridge-core 0.3.0", + "snowbridge-core 0.3.1", "snowbridge-outbound-queue-primitives", "snowbridge-pallet-outbound-queue", "sp-core", @@ -16447,7 +16447,7 @@ dependencies = [ [[package]] name = "snowbridge-pallet-system-v2" -version = "0.3.0" +version = "0.3.1" dependencies = [ "frame-benchmarking", "frame-support", @@ -16459,7 +16459,7 @@ dependencies = [ "parity-scale-codec", "polkadot-primitives", "scale-info", - "snowbridge-core 0.3.0", + "snowbridge-core 0.3.1", "snowbridge-outbound-queue-primitives", "snowbridge-pallet-outbound-queue-v2", "snowbridge-pallet-system", @@ -16475,10 +16475,10 @@ dependencies = [ [[package]] name = "snowbridge-system-v2-runtime-api" -version = "0.3.0" +version = "0.3.1" dependencies = [ "parity-scale-codec", - "snowbridge-core 0.3.0", + "snowbridge-core 0.3.1", "sp-api", "sp-std", "staging-xcm", @@ -16486,7 +16486,7 @@ dependencies = [ [[package]] name = "snowbridge-test-utils" -version = "0.3.0" +version = "0.3.1" dependencies = [ "frame-benchmarking", "frame-support", @@ -16506,12 +16506,12 @@ dependencies = [ [[package]] name = "snowbridge-verification-primitives" -version = "0.3.0" +version = "0.3.1" dependencies = [ "frame-support", "parity-scale-codec", "scale-info", - "snowbridge-beacon-primitives 0.3.0", + "snowbridge-beacon-primitives 0.3.1", "sp-core", "sp-std", ] diff --git a/operator/Cargo.toml b/operator/Cargo.toml index f075f7bd..e5c3a890 100644 --- a/operator/Cargo.toml +++ b/operator/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" homepage = "https://datahaven.xyz/" license = "GPL-3" repository = "https://github.com/datahavenxyz/datahaven" -version = "0.3.0" +version = "0.3.1" [workspace] members = [ diff --git a/operator/runtime/mainnet/src/lib.rs b/operator/runtime/mainnet/src/lib.rs index 078ad078..2fdde07b 100644 --- a/operator/runtime/mainnet/src/lib.rs +++ b/operator/runtime/mainnet/src/lib.rs @@ -123,7 +123,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 200 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 300, + spec_version: 310, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, diff --git a/operator/runtime/stagenet/src/lib.rs b/operator/runtime/stagenet/src/lib.rs index 03d1c24b..5c77207d 100644 --- a/operator/runtime/stagenet/src/lib.rs +++ b/operator/runtime/stagenet/src/lib.rs @@ -126,7 +126,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 200 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 300, + spec_version: 310, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, diff --git a/operator/runtime/testnet/src/lib.rs b/operator/runtime/testnet/src/lib.rs index 544ff7e2..b703637c 100644 --- a/operator/runtime/testnet/src/lib.rs +++ b/operator/runtime/testnet/src/lib.rs @@ -122,7 +122,7 @@ pub const VERSION: RuntimeVersion = RuntimeVersion { // `spec_version`, and `authoring_version` are the same between Wasm and native. // This value is set to 200 to notify Polkadot-JS App (https://polkadot.js.org/apps) to use // the compatible custom types. - spec_version: 300, + spec_version: 310, impl_version: 1, apis: RUNTIME_API_VERSIONS, transaction_version: 1, diff --git a/test/.papi/metadata/datahaven.scale b/test/.papi/metadata/datahaven.scale index 2c9e630da36eb7ca594bd4dff43394b544130262..1f52f62e8c6128e837e8d4777d8270dd6588fde4 100644 GIT binary patch delta 43 ucmdmgRdxSW)rJF7M3lnGx!+I+Gp~y0x=s9vjZ{5_L+Q~YB2y{;0|5@ delta 43 ucmdmgRdxSW)rJF7M3lnGx!*F+Gp~y0x=s9vjZ{5_L+Q~YB2y``VLe8 From d55310d1f4f1e7644f5e1d0982f2e6bd400aebf7 Mon Sep 17 00:00:00 2001 From: Steve Degosserie <723552+stiiifff@users.noreply.github.com> Date: Mon, 27 Oct 2025 00:33:24 +0200 Subject: [PATCH 10/12] =?UTF-8?q?fix:=20=F0=9F=94=A7=20Add=20missing=20lib?= =?UTF-8?q?ldap2-dev=20lib=20to=20DH=20operator=20Docker=20image=20(#252)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/datahaven-production.Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker/datahaven-production.Dockerfile b/docker/datahaven-production.Dockerfile index 142d89b6..3e52e08b 100644 --- a/docker/datahaven-production.Dockerfile +++ b/docker/datahaven-production.Dockerfile @@ -15,7 +15,7 @@ WORKDIR / RUN echo "*** Installing Basic dependencies ***" RUN apt-get update && apt-get install -y ca-certificates && update-ca-certificates -RUN apt install --assume-yes git clang curl libpq-dev libssl-dev llvm libudev-dev make pkg-config unzip +RUN apt install --assume-yes git clang curl libldap2-dev libpq-dev libssl-dev llvm libudev-dev make pkg-config unzip RUN echo "*** Installing protoc v${PROTOC_VER} ***" RUN curl -Lo /tmp/protoc.zip "https://github.com/protocolbuffers/protobuf/releases/download/v${PROTOC_VER}/protoc-${PROTOC_VER}-linux-x86_64.zip" \ From 4b0aba0f38df6f684c789436a9ac8457fd54b4d8 Mon Sep 17 00:00:00 2001 From: Steve Degosserie <723552+stiiifff@users.noreply.github.com> Date: Mon, 27 Oct 2025 13:05:38 +0200 Subject: [PATCH 11/12] =?UTF-8?q?fix:=20=F0=9F=94=A7=20Fix=20incorrect=20s?= =?UTF-8?q?hared=20lib=20name=20in=20DH=20operator=20Docker=20image=20(#25?= =?UTF-8?q?4)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docker/datahaven-production.Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docker/datahaven-production.Dockerfile b/docker/datahaven-production.Dockerfile index 3e52e08b..c5bf751b 100644 --- a/docker/datahaven-production.Dockerfile +++ b/docker/datahaven-production.Dockerfile @@ -50,14 +50,14 @@ COPY --from=builder \ /lib/x86_64-linux-gnu/libssl.so.3 \ /lib/x86_64-linux-gnu/libcrypto.so.3 \ /lib/x86_64-linux-gnu/libgssapi_krb5.so.2 \ - /lib/x86_64-linux-gnu/libldap.so.2 \ + /lib/x86_64-linux-gnu/libldap-2.5.so.0 \ /lib/x86_64-linux-gnu/libz.so.1 \ /lib/x86_64-linux-gnu/libzstd.so.1 \ /lib/x86_64-linux-gnu/libkrb5.so.3 \ /lib/x86_64-linux-gnu/libk5crypto.so.3 \ /lib/x86_64-linux-gnu/libcom_err.so.2 \ /lib/x86_64-linux-gnu/libkrb5support.so.0 \ - /lib/x86_64-linux-gnu/liblber.so.2 \ + /lib/x86_64-linux-gnu/liblber-2.5.so.0 \ /lib/x86_64-linux-gnu/libsasl2.so.2 \ /lib/x86_64-linux-gnu/libkeyutils.so.1 \ /lib/x86_64-linux-gnu/ From b5bc2de11e277bc5a3fab334b876b2542c4295ab Mon Sep 17 00:00:00 2001 From: Steve Degosserie <723552+stiiifff@users.noreply.github.com> Date: Mon, 27 Oct 2025 15:13:14 +0200 Subject: [PATCH 12/12] =?UTF-8?q?fix:=20=F0=9F=94=A7=20Fix=20incorrect=20a?= =?UTF-8?q?rgs=20in=20release=20Docker=20image=20publishing=20workflow=20(?= =?UTF-8?q?#256)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .github/workflows/task-publish-binary.yml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/.github/workflows/task-publish-binary.yml b/.github/workflows/task-publish-binary.yml index a464d20e..b0ad824d 100644 --- a/.github/workflows/task-publish-binary.yml +++ b/.github/workflows/task-publish-binary.yml @@ -135,8 +135,11 @@ jobs: - name: Cargo build uses: ./.github/workflow-templates/publish-docker with: - dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }} - dockerhub_password: ${{ secrets.DOCKERHUB_TOKEN }} + dockerfile: ./operator/Dockerfile + context: . + registry: docker.io + registry_username: ${{ secrets.DOCKERHUB_USERNAME }} + registry_password: ${{ secrets.DOCKERHUB_TOKEN }} image_tags: ${{ steps.prep.outputs.tags }} image_title: ${{ github.event.repository.name }} image_description: ${{ github.event.repository.description }}