Commit Graph
798 Commits
Author SHA1 Message Date
zeekayandGitHub 28b515ebb0 Merge pull request #17 from luxfi/fix/cc-published-leaf-v0.3.0
build(mpc): pin luxfi/cc v0.3.0 (published leaf), drop local ../cc replace
v1.17.1
2026-07-07 17:50:34 -07:00
zeekay 3bee998a73 build(mpc): image-buildable main — pin luxfi/cc v0.3.0, fix poisoned go.sum
Two fixes that make the clean-proxy Docker image build of main succeed:

1. luxfi/cc is now a PUBLISHED public module (immutable proxy+sumdb).
   Pin v0.3.0 (converged 6-vendor attestation verifier) and drop the local
   '=> ../cc' replace so the Docker 'COPY . .' context (no ../cc) resolves
   cc from the proxy. Also unblocks luxfi/dkg (dealerless threshold dep),
   now public.

2. go.sum had two poisoned zip hashes (luxfi/age v1.4.0, luxfi/pq v1.0.3)
   recorded from re-tagged 'direct' GitHub instead of the immutable
   proxy+sumdb — the clean-proxy Dockerfile rejected them (SECURITY ERROR).
   Restored the authentic sum.golang.org values.

Verified (fresh modcache, immutable proxy+sumdb, GOWORK=off, default tags):
  go build ./... = 0, go test ./cmd/... ./pkg/... = 33 ok.
  (2 BLS-dispatcher + 1 CAS-race failures pre-exist on v1.17.0 from the
   threshold v1.12.0 dealerless bump; unrelated to this dep change —
   confirmed identical failure with cc reverted to ../cc.)
