Skip to content

fix(vetkd): use the current ic-cdk call API for management-canister vetKD calls - #308

Open
raymondk wants to merge 1 commit into
mainfrom
fix/272-vetkd-modern-cdk-api
Open

fix(vetkd): use the current ic-cdk call API for management-canister vetKD calls#308
raymondk wants to merge 1 commit into
mainfrom
fix/272-vetkd-modern-cdk-api

Conversation

@raymondk

@raymondk raymondk commented Aug 5, 2026

Copy link
Copy Markdown
Collaborator

Closes #272.

Problem

The Rust snippets called ic_cdk::caller(), ic_cdk::api::call::call, and ic_cdk::api::call::call_with_payment128.

One correction to the issue: it says the code "likely will not compile against its own declared CDK version." It does compile at the pinned ic-cdk = "0.19" — those functions are deprecated there, not gone. The real breakage is one minor version later.

Verification (compiled, not assumed)

I extracted the skill's "Calling management canister directly" block verbatim and built it against the skill's own pinned deps:

ic-cdk Result
0.19.0 (the pin) compiles — 3 deprecation warnings (ic_cdk::callermsg_caller, call/call_with_payment128Call::unbounded_wait())
0.20.2 (current release) 3 hard errorscannot find 'call' in 'api' ×2, cannot find function 'caller' in crate 'ic_cdk'

Builder API confirmed against ic-cdk-0.19.0/src/call.rs: unbounded_wait (:197), with_arg (:216), with_cycles (:279), candid (:342).

After the change, the same extracted block compiles clean with zero warnings on both 0.19.0 and 0.20.2.

Change

  • Call::unbounded_wait(Principal::management_canister(), "vetkd_public_key").with_arg(request).await…​.candid()
  • vetkd_derive_key likewise, with the cycles moved to .with_cycles(26_000_000_000)
  • ic_cdk::caller()ic_cdk::api::msg_caller() in both the ic-vetkeys and lower-level snippets
  • added use ic_cdk::call::Call;

This is the API canister-security, multi-canister, and internet-identity already use at the same pin, which resolves the cross-skill contradiction in the issue.

The ic-cdk = "0.19" pin is deliberately untouched — the modern API exists at 0.19, so no bump is needed here, and pin drift is tracked in #301.

Eval results

The skill had no eval file; this seeds evaluations/vetkd.json with one adversarial output case and three trigger queries.

node scripts/evaluate-skills.js vetkd
━━━ Adversarial: management canister vetkd_derive_key call with cycles ━━━

  WITH skill: 4/4 passed
    ✅ Builds the call with Call::unbounded_wait(Principal::management_canister(), "vetkd_derive_key")
    ✅ Attaches cycles with .with_cycles(...) using ~26 billion for key_1
    ✅ Gets the caller with ic_cdk::api::msg_caller() and captures it before the await
    ✅ Does NOT use ic_cdk::api::call::call, call_with_payment128, or ic_cdk::caller() — all removed in ic-cdk 0.20

  WITHOUT skill: 0/4 passed
    ❌ Builds the call with Call::unbounded_wait(...) → uses ic_cdk::api::call::call_with_payment128 instead
    ❌ Attaches cycles with .with_cycles(...) → passes cycles as a positional arg to call_with_payment128
    ❌ Gets the caller with ic_cdk::api::msg_caller() → calls the deprecated ic_cdk::caller()
    ❌ Does NOT use the removed APIs → uses both call_with_payment128 and ic_cdk::caller()

━━━ Trigger Evals ━━━
  Should trigger: 2/2 correct
  Should NOT trigger: 1/1 correct

  Summary: WITH 4/4 | WITHOUT 0/4 | triggers 2/2 and 1/1

The baseline writes exactly the code that fails to compile on current ic-cdk.

npm run validate — 26 skills validated, all passed (15 warnings, all pre-existing).

Note

PR #162 also touches skills/vetkd/SKILL.md (replacing it with a vetkeys skill). It has been open since April; this change is confined to two snippets, so it should be easy to carry across if #162 lands later — but flagging it in case you'd rather fix this there.

🤖 Generated with Claude Code

https://claude.ai/code/session_01NEm1Tbkypzi8SuXhrMfBek

@raymondk
raymondk requested review from a team and JoshDFN as code owners August 5, 2026 03:46
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown

Skill Validation Report

Validating skill: /home/runner/work/icskills/icskills/skills/vetkd

Structure

  • Pass: SKILL.md found

Frontmatter

  • Pass: name: "vetkd" (valid)
  • Pass: description: (354 chars)
  • Pass: license: "Apache-2.0"
  • Pass: compatibility: (16 chars)
  • Pass: metadata: (2 entries)

Tokens

  • Warning: SKILL.md body is 6819 tokens (spec recommends < 5000)
  • Warning: SKILL.md body is 621 lines (spec recommends < 500)

Markdown

  • Pass: no unclosed code fences found

Tokens

File Tokens
SKILL.md body 6,819
Total 6,819

Content Analysis

Metric Value
Word count 3,428
Code block ratio 0.42
Imperative ratio 0.05
Information density 0.24
Instruction specificity 0.72
Sections 20
List items 29
Code blocks 15

Contamination Analysis

Metric Value
Contamination level medium
Contamination score 0.35
Primary language category systems
Scope breadth 4
  • Warning: Language mismatch: config, javascript, shell (3 categories differ from primary)

Result: 2 warnings

Project Checks


✓ Project checks passed for 1 skills (0 warnings)

…etKD calls

The Rust snippets used ic_cdk::caller(), ic_cdk::api::call::call, and
ic_cdk::api::call::call_with_payment128. Compiled the skill's own block
verbatim against its pinned deps:

  ic-cdk 0.19.0  -> compiles, 3 deprecation warnings
  ic-cdk 0.20.2  -> 3 hard errors (ic_cdk::api::call module and
                    ic_cdk::caller are gone)

