Compact toolchain 0.30.0
- Date: 2026-03-17
- Language version: 0.22.0
- Compact runtime version: 0.15.0
- Environment: Preview Testnet at time of release. For the full compatibility matrix, see the release notes overview
High-level summary
In version 0.30, the Compact toolchain now targets Midnight ledger version 8. Previous toolchain versions (e.g., 0.28 and 0.29) targeted ledger version 7. If you are compiling contracts for a ledger 8 blockchain, you should use Compact toolchain 0.30 or later. Earlier versions might work but these are untested and unsupported, and have known bugs. If you are compiling contracts for a ledger 7 blockchain, you must use Compact toolchain 0.29 or an earlier compatible one.
There is an accompanying Compact devtools release, version 0.5.0. You do not have to update the Compact devtools in order to use Compact toolchain version 0.30.0. However, the devtools update comes with some new features. If you have the devtools already installed, you can update them with the command compact self update. If you do not have the devtools already installed, you can install them with the curl command at https://github.com/midnightntwrk/compact/releases/tag/compact-v0.5.0.
Audience
These release notes are intended for Compact smart contract developers and for DApp developers who use the Compact runtime.
What changed
This release targets the new version of the Midnight ledger, version 8.0. The primary advantage is that this version of the blockchain has fixes for a number of bugs that were affecting users. In addition:
- The compiler supports
--ledger-versionand--runtime-versionflags - The compiler and fixup tool now support
--compact-pathand--trace-searchflags - The standard library
NativePointtype is renamed toJubjubPoint - It is a compiler error to use
persistentHashandpersistentCommiton JavaScript opaque values - There is a new search order for include files and modules imported from files
- The language reference is now largely up to date with the current version of the language
- The release notes are included in the release itself
New features
The compiler now supports --ledger-version and --runtime-version flags. The compiler and fixup tool now support --compact-path and --trace-search flags. The release notes are now included in the release itself.
Ledger and runtime version flags
Description: The compiler binary can now report the Midnight ledger version it targets, via a new --ledger-version flag. It can also now report the Compact runtime version that it will import in generated JavaScript code, via a new --runtime-version flag.
Compact smart contracts are currently compiled for a specific version of the Midnight ledger. The ledger version determines, for example, the format of the public state and the format of prover and verifier keys. Smart contracts will not in general work with a different ledger major version number than the one that they were compiled for.
The compiler can report the ledger version it targets with a new --ledger-version flag, for instance:
$ compact compile --ledger-version
ledger-8.0.0
The ledger version will correspond to a tag (or possibly a Git commit hash or branch name) from the Midnight ledger GitHub repository.
Compiler-generated JavaScript code imports a specific version of the Compact runtime to provide core language features. Until it reaches version 1.0, the Compact runtime may have breaking changes in new minor version numbers, so it is important to configure DApps to use the correct Compact runtime version. The generated JavaScript code will verify that it is using the expected version.
The compiler can report the Compact runtime version that will be imported with a new --runtime-version flag, for instance:
$ compact compile --runtime-version
0.15.0
The Compact runtime package is available from npm.
Other Compact toolchain tools, such as the format and fixup tools, do not depend on the ledger or runtime version so they will not understand these flags.
Search path flags
Description: The compiler and fixup tool now support a --compact-path flag whose value is a search path. If this flag is set, its value is used as the search path and the COMPACT_PATH environment variable is ignored. Both tools support a new --trace-search flag that will show on standard error the search order for included and imported files.
Release notes distributed with the release
Description: the release notes are distributed in the release .zip file as a Markdown document. They were previously available from the Midnight developer documentation, in the Compact release repository, and in the Minokawa project's Compact repository. Now they are also included in the .zip file artifacts that form the release.
The Compact devtools will unzip the artifacts into a subdirectory of its artifact directory. The devtools artifact directory is .compact in your home directory by default, but it can be changed by the COMPACT_DIRECTORY environment variable or the --directory command line flag to the compact devtool command.
So for example, for Apple silicon macOS, and if the default artifact directory is used, the release notes for this release will be found in ~/.compact/versions/0.30.0/aarch64-darwin/toolchain-0.30.0.md.
Improvements
The language reference document has been extensively revised so it now describes the current version of the language. The generated TypeScript code now distinguishes circuits that have prover and verifier keys from other impure circuits.
Improvement: Up to date language reference
The language reference found at https://docs.midnight.network/compact/reference/lang-ref is now largely up to date with the current version of the language.
This is a substantial rewrite and improvement of the document.
Improvement: ProvableCircuits
Description: The generated TypeScript code now includes a ProvableCircuits<PS> type and a provableCircuits field on the Contract class. ProvableCircuits contains only the circuits that have prover and verifier keys.
Previously there were only ImpureCircuits and PureCircuits in the TypeScript code. Impure ones were those that used the public ledger state or called witness functions, and pure ones were the rest. Midnight.js was using the ImpureCircuits type to get a list of the circuits that needed a proof. However, an impure circuit that is only impure because it calls witness functions (that is, it does not use the public ledger state) does not need a proof and trying to create one would fail.
The generated TypeScript code now makes a finer distinction. ProvableCircuits are the ones that need a proof. They are always impure, so they are also included in the ImpureCircuits type. Therefore, this is a non-breaking change.
This change enables a bug fix in Midnight.js.
Deprecations
None.
Breaking changes
The Compact standard library type NativePoint has been renamed to JubjubPoint. It is now a compiler error to use persistentHash or persistentCommit on opaque JavaScript values. The search order for include and external module files has been changed.
NativePoint is renamed to JubjubPoint
What changed: The standard library type NativePoint has been renamed to JubjubPoint and there are corresponding name changes for standard library circuits for creating and accessing curve points.
What breaks: Code that uses the old name will no longer compile.
The native ZK-efficient elliptic curve used in the Midnight network is Jubjub. The name NativePoint is changed to JubjubPoint to more clearly reflect the reality.
The standard library circuits nativePointX, nativePointY, and constructNativePoint have correspondingly been renamed to jubjubPointX, jubjubPointY, and constructJubjubPoint.
The Compact runtime's types NativePoint and CompactTypeNativePoint have been changed to JubjubPoint and CompactTypeJubjubPoint. The runtime also has new functions jubjubPointX, jubjubPointY, and constructJubjubPoint that correspond to the Compact circuits of the same name. Previously versions of these were implemented only in the Compact standard library and not reflected in the Compact runtime.
Required actions: Rename code that uses these identifiers. The compact fixup tool can apply the renamings to Compact code. Update a DApp's TypeScript or JavaScript implementation manually if necessary.
It is a compiler error to use persistentHash or persistentCommit on opaque JavaScript values
What changed: It is now a compiler error to use the standard library circuits persistentHash or persistentCommit directly or indirectly (e.g., via a standard library circuit that uses persistentHash in its implementation) on Compact values that contain opaque JavaScript values (Opaque<'string'> or Opaque<'Uint8Array'>). This also affects the standard library operation merkleTreePathRoot and ledger ADT MerkleTree and HistoricMerkleTree insertion operations.
What breaks: Some code that previously compiled will now be a compiler error.
Values containing Opaque<'string'> or Opaque<'Uint8Array'> cannot be correctly hashed in a ZK proof using persistentHash or persistentCommit. This would fail, in the form of a Rust crash, when the compiler tried to generate prover and verifier keys.
It is now a compiler error instead of a Rust crash.
This is a breaking change because previously it was possible to hash such values in pure circuits which will now be a compiler error.
New search order for included files and modules imported from files
What changed: The Compact compiler and fixup tool's search order for include and external module files has been changed. It still uses the COMPACT_PATH environment variable but it has changed as described below.
What breaks: The new search order might find a different file than intended or it might fail to find a file at all.
The previous implementation did not distinguish between relative and absolute paths, with some unfortunate consequences. For relative paths, it would effectively first look for the included or imported file relative to the directory where the command was invoked. For absolute paths, if they were not found it would append the path to the directory of the including file and to each of the directories in COMPACT_PATH in turn, thus treating them as relative paths.
Required actions: With this change, relative paths will no longer be automatically looked for in the directory where the command was invoked. If this is intended, a workaround is to make the path absolute or else to add the invocation directory to COMPACT_PATH and make sure an unintended path is not found relative to the including or importing file.
And absolute paths will no longer be found relative to the directory of the importing or including file, or by searching COMPACT_PATH. A workaround for this is to remove the prefix that makes the path absolute (i.e., the directory separator or drive specifier) so that it is treated as a relative path.
Known issues
None.
Links and references
- The Compact documentation portal, including the language reference and the standard library documentation
- The Compact runtime TypeScript API for DApps
- Compact compiler usage
- The open-source project on GitHub for bug reports and feature requests
Fixed defect list
The following defects are fixed by updating to Compact toolchain 0.30. These are not necessarily bugs in Compact, they are often bugs in other components of the Midnight network.
- Issue #40: It should be a compiler error to pass
Opaque-typed values to certain standard library circuits - Issue #81: Constraint count doubled for
Vector<32, Uint<8>>toBytes<32>cast inv0.28.0 - Issue #107: Circuit calls fails with NullifiersNEClaimedNullifiers
- Issue #110: Circuit call fails with AllCommitmentsSubsetCheckFailure
- Issue #117: Cannot mint shielded tokens in contract constructor
- Issue #139: compactc search order for include and module files is unintuitive and possibly unsafe
- Issue #151: Circuit call fails when using
sendUnshieldedandreceiveUnshielded - Issue #155: Type declarations containing unspecialized generic Uint fail
- Issue #187: Operand-swapping comparison operators (
>and<=) fail ZKIR verification for unequal operands