Files
chains/bridgevm/attest.go
T
zeekayandHanzo Dev 4ba9544b51 bridgevm: B<->M release path + canonical attestation seam
Completes the bridge cross-chain release leg the recon flagged as missing.

- internal/bridgeattest: the ONE canonical definition of the bridge-transfer
  attestation seam between B (bridgevm) and M (mpcvm). M threshold-signs a
  domain-bound bridge-transfer digest; B and every EVM gateway holding the group
  key's address verifies before mint/release. Domain-bound + replay-safe; test
  proves a signature over one transfer verifies for THAT transfer and no other.
- evmclient.go: the concrete EVM ChainClient B instantiates per external EVM
  (Zoo 200201, Lux testnet C 96368) — chainClients was never populated because
  the interface had SendTransaction but no concrete EVM client; B could not
  broadcast a release. Now wired via evmByChainID in factory.
- release.go: on a confirmed lock/burn in an accepted block, B builds the
  destination release call, obtains + verifies M's threshold attestation, and
  broadcasts to the destination gateway. Both directions (Zoo<->Lux).
- attest.go: injects the two runtime deps (Warp->M, KMS relayer key) as clean
  interface boundaries rather than hard-wiring transports.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-12 16:44:17 -07:00

44 lines
2.2 KiB
Go

// Copyright (C) 2019-2025, Lux Industries Inc. All rights reserved.
// See the file LICENSE for licensing terms.
package bridgevm
// attest.go — the two runtime dependencies the EVM release path needs, defined
// as clean interface boundaries so the concrete transports (Warp to M-Chain,
// KMS for the relayer key) are injected, never hard-wired here.
//
// AttestationClient : B -> M. B hands M a domain-bound BridgeTransfer; M
// returns a threshold-signed attestation. The concrete
// impl issues a Warp CrossChainMPCRequest to M-Chain
// (mpcvm). The cryptographer owns M; this is the seam we
// agreed on (see internal/bridgeattest — one definition of
// the digest, shared by both chains and the on-chain
// gateway).
//
// KeyProvider : resolves the gas-paying relayer key from a KMS path.
// This is the ONLY way a private key enters the VM — never
// from genesis, config JSON, env, or logs. The relayer key
// pays for release-tx inclusion; it does NOT authorise the
// mint (the MPC threshold signature in calldata does).
import (
"context"
"crypto/ecdsa"
"github.com/luxfi/chains/internal/bridgeattest"
)
// AttestationClient is B's boundary to M-Chain. Given a canonical transfer, it
// returns M's self-describing threshold attestation (signature + group key). B
// verifies the attestation locally (bridgeattest.Attestation.Verify) before it
// broadcasts, so a faulty or malicious M-response is caught before any EVM tx.
type AttestationClient interface {
AttestBridgeTransfer(ctx context.Context, transfer bridgeattest.BridgeTransfer) (*bridgeattest.Attestation, error)
}
// KeyProvider resolves a gas-paying relayer key from a KMS path. Production
// wiring supplies a luxfi/kms-backed resolver; tests inject a local key. A nil
// KeyProvider with configured external chains is a hard error at enable time —
// there is no plaintext-key fallback (fail secure).
type KeyProvider func(ctx context.Context, kmsPath string) (*ecdsa.PrivateKey, error)