2026-07-07 17:50:25 -07:00
zeekayandHanzo Dev bfb347d69b fix: gate experimental_tfhe + fail-closed stub; bump threshold v1.12.0 (dealerless daemon) + pulsar v1.9.0
Co-authored-by: Hanzo Dev <[email protected]>
v1.17.0
2026-06-30 16:41:50 -07:00
zeekayandHanzo Dev 0e2bdf443e bump: latest dealerless PQ (corona v0.10.3, pulsar v1.8.0)
Co-authored-by: Hanzo Dev <[email protected]>
2026-06-30 13:26:15 -07:00
zeekay a6f69bef5d docs(brand): add hero banner 2026-06-28 20:35:25 -07:00
zeekay 4abc85fc53 chore(brand): dynamic hero banner 2026-06-28 20:35:25 -07:00
zeekay 9030a79d4a bump: dealerless pulsar/corona/dkg/mlwe (no trusted dealer, no-reconstruct)
Move to the dealerless threshold-signature stack: corona v0.10.2 (Module-LWE
Ringtail, dealerless Pedersen-VSS) + pulsar v1.7.1 (dealerless Mithril RSS keygen
+ no-reconstruct signing, trusted dealer ripped) + dkg v0.3.5 + mlwe v0.2.1.
2026-06-28 19:41:12 -07:00
zeekay 3d8d9c98d6 build: drop GOPRIVATE/GONOSUMDB + resolve poisoned deps via immutable proxy+sumdb
luxfi/* and hanzoai/* are PUBLIC Go modules. The GOPRIVATE / GONOSUMDB /
GOPROXY=direct env in Dockerfile + release.yml routed fetches around
proxy.golang.org + sum.golang.org, "working" only by skipping checksum
verification — which poisons go.sum with force-republished git bytes that no
longer match the immutable checksum db. Drop the bypass; resolve every
luxfi/hanzoai checksum from the public proxy + sumdb instead.

Poisoned deps resolved (strip luxfi/hanzoai go.sum lines, then go mod tidy):
- github.com/luxfi/edwards25519 v0.1.0 -> v0.1.1 (the agl/ed25519 replace
  target, in both go.mod and e2e/go.mod): v0.1.0 was force-republished, its zip
  hash diverges from the sum.golang.org pin and no copy verifies; v0.1.1 is the
  clean patch the proxy + sumdb agree on.
- github.com/luxfi/age v1.4.0, github.com/luxfi/zap v0.8.1: version healthy, but
  go.sum carried poisoned zip hashes — corrected to the sumdb canonical values.
- e2e/go.sum: also completed to the full canonical checksum set (hack-era builds
  with GOPROXY=direct skip go.sum completion).

Verified with GOWORK=off (matching the .dockerignore'd workspace + CI):
- go mod verify -> all modules verified (main + e2e)
- CGO_ENABLED=0 go build ./... clean (main + e2e)
- go test ./... -> 35 ok / 0 FAIL; signing, threshold, keygen, attestation, kms,
  ristretto255 curve, sr25519, and policy-gated sign-flow tests all pass. No
  crypto regression from the edwards25519 curve-lib bump.
2026-06-28 15:14:15 -07:00
zeekay dd8c3631da Revert "build: drop GOPRIVATE/GONOSUMDB — public modules use immutable proxy+sumdb"
This reverts commit 4e2432f633dcd0a6fff8b9ac258c8c7a4b310d76.
2026-06-28 14:53:44 -07:00
zeekay a291a1778f build: drop GOPRIVATE/GONOSUMDB — public modules use immutable proxy+sumdb
luxfi/* and hanzoai/* Go modules are public; GONOSUMDB/GOPRIVATE routed them
direct and bypassed sum.golang.org, so a force-republished tag could poison the
build. Resolve via the public proxy+sumdb (canonical immutable hashes).
2026-06-28 14:51:39 -07:00
zeekay acd726682a examples: port bitcoin/ethereum/lux/solana/tfhe MPC signing demos from hanzoai/mpc
Consolidate the hanzoai/mpc repo into luxfi/mpc (the canonical, deployed MPC —
v1.16.0, running as ghcr.io/luxfi/mpc across all clusters). hanzoai/mpc (legacy
v1.0.6) carried 5 chain-specific threshold-signing examples luxfi/mpc lacked;
they already import github.com/luxfi/mpc/pkg/threshold, so this is a clean port.
hanzoai/mpc is being archived — nothing imports it and the deployments already
run luxfi/mpc.
2026-06-28 14:49:40 -07:00
zeekay 5e04d411e2 refactor(attest): consume the github.com/luxfi/cc leaf; KindNRAS→KindNVTrust
The canonical attestation verifier (cc/attest + pkg/attestation/nvidia) was
extracted into the orthogonal leaf module github.com/luxfi/cc so mpc, the TEE
custody extension, and the confidential-AI system can share ONE verifier
coupled to none of their domains.

- pkg/attestation/composite.go, pkg/kms/release.go: import the leaf
  github.com/luxfi/cc/attest directly; map the NVIDIA issuer to the real
  KindNVTrust (was the KindNRAS stub).
- pkg/attestation/nvidia + cc/attest/{sev,tdx,verifier,...}.go: moved to the
  leaf (clean stdlib/go-sev-guest leaves, zero mpc-internal imports).
- cc/attest now a thin TRANSITION ADAPTER: a zero-logic re-export of the leaf
  (type aliases ⇒ identical types, so the kms.CompositeAttestation release
  gate is satisfied from either import path) plus the deprecated KindNRAS
  symbol that pinned github.com/luxfi/threshold v1.9.9 still references. To be
  removed once threshold republishes against the leaf (its main already has)
  and mpc's threshold/protocols/tfhe dep is resolved.

go.mod: require github.com/luxfi/cc (local replace ../cc until tagged);
threshold stays v1.9.9 (cannot bump: main drops protocols/tfhe that pkg/mpc
needs). go vet ./... clean; attestation/kms/scheduler tests green.
v1.16.0
2026-06-27 12:33:40 -07:00
zeekay 4508cb3f2a security(mpcd): wire fail-closed strict-PQ chain-profile gate — Red M-2
The embedded threshold dispatcher's Sign_Ctx_Profile consults a
thresholdd.ChainProfileResolver before allowing the single-party dealer
shortcut on ctx-bound signing (pulsar/magnetar sign_ctx). mpcd built the
ZapServer with NO resolver, so the gate fell to its documented fail-OPEN
branch — every chainID, strict-PQ chains included, slipped the gate.

Wire the node's chain-profile posture into the dispatcher BEFORE Start:
  - --chain-profile (MPC_CHAIN_PROFILE), default strict-pq → fail-closed.
    Any non-empty chainID not allow-listed resolves to ProfileStrictPQ and
    the dealer shortcut is REFUSED.
  - --legacy-chains (MPC_LEGACY_CHAINS): explicit allow-list of chainIDs
    permitted the shortcut (dev / non-PQ chains co-served by a strict node).

Resolver is the canonical thresholdd.NewStaticChainProfileResolver — no
bespoke type, no luxfi/consensus/config dependency.

Residual: thresholdd.RefuseUnderStrictPQ short-circuits empty chainID to
PASS before consulting the resolver; that short-circuit lives inside the
threshold gate (threshold owns the listener, read-only here). The resolver
wired here is already fail-closed for "" (ResolveChainProfile("") ==
ProfileStrictPQ), so the residual closes the instant the threshold gate
routes "" through the resolver — a one-line change in
threshold/pkg/thresholdd/profile.go (drop `|| chainID == ""`).

Tests: TestStrictPQGate_FailClosed / _LegacyDefaultPermissive drive the
real gate proving refuse-by-default + allow-list opt-out + empty/unknown
fail-closed at the resolver boundary.

Also drops the stale "bls" scheme from the dispatcher start log (BLS
custody was ripped in H-2).
2026-06-26 21:38:59 -07:00
zeekay 8c59d024b1 chore(mpc): commit go.sum/go.mod checksum churn from H-2 BLS-custody rip
Dep-checksum tail left uncommitted after 5c4d5cb removed bls_keygen_session.go.
- main go.sum: luxfi/zap v0.8.1 + luxfi/age v1.4.0 h1 refresh (upstream same-version
  tag re-cut; go mod verify = all modules verified, build green).
- e2e/go.mod + e2e/go.sum: go mod tidy churn (nats.go v1.50.0 -> v1.52.0 within v1,
  added indirects) for the e2e test module.
- go.work.sum: workspace checksum sync.

GOWORK=off go build ./... exit 0; go mod verify clean.
2026-06-26 21:18:02 -07:00
zeekay 567f950fa0 security(mpc): rip trusted-dealer threshold-BLS custody — H-2
BLS is consensus-only. The mpcd validator-key custody path generated a
threshold-BLS group key via a TRUSTED DEALER (blsThreshold.TrustedDealer:
one node, the lowest sorted party ID, generated the entire group secret
key and all shares, then distributed them) — a single point of full-key
compromise, with no DKG and no rogue-key PoP. That violates the
public/leaderless/permissionless invariant "no single node can sign or
extract a key".

Orphan-safe: this path was incomplete (no proof/sign-off doc unlike
cmp/frost; no deployment manifest provisions validator-BLS; BLS keygen
had no dispatch caller) and NOT live custody. A validator's real BLS
consensus key is its own NATIVE per-validator crypto/bls key (PoP +
aggregation, the consensus fast-path), held at the node — never
threshold-custodied here. Corona PQ-threshold custody (dealerless DKG)
stays. So a validator keyset = {native BLS (consensus, no custody) +
corona PQ-threshold (custodied)}.

Delete: bls_keygen_session.go, bls_signing_session.go, bls_config_marshal.go,
bls_session_test.go, signing_handler_bls.go. Remove KeyTypeBLS (mpc + types),
SessionTypeBLS, CreateBLS{KeyGen,Sign}Session, the BLS signing/keytype
dispatch cases, the keygen-result BLSPubKey field, and the bls: key-share
prefix. handlers_kms.go: drop the BLS-custody half of ValidatorKeySet and
the generate/sign/rotate BLS branches; KMS custodies corona only.

Verified: GOWORK=off go build ./... + go vet green; pkg/mpc, pkg/api,
pkg/types tests pass. Zero residual refs to deleted BLS symbols.
2026-06-26 21:18:02 -07:00
zeekay 255faab1cd fix(transport): propagate peer Ed25519 keys to consensus identity store
Consensus mode learned only its OWN Ed25519 public key: peer keys arrive in
ReadySignal.PublicKey during the transport identity handshake (sendIdentity) but
were discarded — never fed to the ConsensusIdentityStore that VerifyWireMessage
consults. Result: every inbound CGGMP21/FROST/signing wire message from a peer
was dropped ("public key not found for node …") and keygen/signing stalled to a
60s timeout. The HTTP /keygen and /sign endpoints could not work in any real
multi-node ensemble.

Fix (orthogonal, no import cycle): transport.Config.OnPeerIdentity observer is
invoked (notifyPeerIdentity, with self/empty/length guards + defensive copy)
whenever a peer key is learned — from the MsgMPCReady handshake in handleMessage
and handleIncoming. The acceptor now also replies with its own identity so the
key exchange is symmetric on the single tie-broken connection. main.go wires the
observer to ConsensusIdentityStore.AddPeerPublicKey. This is the consensus-mode
analog of the legacy NATS path's peers.json + *_identity.json seeding.

Proof: e2e/live_http_sign_test.go (//go:build integration) builds mpcd from the
repo root, starts a real 3-node 2-of-3 consensus ensemble, and over the live
HTTP API proves: distributed CGGMP21 keygen (real evm address), a real threshold
signature, idempotency cached-match, anti-oracle 409 on key reuse with new
content, 400 on empty key, and no plaintext key in any response or node log.
Unit coverage for the observer guards in pkg/transport/peer_identity_test.go.

Also fixes a pre-existing standalone_test.go bug: it set only ZAPDB_PASSWORD but
the env HSM provider reads MPC_PASSWORD — set both so the node starts.
2026-06-26 21:18:02 -07:00
zeekay 133131d943 feat(mpcd): HTTP POST /sign endpoint (idempotent, t-of-n quorum-gated) 2026-06-26 21:18:02 -07:00
zeekay b4be842240 chore: complete corona rename — strip residual corona identifiers (wire bytes preserved)
Bump e2e submodule's luxfi/threshold pin (v1.5.5 → v1.9.9) to drop the only
remaining corona puller in this workspace. Removes the residual
'github.com/luxfi/corona v0.2.0/go.mod' hash line from go.work.sum.
Align go.work go directive to 1.26.4 to match both workspace siblings
(../threshold and ./e2e). No source code in this repo imported corona;
this was workspace-graph hygiene only. R-LWE threshold primitive is now
referenced exclusively via luxfi/corona upstream.
2026-06-15 00:45:13 -07:00
zeekay 184193bae6 scrub branding + corona from docs/comments/tests
- Genericize all -brand references in comments, LLM.md, and
  FIREBLOCKS_PARITY.md: ' MPC API'→'MPC API', drop
  ~/work/liquidity/openapi/mpc.yaml paths, 'Liquid operator'→'the operator',
  'liquid-mpc'→'the mpc cluster'.
- Genericize tenant fixtures/examples: liquidity→acme, mlc→globex across
  treasury_test.go + db model comments (cross-tenant isolation tests keep
  their semantics with neutral org names).
- Rename corona→corona in docs (active Go code had none).
lux OSS names no white-label tenant. Build + api/webauthn tests green.
2026-06-10 22:55:37 -07:00
zeekay 51821ad233 deps: align threshold/corona/zap so cmd/mpcd builds
The Corona-rename WIP bumped cmd/mpcd to the luxfi/threshold thresholdd
NewZapServer/ZapServerConfig API but left go.mod pinned at the predating
v1.8.2, leaving the module unbuildable. Forward the dep set within v1.x:

  luxfi/threshold v1.8.2 → v1.9.9  (thresholdd.NewZapServer surface)
  luxfi/corona    v0.4.1 → v0.7.6  (pulled by threshold)
  luxfi/zap       v0.2.0 → v0.8.1  (threshold v1.9.9 uses zap.NodeConfig.TLS)
  luxfi/lattice/v7 v7.1.0 → v7.1.4

go build ./... is green again; pkg/webauthn tests pass.
2026-06-10 22:37:48 -07:00
zeekay ec0fb82eaa webauthn: vendor-neutral pluggable liveness Verifier; drop
lux OSS names no PAD-2 / liveness vendor. Decomplect the verifier into a
pluggable extension point so a white-label deployment (e.g. liquidity)
registers its own provider without forking:

- pkg/webauthn: add Verifier interface + Binding (vendor-neutral per-call
  input) + Ed25519EnvelopeVerifier (OSS default, delegates to the audited
  VerifyLiveness) + RegisterVerifier/LookupVerifier registry. Tests cover
  the default verifier, the registry, and a custom non-Ed25519 scheme.
- pkg/api: resolve the active Verifier at boot from MPC_LIVENESS_PROVIDER_ID
  (registered custom wins; else Ed25519 from MPC_LIVENESS_PUBKEY_ED25519;
  else nil → enroll fails closed 503). handleBiometricEnroll calls
  s.livenessVerifier.Verify(...) — no vendor code in lux.
- Rename MPC__* env vars → MPC_LIVENESS_*; drop every 
  identifier/comment across code + LLM.md. Zero /onyxd in lux/mpc.

Also finish the half-done decomplect from a326cc6 'rip zapauth gate' that
left pkg/api/zap_kms_server.go calling a removed checkAuth and missing the
encoding/json import — restore the import, drop the orphaned guard.

(Pre-existing, unrelated: cmd/mpcd still references thresholdd.NewZapServer
from the same in-flight WIP — not touched here.)
2026-06-10 21:42:27 -07:00
zeekay 7bbbe94236 ci: route to canonical native arcd labels [self-hosted, linux, <arch>]
Replaces non-canonical scale-set / org-prefixed labels with the
existing labels every arcd host registers with. Matches evo for
amd64 and spark for arm64. No new labels added.
2026-06-10 20:23:33 -07:00
zeekay 96a9a06b6f go: 1.26.3 → 1.26.4 (security: crypto/x509, mime, net/textproto) 2026-06-06 22:11:17 -07:00
Abhishek KrishnaandGitHub 8516e08ac2 docs: lead INSTALLATION with consensus-mode + add operator runbook outline (#15) 2026-06-06 21:57:01 -07:00
zeekay a326cc6418 mpc: rip zapauth bearer-token gate (decomplect)
Trust at the network boundary (NetworkPolicy + ZAP wire), not in the
application envelope. Companion to luxfi/keys v1.2.0 (LoadMnemonic
identity-free) and luxfi/kms v1.12.0 (iamclient gone).

Killed:
  - pkg/zapauth/     (JWKS verifier + AuthHelloFrame parser)
  - pkg/api/zap_kms_server.go: KMSZapConfig, auth+authRequired fields,
    handleAuthHello, respondAuthHello, checkAuth, StartKMSZAPWith
  - cmd/mpcd: ZAP_JWKS_URL, ZAP_EXPECTED_ISS, ZAP_EXPECTED_AUDIENCES,
    ZAP_AUTH_REQUIRED — all gone.

Note: mpc still has a pre-existing build block from upstream luxfi/geth
v1.16.79 → precompile pseudo-version (unrelated to this change).
2026-06-06 21:06:17 -07:00
zeekay be3d9f3ee7 corona → corona total rename — no alias, no wire compat
Per CTO directive: kill any alias, any shim. R-LWE threshold sig is
named Corona across all live code. Forward-only.

Sweep covers Go + TS + Sol + k8s YAML + JSON + LP markdown + skills
+ docs. Skipped: papers/audits/legal/licenses/blog/HISTORY (immutable
historical record).
2026-06-06 13:56:42 -07:00
zeekay ba4995dcf5 WIP: session checkpoint 2026-06-05 (codec rip in flight) 2026-06-05 15:33:58 -07:00
zeekay f16dec31f6 mpc: swap minio-go/v7 → hanzos3/go-sdk v1.0.2
Canonical S3 SDK across the stack is the Hanzo S3 fork at
github.com/hanzos3/go-sdk (package `s3`). Imports use an explicit
`s3 "github.com/hanzos3/go-sdk"` alias to avoid the `go-sdk` last-path-
segment mismatch with `package s3`.

`pkg/backup/s3.go` swept: `minio.Client` → `s3.Client`, `minio.New` →
`s3.New`, `minio.Options` → `s3.Options`, `minio.MakeBucketOptions` →
`s3.MakeBucketOptions`, `minio.PutObjectOptions` → `s3.PutObjectOptions`.

Field name `s3Client *s3.Client` is fine (no shadow with the package
qualifier).

Dropped stale `luxfi/zapdb v1.0.0` entries in go.work.sum that were
blocking go mod tidy (their hashes no longer match the proxy after
zapdb's own sweep).

No behavioral changes.
2026-06-03 11:07:39 -07:00
zeekay da277ae96a fix: gofmt -s across repo (CI format check) 2026-06-02 11:39:20 -07:00
zeekay 94be305ce9 chore(deps): go get -u ./...
Updated dependencies to latest minor versions via go get -u + go mod tidy.
2026-06-02 11:16:12 -07:00
zeekay 900d049cb9 merge: feat/scale-standard 2026-06-01 16:35:38 -07:00
zeekay c1450db78a merge: env/drop-lux-prefix 2026-06-01 16:35:36 -07:00
zeekay 4cb96bdc0e merge: daemon-standalone-consensus-2026-04-28 2026-06-01 16:35:36 -07:00
zeekayandGitHub b25d9422d0 build(mpc): GOEXPERIMENT=jsonv2 alongside runtimesecret per SCALE_STANDARD (#13)
* build(mpc): GOEXPERIMENT=jsonv2 alongside runtimesecret per SCALE_STANDARD

Per SCALE_STANDARD.md §2 (~/work/hanzo/hips/docs/SCALE_STANDARD.md) —
every Go production Dockerfile that emits JSON to a client builds with
GOEXPERIMENT=jsonv2. Verified on hanzoai/zip's json_bench_test.go:
- Edge POST roundtrip: -12% time, -23% allocs
- Marshal-only: -22% time
- Unmarshal-only: -19% time, -25% allocs

GOEXPERIMENT is comma-separated, so jsonv2 composes cleanly with the
pre-existing runtimesecret experiment used by the MPC data plane.

* ci: switch workflows to lux-build (luxfi-scoped ARC pool)

Cross-org runs-on dispatch failure: hanzo-build-linux-amd64 scale set is
registered to github.com/hanzoai and silently rejects luxfi/* jobs.
Switch to lux-build (githubConfigUrl=github.com/luxfi, max 20).

* test/zapauth: deterministic invalid-signature test (was flaky)

TestZapAuthInvalidSignature flipped one base64 char of the signature
segment. ECDSA accepts a wrong sig with probability ≈ 1/2^6 per
single-char flip (alphabet is 64), making the test ~1.5% flake rate
in CI.

Fix: replace the entire signature segment with all-A's. Still
decodable as base64url but cryptographically guaranteed-invalid
bytes — Verify rejection is now deterministic.

Verified: ran -count=10 ./pkg/zapauth/ — all pass.

* deps: bump accel/crypto/corona/threshold/fhe/lens/math to current tags

* api/db: decomplect — KeccakAddress on Wallet / TreasuryWallet / KeygenResult

Wave 5 of the workspace-wide eth* naming purge.

pkg/db/models.go — Wallet + TreasuryWallet:
- New canonical KeccakAddress *string field with json `keccakAddress`
- EthAddress kept with json `ethAddress` as `// Deprecated:` alias
- NormalizeAddresses() method on both structs mirrors the two fields
  via the package-private mirrorAddrPtrPair helper

pkg/api/server.go — KeygenResult (backend response):
- New canonical KeccakAddress string field with json `keccak_address`
- EthAddress kept with json `eth_address` as `// Deprecated:` alias
- NormalizeAddresses() method mirrors both fields

pkg/api/handlers_wallets.go, handlers_treasury.go, handlers_bridge.go,
handlers_mpc.go — all sites that constructed wallet rows from MPC
backend results now:
  1. Call result.NormalizeAddresses() on the backend response so both
     KeccakAddress / EthAddress carry the same value before copy
  2. Copy both fields onto the persisted Wallet / TreasuryWallet row
  3. Call wal.NormalizeAddresses() to ensure DB row has both
  4. Read from the canonical KeccakAddress at response-construction
     sites (toWalletResponse, treasury response, bridge response)

The "ethereum"/"lux"/"xrp" labels in addresses map (handleGetWalletAddresses)
are per-chain DISPLAY labels keyed by chain name a client knows;
the values are the Keccak-derived 20-byte address. Map keys NOT
decomplected here — they're per-chain UI labels, not internal naming.

Effect on the wire:
- API consumers reading wallet.ethAddress see the same value as
  wallet.keccakAddress
- New consumers can switch to keccakAddress today
- ORM persistence stores both fields (eventually consistent via
  NormalizeAddresses calls at handler boundaries)

Tests: pkg/api unit tests pass (1.8s); pkg/db has no test files.
Deprecation alias retention means downstream KMS / dashboards
keep working at every step of the migration.

Per CLAUDE.md x.x.x+1.

* strip KeccakAddress + EthAddress dual-field bridge (no aliases)

Forward-only completion of the workspace strip-aliases cascade. The
canonical JSON field is evmAddress, the Go field is EVMAddress. No
NormalizeAddresses helpers, no mirrorAddrPtrPair, no deprecated
KeccakAddress, no deprecated EthAddress.

Touched:
  pkg/api/server.go            KeygenResult drops KeccakAddress +
                               EthAddress + NormalizeAddresses
  pkg/db/models.go             Wallet drops KeccakAddress + EthAddress
                               TreasuryWallet drops KeccakAddress +
                               EthAddress
                               Drops NormalizeAddresses + mirrorAddrPtrPair
  pkg/api/handlers_wallets.go  rip mirror calls; only EVMAddress
                               populated on Wallet rows
  pkg/api/handlers_treasury.go rip mirror calls on TreasuryWallet
  pkg/api/handlers_mpc.go      rip NormalizeAddresses calls; rename
                               filter("ethAddress=") → ("evmAddress=")
  pkg/api/handlers_bridge.go   local var keccakAddress → evmAddr
  pkg/api/handlers_smart_wallets.go wallet.EthAddress → wallet.EVMAddress
  pkg/api/treasury_test.go     mock KeygenResult EthAddress → EVMAddress
  pkg/api/zap_kms_server_test.go same
  cmd/mpcd/main.go             pubKeyToEthAddress → pubKeyToEVMAddress,
                               \"eth_address\" → \"evm_address\",
                               local var ethAddr → evmAddr, KeygenResult
                               EthAddress → EVMAddress field

Deps: bump luxfi/metric v1.5.1 → v1.5.7 to pick up ExponentialBuckets
(via transitive luxfi/threshold dep).

The value IS \"EVM-runtime account address\" — that's the data model.
The Keccak256(secp256k1 pubkey) derivation is HOW.
2026-05-29 21:05:40 -07:00
zeekay 91d70a43a4 strip KeccakAddress + EthAddress dual-field bridge (no aliases)
Forward-only completion of the workspace strip-aliases cascade. The
canonical JSON field is evmAddress, the Go field is EVMAddress. No
NormalizeAddresses helpers, no mirrorAddrPtrPair, no deprecated
KeccakAddress, no deprecated EthAddress.

Touched:
  pkg/api/server.go            KeygenResult drops KeccakAddress +
                               EthAddress + NormalizeAddresses
  pkg/db/models.go             Wallet drops KeccakAddress + EthAddress
                               TreasuryWallet drops KeccakAddress +
                               EthAddress
                               Drops NormalizeAddresses + mirrorAddrPtrPair
  pkg/api/handlers_wallets.go  rip mirror calls; only EVMAddress
                               populated on Wallet rows
  pkg/api/handlers_treasury.go rip mirror calls on TreasuryWallet
  pkg/api/handlers_mpc.go      rip NormalizeAddresses calls; rename
                               filter("ethAddress=") → ("evmAddress=")
  pkg/api/handlers_bridge.go   local var keccakAddress → evmAddr
  pkg/api/handlers_smart_wallets.go wallet.EthAddress → wallet.EVMAddress
  pkg/api/treasury_test.go     mock KeygenResult EthAddress → EVMAddress
  pkg/api/zap_kms_server_test.go same
  cmd/mpcd/main.go             pubKeyToEthAddress → pubKeyToEVMAddress,
                               \"eth_address\" → \"evm_address\",
                               local var ethAddr → evmAddr, KeygenResult
                               EthAddress → EVMAddress field

Deps: bump luxfi/metric v1.5.1 → v1.5.7 to pick up ExponentialBuckets
(via transitive luxfi/threshold dep).

The value IS \"EVM-runtime account address\" — that's the data model.
The Keccak256(secp256k1 pubkey) derivation is HOW.
2026-05-24 08:13:04 -07:00
zeekay a5f75a5b6b api/db: decomplect — KeccakAddress on Wallet / TreasuryWallet / KeygenResult
Wave 5 of the workspace-wide eth* naming purge.

pkg/db/models.go — Wallet + TreasuryWallet:
- New canonical KeccakAddress *string field with json `keccakAddress`
- EthAddress kept with json `ethAddress` as `// Deprecated:` alias
- NormalizeAddresses() method on both structs mirrors the two fields
  via the package-private mirrorAddrPtrPair helper

pkg/api/server.go — KeygenResult (backend response):
- New canonical KeccakAddress string field with json `keccak_address`
- EthAddress kept with json `eth_address` as `// Deprecated:` alias
- NormalizeAddresses() method mirrors both fields

pkg/api/handlers_wallets.go, handlers_treasury.go, handlers_bridge.go,
handlers_mpc.go — all sites that constructed wallet rows from MPC
backend results now:
  1. Call result.NormalizeAddresses() on the backend response so both
     KeccakAddress / EthAddress carry the same value before copy
  2. Copy both fields onto the persisted Wallet / TreasuryWallet row
  3. Call wal.NormalizeAddresses() to ensure DB row has both
  4. Read from the canonical KeccakAddress at response-construction
     sites (toWalletResponse, treasury response, bridge response)

The "ethereum"/"lux"/"xrp" labels in addresses map (handleGetWalletAddresses)
are per-chain DISPLAY labels keyed by chain name a client knows;
the values are the Keccak-derived 20-byte address. Map keys NOT
decomplected here — they're per-chain UI labels, not internal naming.

Effect on the wire:
- API consumers reading wallet.ethAddress see the same value as
  wallet.keccakAddress
- New consumers can switch to keccakAddress today
- ORM persistence stores both fields (eventually consistent via
  NormalizeAddresses calls at handler boundaries)

Tests: pkg/api unit tests pass (1.8s); pkg/db has no test files.
Deprecation alias retention means downstream KMS / dashboards
keep working at every step of the migration.

Per CLAUDE.md x.x.x+1.
2026-05-23 21:06:23 -07:00
zeekay a10c195126 deps: bump accel/crypto/corona/threshold/fhe/lens/math to current tags 2026-05-21 15:00:31 -07:00
zeekay 8969c00426 test/zapauth: deterministic invalid-signature test (was flaky)
TestZapAuthInvalidSignature flipped one base64 char of the signature
segment. ECDSA accepts a wrong sig with probability ≈ 1/2^6 per
single-char flip (alphabet is 64), making the test ~1.5% flake rate
in CI.

Fix: replace the entire signature segment with all-A's. Still
decodable as base64url but cryptographically guaranteed-invalid
bytes — Verify rejection is now deterministic.

Verified: ran -count=10 ./pkg/zapauth/ — all pass.
2026-05-21 12:22:22 -07:00
zeekay efc9907a23 ci: switch workflows to lux-build (luxfi-scoped ARC pool)
Cross-org runs-on dispatch failure: hanzo-build-linux-amd64 scale set is
registered to github.com/hanzoai and silently rejects luxfi/* jobs.
Switch to lux-build (githubConfigUrl=github.com/luxfi, max 20).
2026-05-19 13:21:15 -07:00
zeekay fb0a525351 build(mpc): GOEXPERIMENT=jsonv2 alongside runtimesecret per SCALE_STANDARD
Per SCALE_STANDARD.md §2 (~/work/hanzo/hips/docs/SCALE_STANDARD.md) —
every Go production Dockerfile that emits JSON to a client builds with
GOEXPERIMENT=jsonv2. Verified on hanzoai/zip's json_bench_test.go:
- Edge POST roundtrip: -12% time, -23% allocs
- Marshal-only: -22% time
- Unmarshal-only: -19% time, -25% allocs

GOEXPERIMENT is comma-separated, so jsonv2 composes cleanly with the
pre-existing runtimesecret experiment used by the MPC data plane.
2026-05-19 12:35:01 -07:00
zeekay e6d97f63d1 fix: edwards25519 go.sum hash refresh (h1 + /go.mod both) 2026-05-19 09:57:04 -07:00
zeekay 98515a75f6 merge: fix/edwards25519-gosum-hash — CI cross-compile arm64 from hanzo-build-linux-amd64 + gosum hash fix 2026-05-19 09:54:45 -07:00
zeekay 4a60b7fe1b ci: cross-compile arm64 from amd64 (no GH-hosted arm runners)
- docker.yml: drop ubuntu-24.04-arm. Both arches now build on
  hanzo-build-linux-amd64 via docker buildx + QEMU for the arm64 leg
  (QEMU is acceptable for Docker builds per policy).
- release.yml: drop the imaginary hanzo-build-linux-arm64 runner. Both
  arches cross-compile on hanzo-build-linux-amd64 with GOOS=linux
  GOARCH=<arch> (CGO_ENABLED=0).
2026-05-19 09:11:26 -07:00
zeekayandGitHub 34d5ee5a65 Merge pull request #12 from luxfi/fix/edwards25519-gosum-hash
fix: pin luxfi/edwards25519 v0.1.0 go.sum to proxy hash
2026-05-16 18:27:43 -07:00
zeekay 8aacc67dbb go.sum: pin luxfi/edwards25519 v0.1.0 to proxy hash
Same pattern as the threshold fhe + protocol zapdb fixes. Local-direct
hash differs from proxy.golang.org hash; CI uses proxy + sum.golang.org
and was failing on `GOWORK=off go mod download` with checksum mismatch.

Pin canonical proxy hash (h1:zuSrBtg... / h1:tFuuyXvI...).
2026-05-16 18:27:34 -07:00
zeekayandGitHub 3138a2b1f8 Merge pull request #11 from luxfi/fix/pnpm-docker-build
fix(ui): pin pnpm 10.16.1 + onlyBuiltDependencies allowlist
2026-05-16 18:17:48 -07:00
zeekay 0c9f8ecab5 fix(ui): pin pnpm 10.16.1 + onlyBuiltDependencies allowlist
Docker build was failing on `pnpm install` because corepack pulled the
latest pnpm (v11.x) which exits non-zero when build scripts (esbuild)
are present without explicit approval. Pin to v10.16.1 (stable, ships
the same `onlyBuiltDependencies` shape) and declare the esbuild build
script in package.json so future v11+ upgrades stay non-interactive.

Also swap `2>/dev/null || pnpm install` for `|| pnpm install --no-frozen-lockfile`
so we don't swallow real diagnostics — fall back to a controlled lockfile
update only when --frozen-lockfile fails.
2026-05-16 18:17:31 -07:00
zeekay a37edbcf3c deps: bump hanzoai/orm v0.4.0 → v0.5.2 (pure-Go SQLite, CGO_ENABLED=0) 2026-05-16 17:20:20 -07:00
zeekayandGitHub 2631645e21 chore: bump Go toolchain to 1.26.3 (#10)
Pin Go version to 1.26.3 across go.mod, CI workflows, and Dockerfiles
for canonical alignment with the rest of the luxfi/* stack.
2026-05-16 16:44:26 -07:00
zeekayandGitHub 009eaddaeb Merge pull request #9 from luxfi/licensing/canonical-pointer
docs: add LICENSING.md pointer to canonical Lux IP strategy
2026-05-15 16:38:34 -07:00