Skip to content

Exercise UserService accept by package name - #65

Merged
hubagaspar91 merged 5 commits into
mainfrom
fix/credential-accept-template-id
Oct 20, 2026
Merged

hubagaspar91 merged 5 commits into
mainfrom
fix/credential-accept-template-id

Conversation

@scolear

@scolear scolear commented Oct 19, 2026 •

Copy link
Copy Markdown
Member

What

token::credentials::accept_credential_offer now exercises UserService_AcceptFreeCredentialOffer with the package-name template id, #utility-credential-app-v0:...:UserService. It used to send the template id of the UserService created event. AcceptCredentialOfferParams loses its user_service_template_id field.

A second commit bumps zip from 2.4.2 to 9.0.5 so Cargo Deny passes again; see below.

Why

A created event's template id carries the package id the contract was created with. The accept therefore pinned the utility-credential-app-v0 version the UserService was created under, instead of letting the participant resolve the name.

G20Group hit this on mainnet. Their UserService was created under 0.1.0. bitsafe-validator-1 hosts the BETH issuer party and vets 0.2.2 and later, so the participant rejected the accept with INVALID_PRESCRIBED_SYNCHRONIZER_ID: participant bitsafe-validator-1 has not vetted package bbe070b7…. With the package-name form the command resolves to the highest version every informee host vets, 0.4.3 today.

The zip bump

RUSTSEC-2026-0367 and RUSTSEC-2026-0368 were published on 2026-10-09 against zip 2.4.2, after the last green run on main, so every PR fails Cargo Deny until the crate moves past them. The token crate only reads META-INF/MANIFEST.MF from a DAR in memory through ZipArchive::new and by_name, both unchanged in 9.x, so the bump needs no code change. cargo deny check advisories passes locally.

How tested

  • New unit test accept_exercises_user_service_by_package_name builds the exercise and asserts the template id is the package-name constant. It failed before the change and passes after.
  • cargo test -p token --lib: 127 passed, 25 ignored (live-ledger tests), before and after the zip bump.
  • cargo clippy --workspace --all-targets is clean. The changed file passes rustfmt --check.

Breaking change

Callers drop user_service_template_id from AcceptCredentialOfferParams. The only known callers are the credentials examples in bitsafe-token-lib; DLC-link/bitsafe-token-lib#6 bumps the dependency and removes the field. This needs a minor release, 0.12.0.

accept_credential_offer sent the template id of the UserService
created event. That id carries the package the UserService was
created with, so the accept pinned that version. A participant that
no longer vets the old version rejected the command with
INVALID_PRESCRIBED_SYNCHRONIZER_ID. G20Group hit this on mainnet
against bitsafe-validator-1, which starts at 0.2.2.

The exercise now uses the package-name template id, so the
participant resolves it to the highest version every informee host
vets. The user_service_template_id parameter goes away.
@scolear
scolear requested review from a team and sosaucily and a balanced review from Copilot October 19, 2026 12:07

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟢 Approval recommended

The focused change matches the intended behavior, documents the API break, and has no identified blocking issues.

No open issues 🎉

What changed in this PR

Updates credential-offer acceptance to use a package-name template ID, avoiding failures caused by pinning the UserService’s original package version.

Changes:

  • Removes user_service_template_id from acceptance parameters.
  • Extracts command construction and adds a regression test.
  • Documents the breaking API change and caller migration.
File Description
crates/​token/​src/​credentials.rs Uses package-name resolution and tests command construction.
CHANGELOG.md Documents the fix and removed parameter.

Review effort: Balanced

@scolear

scolear commented Oct 19, 2026

Copy link
Copy Markdown
Member Author

Cargo Deny fails on advisories RUSTSEC-2026-0367 and RUSTSEC-2026-0368 for the zip 2.4.2 crate, a direct dependency of the token crate. Both were published on 2026-10-09, after the last green run on main, so main fails the same way today. The patched line is zip 9.0.0 or later, a major bump that touches the DAR handling. That belongs in its own PR, not this fix.

cargo deny fails on the zip 2.4.2 extraction advisories published on
2026-10-09. The token crate only reads a DAR's manifest in memory, so
the bugs never applied, but the CI gate blocks every PR until the
crate moves past them. ZipArchive::new and by_name are unchanged in
9.x, so dar_check needs no code change.
@socket-security

socket-security Bot commented Oct 19, 2026 •

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Updatedzip@​2.4.2 ⏵ 9.0.5100 +1910099 +6100100

View full report

hubagaspar91
hubagaspar91 previously approved these changes Oct 19, 2026
@hubagaspar91
hubagaspar91 dismissed their stale review October 19, 2026 17:04

I dismiss my approval so that the nits in my next review come first. I will approve again after the author answers them.

@hubagaspar91 hubagaspar91 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Four nits from a security review and a PM review. None of them blocks the fix, and the fix itself looks correct.

Comment thread crates/token/src/credentials.rs
Comment thread Cargo.toml Outdated
Comment thread CHANGELOG.md Outdated
Comment thread crates/token/src/credentials.rs
hubagaspar91 and others added 3 commits October 20, 2026 14:39
The token crate reads one manifest from each DAR, and DARs use
deflate. The zip default features also pull in AES, bzip2, lzma,
ppmd and zstd, and zstd-sys builds C code in a build script. Each
unused crate adds supply-chain risk. An advisory against any of
them fails Cargo Deny here and in every repo that uses canton-lib.

The CHANGELOG also drops "in memory": dar_check opens the DAR from
disk and never extracts it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The test compared the template id with USER_SERVICE_TEMPLATE_ID,
the same constant that the code uses. A package-id value in the
constant brings back the mainnet bug, and the old test still passed.
The test now asserts the literal package-name string and the choice
argument.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
CredentialOffer, UserCredential and UserServiceInfo expose the
template id of the created event. The old examples passed this
value into a command, and that caused the mainnet accept failure.
The doc comment tells callers to use the package-name form.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@hubagaspar91
hubagaspar91 merged commit 423dc14 into main Oct 20, 2026
3 checks passed
hubagaspar91 added a commit that referenced this pull request Oct 21, 2026
0.12.0 ships #65, which removes the public field
AcceptCredentialOfferParams::user_service_template_id. Semver for
0.x versions treats a breaking change as a minor bump.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
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.

4 participants