Skip to content

samwtk/TK-Signer_Midnight

Repository files navigation

midnight-turnkey-signer

Reference integration for signing Midnight Network unshielded transactions with a Turnkey-held secp256k1 Schnorr key.

A developer can custody a user's Midnight unshielded signing key inside a Turnkey enclave, derive the corresponding Midnight address, and route unshielded transaction signing through Turnkey — without exposing the secret key. The standard Midnight wallet SDK is unchanged; a single provider swap delivers Turnkey's policy engine, audit log, key lifecycle, and enclave-backed signing to any Midnight application.

This repository contains:

  • A working Midnight CLI that flips between local-key and Turnkey-key signing.
  • A drop-in UnshieldedKeystore implementation backed by Turnkey.
  • Reproducible end-to-end scripts that prove Turnkey signatures verify under the same Midnight verifying key.
  • A long-form integration note for the Midnight team at docs/signing.md.

Quick start

npm install
cp .env.example .env       # fill in Turnkey credentials + signing identity
npm run turnkey:e2e        # standalone proof: Turnkey-signed payload, local verify
npm run turnkey:smoke      # exercise the same wiring the CLI uses

Expected tail of npm run turnkey:e2e:

signWith            : bc1p…
x-only pubkey (32B) : c11b4f48…0706f87
Midnight addr (hex) : 86eac943…967615f4
Midnight bech32     : mn_addr_undeployed1sm4vjsu…zmqpe3
signature (64B)     : 031e3c9c…cf1914f
schnorr.verify      : true

How it works

Midnight unshielded signing is Schnorr over secp256k1: a 32-byte x-only verifying key, a 64-byte r‖s signature, applied to the SHA-256 digest of the transaction payload. A Turnkey secp256k1 Schnorr-capable account produces exactly that signature shape via signRawPayload with HASH_FUNCTION_NO_OP. Deriving the Midnight verifying key from the same public key Turnkey publishes for the signing identity keeps the two sides aligned.

sequenceDiagram
  participant App as Developer app
  participant Wallet as Midnight Wallet SDK
  participant Signer as TurnkeyNightSigner
  participant TK as Turnkey enclave
  participant MN as Midnight node
  App->>Wallet: build unshielded transaction
  Wallet->>Signer: signData(payload)
  Signer->>Signer: SHA-256(payload)
  Signer->>TK: signRawPayload(digest, NO_OP)
  TK-->>Signer: { r, s }
  Signer-->>Wallet: 64-byte r‖s signature
  Wallet->>MN: submit signed transaction
Loading

Full architectural detail, sequence diagrams, key-alignment notes, hash- function table, and recommended follow-ups for the Midnight team: docs/signing.md.

What works today

  • Provision a Turnkey Midnight signing key.
  • Derive the Midnight unshielded address from the Turnkey-published public key.
  • Sign Midnight unshielded transactions and arbitrary messages with Turnkey.
  • Validate the signature locally against Midnight's verifying key.
  • Route the Midnight wallet SDK through a Turnkey-backed UnshieldedKeystore via a single environment flag (MIDNIGHT_NIGHT_SIGNER=turnkey).
  • Combine the Midnight account with Ethereum, Solana, Bitcoin, and other Turnkey-supported chain accounts in the same wallet.

Scope

Shielded (Zswap) and Dust signing remain local. Those secrets are consumed inside zero-knowledge proofs, which Turnkey does not expose a primitive for today. The hybrid model — local shielded + Turnkey unshielded — is the production-ready posture and is what this repository demonstrates. docs/signing.md lists the small wallet-SDK additions that would extend Turnkey custody to the shielded/Dust legs.

Project layout

src/
  cli.ts            Working Midnight CLI; resolves signer from MIDNIGHT_NIGHT_SIGNER.
  night-signer.ts   localNightSigner + turnkeyNightSigner (UnshieldedKeystore impls).
  setup.ts          End-to-end devnet bootstrap.
  deploy.ts         Compiles and deploys the bundled contract.
  network.ts        Network resolution, seed persistence, deploy records.
  check-balance.ts  Wallet balance helper.
scripts/
  turnkey-night-e2e.ts   Standalone Turnkey-sign / local-verify proof.
  cli-night-smoke.ts     Exercises the CLI's resolver path without the proof server.
  e2e-check.ts           Full devnet contract round-trip (proof server required).
contracts/
  hello-world.compact    Minimal Compact contract used by the CLI demo.
docs/
  signing.md             Integration note for the Midnight team.

Prerequisites

  • Node 22+
  • A Turnkey organization and API key pair (Settings → API Keys)
  • A CURVE_SECP256K1 Turnkey signing identity, ideally as a P2TR wallet account so the bech32m form encodes the x-only verifying key

For the full Midnight CLI demo (npm run cli) you additionally need:

  • Docker with Compose v2
  • The Compact compiler version pinned by create-mn-app

The standalone Turnkey scripts (turnkey:e2e, turnkey:smoke) do not need Docker or the Compact compiler.

License

MIT

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors