mirror of
https://github.com/luxfi/mpc.git
synced 2026-09-24 00:26:24 +00:00
merge: mpc-bump-hsm-airgap-2026-04-28
This commit is contained in:
@@ -21,12 +21,14 @@ import (
|
||||
// surface for working with airgapped hardware wallets (Coldcard,
|
||||
// Foundation Passport, Keystone Pro, NGRAVE Zero).
|
||||
//
|
||||
// The signing ceremony is file-mediated: mpcd writes the challenge to a
|
||||
// working directory, the operator hand-carries it to the offline device
|
||||
// via microSD or QR, and the signed response is dropped back into the
|
||||
// same directory. This file owns the ceremony orchestration; in-process
|
||||
// Signer construction for these devices is gated on a luxfi/hsm release
|
||||
// that exports the airgap factory cases.
|
||||
// The signing ceremony is file-mediated by design: Coldcard's canonical
|
||||
// product flow uses microSD, Foundation Passport uses BBQr-encoded QR,
|
||||
// and Keystone/NGRAVE use UR-encoded animated QR — all of which surface
|
||||
// as challenge bytes the host writes to disk for the operator to ferry
|
||||
// to the offline device. The response file is signed bytes the operator
|
||||
// drops back into the same directory. mpcd owns the ceremony I/O; the
|
||||
// per-vendor envelope semantics (PSBT vs UR vs BBQr) are owned by the
|
||||
// luxfi/hsm Signer, which is constructible since v1.1.3 via NewSigner.
|
||||
//
|
||||
// The subcommands here are intentionally narrow:
|
||||
//
|
||||
@@ -49,9 +51,11 @@ func airgapCommand() *cli.Command {
|
||||
}
|
||||
|
||||
// airgapProviders is the canonical set of airgap-capable provider names
|
||||
// reserved by luxfi/hsm. Adding entries here is a contract change — they
|
||||
// must round-trip through hsm.NewSigner once the airgap surface is
|
||||
// published downstream.
|
||||
// reserved by luxfi/hsm. Adding entries here is a contract change —
|
||||
// every name MUST round-trip through hsm.NewSigner. Coverage lives in
|
||||
// airgap_command_test.go so the dispatch table is exercised by `go test`
|
||||
// rather than crashing the daemon at boot when an operator probes with
|
||||
// an unconfigured provider.
|
||||
func airgapProviders() []string {
|
||||
return []string{"coldcard", "foundation", "keystone", "ngrave"}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// Copyright (C) 2020-2026, Lux Industries Inc. All rights reserved.
|
||||
// See the file LICENSE for licensing terms.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/luxfi/hsm"
|
||||
)
|
||||
|
||||
// TestAirgapProvidersRoundTripFactory enforces the contract documented
|
||||
// on airgapProviders(): every reserved provider name MUST be a known
|
||||
// factory case in luxfi/hsm. We supply each constructor's required
|
||||
// fields so we exercise the dispatch table and the per-signer
|
||||
// validators — the goal is to catch missing factory cases or rename
|
||||
// drift, not to validate operational config.
|
||||
func TestAirgapProvidersRoundTripFactory(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
cases := map[string]map[string]string{
|
||||
"coldcard": {"device_id": "test"},
|
||||
"foundation": {"device_id": "test"},
|
||||
"keystone": {"device_id": "test", "ur_type": "eth-sign-request"},
|
||||
"ngrave": {"device_id": "test", "ur_type": "eth-sign-request"},
|
||||
}
|
||||
|
||||
for _, p := range airgapProviders() {
|
||||
cfg, ok := cases[p]
|
||||
if !ok {
|
||||
t.Fatalf("airgap_command_test: missing test config for provider %q — extend cases", p)
|
||||
}
|
||||
signer, err := hsm.NewSigner(p, cfg)
|
||||
if err != nil {
|
||||
t.Fatalf("hsm.NewSigner(%q): %v", p, err)
|
||||
}
|
||||
if signer == nil {
|
||||
t.Fatalf("hsm.NewSigner(%q): nil signer with no error", p)
|
||||
}
|
||||
if got := signer.Provider(); got != p {
|
||||
t.Fatalf("hsm.NewSigner(%q).Provider() = %q", p, got)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -31,7 +31,7 @@ require (
|
||||
github.com/luxfi/crypto v1.17.45
|
||||
github.com/luxfi/database v1.17.44
|
||||
github.com/luxfi/fhe v1.7.7
|
||||
github.com/luxfi/hsm v1.1.2
|
||||
github.com/luxfi/hsm v1.1.3
|
||||
github.com/luxfi/log v1.4.1
|
||||
github.com/luxfi/metric v1.5.1
|
||||
github.com/luxfi/threshold v1.6.0
|
||||
@@ -70,6 +70,8 @@ require (
|
||||
github.com/ChainSafe/go-schnorrkel v1.1.0 // indirect
|
||||
github.com/ProjectZKM/Ziren/crates/go-runtime/zkvm_runtime v0.0.0-20260311194731-d5b7577c683d // indirect
|
||||
github.com/agl/ed25519 v0.0.0-20200225211852-fd4d107ace12 // indirect
|
||||
github.com/ansel1/merry v1.8.1 // indirect
|
||||
github.com/ansel1/merry/v2 v2.2.2 // indirect
|
||||
github.com/armon/go-metrics v0.4.1 // indirect
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.5 // indirect
|
||||
@@ -101,6 +103,8 @@ require (
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.13 // indirect
|
||||
github.com/ganigeorgiev/fexpr v0.5.0 // indirect
|
||||
github.com/gemalto/flume v1.0.0 // indirect
|
||||
github.com/gemalto/kmip-go v0.1.0 // indirect
|
||||
github.com/go-ini/ini v1.67.0 // indirect
|
||||
github.com/go-logr/logr v1.4.3 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
@@ -158,7 +162,9 @@ require (
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mattn/go-sqlite3 v2.0.3+incompatible // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d // indirect
|
||||
github.com/miekg/dns v1.1.72 // indirect
|
||||
github.com/miekg/pkcs11 v1.1.1 // indirect
|
||||
github.com/mimoo/StrobeGo v0.0.0-20220103164710-9a04d6ca976b // indirect
|
||||
github.com/minio/crc64nvme v1.1.1 // indirect
|
||||
github.com/minio/md5-simd v1.1.2 // indirect
|
||||
@@ -202,6 +208,8 @@ require (
|
||||
go.temporal.io/sdk v1.41.1 // indirect
|
||||
go.uber.org/atomic v1.11.0 // indirect
|
||||
go.uber.org/mock v0.6.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
go.uber.org/zap v1.27.1 // indirect
|
||||
go.yaml.in/yaml/v2 v2.4.4 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/exp v0.0.0-20260312153236-7ab1446f8b90 // indirect
|
||||
|
||||
Reference in New Issue
Block a user