Files
zeekay 275fe22047 teleport/mpc: retarget signers at mpcd; canonicalize MPCD_URL
The unified Go daemon teleport's threshold signers talk to is now
luxfi/mpc's production binary mpcd, which embeds the JSON-RPC
dispatcher from luxfi/threshold/pkg/thresholdd on its
--threshold-listen port (default 127.0.0.1:7300). There is no
separate thresholdd to deploy.

Changes:

- rpc.ts: add defaultMpcdUrl() / defaultMpcdTransport() as the single
  source of truth for daemon URL resolution. Precedence:
    MPCD_URL > THRESHOLD_DAEMON_URL > http://127.0.0.1:7300
  THRESHOLD_DAEMON_URL is kept as a back-compat alias for environments
  that already set it against the standalone thresholdd CLI.

- cggmp21.ts / pulsar.ts / corona.ts: drop per-file defaultTransport()
  duplication, route through defaultMpcdTransport(). Prose updated to
  mention mpcd instead of thresholdd.

- frost.ts: envTransport() now honors both env vars (MPCD_URL first).
  Default path stays in-process @noble/curves; daemon path is opt-in.

- __tests__/signers.test.ts: rename "→ thresholdd" describe to
  "→ mpcd"; add three new tests pinning the env-var precedence
  contract (MPCD_URL > THRESHOLD_DAEMON_URL > loopback).

- index.ts: fail-closed LUX_PROFILE resolution (from prior work in
  this session) — no implicit ECDSA fallback when profile is unset,
  symmetric refusal when profile and scheme disagree, hybrid warns
  on every scheme choice. Pairs with the mpcd routing so the wire a
  caller picks is always the wire the gate expects.

Test count: 28 → 31 (signers suite). All pass.
2026-05-13 15:58:31 -07:00

69 lines
2.2 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "../contracts/interfaces/IVerifier.sol";
import "@luxfi/p3q-evm/src/IP3QVerifier.sol";
import "@luxfi/pq-profile-ids/src/PQProfileIDs.sol";
import "../contracts/StrictPQProfileGate.sol";
/// @dev Test-only mock that returns a configured policyId. Lets the
/// StrictPQProfileGate test exercise allow / refuse paths without
/// depending on a real proof backend.
contract MockVerifier is IVerifier {
bytes32 private immutable _policyId;
constructor(bytes32 policy) {
_policyId = policy;
}
function verify(bytes calldata, bytes32) external pure returns (bool) {
return true;
}
function policyId() external view returns (bytes32) {
return _policyId;
}
}
/// @dev Thin harness so the library `internal view` function can be
/// reached from Hardhat tests.
contract StrictPQProfileGateHarness {
function check(bytes32 profile, IVerifier verifier) external view {
StrictPQProfileGate.refuseUnderStrictPQ(profile, verifier);
}
function profileClassical() external pure returns (bytes32) {
return StrictPQProfileGate.PROFILE_CLASSICAL_COMPAT;
}
function profileStrictPQ() external pure returns (bytes32) {
return StrictPQProfileGate.PROFILE_QUASAR_STRICT_PQ;
}
function policyGroth16BN254() external pure returns (bytes32) {
return StrictPQProfileGate.POLICY_GROTH16_BN254;
}
function policyPLONKBN254() external pure returns (bytes32) {
return StrictPQProfileGate.POLICY_PLONK_BN254;
}
function policyKZGBLS12381() external pure returns (bytes32) {
return StrictPQProfileGate.POLICY_KZG_BLS12381;
}
}
/// @dev Test-only IP3QVerifier mock with a NON-PQ policyId (Groth16).
/// Exercises the gate-fires-first path in `claimWithProof`.
contract NonPQP3QStub is IP3QVerifier {
function policyId() external pure returns (bytes32) {
return PQProfileIDs.POLICY_GROTH16_BN254;
}
function verify(bytes calldata, bytes32) external returns (bool) {
// Would happily accept any proof — but the gate should refuse
// this verifier before we ever get here under strict-PQ.
return true;
}
}