From d4323da799e6883a0376a23aa960376ca9660674 Mon Sep 17 00:00:00 2001 From: zeekay Date: Fri, 3 Jul 2026 01:23:03 -0700 Subject: [PATCH] =?UTF-8?q?node:=20rename=20thresholdvm=20=E2=86=92=20mpcv?= =?UTF-8?q?m;=20split=20M/F=20registries=20(LP-0130)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - vms/thresholdvm/ → vms/mpcvm/ (dir + inner files + package decl). - node/vms.go optional-VM registry: drop ThresholdVMID row, add MPCVMID and FHEVMID rows (matching the new split). - genesis/builder/registry.go: T-Chain entry → M-Chain (MPCVMID) + F-Chain (FHEVMID); registry_test.go parity assertions updated. - genesis/builder/builder.go: TChainAliases → MChainAliases + FChainAliases; ThresholdVMID switch case split to MPCVMID / FHEVMID; optIn chain slice uses config.MChainGenesis + config.FChainGenesis (T-Chain slot retired). - LLM.md: point at LP-0130 as canonical topology + fee spec; correct the quantumvm posture to service-only per LP-0130 §6 (Q-Chain has no user-payable blockspace). Build + vet clean on chains/mpcvm/... + node/{vms/mpcvm,genesis,node}/... Co-authored-by: Hanzo Dev --- Dockerfile | 8 +- LLM.md | 39 ++++++++-- SECURITY.md | 2 +- genesis/builder/builder.go | 28 ++++--- genesis/builder/registry.go | 3 +- genesis/builder/registry_test.go | 6 +- genesis/builder/zzz_gateprobe_test.go | 73 +++++++++++++++++++ node/vms.go | 3 +- node/vms_purity_test.go | 2 +- scripts/publish_plugin_set.sh | 2 +- vms/{thresholdvm => mpcvm}/backend.go | 14 ++-- vms/mpcvm/mpcvm.go | 27 +++++++ .../thresholdvm_gpu.go => mpcvm/mpcvm_gpu.go} | 54 +++++++------- vms/mpcvm/mpcvm_gpu_nocgo.go | 49 +++++++++++++ .../mpcvm_gpu_parity_test.go} | 10 +-- .../mpcvm_gpu_test.go} | 4 +- vms/thresholdvm/thresholdvm.go | 27 ------- vms/thresholdvm/thresholdvm_gpu_nocgo.go | 49 ------------- vms/types/fee/policy.go | 4 +- 19 files changed, 257 insertions(+), 147 deletions(-) create mode 100644 genesis/builder/zzz_gateprobe_test.go rename vms/{thresholdvm => mpcvm}/backend.go (71%) create mode 100644 vms/mpcvm/mpcvm.go rename vms/{thresholdvm/thresholdvm_gpu.go => mpcvm/mpcvm_gpu.go} (56%) create mode 100644 vms/mpcvm/mpcvm_gpu_nocgo.go rename vms/{thresholdvm/thresholdvm_gpu_parity_test.go => mpcvm/mpcvm_gpu_parity_test.go} (95%) rename vms/{thresholdvm/thresholdvm_gpu_test.go => mpcvm/mpcvm_gpu_test.go} (97%) delete mode 100644 vms/thresholdvm/thresholdvm.go delete mode 100644 vms/thresholdvm/thresholdvm_gpu_nocgo.go diff --git a/Dockerfile b/Dockerfile index 68d9b2d20..674ea3d6d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -302,13 +302,13 @@ RUN --mount=type=cache,target=/root/.cache/go-build \ # oraclevm -> r5m1ujrmXxVcQetG3CQfuDLHp2RHKh6vCDaFgBRQfUcTZh7eS # quantumvm -> ry9Sg8rZdT26iEKvJDmC2wkESs4SDKgZEhk5BgLSwg1EpcNug # relayvm -> sP6dLqrrBR9w3soP18fbJ3YzZecZdD7DDdfH2cFhhLq7Hy9bz -# thresholdvm -> tGVBwRxpmD2aFdg3iYjgRvrCe8Jcmq9UNKxyHMus2NZ8WcD8t +# mpcvm -> tGVBwRxpmD2aFdg3iYjgRvrCe8Jcmq9UNKxyHMus2NZ8WcD8t # zkvm -> vv3qPfyTVXZ5ArRZA9Jh4hbYDTBe43f7sgQg4CHfNg1rnnvX9 # MUST track node's go.mod luxfi/chains (the D-Chain dexvm + 10 VM plugins). # Bump with every chains release or the bundled VM plugins go stale vs node's deps. # v1.4.7 == node go.mod's luxfi/chains pin: warp consolidated to ONE luxfi/warp -# helper (bridgevm/zkvm/thresholdvm), graphvm genesis-last-accepted fix, built on +# helper (bridgevm/zkvm/mpcvm), graphvm genesis-last-accepted fix, built on # evm v1.99.48 + precompile v0.16.0 (enable-everything builder surface). Keeps the # baked VM plugins in lockstep with the host node. ARG CHAINS_REF=v1.7.0 @@ -345,8 +345,8 @@ RUN --mount=type=cache,target=/root/.cache/go-build \ -o /luxd/build/plugins/ry9Sg8rZdT26iEKvJDmC2wkESs4SDKgZEhk5BgLSwg1EpcNug ./cmd/plugin ) || echo "WARN: quantumvm plugin build skipped" ; \ ( cd /tmp/chains/relayvm && CGO_ENABLED=0 GOFLAGS=-mod=mod go build -ldflags="-s -w" \ -o /luxd/build/plugins/sP6dLqrrBR9w3soP18fbJ3YzZecZdD7DDdfH2cFhhLq7Hy9bz ./cmd/plugin ) || echo "WARN: relayvm plugin build skipped" ; \ - ( cd /tmp/chains/thresholdvm && CGO_ENABLED=0 GOFLAGS=-mod=mod go build -ldflags="-s -w" \ - -o /luxd/build/plugins/tGVBwRxpmD2aFdg3iYjgRvrCe8Jcmq9UNKxyHMus2NZ8WcD8t ./cmd/plugin ) || echo "WARN: thresholdvm plugin build skipped" ; \ + ( cd /tmp/chains/mpcvm && CGO_ENABLED=0 GOFLAGS=-mod=mod go build -ldflags="-s -w" \ + -o /luxd/build/plugins/tGVBwRxpmD2aFdg3iYjgRvrCe8Jcmq9UNKxyHMus2NZ8WcD8t ./cmd/plugin ) || echo "WARN: mpcvm plugin build skipped" ; \ ( cd /tmp/chains/zkvm && CGO_ENABLED=0 GOFLAGS=-mod=mod go build -ldflags="-s -w" \ -o /luxd/build/plugins/vv3qPfyTVXZ5ArRZA9Jh4hbYDTBe43f7sgQg4CHfNg1rnnvX9 ./cmd/plugin ) || echo "WARN: zkvm plugin build skipped" ; \ ( chmod +x /luxd/build/plugins/* 2>/dev/null || true ) && \ diff --git a/LLM.md b/LLM.md index 378a91e5c..c9cab263b 100644 --- a/LLM.md +++ b/LLM.md @@ -85,6 +85,29 @@ selection, and EVM contract auth. ## FeePolicy — canonical user-tx fee gate +> **Topology + UTXO ownership + cross-chain fee model** are normatively +> specified by [**LP-0130** (Chain Topology, UTXO Ownership, and Fee +> Model)](https://github.com/luxfi/lps/blob/main/LPs/lp-0130-chain-topology-utxo-ownership-and-fee-model.md). +> Read that LP before touching any VM's fee/settlement path or any +> cross-chain import/export flow. In particular: +> +> - Only **P** and **X** are canonical UTXO state machines (LP-0130 §2). +> - **X** is the money rail; **P** is the staking/reward rail; **LUX** +> is the fee currency everywhere (LP-0130 §3, §5). +> - **Q-Chain has no user-payable blockspace** — finality is a +> validator obligation paid via P (LP-0130 §6). `quantumvm` MUST +> use `NoUserTxPolicy{}`; the row below is being corrected. +> - **M-Chain fees are service fees** deducted from the originating +> chain's fee pool, not a user M-balance (LP-0130 §7). `mpcvm` +> already runs `NoUserTxPolicy{}` — correct. +> - **B-Chain fees** are deducted from the bridged amount (LP-0130 §8). +> - Every non-P/X chain settles worker rewards to X (asset payouts) or +> P (staker rewards) via epoch fee roots reconciled at Q finality +> (LP-0130 §4, §11). +> - **Σ-escrow invariant** (LP-0130 I-8): `Σ non-P/X fee balances == +> Σ X-side fee escrow` at every Q checkpoint. Drift is a +> finality-blocking fault. + Every Lux VM that accepts user-submitted txs declares a `fee.Policy` (package `vms/types/fee`). There is one interface and one validator — no per-VM bespoke fee structs. @@ -97,14 +120,14 @@ no per-VM bespoke fee structs. | zkvm | Z-Chain | user-tx | `FlatPolicy{Fee: MinTxFeeFloor, ...}` | | aivm | A-Chain | user-tx | `FlatPolicy{Fee: MinTxFeeFloor, ...}` | | keyvm | K-Chain | user-tx | `FlatPolicy{Fee: MinTxFeeFloor, ...}` | -| bridgevm | B-Chain | user-tx | `FlatPolicy{Fee: MinTxFeeFloor, ...}` | -| quantumvm | Q-Chain | user-tx | `FlatPolicy{Fee: MinTxFeeFloor, ...}` | +| bridgevm | B-Chain | user-tx | `FlatPolicy{Fee: MinTxFeeFloor, ...}` (deducted from bridged amount, LP-0130 §8) | +| quantumvm | Q-Chain | **service-only** (LP-0130 §6) | `NoUserTxPolicy{}` — validator obligation, no user-payable blockspace | | identityvm | I-Chain | user-tx | `FlatPolicy{Fee: MinTxFeeFloor, ...}` | -| thresholdvm | M-Chain | service-only | `NoUserTxPolicy{}` | +| mpcvm | M-Chain | service-only (LP-0130 §7) | `NoUserTxPolicy{}` — fees pulled from originating chain's fee pool | | oraclevm | O-Chain | service-only | `NoUserTxPolicy{}` | | relayvm | R-Chain | service-only | `NoUserTxPolicy{}` | | graphvm | G-Chain | read-only | `NoUserTxPolicy{}` (GraphQL refuses `mutation`) | -| evm | C-Chain | user-tx | native EVM gas (gas * gasPrice >= 0 enforced upstream) | +| evm | C-Chain | user-tx | native EVM gas (gas * gasPrice >= 0 enforced upstream); balance is X-imported LUX (LP-0130 §10) | | platformvm | P-Chain | user-tx | native `TxFee` field on Config | | avm | X-Chain | user-tx | native `TxFee` field on Config | @@ -230,7 +253,7 @@ Located in `/vms/`: - **platformvm**: Staking, validation, network management - **xvm**: Asset transfers, UTXO model - **dexvm**: DEX with order book, perpetuals, AMM -- **thresholdvm**: Threshold MPC and FHE for confidential computing +- **mpcvm**: Threshold MPC and FHE for confidential computing - **quantumvm**: PQ consensus coordination (ML-DSA, Corona) - **identityvm**: Decentralized identity (DID, verifiable credentials) - **keyvm**: Post-quantum key management (ML-KEM, ML-DSA) @@ -320,11 +343,11 @@ github.com/luxfi/genesis (JSON config) → github.com/luxfi/node/genesis/build ### CGO Dependencies These require CGO for full functionality (graceful fallback when disabled): - `consensus/quasar` - GPU NTT acceleration -- `vms/thresholdvm/fhe` - GPU FHE operations +- `vms/mpcvm/fhe` - GPU FHE operations - `x/blockdb` - zstd compression ### FHE (Fully Homomorphic Encryption) -Located in `vms/thresholdvm/fhe/`: +Located in `vms/mpcvm/fhe/`: - Uses `github.com/luxfi/lattice/multiparty` for DKG - Lattice-based cryptography only (no fallbacks) - Threshold decryption via Warp messaging @@ -639,7 +662,7 @@ strings.Contains(errStr, "not found") // parent block not in local state ### Known CGO Stubs When CGO disabled, these use CPU fallbacks: - `consensus/quasar/gpu_ntt_nocgo.go` -- `vms/thresholdvm/fhe/gpu_fhe_nocgo.go` +- `vms/mpcvm/fhe/gpu_fhe_nocgo.go` - `vms/zkvm/accel/accel_mlx.go` ### 8. ZAP CreateHandlers for VM HTTP Endpoints diff --git a/SECURITY.md b/SECURITY.md index 7836452bd..d63864575 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -145,7 +145,7 @@ Production implementations live in `lux/crypto/` and `lux/lattice/`. Formal veri | `audits/2025-12-30-other-vms-audit.md` | Secondary VMs | | `audits/2025-12-30-platformvm-audit.md` | PlatformVM (P-Chain) | | `audits/2025-12-30-proposervm-evm-audit.md` | ProposerVM and EVM integration | -| `audits/2025-12-30-thresholdvm-audit.md` | ThresholdVM (T-Chain) | +| `audits/2025-12-30-mpcvm-audit.md` | ThresholdVM (T-Chain) | | `audits/2025-12-30-warp-audit.md` | Warp cross-chain messaging | | `audits/2025-12-30-zkvm-audit.md` | ZKVM (Z-Chain) | diff --git a/genesis/builder/builder.go b/genesis/builder/builder.go index a89efdcbb..c83ba4653 100644 --- a/genesis/builder/builder.go +++ b/genesis/builder/builder.go @@ -54,7 +54,8 @@ var ( QChainAliases = AliasesFor("Q") AChainAliases = AliasesFor("A") BChainAliases = AliasesFor("B") - TChainAliases = AliasesFor("T") + MChainAliases = AliasesFor("M") + FChainAliases = AliasesFor("F") ZChainAliases = AliasesFor("Z") GChainAliases = AliasesFor("G") KChainAliases = AliasesFor("K") @@ -604,7 +605,8 @@ func FromConfig(config *genesiscfg.Config) ([]byte, ids.ID, error) { {[]byte(config.CChainGenesis), constants.EVMID, "C-Chain", nil}, {[]byte(config.DChainGenesis), constants.DexVMID, "D-Chain", nil}, {[]byte(config.BChainGenesis), constants.BridgeVMID, "B-Chain", nil}, - {[]byte(config.TChainGenesis), constants.ThresholdVMID, "T-Chain", nil}, + {[]byte(config.MChainGenesis), constants.MPCVMID, "M-Chain", nil}, + {[]byte(config.FChainGenesis), constants.FHEVMID, "F-Chain", nil}, {[]byte(config.QChainGenesis), constants.QuantumVMID, "Q-Chain", nil}, {[]byte(config.ZChainGenesis), constants.ZKVMID, "Z-Chain", nil}, // A/G/K carry genesis blobs and are deterministic genesis chains @@ -832,16 +834,24 @@ func Aliases(genesisBytes []byte) (map[string][]string, map[ids.ID][]string, err path.Join(constants.ChainAliasPrefix, "bridge"), } chainAliases[chainID] = BChainAliases - case constants.ThresholdVMID: + case constants.MPCVMID: apiAliases[endpoint] = []string{ - "T", - "threshold", - "thresholdvm", + "M", "mpc", - path.Join(constants.ChainAliasPrefix, "T"), - path.Join(constants.ChainAliasPrefix, "threshold"), + "mpcvm", + path.Join(constants.ChainAliasPrefix, "M"), + path.Join(constants.ChainAliasPrefix, "mpc"), } - chainAliases[chainID] = TChainAliases + chainAliases[chainID] = MChainAliases + case constants.FHEVMID: + apiAliases[endpoint] = []string{ + "F", + "fhe", + "fhevm", + path.Join(constants.ChainAliasPrefix, "F"), + path.Join(constants.ChainAliasPrefix, "fhe"), + } + chainAliases[chainID] = FChainAliases case constants.ZKVMID: apiAliases[endpoint] = []string{ "Z", diff --git a/genesis/builder/registry.go b/genesis/builder/registry.go index 780cd0f9b..7f52d3343 100644 --- a/genesis/builder/registry.go +++ b/genesis/builder/registry.go @@ -62,7 +62,8 @@ var Registry = []ChainSpec{ {Letter: "Q", VMID: constants.QuantumVMID, Aliases: []string{"quantum", "quantumvm", "pq"}, Name: "Q-Chain"}, {Letter: "A", VMID: constants.AIVMID, Aliases: []string{"attest", "ai", "aivm"}, Name: "A-Chain"}, {Letter: "B", VMID: constants.BridgeVMID, Aliases: []string{"bridge", "bridgevm"}, Name: "B-Chain"}, - {Letter: "T", VMID: constants.ThresholdVMID, Aliases: []string{"threshold", "thresholdvm", "mpc"}, Name: "T-Chain"}, + {Letter: "M", VMID: constants.MPCVMID, Aliases: []string{"mpc", "mpcvm"}, Name: "M-Chain"}, + {Letter: "F", VMID: constants.FHEVMID, Aliases: []string{"fhe", "fhevm"}, Name: "F-Chain"}, {Letter: "Z", VMID: constants.ZKVMID, Aliases: []string{"zk", "zkvm"}, Name: "Z-Chain"}, {Letter: "G", VMID: constants.GraphVMID, Aliases: []string{"graph", "graphvm", "dgraph"}, Name: "G-Chain"}, {Letter: "K", VMID: constants.KeyVMID, Aliases: []string{"key", "keyvm"}, Name: "K-Chain"}, diff --git a/genesis/builder/registry_test.go b/genesis/builder/registry_test.go index 036d8d7c8..58be8b046 100644 --- a/genesis/builder/registry_test.go +++ b/genesis/builder/registry_test.go @@ -41,7 +41,8 @@ func TestChainAliasesRegistryParity(t *testing.T) { {"Q", QChainAliases, []string{"Q", "quantum", "quantumvm", "pq"}}, {"A", AChainAliases, []string{"A", "attest", "ai", "aivm"}}, {"B", BChainAliases, []string{"B", "bridge", "bridgevm"}}, - {"T", TChainAliases, []string{"T", "threshold", "thresholdvm", "mpc"}}, + {"M", MChainAliases, []string{"M", "mpc", "mpcvm"}}, + {"F", FChainAliases, []string{"F", "fhe", "fhevm"}}, {"Z", ZChainAliases, []string{"Z", "zk", "zkvm"}}, {"G", GChainAliases, []string{"G", "graph", "graphvm", "dgraph"}}, {"K", KChainAliases, []string{"K", "key", "keyvm"}}, @@ -72,7 +73,8 @@ func TestVMAliasesRegistryParity(t *testing.T) { constants.QuantumVMID: {"quantumvm", "quantum", "pq"}, constants.AIVMID: {"aivm", "attest", "ai"}, constants.BridgeVMID: {"bridgevm", "bridge"}, - constants.ThresholdVMID: {"thresholdvm", "threshold", "mpc"}, + constants.MPCVMID: {"mpc", "mpcvm"}, + constants.FHEVMID: {"fhe", "fhevm"}, constants.ZKVMID: {"zkvm", "zk"}, constants.GraphVMID: {"graphvm", "graph", "dgraph"}, constants.KeyVMID: {"keyvm", "key"}, diff --git a/genesis/builder/zzz_gateprobe_test.go b/genesis/builder/zzz_gateprobe_test.go new file mode 100644 index 000000000..a9fd7ba52 --- /dev/null +++ b/genesis/builder/zzz_gateprobe_test.go @@ -0,0 +1,73 @@ +// Copyright (C) 2019-2026, Lux Industries Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// zzz_gateprobe_test.go is a BLUE-team gate instrument for the +// mpcvm-decomplect surgery (LP-134 / LP-7050). NOT a behavioral +// assertion — it emits a deterministic per-chain digest of the fully +// built P-Chain genesis for every network so before/after can be diffed +// to PROVE which chains changed and which stayed byte-identical. +// zzz_ prefix keeps it last. Delete after RED sign-off. +package builder + +import ( + "crypto/sha256" + "encoding/hex" + "fmt" + "sort" + "testing" + + "github.com/luxfi/node/vms/platformvm/genesis" + pchaintxs "github.com/luxfi/node/vms/platformvm/txs" +) + +func TestZZZ_GateProbe_PerChainDigest(t *testing.T) { + nets := []struct { + name string + id uint32 + }{ + {"mainnet", 1}, + {"testnet", 2}, + {"devnet", 3}, + {"localnet", 1337}, + } + + for _, n := range nets { + cfg := GetConfig(n.id) + if cfg == nil { + t.Fatalf("%s GetConfig: nil", n.name) + } + gb, rootID, err := FromConfig(cfg) + if err != nil { + t.Fatalf("%s FromConfig: %v", n.name, err) + } + gen, err := genesis.Parse(gb) + if err != nil { + t.Fatalf("%s Parse: %v", n.name, err) + } + + type row struct { + name string + vmid string + dataSum string + chainID string + } + rows := make([]row, 0, len(gen.Chains)) + for _, c := range gen.Chains { + u := c.Unsigned.(*pchaintxs.CreateChainTx) + sum := sha256.Sum256(u.GenesisData) + rows = append(rows, row{ + name: u.BlockchainName, + vmid: u.VMID.String(), + dataSum: hex.EncodeToString(sum[:]), + chainID: c.ID().String(), + }) + } + sort.Slice(rows, func(i, j int) bool { return rows[i].name < rows[j].name }) + + fmt.Printf("=== NET %s (id=%d) P-ROOT=%s ===\n", n.name, n.id, rootID.String()) + for _, r := range rows { + fmt.Printf(" CHAIN name=%-10s vmid=%-52s dataSHA256=%s chainTxID=%s\n", + r.name, r.vmid, r.dataSum, r.chainID) + } + } +} diff --git a/node/vms.go b/node/vms.go index 241282e15..e1344c687 100644 --- a/node/vms.go +++ b/node/vms.go @@ -124,7 +124,8 @@ var OptionalVMs = map[ids.ID]PluginSpec{ constants.KeyVMID: {Name: "keyvm"}, constants.OracleVMID: {Name: "oraclevm"}, constants.RelayVMID: {Name: "relayvm"}, - constants.ThresholdVMID: {Name: "thresholdvm"}, + constants.MPCVMID: {Name: "mpcvm"}, + constants.FHEVMID: {Name: "fhevm"}, } func init() { diff --git a/node/vms_purity_test.go b/node/vms_purity_test.go index 7c880458f..05a1bf51a 100644 --- a/node/vms_purity_test.go +++ b/node/vms_purity_test.go @@ -58,7 +58,7 @@ func TestOptionalVMsNotLinkedInProcess(t *testing.T) { "github.com/luxfi/chains/keyvm", "github.com/luxfi/chains/oraclevm", "github.com/luxfi/chains/relayvm", - "github.com/luxfi/chains/thresholdvm", + "github.com/luxfi/chains/mpcvm", } for _, pkg := range []string{"./node/", "./main"} { deps := goListDeps(t, pkg) diff --git a/scripts/publish_plugin_set.sh b/scripts/publish_plugin_set.sh index 27bfe052a..46face6d6 100755 --- a/scripts/publish_plugin_set.sh +++ b/scripts/publish_plugin_set.sh @@ -60,7 +60,7 @@ PLUGINS=( r5m1ujrmXxVcQetG3CQfuDLHp2RHKh6vCDaFgBRQfUcTZh7eS # oraclevm ry9Sg8rZdT26iEKvJDmC2wkESs4SDKgZEhk5BgLSwg1EpcNug # quantumvm sP6dLqrrBR9w3soP18fbJ3YzZecZdD7DDdfH2cFhhLq7Hy9bz # relayvm - tGVBwRxpmD2aFdg3iYjgRvrCe8Jcmq9UNKxyHMus2NZ8WcD8t # thresholdvm + tGVBwRxpmD2aFdg3iYjgRvrCe8Jcmq9UNKxyHMus2NZ8WcD8t # mpcvm vv3qPfyTVXZ5ArRZA9Jh4hbYDTBe43f7sgQg4CHfNg1rnnvX9 # zkvm ) diff --git a/vms/thresholdvm/backend.go b/vms/mpcvm/backend.go similarity index 71% rename from vms/thresholdvm/backend.go rename to vms/mpcvm/backend.go index 936e2e3af..8c00200f6 100644 --- a/vms/thresholdvm/backend.go +++ b/vms/mpcvm/backend.go @@ -1,9 +1,9 @@ // Copyright (C) 2026, Lux Industries Inc. All rights reserved. // See the file LICENSE for licensing terms. -// Package thresholdvm — backend selection re-export. +// Package mpcvm — backend selection re-export. // -// The canonical dlopen probe lives in github.com/luxfi/chains/thresholdvm. +// The canonical dlopen probe lives in github.com/luxfi/chains/mpcvm. // Its init() runs once at package load time and pins a process-wide // GPUBackend handle (cuda → hip → metal → vulkan → webgpu probe order). // This file is the node-side entry point for diagnostics and ops tooling. @@ -13,20 +13,20 @@ // NOT yet registered in running luxd"). This file provides the bridge // surface only — flipping the manager hook-up is a separate ops PR. -package thresholdvm +package mpcvm // SelectGPUBackend returns the resolved GPU plugin (or nil) and a single // human-readable diagnostic string. luxd startup logs use this to surface -// "thresholdvm-gpu backend=" lines alongside the cevm backend +// "mpcvm-gpu backend=" lines alongside the cevm backend // selection, matching the cevm.go pattern at // ~/work/lux/chains/evm/backend_cgo.go. // // Calling this multiple times is cheap — the underlying probe runs once -// at package init via sync.Once in chains/thresholdvm/backend.go. +// at package init via sync.Once in chains/mpcvm/backend.go. func SelectGPUBackend() (*GPUBackend, string) { g := GPUBackendInstance() if g == nil || !g.IsAvailable() { - return nil, "thresholdvm-gpu: no plugin resolved (CPU-only)" + return nil, "mpcvm-gpu: no plugin resolved (CPU-only)" } - return g, "thresholdvm-gpu: backend=" + g.Kind.String() + " path=" + g.Path + return g, "mpcvm-gpu: backend=" + g.Kind.String() + " path=" + g.Path } diff --git a/vms/mpcvm/mpcvm.go b/vms/mpcvm/mpcvm.go new file mode 100644 index 000000000..ae571ede8 --- /dev/null +++ b/vms/mpcvm/mpcvm.go @@ -0,0 +1,27 @@ +// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +// Package mpcvm re-exports the canonical Threshold (FHE / MPC) +// VM from github.com/luxfi/chains/mpcvm so existing callers +// that imported github.com/luxfi/node/vms/mpcvm pre-extraction +// keep working without source changes. +// +// New code should import the canonical path: +// "github.com/luxfi/chains/mpcvm" +// +// This file is a thin alias wrapper kept for backward compatibility. +package mpcvm + +import "github.com/luxfi/chains/mpcvm" + +type ( + Block = mpcvm.Block + BlockError = mpcvm.BlockError + Client = mpcvm.Client + Operation = mpcvm.Operation +) + +var ( + ErrInvalidOperation = mpcvm.ErrInvalidOperation + NewClient = mpcvm.NewClient +) diff --git a/vms/thresholdvm/thresholdvm_gpu.go b/vms/mpcvm/mpcvm_gpu.go similarity index 56% rename from vms/thresholdvm/thresholdvm_gpu.go rename to vms/mpcvm/mpcvm_gpu.go index 578b77e6c..64a6efd0f 100644 --- a/vms/thresholdvm/thresholdvm_gpu.go +++ b/vms/mpcvm/mpcvm_gpu.go @@ -3,20 +3,20 @@ //go:build cgo -// Package thresholdvm re-exports the GPU bridge from -// github.com/luxfi/chains/thresholdvm so callers that import the legacy +// Package mpcvm re-exports the GPU bridge from +// github.com/luxfi/chains/mpcvm so callers that import the legacy // node path keep working without source changes. // // One and only one way to dlopen: the canonical bridge lives in -// chains/thresholdvm. This package is a typed alias layer — both the +// chains/mpcvm. This package is a typed alias layer — both the // types and the GPUBackend singleton come straight from the upstream. // There is exactly one dlopen handle, one symbol table, one init() // probe across the entire luxd process. Consumers of either import path // share the same plugin instance. -package thresholdvm +package mpcvm -import "github.com/luxfi/chains/thresholdvm" +import "github.com/luxfi/chains/mpcvm" // ============================================================================= // Type re-exports — Go aliases preserve the public API so external callers @@ -26,37 +26,37 @@ import "github.com/luxfi/chains/thresholdvm" // ============================================================================= type ( - GPUBackend = thresholdvm.GPUBackend - GPUBackendKind = thresholdvm.GPUBackendKind + GPUBackend = mpcvm.GPUBackend + GPUBackendKind = mpcvm.GPUBackendKind - GPUCeremony = thresholdvm.GPUCeremony - GPUKeyShare = thresholdvm.GPUKeyShare - GPUContribution = thresholdvm.GPUContribution - GPUMPCVMState = thresholdvm.GPUMPCVMState - GPUMPCVMRoundDescriptor = thresholdvm.GPUMPCVMRoundDescriptor - GPUCeremonyOp = thresholdvm.GPUCeremonyOp - GPUContributionOp = thresholdvm.GPUContributionOp - GPUMPCVMTransitionResult = thresholdvm.GPUMPCVMTransitionResult + GPUCeremony = mpcvm.GPUCeremony + GPUKeyShare = mpcvm.GPUKeyShare + GPUContribution = mpcvm.GPUContribution + GPUMPCVMState = mpcvm.GPUMPCVMState + GPUMPCVMRoundDescriptor = mpcvm.GPUMPCVMRoundDescriptor + GPUCeremonyOp = mpcvm.GPUCeremonyOp + GPUContributionOp = mpcvm.GPUContributionOp + GPUMPCVMTransitionResult = mpcvm.GPUMPCVMTransitionResult ) -// Backend constants re-exported. Matches the chains/thresholdvm dlopen +// Backend constants re-exported. Matches the chains/mpcvm dlopen // probe order: cuda → hip → metal → vulkan → webgpu. const ( - GPUBackendNone = thresholdvm.GPUBackendNone - GPUBackendCUDA = thresholdvm.GPUBackendCUDA - GPUBackendHIP = thresholdvm.GPUBackendHIP - GPUBackendMetal = thresholdvm.GPUBackendMetal - GPUBackendVulkan = thresholdvm.GPUBackendVulkan - GPUBackendWebGPU = thresholdvm.GPUBackendWebGPU + GPUBackendNone = mpcvm.GPUBackendNone + GPUBackendCUDA = mpcvm.GPUBackendCUDA + GPUBackendHIP = mpcvm.GPUBackendHIP + GPUBackendMetal = mpcvm.GPUBackendMetal + GPUBackendVulkan = mpcvm.GPUBackendVulkan + GPUBackendWebGPU = mpcvm.GPUBackendWebGPU ) // ErrGPUNotAvailable is the canonical "no plugin loaded" error. Callers -// `errors.Is(err, thresholdvm.ErrGPUNotAvailable)` to distinguish a +// `errors.Is(err, mpcvm.ErrGPUNotAvailable)` to distinguish a // fallback-to-CPU condition from a hard launcher failure. -var ErrGPUNotAvailable = thresholdvm.ErrGPUNotAvailable +var ErrGPUNotAvailable = mpcvm.ErrGPUNotAvailable // GPUBackendInstance returns the dlopen'd GPU plugin handle resolved at -// chains/thresholdvm package init. nil means no plugin was loaded +// chains/mpcvm package init. nil means no plugin was loaded // (CPU-only mode). The handle is shared across the whole process — both // the node and chains paths see the same instance. // @@ -65,7 +65,7 @@ var ErrGPUNotAvailable = thresholdvm.ErrGPUNotAvailable // package, and `Backend` is already a domain term in the threshold // state machine. Callers write: // -// if g := thresholdvm.GPUBackendInstance(); g != nil && g.IsAvailable() { +// if g := mpcvm.GPUBackendInstance(); g != nil && g.IsAvailable() { // _, err := g.CeremonyApply(desc, ops, ceremonies) // ... // } @@ -74,5 +74,5 @@ var ErrGPUNotAvailable = thresholdvm.ErrGPUNotAvailable // `cevm.LibraryABIVersion()` — discovery via package-scope function, // not via a global variable. func GPUBackendInstance() *GPUBackend { - return thresholdvm.Backend() + return mpcvm.Backend() } diff --git a/vms/mpcvm/mpcvm_gpu_nocgo.go b/vms/mpcvm/mpcvm_gpu_nocgo.go new file mode 100644 index 000000000..a08290c23 --- /dev/null +++ b/vms/mpcvm/mpcvm_gpu_nocgo.go @@ -0,0 +1,49 @@ +// Copyright (C) 2026, Lux Industries Inc. All rights reserved. +// See the file LICENSE for licensing terms. + +//go:build !cgo + +// nocgo re-export of the chains/mpcvm GPU bridge. Under !cgo the +// upstream GPUBackend methods all return ErrGPUNotAvailable and +// Backend() returns nil; this layer transparently passes that through +// so callers see identical behaviour regardless of build mode. +// +// One and only one nocgo stub for the entire process: it lives in +// chains/mpcvm. This package just re-exports the types and the +// sentinel error. + +package mpcvm + +import "github.com/luxfi/chains/mpcvm" + +type ( + GPUBackend = mpcvm.GPUBackend + GPUBackendKind = mpcvm.GPUBackendKind + + GPUCeremony = mpcvm.GPUCeremony + GPUKeyShare = mpcvm.GPUKeyShare + GPUContribution = mpcvm.GPUContribution + GPUMPCVMState = mpcvm.GPUMPCVMState + GPUMPCVMRoundDescriptor = mpcvm.GPUMPCVMRoundDescriptor + GPUCeremonyOp = mpcvm.GPUCeremonyOp + GPUContributionOp = mpcvm.GPUContributionOp + GPUMPCVMTransitionResult = mpcvm.GPUMPCVMTransitionResult +) + +const ( + GPUBackendNone = mpcvm.GPUBackendNone + GPUBackendCUDA = mpcvm.GPUBackendCUDA + GPUBackendHIP = mpcvm.GPUBackendHIP + GPUBackendMetal = mpcvm.GPUBackendMetal + GPUBackendVulkan = mpcvm.GPUBackendVulkan + GPUBackendWebGPU = mpcvm.GPUBackendWebGPU +) + +var ErrGPUNotAvailable = mpcvm.ErrGPUNotAvailable + +// GPUBackendInstance returns nil under !cgo — the upstream Backend() +// returns nil because no dlopen ever happens. Callers branch on the +// IsAvailable() check (or `g == nil`) and route to the CPU reference. +func GPUBackendInstance() *GPUBackend { + return mpcvm.Backend() +} diff --git a/vms/thresholdvm/thresholdvm_gpu_parity_test.go b/vms/mpcvm/mpcvm_gpu_parity_test.go similarity index 95% rename from vms/thresholdvm/thresholdvm_gpu_parity_test.go rename to vms/mpcvm/mpcvm_gpu_parity_test.go index d859a3db4..e5ea33202 100644 --- a/vms/thresholdvm/thresholdvm_gpu_parity_test.go +++ b/vms/mpcvm/mpcvm_gpu_parity_test.go @@ -1,14 +1,14 @@ // Copyright (C) 2026, Lux Industries Inc. All rights reserved. // See the file LICENSE for licensing terms. -package thresholdvm +package mpcvm // TestGPUBridgeCgoNocgoParity is the node-side mirror of the parity -// test in chains/thresholdvm — proves that the re-exported GPUBackend +// test in chains/mpcvm — proves that the re-exported GPUBackend // method set produces byte-identical MPC ceremony state transitions // regardless of build flavor (cgo / nocgo) and plugin presence. // -// The node package is a thin alias layer over chains/thresholdvm — +// The node package is a thin alias layer over chains/mpcvm — // type aliases on the wire structs and a re-exported GPUBackendInstance // accessor — so the parity properties of the canonical bridge transfer // directly. We re-run the four-op pipeline through the node-side @@ -19,13 +19,13 @@ import ( "strings" "testing" - chainsthreshold "github.com/luxfi/chains/thresholdvm" + chainsthreshold "github.com/luxfi/chains/mpcvm" ) // TestGPUBridgeCgoNocgoParity runs a 3-of-5 FROST keygen ceremony // through GPUBackendInstance() (the node-side accessor) and compares // the resulting arena byte-for-byte to a fresh run via the canonical -// bridge in chains/thresholdvm. Under cgo, the comparison is the +// bridge in chains/mpcvm. Under cgo, the comparison is the // upstream cgo bridge vs itself (both runs hit the same dispatcher). // Under !cgo, the comparison is the upstream nocgo bridge vs itself. // Either path proves the alias layer is transparent and the substrate diff --git a/vms/thresholdvm/thresholdvm_gpu_test.go b/vms/mpcvm/mpcvm_gpu_test.go similarity index 97% rename from vms/thresholdvm/thresholdvm_gpu_test.go rename to vms/mpcvm/mpcvm_gpu_test.go index ba311ae81..b9e305c00 100644 --- a/vms/thresholdvm/thresholdvm_gpu_test.go +++ b/vms/mpcvm/mpcvm_gpu_test.go @@ -1,7 +1,7 @@ // Copyright (C) 2026, Lux Industries Inc. All rights reserved. // See the file LICENSE for licensing terms. -package thresholdvm +package mpcvm import ( "errors" @@ -13,7 +13,7 @@ import ( // device-side __align__(16) values declared in // the GPU plugin install tree ops/mpcvm/cuda/mpcvm_kernels_common.cuh. // -// Even though the structs are type aliases to chains/thresholdvm, this +// Even though the structs are type aliases to chains/mpcvm, this // test sits at the node import boundary — if upstream sizes drift the // node-side surface MUST also fail loud rather than miscompile. func TestNodeGPULayoutSizes(t *testing.T) { diff --git a/vms/thresholdvm/thresholdvm.go b/vms/thresholdvm/thresholdvm.go deleted file mode 100644 index 77642ed05..000000000 --- a/vms/thresholdvm/thresholdvm.go +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -// Package thresholdvm re-exports the canonical Threshold (FHE / MPC) -// VM from github.com/luxfi/chains/thresholdvm so existing callers -// that imported github.com/luxfi/node/vms/thresholdvm pre-extraction -// keep working without source changes. -// -// New code should import the canonical path: -// "github.com/luxfi/chains/thresholdvm" -// -// This file is a thin alias wrapper kept for backward compatibility. -package thresholdvm - -import "github.com/luxfi/chains/thresholdvm" - -type ( - Block = thresholdvm.Block - BlockError = thresholdvm.BlockError - Client = thresholdvm.Client - Operation = thresholdvm.Operation -) - -var ( - ErrInvalidOperation = thresholdvm.ErrInvalidOperation - NewClient = thresholdvm.NewClient -) diff --git a/vms/thresholdvm/thresholdvm_gpu_nocgo.go b/vms/thresholdvm/thresholdvm_gpu_nocgo.go deleted file mode 100644 index 7acd43413..000000000 --- a/vms/thresholdvm/thresholdvm_gpu_nocgo.go +++ /dev/null @@ -1,49 +0,0 @@ -// Copyright (C) 2026, Lux Industries Inc. All rights reserved. -// See the file LICENSE for licensing terms. - -//go:build !cgo - -// nocgo re-export of the chains/thresholdvm GPU bridge. Under !cgo the -// upstream GPUBackend methods all return ErrGPUNotAvailable and -// Backend() returns nil; this layer transparently passes that through -// so callers see identical behaviour regardless of build mode. -// -// One and only one nocgo stub for the entire process: it lives in -// chains/thresholdvm. This package just re-exports the types and the -// sentinel error. - -package thresholdvm - -import "github.com/luxfi/chains/thresholdvm" - -type ( - GPUBackend = thresholdvm.GPUBackend - GPUBackendKind = thresholdvm.GPUBackendKind - - GPUCeremony = thresholdvm.GPUCeremony - GPUKeyShare = thresholdvm.GPUKeyShare - GPUContribution = thresholdvm.GPUContribution - GPUMPCVMState = thresholdvm.GPUMPCVMState - GPUMPCVMRoundDescriptor = thresholdvm.GPUMPCVMRoundDescriptor - GPUCeremonyOp = thresholdvm.GPUCeremonyOp - GPUContributionOp = thresholdvm.GPUContributionOp - GPUMPCVMTransitionResult = thresholdvm.GPUMPCVMTransitionResult -) - -const ( - GPUBackendNone = thresholdvm.GPUBackendNone - GPUBackendCUDA = thresholdvm.GPUBackendCUDA - GPUBackendHIP = thresholdvm.GPUBackendHIP - GPUBackendMetal = thresholdvm.GPUBackendMetal - GPUBackendVulkan = thresholdvm.GPUBackendVulkan - GPUBackendWebGPU = thresholdvm.GPUBackendWebGPU -) - -var ErrGPUNotAvailable = thresholdvm.ErrGPUNotAvailable - -// GPUBackendInstance returns nil under !cgo — the upstream Backend() -// returns nil because no dlopen ever happens. Callers branch on the -// IsAvailable() check (or `g == nil`) and route to the CPU reference. -func GPUBackendInstance() *GPUBackend { - return thresholdvm.Backend() -} diff --git a/vms/types/fee/policy.go b/vms/types/fee/policy.go index e4765ee0e..b5475122c 100644 --- a/vms/types/fee/policy.go +++ b/vms/types/fee/policy.go @@ -9,7 +9,7 @@ // charging 1,000x too little (quantumvm). The root cause was that fee // policy lived as ad-hoc fields on each VM's Config — there was no shared // surface to enforce a non-zero floor, and no sentinel for chains that -// legitimately accept no user txs (thresholdvm, oraclevm, relayvm — +// legitimately accept no user txs (mpcvm, oraclevm, relayvm — // committee-driven, no user mempool). // // This package provides exactly one way to declare a fee policy: @@ -122,7 +122,7 @@ func (p FlatPolicy) ValidateFee(paid uint64, asset ids.ID) error { } // NoUserTxPolicy is the sentinel policy for chains that accept no -// user-submitted txs — committee-driven only (thresholdvm, oraclevm, +// user-submitted txs — committee-driven only (mpcvm, oraclevm, // relayvm). Distinguishing this from "policy not set" is what makes // Manager's boot-time Validate able to refuse zero-fee user-facing // chains without false-positive-ing the committee chains.