-
Notifications
You must be signed in to change notification settings - Fork 3
feat/aiken uplc plugin #116
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
… wasm and it is a opt in solution not built-in impl
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR introduces a new @evolution-sdk/aiken-uplc package for WASM-based local UPLC script evaluation, adds transaction builder composition capabilities, fixes a validity interval fee calculation bug, and improves error handling throughout the codebase.
Key Changes:
- New aiken-uplc package with Rust/WASM implementation for offline script evaluation
- Added
compose()andgetPrograms()methods to TransactionBuilder for modular transaction building - Fixed validity interval fee calculation bug by including ttl/validityIntervalStart in fee estimation loop
- Changed Evaluator interface to accept Transaction object instead of CBOR hex string
- Improved error messages to include underlying error details
- Corrected error types from TransactionBuilderError to never for pure constructor functions
Reviewed changes
Copilot reviewed 43 out of 52 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/aiken-uplc/* | New package with Rust WASM bindings for Aiken UPLC evaluator with Node.js and browser support |
| packages/evolution/src/sdk/builders/TransactionBuilder.ts | Added compose() and getPrograms() methods for builder composition; changed Evaluator interface |
| packages/evolution/src/sdk/builders/TxBuilderImpl.ts | Added validity interval conversion before fee calculation loop; improved error messages |
| packages/evolution/src/sdk/builders/phases/Evaluation.ts | Filters PlutusV2 cost models to prevent i64 overflow; passes Transaction to evaluator |
| packages/evolution/src/sdk/builders/phases/FeeCalculation.ts | Added BuildOptionsTag dependency for slot config access |
| packages/evolution-devnet/test/TxBuilder.Compose.test.ts | New comprehensive tests for builder composition feature |
| packages/evolution-devnet/test/TxBuilder.Scripts.test.ts | Added test for Aiken WASM evaluator integration |
| packages/evolution-devnet/test/TxBuilder.Validity.test.ts | Updated tests to verify validity interval submissions |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| "provenance": true, | ||
| "exports": { | ||
| ".": { | ||
| "types": "./dist/evaluator.d.ts", |
Copilot
AI
Dec 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The types path in publishConfig points to "./dist/evaluator.d.ts" but the exports at the top level point to "./src/index.node.ts". After building, the types should point to the compiled declaration file. However, based on the file structure, it should be "./dist/index.node.d.ts" not "./dist/evaluator.d.ts". This mismatch could cause TypeScript resolution issues for consumers of the package.
| "types": "./dist/evaluator.d.ts", | |
| "types": "./dist/index.node.d.ts", |
| budget_steps: bigint, | ||
| budget_mem: bigint, |
Copilot
AI
Dec 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The parameter names in the TypeScript interface (budget_steps, budget_mem) don't match the Rust function signature (initial_budget_n, initial_budget_d). Based on the Rust code, these represent numerator and denominator for the budget calculation, not steps and memory directly. The TypeScript interface should use initial_budget_n and initial_budget_d to match the Rust implementation and avoid confusion about what these parameters represent.
| budget_steps: bigint, | |
| budget_mem: bigint, | |
| initial_budget_n: bigint, | |
| initial_budget_d: bigint, |
| const redeemer_tag: EvalRedeemer.EvalRedeemer["redeemer_tag"] = Effect.gen(function* () { | ||
| // Handle Conway-era tags (vote=4, propose=5) | ||
| if (tagBigInt === 4n) return "vote" | ||
| if (tagBigInt === 5n) return "propose" | ||
|
|
||
| // Standard tags (0-3) | ||
| const mappedTag = tagMap[redeemer.tag] | ||
| if (!mappedTag) { | ||
| throw new Error(`Unknown redeemer tag: ${redeemer.tag} (${tagBigInt})`) | ||
| } | ||
| return mappedTag | ||
| }).pipe(Effect.runSync) |
Copilot
AI
Dec 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using Effect.gen with Effect.runSync just to perform simple conditional logic is unnecessarily complex and could fail at runtime. This could be replaced with a simple if-else statement or ternary operator. The Effect.runSync call means this code could throw unexpected runtime errors if the Effect has any async dependencies. A straightforward implementation would be more readable and safer.
| const plutusV1Costs = Object.values(protocolParams.costModels.PlutusV1).map((v) => BigInt(v)) | ||
| const plutusV2Costs = Object.values(protocolParams.costModels.PlutusV2).map((v) => BigInt(v)) | ||
| const plutusV2Costs = Object.values(protocolParams.costModels.PlutusV2) | ||
| .map((v) => BigInt(v)) | ||
| // Filter out devnet placeholder values (2^63) that overflow i64 in WASM CBOR decoder | ||
| .filter((v) => v <= INT64_MAX) | ||
| const plutusV3Costs = Object.values(protocolParams.costModels.PlutusV3).map((v) => BigInt(v)) |
Copilot
AI
Dec 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The filtering of PlutusV2 cost model values that exceed INT64_MAX is only applied to PlutusV2, but the comment suggests this is a general issue with devnet placeholder values. PlutusV1 and PlutusV3 cost models could also have the same overflow issue. This filtering should be consistently applied to all three Plutus versions to prevent WASM CBOR decoder overflow errors.
| crate-type = ["cdylib"] | ||
|
|
||
| [dependencies] | ||
| uplc = "1.1.17" |
Copilot
AI
Dec 26, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Version mismatch between Cargo.toml and Cargo.lock for the uplc dependency. Cargo.toml specifies version "1.1.17" but Cargo.lock has "1.1.21". This indicates the lockfile was updated without updating the TOML specification. Consider updating Cargo.toml to explicitly specify "1.1.21" or use a semver range like "1.1" to allow patch updates.
| uplc = "1.1.17" | |
| uplc = "1.1" |
No description provided.