mirror of
https://github.com/luxfi/mpc.git
synced 2026-09-24 00:26:24 +00:00
Adds the topology contract that lets a fund run mpcd as its own private
cluster — no Lux primary network registration, no shared M-Chain audit
ledger — using the same code path and the same operator surface.
Mode flag at cmd/mpcd/main.go:
--network=primary|private # registration target
--audit-store=mchain|local-worm|... # audit log destination
--registrar-url, --registrar-auth # primary-mode announcement
--audit-worm-path, --audit-mchain-url # backend selectors
pkg/audit:
- Append-only Merkle hash chain. Tampering with any historical event
invalidates every subsequent hash. Canonical bytes use fixed-order
concatenation (json.Marshal map ordering is non-deterministic).
- WORMDispatcher: NDJSON append, replay-on-start, fsync per Append.
- MChainDispatcher: batched POST of (batchHash, fromSeq, toSeq) to a
configurable anchor RPC.
- compositeDispatcher: fan-out to multiple legs with per-leg sealing.
- S3 Glacier Vault / Azure Immutable / GCS Object Lock dispatchers
fail closed — wired into the flag surface but gated behind the
cloud-audit build tag, no silent fallback.
pkg/identity/bootstrap.go: identity creation + (primary-mode only)
registrar announcement. Same on-disk format as the previous
loadOrGenerateIdentity (which is now removed); private mode is silent.
deployments/k8s-private: fund-only Kustomize overlay. Standalone
namespace, NetworkPolicy that blocks egress to anything outside the
fund's VPC, hardware-WORM PVC for the audit log, KMS-driven secret
template.
deployments/k8s-primary: env-var patch overlay on the existing lux-mpc
base. composite(local-worm,mchain) by default.
deployments/terraform/{aws,gcp,azure}: VPC + audit storage modules.
terraform validate passes; EKS/GKE/AKS + HSM modules are stubbed and
not yet plan-tested.
deployments/onprem/README.md: WORM storage + PKCS#11 HSM checklist.
Tests (14 total, all passing):
pkg/audit: 6/6 (chain, WORM replay, MChain batching, composite,
cloud stubs fail loud, double-seal rejected)
pkg/identity: 4/4 (private no-call, primary call, primary empty
URL no-op, primary registrar 503 surfaces)
internal/privatemode: 4/4 (no registrar traffic, restart, tamper-detect,
cloud stubs fail loud)
Companion runbook in lux/papers/lux-private-mpc-deployment/
(LaTeX, 5 pages, tectonic-clean).
72 lines
2.9 KiB
Go
72 lines
2.9 KiB
Go
package approval
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
// NewProvider constructs an ApprovalProvider by name. Configuration is
|
|
// passed as a map[string]string so the factory stays orthogonal to the
|
|
// concrete provider's option struct — the provider parses what it needs.
|
|
//
|
|
// Supported provider types:
|
|
//
|
|
// ledger-enterprise — Ledger Enterprise (Vault) REST, ECDSA-P256 attestations
|
|
// ledger-device — USB Ledger Nano via APDU, secp256k1 / Ed25519
|
|
// webauthn — FIDO2 / passkey, ES256
|
|
// aws-kms — AWS KMS asymmetric ECDSA via luxfi/hsm
|
|
// gcp-kms — Google Cloud KMS via luxfi/hsm
|
|
// azure-keyvault — Azure Key Vault via luxfi/hsm
|
|
// zymbit — Zymbit SCM via luxfi/hsm
|
|
// yubihsm — Yubico YubiHSM 2 via luxfi/hsm
|
|
// mldsa — Post-quantum ML-DSA-65 via luxfi/hsm
|
|
// safe-multisig — Gnosis Safe execTransaction, on-chain approval
|
|
// local-dev — Software Ed25519 (test only; refuses production)
|
|
//
|
|
// Production safety: providers that hold a private key only acceptable in
|
|
// non-prod environments (currently only "local-dev") refuse to start when
|
|
// MPC_ENV=production.
|
|
func NewProvider(providerType string, config map[string]string) (ApprovalProvider, error) {
|
|
providerType = strings.TrimSpace(strings.ToLower(providerType))
|
|
switch providerType {
|
|
case "ledger-enterprise":
|
|
return NewLedgerEnterprise(config)
|
|
case "ledger-device":
|
|
return NewLedgerDevice(config)
|
|
case "webauthn":
|
|
return NewWebAuthn(config)
|
|
case "aws-kms":
|
|
return NewAWSKMS(config)
|
|
case "gcp-kms":
|
|
return NewGCPKMS(config)
|
|
case "azure-keyvault":
|
|
return NewAzureKeyVault(config)
|
|
case "zymbit":
|
|
return NewZymbit(config)
|
|
case "yubihsm", "yubico", "yubi":
|
|
return NewYubiHSM(config)
|
|
case "mldsa":
|
|
return NewMLDSA(config)
|
|
case "safe-multisig":
|
|
return NewSafeMultisig(config)
|
|
case "local-dev":
|
|
if env := strings.ToLower(os.Getenv("MPC_ENV")); env == "production" || env == "prod" {
|
|
return nil, errors.New("approval: local-dev provider forbidden in production (MPC_ENV=" + env + ")")
|
|
}
|
|
return NewLocalDev(config)
|
|
default:
|
|
return nil, fmt.Errorf("approval: unknown provider %q (supported: ledger-enterprise, ledger-device, webauthn, aws-kms, gcp-kms, azure-keyvault, zymbit, yubihsm, mldsa, safe-multisig, local-dev)", providerType)
|
|
}
|
|
}
|
|
|
|
// errNotImplemented is returned by providers that ship as documented stubs
|
|
// pending vendor-SDK or hardware availability. Callers MUST treat this as a
|
|
// hard failure — never as "approved by default".
|
|
var errNotImplemented = errors.New("approval: provider not implemented in this build (see provider docs for shipping plan)")
|
|
|
|
// ErrNotImplemented exposes the sentinel for callers that want to detect the
|
|
// stub case (e.g. fall back to a different provider for the same approver).
|
|
func ErrNotImplemented() error { return errNotImplemented }
|