node: rename thresholdvm → mpcvm; split M/F registries (LP-0130)

- 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 <dev@hanzo.ai>
This commit is contained in:
zeekay
2026-07-03 01:23:03 -07:00
co-authored by Hanzo Dev
parent 97d9745ea9
commit d4323da799
19 changed files with 257 additions and 147 deletions
+4 -4
View File
@@ -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 ) && \
+31 -8
View File
@@ -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
+1 -1
View File
@@ -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) |
+19 -9
View File
@@ -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",
+2 -1
View File
@@ -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"},
+4 -2
View File
@@ -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"},
+73
View File
@@ -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)
}
}
}
+2 -1
View File
@@ -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() {
+1 -1
View File
@@ -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)
+1 -1
View File
@@ -60,7 +60,7 @@ PLUGINS=(
r5m1ujrmXxVcQetG3CQfuDLHp2RHKh6vCDaFgBRQfUcTZh7eS # oraclevm
ry9Sg8rZdT26iEKvJDmC2wkESs4SDKgZEhk5BgLSwg1EpcNug # quantumvm
sP6dLqrrBR9w3soP18fbJ3YzZecZdD7DDdfH2cFhhLq7Hy9bz # relayvm
tGVBwRxpmD2aFdg3iYjgRvrCe8Jcmq9UNKxyHMus2NZ8WcD8t # thresholdvm
tGVBwRxpmD2aFdg3iYjgRvrCe8Jcmq9UNKxyHMus2NZ8WcD8t # mpcvm
vv3qPfyTVXZ5ArRZA9Jh4hbYDTBe43f7sgQg4CHfNg1rnnvX9 # zkvm
)
@@ -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=<name>" lines alongside the cevm backend
// "mpcvm-gpu backend=<name>" 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
}
+27
View File
@@ -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
)
@@ -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()
}
+49
View File
@@ -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()
}
@@ -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
@@ -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) {
-27
View File
@@ -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
)
-49
View File
@@ -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()
}
+2 -2
View File
@@ -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.