- Add bearer token auth to internal MPC API (port 9800): /keygen, /keys,
/backup now require Authorization header. Token from MPC_INTERNAL_API_KEY
env (KMS-synced) or derived from Ed25519 node identity.
- Replace DualModeListener with TLSOnlyListener: plaintext peer connections
are rejected. TLS 1.3 with PQ key exchange is mandatory.
- Add dedicated 20 RPM rate limiter on bridge signing and intent signing
endpoints (separate from global 100 RPM).
- Add body size limit (1MB), read/write timeouts, and 10 RPM rate limiter
to internal MPC API server.
- Restrict K8s NetworkPolicy egress for MPC nodes to peers, postgres,
valkey, DNS, and HTTPS only (was unrestricted).
- Wire cluster-api-key in api-deployment for authenticated proxy to
internal MPC API. Forward as Authorization: Bearer header.
- Remove hardcoded dev JWT_SECRET default from compose.yml (now required).
- Add internal-api-key to KMSSecret CRD and StatefulSet env.
- /health returns connected_peers as int (count) not string array
- /keygen derives eth_address from 32-byte keys (was >= 33, now >= 32)
- Skip initiator verification when no explicit key configured (consensus mode)
- ConsensusIdentityStore now uses node's own key as initiator key when
no explicit event_initiator_pubkey is configured (consensus mode)
- /keygen HTTP endpoint signs GenerateKeyMessage with node's Ed25519 key
- ConsensusMPCBackend.TriggerKeygen/TriggerSign sign messages before publish
- apiOnlyMPCBackend forwards to /keygen and /health (internal API paths)
instead of /api/v1/keygen and /api/v1/status (dashboard API paths)
- mpc-api deployment points to port 9800 (internal API, no auth required)
instead of port 8081 (dashboard API, auth required)
- /health response uses snake_case keys matching ClusterStatus JSON tags
- goimports -w on all pkg/api, pkg/db, cmd/mpcd files
- TestError_PanicsOnOddKeyValues → TestError_OddKeyValuesLogsWarning
(logger was intentionally changed to warn+sentinel instead of panic)
- int(threshold) → threshold (threshold is already int from c.Int())
- ConsensusIdentityStore.VerifyInitiatorMessage: implement real Ed25519
signature verification using the configured event_initiator_pubkey
instead of blindly accepting all messages
- cggmp21Aggregator.VerifyShare: implement ECDSA partial signature
verification using secp256k1 curve arithmetic (R' = u1*G + u2*Y_i,
check R'.x == r mod n) against the party's public key share
- frostAggregator.VerifyShare: implement Schnorr/BIP-340 partial
signature verification (compute R_i = s_i*G - c*Y_i, verify on curve)
- logger.Error: replace panic on odd keyValues with warning log and
sentinel value to avoid crashing production
- session.ProcessInboundMessage/ProcessOutboundMessage: replace panics
with error log and graceful no-op for unoverridden base methods
- eddsaReshareSession: implement ProcessInboundMessage (unmarshal wire
format, dedup, route to FROST party) and ProcessOutboundMessage (read
from party Messages channel, wrap in wire format, send)
- cggmp21ReshareSession: implement matching message handlers
- eddsaReshareSession.Reshare: extract actual Ed25519 public key from
FROST result via GetPublicKeyBytes() instead of empty placeholder
- Implement CREATE2 address prediction in PredictAccountAddress() using
keccak256(0xff ++ factory ++ salt ++ keccak256(initCode))[12:] formula.
Also add general-purpose PredictCreate2Address() with raw [20]byte params.
- Create pkg/hsm package with PasswordProvider interface and 5 implementations:
- AWSKMSProvider: decrypts ZAPDB_ENCRYPTED_PASSWORD via AWS KMS Decrypt API
with full SigV4 signing and EC2 instance metadata credential fallback
- GCPKMSProvider: decrypts via GCP Cloud KMS REST API with GCE metadata OAuth2
- AzureKVProvider: unwraps via Azure Key Vault REST API with MSI token auth
- EnvProvider: reads from LUX_MPC_PASSWORD/ZAPDB_PASSWORD env vars (default)
- FileProvider: reads from file (K8s mounted secrets)
- Add NewPasswordProvider factory (pkg/hsm/factory.go) driven by MPC_HSM_PROVIDER
env var (values: aws, gcp, azure, env, file)
- Wire HSM provider into mpcd consensus startup, replacing direct env var read
with graceful fallback chain: HSM provider -> viper config -> dev default
- Add --hsm-provider and --hsm-key-id CLI flags with MPC_HSM_PROVIDER/MPC_HSM_KEY_ID
env var sources
- 25 tests passing (9 smart + 16 HSM)
- Replace direct github.com/luxfi/zapdb/v4 imports with github.com/luxfi/database
abstraction in pkg/kvstore/ (zapdb.New + encdb.New for encryption)
- BadgerKVStore now uses database.Database interface internally — backend is
pluggable (zapdb/leveldb/memdb) without changing MPC code
- Remove custom badger_logger.go (database module handles its own logging)
- Update BadgerBackupExecutor to use database.Database instead of *badger.DB;
RestoreAllBackupsEncrypted loads into raw zapdb (values are already
individually encrypted by encdb)
- Rewrite backup_test.go to use KVStore interface instead of raw badger API
- Update migration script to use KVStore Put/Get/Delete/Keys instead of txn API
- Rename all user-visible "BadgerDB"/"Badger" strings to "ZapDB" in logs,
prompts, and comments across cmd/mpcd/main.go, pkg/kvstore/, pkg/transport/
- Fix backup_test.go type reference: badgerBackupExecutor→BadgerBackupExecutor
(resolves CI test and lint failures)
- Replace github.com/dgraph-io/badger/v4 with github.com/luxfi/zapdb/v4 v4.9.2
throughout pkg/kvstore/, pkg/transport/, cmd/mpcd/, e2e/, scripts/
- Rename BadgerPath/BadgerPassword → ZapDBPath/ZapDBPassword in FactoryConfig
- Remove local replace directives from go.mod:
- hanzoai/orm: now uses published v0.3.2 (tagged on GitHub)
- hanzoai/kv-go/v9: now uses published v9.17.2-hanzo.1
- Only remaining replace: agl/ed25519 → luxfi/edwards25519
- Add vendor/ directory (GOWORK=off go mod vendor) for reproducible builds
- Update Dockerfile to golang:1.26-alpine + -mod=vendor build flag
- Update CI/CD to use self-hosted linux/amd64 runners (no cross-compilation)
- Add k8s/valkey.yaml for session KV store
- Update k8s manifests: api-kv support, ZapDB password env, fresh secrets
- Dashboard API and MPC nodes all tested running on cluster (3/3 nodes healthy)
TriggerSign was subscribing to mpc_signing_result.{txID} but the
signing session publishes to mpc_signing_result.{walletID}. Also
fixed result parsing: R/S are []byte (base64 in JSON), not hex strings.
ConsensusKeyInfoStore.Get() was returning empty ParticipantPeerIDs,
causing "Not enough participants to sign" errors. Now populates from
peer registry's ready peers list.
- TriggerSign now looks up key type from keyInfoStore (was empty, causing
"CGGMP21 only supports Secp256k1" errors)
- Wire keyInfoStore into ConsensusMPCBackend
- Increase HTTP middleware timeout from 30s to 120s for MPC signing
CGGMP21 keygen returns 32-byte x-coordinate, not 33-byte compressed key.
Added secp256k1 point decompression (y² = x³ + 7 mod p) to recover the
full uncompressed public key for keccak256 address derivation.
mpcd api --db $DATABASE_URL --jwt-secret $JWT_SECRET --listen :8081
Runs the Dashboard API server without MPC transport, suitable for
cloud dashboard deployments where MPC operations are handled by
separate MPC nodes.
- Add POST /keygen endpoint for triggering MPC keygen via HTTP API
- Fix PubSub self-delivery: Publish now delivers to local subscribers
before broadcasting to peers (required for consensus mode keygen)
- Increase KeyGenTimeOut from 30s to 120s (Paillier prime generation
takes 6-15s per node, multi-round protocol needs more time)
- Add pubKeyToEthAddress helper for deriving ETH addresses from ECDSA keys
- Bump version to 0.3.3
- Add S3 backup manager (pkg/backup/s3.go) for periodic encrypted BadgerDB
backups with upload to S3-compatible storage (MinIO)
- Add 30s keepalive pings in transport layer to prevent idle read timeouts
- Increase read timeout from 30s to 5 minutes
- Add connection tie-breaking for simultaneous peer connections (lower node
ID keeps outbound) to prevent connection storms
- Add pointer-specific peer removal (removePeerConn) to prevent orphaned
goroutines from removing replacement connections
- Export BadgerBackupExecutor type for use by backup package
- Add /backup HTTP endpoint for on-demand backup triggers
- Bump version to 0.3.2
- Update .golangci.yml to v2 format with formatters section
- Fix goimports for local package grouping (tfhe_session.go, crypto_adapter.go, manager_test.go)
- Remove unnecessary int() conversion in mpcd main.go
- Remove local replace directive for threshold library
- Fix unused directMessaging variable warning
- Replace undefined logger.NewLogger with zap.NewProduction
- Fix GetMessage method call to use Raw()
- Mark bridge implementation as TODO