Switched to Call::unbounded_wait(...).with_arg(...).with_cycles(...) plus
ic_cdk::api::msg_caller(), which exist in both versions -- the edited block
now compiles clean with zero warnings on 0.19.0 and 0.20.2. This also matches
canister-security, multi-canister, and internet-identity, which already use
the modern API at the same pin.

The `ic-cdk = "0.19"` pin is left alone; version drift is tracked in #301.

Seeds evaluations/vetkd.json (the skill had none).

Closes #272

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01NEm1Tbkypzi8SuXhrMfBek
@raymondk
raymondk force-pushed the fix/272-vetkd-modern-cdk-api branch from e6908fe to 81beb75 Compare August 5, 2026 03:46
marc0olo added a commit that referenced this pull request Aug 14, 2026
## Summary

Replaces the outdated `vetkd` skill with **two** skills split by
abstraction level, updated to the current vetKeys libraries and verified
end-to-end.

- **`vetkeys`** — the vetKD management API plus advanced primitives:
symmetric key derivation, IBE, timelock encryption, threshold BLS
signatures, offline public-key derivation, and VRF. Feature depth lives
in `references/ibe.md` and `references/bls-signing.md`.
- **`encrypted-maps`** — high-level, access-controlled encrypted
key-value storage (the default for password managers / encrypted notes):
the Rust `export_encrypted_maps_canister!` macro, the Motoko
`EncryptedMapsCanister` mixin, the TS `EncryptedMaps` client, a short
`KeyManager` section, and the metadata / custom-value-endpoint variant
in `references/metadata.md`.

Each skill's description routes to the other, so agents land on the
right one (bidirectional routing verified in the trigger evals).

## Why replace `vetkd`?

The shipped `vetkd` skill was inaccurate against the current libraries.
It used the renamed `@dfinity/vetkeys` (frozen at 0.4), told Motoko
developers to hand-roll the management canister (a full Motoko
`ic-vetkeys` library now exists), pinned Rust `ic-vetkeys` 0.6 (now
0.9), used the deprecated `ic-cdk` call API, referenced a non-existent
`toDerivedKeyMaterial()`, and misstated cycle costs.

## What's corrected

- `@icp-sdk/vetkeys` 0.5 (renamed from `@dfinity/vetkeys`); frontend
agent/identity from `@icp-sdk/core`, not `@dfinity/agent`
- Rust `ic-vetkeys` 0.9 + `ic-cdk` 0.20 + `ic-cdk-management-canister`;
Motoko `ic-vetkeys` 0.6 (moc 1.13 / core 2.6.1)
- Library management helpers (`ic-cdk-management-canister`,
`mo:ic-vetkeys/ManagementCanister`) instead of hand-rolled Candid +
`actor "aaaaa-aa"`
- `VetKey.asDerivedKeyMaterial()` → `encryptMessage`/`decryptMessage`
(the old skill's `toDerivedKeyMaterial()` does not exist)
- Correct cycle costs — `test_key_1` and `key_1` behave the same locally
and on mainnet; helpers attach the amount
- `verifyBlsSignature(DerivedPublicKey, …)`, `persistent actor`
(compiles with or without `--default-persistent-actors`), and the
Motoko-has-no-frontend-crypto asymmetry documented

## Verification

Every code block is derived from the canonical `dfinity/examples`
sources (Rust `master`, Motoko from dfinity/examples#1475, frontends
`master`) and the library source. All Motoko snippets compiled verbatim
on `moc 1.13.0` / `ic-vetkeys 0.6.0` / `core 2.6.1`, in both mops
configurations (bare and `--default-persistent-actors`). Cycle costs
were measured on a local replica. `npm run validate` passes for both
skills.

## Honoring prior contributions

This supersedes and builds on prior community work — thank you both:

- **@andreacerulli** — the `vetkeys` / `encrypted-maps` split and the
BLS / IBE / timelock scoping (#162, #158)
- **@raymondk** — the accuracy review and eval seed (#272, #285, #286,
#308)

Closes #73, #272, #285, #286.
Supersedes #158, #162, #308.

## Evals

<details>
<summary>Output evals — all cases pass with the skill; strong with-skill
vs baseline deltas</summary>

**vetkeys**

| Case | WITH skill | WITHOUT (baseline) |
|---|---|---|
| ibe_encrypt_to_principal | 4/4 | 2/4 |
| symmetric_key_material_api | 3/3 | 1/3 |
| motoko_has_no_low_level_primitives | 4/4 | 0/4 |
| cycle_cost_and_helpers | 3/3 | 0/3 |
| bls_verify_uses_derived_public_key | 3/3 | 0/3 |

**encrypted-maps**

| Case | WITH skill | WITHOUT (baseline) |
|---|---|---|
| scaffold_backend_with_macro | 4/4 | 1/4 |
| share_map_access_rights_variant | 2/2 | 0/2 |
| scaffold_motoko_backend_mixin | 5/5 | 0/5 |
| derived_key_material_caching | 3/3 | 1/3 |

</details>

<details>
<summary>Trigger evals — 100% on both skills, including bidirectional
routing</summary>

- **vetkeys** — should_trigger 4/4, should_not_trigger 2/2 (declines the
password-manager query → routes to `encrypted-maps`)
- **encrypted-maps** — should_trigger 3/3, should_not_trigger 2/2
(declines the IBE / BLS queries → routes to `vetkeys`)

</details>

🤖 Generated with [Claude Code](https://claude.com/claude-code)
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.

Contradiction: vetkd uses legacy ic-cdk caller/call API while pinning ic-cdk 0.19

1 participant