Skip to content

Support external key custody / remote signing (Turnkey, KMS) for payment signers #3941

Description

@rickstaa

Note

Idea originally raised by @eliteprox.

Summary

Allow the remote payment signer (-remoteSigner) to use an external key-custody / remote-signing backend (e.g. Turnkey, AWS KMS, GCP KMS, clef) instead of only a local keystore, behind a pluggable signing interface.

Motivation

The remote signer holds an Ethereum hot key to sign PM tickets and to fund on-chain deposit/reserve. Today that key is a local keystore on the signer host. For a shared, pooled-wallet payment signer that is the single biggest risk: compromise the host and the deposit/reserve can be drained, and there are no wallet-level spend controls.

Proposal

Make the signing path pluggable and add one external-signer client that speaks a standard remote-signing protocol, rather than integrating each provider. Backends then sit behind that protocol, outside go-livepeer:

  • Port (in go-livepeer): a standard external-signer client, e.g. go-ethereum's accounts/external (clef JSON-RPC) or a Web3Signer-compatible API.
  • Adapters (outside go-livepeer): Turnkey, AWS KMS, GCP KMS, HashiCorp Vault, HSM. Web3Signer already ships plugins for KMS/Vault/HSM; others reach the port via a thin shim. Adding a backend means running a sidecar/config change, no go-livepeer change.

The key never leaves the enclave/KMS; the signer asks the backend to sign:

  • PM ticket payloads (raw secp256k1 message signing)
  • State-blob and orchestrator-info signatures
  • On-chain transactions (fundDeposit / fundReserve / withdraw) — go-livepeer still builds the tx (nonce, gas) and broadcasts via its own RPC; the backend only returns a signature.

Note: providers like Turnkey are wallet / key-management infrastructure (enclave-secured keys), not a "signer" product. The overloaded term here is go-livepeer's -remoteSigner; the external signer is the key backend.

Integration point (current code)

Signing already goes through a clean interface, so this is additive, not surgery:

  • pm.Signer (pm/signer.go): Sign(msg []byte) ([]byte, error) + Account() accounts.Account.
  • eth.AccountManager (eth/accountmanager.go) is the only implementation today and wraps a local go-ethereum keystore.KeyStore (Sign, SignTypedData, Unlock).
  • server/remote_signer.go only ever signs via these interfaces (Eth.Sign(...)), never a raw key.

So the work is an alternative AccountManager/Signer implementation backed by the external client, plus a flag to select it. remote_signer.go itself does not change.

Benefits for payment signers

  • No hot key on the signer host. The pooled wallet key lives in the enclave/KMS, removing the worst failure mode of running a shared payment signer.
  • Policy-based loss prevention. Providers like Turnkey enforce signing policies (max value per period, allowlisted recipients/contracts, quorum on withdrawals) — i.e. anti-drain on deposit/reserve at the key layer, even if the signer is compromised.
  • Safer HA / redundancy. Run redundant signers without copying a raw private key to each host.
  • No protocol change. Tickets, deposit/reserve, redemption, and the gateway→orchestrator flow stay byte-identical. Only how a signature is produced changes.

Scope / considerations

  • Implement behind the existing pm.Signer / AccountManager interface so the backend (local keystore vs Turnkey/KMS/HSM) is a swappable adapter.
  • Raw-hash signing: PM tickets are signed as a raw keccak hash. Some remote signers refuse raw-hash signing for safety, so the chosen interface must allow it (clef account_signData and Web3Signer eth1 modes can) — verify against the ticket format.
  • Hot-path latency + cost: PM mints tickets frequently, so per-signature API round-trips add latency and cost vs a local key. Worth measuring against minting rate; batch/cached signing may be needed.
  • This is cleanly enabled by factoring the signer into a standalone package, but can land as a contained adapter on the current -remoteSigner mode.

Out of scope

  • Per-user / embedded wallets (a larger non-custodial direction) — separate discussion.
  • Clearinghouse / accounting changes — none required; this sits below the signer seam.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions