zoo-mpc (5-node, 3-of-5, ghcr.io/zooai/mpc:1.17.9) + zoo-kms (ghcr.io/zooai/kms:1.11.8, lux-kms-go parity, Zoo-branded OIDC) in do-sfo3-zoo-k8s. DKG proven: wallet zoo-treasury-v1 EVM 0x8756621734fe274fdc426381c9a4f9dec8656243, 3-of-5 threshold sign OK. KMS in-cluster health+login 200. Investigation: ZERO Zoo secrets in the Hanzo KMS (proven) -> repoint strands nothing. Repoint + DAO/Z Safes staged, HELD for owner go (Zoo EVM 200200 not producing blocks). Co-authored-by: Hanzo Dev <[email protected]>
200 lines
6.4 KiB
YAML
200 lines
6.4 KiB
YAML
# Zoo MPC — Zoo's OWN canonical threshold-signing ring (crypto-sovereign).
|
|
# Namespace: zoo-mpc. Architecture: 5-node consensus, threshold 3-of-5.
|
|
# Image: ghcr.io/zooai/mpc:v1.17.9 — the Zoo-branded rebrand of the canonical
|
|
# lux-native mpcd (wraps ghcr.io/luxfi/mpc:v1.17.9; same convention as
|
|
# hanzoai/mpc). Binary is `mpcd`. Pin is semver-immutable (no :main/:latest).
|
|
#
|
|
# Mirrors the PROVEN hanzo-mpc / lux-mpc rings (own DKG key, own store), but
|
|
# 3-of-5 and in the dedicated zoo-mpc namespace the Zoo bridge tenant.yaml
|
|
# already targets (mpc-node-0..4.mpc-node-headless.zoo-mpc.svc, threshold 3).
|
|
#
|
|
# DNS/pod identity: StatefulSet `mpc-node` → pods mpc-node-{0..4} (matches the
|
|
# bridge tenant mpc.url). MPC protocol node-id = zoo-mpc-node-{ordinal} (matches
|
|
# the bridge tenant `operators` allowlist). Both contracts satisfied.
|
|
---
|
|
apiVersion: apps/v1
|
|
kind: StatefulSet
|
|
metadata:
|
|
name: mpc-node
|
|
namespace: zoo-mpc
|
|
labels:
|
|
app: mpc-node
|
|
app.kubernetes.io/name: mpc-node
|
|
app.kubernetes.io/component: signer
|
|
app.kubernetes.io/part-of: mpc
|
|
brand: zoo
|
|
spec:
|
|
serviceName: mpc-node-headless
|
|
replicas: 5
|
|
podManagementPolicy: Parallel
|
|
selector:
|
|
matchLabels:
|
|
app: mpc-node
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app: mpc-node
|
|
app.kubernetes.io/part-of: mpc
|
|
brand: zoo
|
|
spec:
|
|
imagePullSecrets:
|
|
- name: ghcr-zooai
|
|
containers:
|
|
- name: mpc-node
|
|
image: ghcr.io/zooai/mpc:1.17.9
|
|
imagePullPolicy: IfNotPresent
|
|
# mpcd flags: DNS peer list over StatefulSet DNS (stable + deterministic);
|
|
# 3-of-5 threshold; p2p :9999, internal API :9800, dashboard API :8081.
|
|
# node-id carries the Zoo operator prefix to match the bridge allowlist.
|
|
command:
|
|
- /bin/sh
|
|
- -c
|
|
- |
|
|
ORD="${POD_NAME##*-}"
|
|
# Peers MUST use the explicit `nodeID@host:port` form so the registry's
|
|
# filterSelf() matches this node's --node-id and drops the self-entry
|
|
# (a bare host:port yields synthetic `peer-N` ids that never match self,
|
|
# inflating the expected-peer count to N+1 and stalling keygen). The
|
|
# nodeIDs (zoo-mpc-node-0..4) are identical across all pods and match
|
|
# the Zoo bridge tenant `operators` allowlist.
|
|
exec mpcd start \
|
|
--node-id="zoo-mpc-node-${ORD}" \
|
|
--data=/data/mpcd \
|
|
--listen=:9999 \
|
|
--api=:9800 \
|
|
--api-listen=:8081 \
|
|
--threshold=3 \
|
|
--jwt-secret="${MPC_JWT_SECRET}" \
|
|
--peer="zoo-mpc-node-0@mpc-node-0.mpc-node-headless.zoo-mpc.svc.cluster.local:9999" \
|
|
--peer="zoo-mpc-node-1@mpc-node-1.mpc-node-headless.zoo-mpc.svc.cluster.local:9999" \
|
|
--peer="zoo-mpc-node-2@mpc-node-2.mpc-node-headless.zoo-mpc.svc.cluster.local:9999" \
|
|
--peer="zoo-mpc-node-3@mpc-node-3.mpc-node-headless.zoo-mpc.svc.cluster.local:9999" \
|
|
--peer="zoo-mpc-node-4@mpc-node-4.mpc-node-headless.zoo-mpc.svc.cluster.local:9999"
|
|
ports:
|
|
- containerPort: 9999
|
|
name: p2p
|
|
protocol: TCP
|
|
- containerPort: 9800
|
|
name: internal
|
|
protocol: TCP
|
|
- containerPort: 8081
|
|
name: api
|
|
protocol: TCP
|
|
env:
|
|
- name: POD_NAME
|
|
valueFrom:
|
|
fieldRef:
|
|
fieldPath: metadata.name
|
|
# All secret material is bootstrap-generated into the mpc-secrets Secret
|
|
# (see secrets.yaml + deploy.sh) and mirrored into the Zoo KMS for
|
|
# durability. NEVER hardcoded, NEVER committed in plaintext.
|
|
# Bearer/dashboard JWT signing key:
|
|
- name: MPC_JWT_SECRET
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: mpc-secrets
|
|
key: jwt-secret
|
|
# ZapDB at-rest encryption password (REK). hsm-provider defaults to
|
|
# `env`, which reads MPC_PASSWORD. LOSS = unreadable DKG store.
|
|
- name: MPC_PASSWORD
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: mpc-secrets
|
|
key: mpc-password
|
|
# Shared static bearers — identical across all 5 nodes so cloud/peers
|
|
# present ONE token. Random 32-byte, in the mpc-internal-api Secret.
|
|
- name: MPC_INTERNAL_API_KEY
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: mpc-internal-api
|
|
key: MPC_INTERNAL_API_KEY
|
|
- name: MPC_THRESHOLD_AUTH_TOKEN
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: mpc-internal-api
|
|
key: MPC_THRESHOLD_AUTH_TOKEN
|
|
resources:
|
|
requests:
|
|
memory: "512Mi"
|
|
cpu: "200m"
|
|
limits:
|
|
memory: "2Gi"
|
|
cpu: "1000m"
|
|
volumeMounts:
|
|
- name: data
|
|
mountPath: /data/mpcd
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /readyz
|
|
port: api
|
|
initialDelaySeconds: 10
|
|
periodSeconds: 10
|
|
timeoutSeconds: 5
|
|
failureThreshold: 3
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /health
|
|
port: api
|
|
initialDelaySeconds: 30
|
|
periodSeconds: 30
|
|
timeoutSeconds: 5
|
|
failureThreshold: 3
|
|
volumeClaimTemplates:
|
|
- metadata:
|
|
name: data
|
|
labels:
|
|
app.kubernetes.io/part-of: mpc
|
|
spec:
|
|
accessModes: ["ReadWriteOnce"]
|
|
# Retain so an accidental PVC delete never nukes the Zoo DKG store.
|
|
storageClassName: do-block-storage-retain
|
|
resources:
|
|
requests:
|
|
storage: 10Gi
|
|
---
|
|
# Headless service for StatefulSet DNS (pod-to-pod peer discovery).
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: mpc-node-headless
|
|
namespace: zoo-mpc
|
|
labels:
|
|
app: mpc-node
|
|
app.kubernetes.io/part-of: mpc
|
|
brand: zoo
|
|
spec:
|
|
clusterIP: None
|
|
selector:
|
|
app: mpc-node
|
|
ports:
|
|
- port: 9999
|
|
targetPort: 9999
|
|
name: p2p
|
|
- port: 9800
|
|
targetPort: 9800
|
|
name: internal
|
|
- port: 8081
|
|
targetPort: 8081
|
|
name: api
|
|
---
|
|
# Dashboard/API service — fronts all 5 nodes on the dashboard API port.
|
|
# Backs the mpc.zoo.network route (ingress.yaml).
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: mpc-api-svc
|
|
namespace: zoo-mpc
|
|
labels:
|
|
app: mpc-node
|
|
app.kubernetes.io/component: api
|
|
app.kubernetes.io/part-of: mpc
|
|
brand: zoo
|
|
spec:
|
|
type: ClusterIP
|
|
selector:
|
|
app: mpc-node
|
|
ports:
|
|
- port: 8081
|
|
targetPort: 8081
|
|
name: api
|