Skip to content

feat: KMS-backed signer for the write path (createWithKms / initWithKms) - #31

Merged
koko1123 merged 2 commits into
mainfrom
koko/zig-sdk-kms-signer
Jul 14, 2026
Merged

koko1123 merged 2 commits into
mainfrom
koko/zig-sdk-kms-signer

Conversation

@koko1123

@koko1123 koko1123 commented Jul 14, 2026 •

Copy link
Copy Markdown
Contributor

What

Adds a KMS signing path so the SDK's write/money path signs with the private key staying in AWS KMS, instead of requiring a raw 32-byte key in process memory.

Why

Until now PerpCityContext.init accepted only a raw [32]u8 key -- so a production liquidator could not run its full flow (discover -> simulate -> sign -> send) through the SDK without holding key material. eth.zig ships a KmsSigner and a Signer abstraction; this wires them in.

Changes

  • EthChainClient.createWithKms(rpc_url, region, key_id): builds the wallet via eth.signer.Signer.fromKms over a heap-owned, stable KmsSigner (the wallet's Signer holds a borrowed pointer). Owns a copy of key_id (the signer borrows it) and derives+caches the wallet address from KMS at construction. destroy() deinits and frees the signer + key id.
  • PerpCityContext.initWithKms(rpc_url, region, key_id, deployments): the KMS counterpart of init(). The raw-key init() is unchanged.
  • The KMS key must be ECC_SECG_P256K1; credentials resolve from the env / container role at call time.

Tests

  • create/destroy on the raw-key path is network-free (the address derives locally from the key), so it regression-guards the destroy() change: the kms_signer == null branch must free cleanly under the testing allocator.
  • The KMS constructors are referenced at compile time (a signature change breaks the build).
  • The KMS signing path itself calls kms:GetPublicKey (needs AWS credentials), so it is exercised by integration, not CI -- consistent with how the eth-backed path is tested.
  • zig build test: 497/497
  • zig build contract-test (Debug + ReleaseFast): 96/96
  • zig fmt --check: clean

Summary by CodeRabbit

  • New Features
    • Added AWS KMS–based signing during blockchain client initialization.
    • Added a new context initializer that creates the client using an AWS KMS key id, region, and RPC endpoint (no locally stored private key required).
  • Tests
    • Added contract/regression tests to verify client lifecycle behavior and KMS-related initializer wiring.
    • Included the new contract tests in the standard test suite.

The SDK could only sign from a raw 32-byte private key, so a production
liquidator had to hold key material in process memory. This adds a KMS
signing path (eth.zig KmsSigner) so the money path signs with the key
staying in AWS KMS.

- EthChainClient.createWithKms(rpc_url, region, key_id): builds the wallet
  via eth.signer.Signer.fromKms over a heap-owned, stable KmsSigner; owns a
  copy of key_id (the signer borrows it) and derives+caches the wallet
  address from KMS at construction. destroy() deinits and frees the signer.
- PerpCityContext.initWithKms(rpc_url, region, key_id, deployments): the
  KMS counterpart of init(). The raw-key init() is unchanged.

The KMS key must be ECC_SECG_P256K1; credentials resolve from the env /
container role at call time.

Tests: create/destroy on the raw-key path is network-free (address derives
locally), so it regression-guards the destroy() change (kms_signer == null
frees clean under the testing allocator); the KMS constructors are
referenced at compile time. The KMS signing path itself hits kms:GetPublicKey
and is exercised by integration, not CI.

zig build test 497, contract-test 96 (Debug + ReleaseFast).
@coderabbitai

coderabbitai Bot commented Jul 14, 2026 •

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 237a0255-4366-44cf-b4e1-ecd924e9309f

📥 Commits

Reviewing files that changed from the base of the PR and between 1e043b4 and 9296567.

📒 Files selected for processing (1)
  • tests/contract/chain_client_test.zig
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/contract/chain_client_test.zig

📝 Walkthrough

Walkthrough

Adds AWS KMS-backed signing construction to EthChainClient, exposes it through PerpCityContext.initWithKms, manages signer and key-ID ownership, and adds contract tests for lifecycle and API wiring.

Changes

AWS KMS signing

Layer / File(s) Summary
KMS client construction and cleanup
src/chain_client.zig, tests/contract/chain_client_test.zig
EthChainClient creates wallets from a heap-owned KmsSigner, retains the duplicated key ID, cleans up KMS resources during destruction, and verifies raw-key lifecycle behavior.
KMS context initialization
src/context.zig
PerpCityContext.initWithKms creates the KMS-backed chain client and initializes deployment, approval, configuration, and state caches.
KMS API contract coverage
tests/contract/chain_client_test.zig, tests/contract_tests.zig
Contract tests validate KMS initializer signatures, parameter types, return types, and test-suite inclusion.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant PerpCityContext
  participant EthChainClient
  participant KmsSigner
  participant Wallet
  PerpCityContext->>EthChainClient: createWithKms(region, key_id)
  EthChainClient->>KmsSigner: initialize(region, key_id)
  EthChainClient->>Wallet: create from KmsSigner
  EthChainClient-->>PerpCityContext: initialized client
  EthChainClient->>KmsSigner: deinitialize and free during destroy()
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: adding KMS-backed signing for the write path via the new constructors.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch koko/zig-sdk-kms-signer

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/contract/chain_client_test.zig`:
- Around line 33-41: Update the compile-time-only test “KMS constructors are
wired” to assign sdk.context.PerpCityContext.initWithKms and
EthChainClient.createWithKms to explicitly declared function types matching
their intended parameter order, parameter types, and return types. Replace the
generic `@typeInfo` checks while preserving the no-invocation behavior that avoids
network calls.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 7c3ec07a-8c63-40c6-8d8d-e89a1d4b776e

📥 Commits

Reviewing files that changed from the base of the PR and between 779ee13 and 1e043b4.

📒 Files selected for processing (4)
  • src/chain_client.zig
  • src/context.zig
  • tests/contract/chain_client_test.zig
  • tests/contract_tests.zig

Comment thread tests/contract/chain_client_test.zig Outdated
CodeRabbit (Minor): the @typeinfo == .fn check passed for any signature.
Assert the exact parameter types and return payload of createWithKms /
initWithKms via @typeinfo, so a change to parameter order/types or the
return type breaks the build. Still not invoked (KMS init is network).
@koko1123
koko1123 merged commit ad03af2 into main Jul 14, 2026
6 checks passed
@koko1123
koko1123 deleted the koko/zig-sdk-kms-signer branch July 14, 2026 21:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant