paritytech / paritytech/contract-dependency-manager
Rust version pinning: cdm::import! calls execute latest — needs a CallBuilder calldata preamble upstream
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 4
- Forks
- 3
- Avg merge
- 4d 13h
- Merged PRs (30d)
- 3
Description
Problem
Since #76, cdm.json pins an exact version per dependency and cdm::import! generates type-safe stubs from that version's exact ABI — but the generated calls go out as plain calldata, which the per-name proxy routes to the latest implementation. Rust consumers today get "pinned ABI, latest execution" (same gap as TypeScript #78 and Solidity #79, different blocker).
The on-chain side is deployed and e2e-proven: prefixing calldata with [MAGIC 0xa2264d53][u128 versionKey] executes exactly that version.
The blocker is upstream, and it's small
cdm::import! delegates all call-stub generation to pvm_contract_sdk::abi_import! (cargo-pvm-contract). Every generated .call(self) funnels into one function, CallBuilder::call_raw_inner in pvm-contract-core/src/call.rs, which is hardcoded to write [4-byte selector][ABI args] and immediately send:
input_buf[..4].copy_from_slice(&self.selector[..]);
self.payload.encode_to(&mut input_buf[4..]);
host.call_evm(flags, &address.0, gas, &value, input_buf, None)
There is no seam for a calldata prefix, and the workarounds are dead ends (verified during #76):
- a wrapper
Hostcan't be injected — users passselfas the call context, whose host type is fixed by#[contract]; - an extension-trait
.callsilently loses method resolution to the inherent.call(worse than not existing: habit-typed calls would route to latest with no error); - pre-sliced buffers don't help —
call_raw_innersends the same slice it writes.
Upstream ask (cargo-pvm-contract, ~30 lines, CDM-agnostic): an optional calldata preamble on CallBuilder — e.g. preamble: Option<&'static [u8]> (or fixed [u8; 20]) written before the selector in call_raw_inner/delegate_call_raw_inner, plus buffer-size accounting at abi_import's four 4 + encode_len() allocation sites. Inert when unset; useful to any proxy/envelope scheme, not just CDM.
CDM side, once the hook exists
pvm_cdm::reference!already receives the package name at expansion time andcdm-macrosalready reads the pinnedversionfrom cdm.json — bake the packed key (major<<64|minor<<32|patch, constants mirrored incontract-registry-core::versioning) into the generated handle's preamble. User code doesn't change:
cdm::import!("@example/counter");
let counter = counter::Counter::cdm_lookup();
counter.increment().call(self)?; // executes the pinned version, not latest
- A
"latest"spec in cdm.json ⇒ no preamble (today's behavior, made opt-in). - Same change enables the follow-on optimization: bake the stable proxy address at build time (
cdm_from_env-style) and drop the per-callgetAddress(string)registry round-trip fromcdm_lookup()— the address is permanent per name now. - Extend
test:macroandproxy.e2e.test.tswith a pinned Rust consumer case.
Sequencing
- Upstream PR/issue on paritytech/cargo-pvm-contract for the
CallBuilderpreamble (this issue's second section is paste-ready). - Once merged (deps float on
branch = "main", so it flows in automatically): CDM-side wiring inpvm-cdm-macros+ tests — no on-chain changes, the wire format has been live since #76.
References
- #76 (wire format + e2e proof of versioned routing), #78 (TypeScript counterpart), #79 (Solidity counterpart).
reference-repos/cargo-pvm-contract:crates/pvm-contract-core/src/call.rs(call_raw_inner),crates/pvm-contract-macros/src/abi_import/mod.rs(buffer allocation sites).
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with reference-repos/cargo-pvm-contract/crates/pvm-contract-core/src/call.rs and crates/pvm-contract-macros/src/abi_import/mod.rs, then review the CDM macro paths that generate handles. Verify the upstream preamble hook accounts for buffer sizing and remains inert when unset; then wire pinned versions in pvm-cdm-macros and extend test:macro and proxy.e2e.test.ts with a pinned Rust consumer case.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust, typescript
- Domain
- developer-experience, testing-qa, tooling
- Issue type
- Feature
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100