Miden 0.17.0
This guide covers all breaking changes you need to migrate an application to Miden 0.17.0. Like the 0.16 guide, it is intentionally user-facing: you do not need to know or care which internal crate (VM, protocol, client) a change came from. If you are:
- building accounts, notes, or transactions
- running a client, web client or React SDK
- writing or compiling MASM
- writing Rust smart contracts with the
midenSDK - interacting with storage, auth, or RPCs
this document is for you. It folds together the breaking changes from the protocol crates (0.16.1 → 0.17.0), the VM crates (miden-vm and miden-crypto, 0.29.2 → 0.35.0), miden-client (0.16.1 → 0.17.0), the Web SDK (@miden-sdk/* 0.16.3 → 0.17.0), and the miden Rust contract SDK / compiler (0.14 → 0.15.0, midenc 0.10 → 0.11.0).
Quick Upgrade
Try upgrading first. Most projects can start with a dependency update:
# Replace these
miden-client = "0.16.1"
miden-client-sqlite-store = "0.16.1"
miden-protocol = "0.16.1"
miden-standards = "0.16.1"
miden-tx = "0.16.1"
miden-tx-batch = "0.16.1"
miden-assembly = "0.29.2"
miden-core = "0.29.2"
miden-core-lib = "0.29.2"
miden-processor = "0.29.2"
miden-prover = "0.29.2"
miden-verifier = "0.29.2"
miden-crypto = "0.29.2"
# With these
miden-client = "0.17.0"
miden-client-sqlite-store = "0.17.0"
miden-protocol = "0.17.0"
miden-standards = "0.17.0"
miden-tx = "0.17.0"
miden-tx-batch = "0.17.0"
miden-objects = "0.17.0" # new: AccountFile / NoteFile and the Protobuf encodings
miden-assembly = "0.35.0"
miden-core = "0.35.0"
miden-core-lib = "0.35.0"
miden-processor = "0.35.0"
miden-prover = "0.35.0"
miden-verifier = "0.35.0"
miden-crypto = "0.35.0"
{
"@miden-sdk/miden-sdk": "0.17.0",
"@miden-sdk/react": "0.17.0"
}
Then run:
cargo update && cargo build
npm install @miden-sdk/[email protected] @miden-sdk/[email protected]
If you encounter errors, continue reading for detailed migration steps.
Packages move to format 7.0.0, 0.16 proofs do not decode, and account and note files are now Protobuf, so files exported by 0.16 do not import into 0.17. A 0.16 SQLite store is rejected at open with store is at schema version 2, which is newer than the highest version this client supports (1). The IndexedDB store deletes its whole database on first open, and the default browser keystore keeps its secret keys in that database, so back the keys up on 0.16.3 first (see Client Changes). Consume private notes before you upgrade, re-assemble every package, and re-sync into a fresh store. Stores created by a 0.17 release candidate fail too: a SQLite one at open, an IndexedDB one is kept and then fails, so delete it. See 0.16 artifacts do not carry over.
A 0.17.0 client is accepted only by a 0.17 node. A 0.16 node rejects it at the version check. The remote prover wire format and the note transport service changed as well: point the note transport endpoint at a 0.17 service together with the RPC endpoint, or private notes silently stop arriving while sync keeps succeeding. See Client Changes.
This guide is for:
- Rust client developers migrating from v0.16 → v0.17
- Web SDK developers using the JavaScript/TypeScript SDK or the React hooks
- Smart contract authors writing MASM or Rust contracts, or using protocol APIs
- App developers using the protocol, standards, or client crates
If you're starting fresh on v0.17, you can skip this guide and go directly to the Get Started guide.
At a Glance
Big themes in 0.17:
| Change | Summary |
|---|---|
The fee asset moved into ProtocolConfig | The block header no longer names the fee faucet. It commits to a ProtocolConfig that every DataStore and TransactionInputs::new call must supply, and that clients obtain through sync. Fees are paid only in the native fee asset at rate 1/1. The Web SDK reads it with client.feeFaucetId(). |
| Multisig binds a caller-chosen block | Multisig accounts need a MultisigAuthArgs preimage on every chain, fee-free ones included, and every party executes at its own tip with the bound block included via block_numbers. The 0.16 ChainAnchor pattern for multisig no longer applies. 0.16 multisig code compiles and then fails at run time. |
| Versions everywhere, so values change silently | Accounts, asset IDs, note metadata and transaction summaries carry versions, and account procedures are sorted. Account commitments and IDs, asset IDs, note IDs, P2ID recipients and every standard note script root change without a compile error. |
Asset is a struct | Asset holds an AssetId and an AssetValue instead of being an enum, and AccountVaultDelta tracks whole assets. match Asset::Fungible(..) no longer compiles in Rust, and fungible() / FungibleAssetDelta are gone from both the Rust crates and the Web SDK. |
| P2ID storage has four items | P2ID gained two salt elements. A P2ID recipient still built by hand with two items produces a note nobody can consume, and P2ID has no reclaim path. |
| MASM calls can change meaning without failing | Several procedures kept their names but changed their stack effect, and the assembler does not check call sites against signatures. tx::get_block_commitment now takes a block number, and an old guardian::verify_signature call silently skips the guardian check. |
Verification can return Ok with work outstanding | The free verify is gone. Verifier::new().verify(&claim, &proof) returns a VerificationOutcome, and transaction proofs defer their precompile claims, so check is_complete(). ProvingOptions became a Prover. |
Account and note files moved to miden-objects | AccountFile and NoteFile live in the new miden-objects crate and are Protobuf-encoded. 0.16 .mac / .mno files and Web export bytes do not load. |
| Network accounts and network notes are stricter | AuthNetworkAccount::new installs BasicWallet and allowlists P2ID, a network account cannot be deployed by an empty transaction and must use the chain's fee asset, and emitting a network note caps the transaction's expiration at 20 blocks. |
| Accounts can upgrade their code | native_account::upgrade now replaces the account's code (in 0.16 it was a no-op), validated like a new account's and switched after the auth procedure. Install UpgradeManager; network accounts are upgraded with an UpgradeNote. |
Standard components link miden-standards dynamically | The standard singlesig, multisig and network-account auth roots change, so those accounts get new code commitments and IDs. A custom MastForestStore / DataStore must also serve StandardsLib. |
| Code and scripts serialize without node hashes | AccountCode, NoteScript and TransactionScript write the hashless MAST format and rebuild the hashes on read. Roots and commitments do not change; stored bytes and note-script felt encodings do. |
| Private notes are relayed with an inclusion proof | The note transport accepts a private note only together with its inclusion proof, so relay it after the creating transaction commits and the client syncs. |
| Old stores fail at open | SQLite stores from 0.16 and from any 0.17 release candidate are rejected with store is at schema version N, which is newer than ..., although they are older. A 0.16.3 IndexedDB store is reset; one from a 0.17 release candidate is kept and then fails. |
VM and miden-crypto jump to 0.35 | Six minor releases (0.29.2 → 0.35.0): package format 7.0.0, core library 0.35 (re-assemble every package that links it dynamically), and Plonky3 0.8. |
| 0.16.x fee helpers are replaced | fee::estimate_fee, fee::assert_fee_bound and multisig::pay_bounded_fee give way to native 1/1 fee payment inside fee::pay_fee. The Web SDK also drops the 0.16.1 prefetched foreign accounts; the Rust client keeps ForeignAccount::Prefetched. |
If you only skim a few sections, skim Transaction Changes, Client Changes, MASM Changes, and Note Changes.
Compatibility
| Component | Required | Tested With |
|---|---|---|
| Miden VM crates | 0.35 | 0.35.0 |
| miden-crypto | 0.35 | 0.35.0 |
| miden-protocol | 0.17.0 | 0.17.0 |
| miden-standards | 0.17.0 | 0.17.0 |
| miden-client | 0.17.0 | 0.17.0 |
Web SDK (@miden-sdk/*) | 0.17.0 | 0.17.0 |
| Node | 0.17.0 | 0.17.0 |
miden contract SDK | 0.15.0 | 0.15.0 |
midenc / cargo-miden | 0.11.0 | 0.11.0 |
| Rust (client / protocol) | 1.98.1+ | 1.98.1 |
| Rust (VM) | 1.96.1+ | 1.98.1 |
| Rust (contract SDK / compiler) | 1.99+ | nightly-2026-09-01 |
Migration Sections
Work through these sections in order for a complete migration:
| Section | Topics |
|---|---|
| 1. Imports & Dependencies | Crate bumps, VM 0.29 → 0.35, the new miden-objects and miden-usdcx crates, dynamic linking of miden-standards, artifacts and stores that do not carry over |
| 2. Hashing & Crypto Changes | serde removed from Word and Merkle types, SmtForest → LargeSmtForest, PartialSmt bytes, stricter decoders, random-value helpers removed and Falcon RNGs needing CryptoRng |
| 3. Account Changes | Versioned accounts, sorted procedures, account code upgrades and AccountCodePatch, network accounts, from_package by value, StorageMap, RBAC and ApproverSet |
| 4. Note Changes | P2ID with four storage items, new standard script roots and costs, UpgradeNote, sealed PSWAP outputs, config notes |
| 5. Assets, Vault & Faucet | Asset as a struct, AccountVaultDelta with whole assets, versioned asset IDs, new standard faucet IDs, callbacks and mint policies |
| 6. Transaction Changes | ProtocolConfig, MultisigAuthArgs and executing at the tip, native-asset fees, 20-block network-note cap, hashless NoteScript / TransactionScript bytes, VerificationOutcome |
| 7. Client Changes | Stores rejected at open, client and node pairing, private notes relayed with an inclusion proof, fee faucet from sync, Rust/Web/React/CLI changes |
| 8. MASM Changes | Procedures whose stack effect changed, a working upgrade, output-note sealing, shifted kernel offsets, miden-standards linked dynamically, renamed accessors, moved standards and core-library modules, trace is back |
| 9. VM & Assembler Changes | Package format 7.0.0 and miden-core 0.35 manifests, Verifier and VerificationOutcome, Prover and the precompile memory budget, FastProcessor, advice budget and AdviceInputs |
| 10. Rust Contract SDK & Compiler | Rebuilding with cargo-miden 0.11, Asset.id, renamed tx accessors, silent auth and P2ID traps |
Final Checklist
Complete these steps to verify your migration:
- Bump all Miden crates per section 1
- Bump every
@miden-sdk/*package to0.17.0together - Consume private notes on 0.16 before upgrading: 0.16 account and note exports do not import into 0.17
- Back up browser-keystore secret keys on 0.16.3: the 0.17 IndexedDB reset deletes them
- Delete and recreate your local SQLite store (with its
-waland-shmfiles), then re-sync. A 0.16.3 IndexedDB store resets itself; delete one created by a 0.17 release candidate - Upgrade the client, node, remote prover and note transport service together, and switch both the RPC and the note transport endpoint
- Re-assemble every
.masppackage and rebuild every contract withcargo-miden0.11; discard proofs and serialized requests from 0.16 - Recreate the CLI's
.miden/packages - Supply a
ProtocolConfigwherever you buildTransactionInputsor implementDataStore; in the Web SDK read the fee faucet withclient.feeFaucetId() - Serve
StandardsLibfrom any customMastForestStore/DataStore - Check every call to
native_account::upgrade(it now really upgrades the code), and move delta and patch code toAccountCodePatch/try_to_new_account() - Add match arms for
StandardNote::UPGRADEandTransactionEventId::AccountBeforeCodeUpgrade, and switch note-script felt encoding toNoteScript::to_elements() - Do not modify PSWAP outputs after the script seals them
- Relay private notes only after the creating transaction commits, with its inclusion proof
- Pay fees in the native fee asset at rate 1/1
- For multisig accounts, build
MultisigAuthArgs, add the bound block withblock_numbers, and execute at the tip rather than at a sharedChainAnchor - Drop the
serdefeature ofmiden-coreandbus-debuggerofmiden-processor, serializeWordand Merkle types without serde, and replaceSmtForestwithLargeSmtForest - Replace
matcharms onAsset::Fungible/Asset::NonFungibleand uses ofFungibleAssetDelta/fungible() - Recompute every hard-coded account ID, code commitment, asset ID, note ID, P2ID recipient and standard note script root
- Build P2ID recipients with four storage items, or through the standard builders
- Deploy network accounts with a transaction that has an effect, using the chain's fee asset
- Re-check every MASM call to a procedure whose stack effect changed, starting with
tx::get_block_commitmentandguardian::verify_signature - Rename
tx::get_fee_faucet_id→tx::get_fee_asset_id,active_account::compute_commitment→native_account::compute_commitment, andmiden::precompiles::*→miden::core::precompiles::* - Verify proofs with
Verifier::new().verify(&claim, &proof)and checkis_complete() - Replace
ProvingOptionswith aProver, and freeexecutecalls withFastProcessor - Move
AccountFile/NoteFileimports tomiden-objects - (If you write Rust contracts) rename
Asset.key→Asset.id, and hash the versioned transaction summary in custom auth components - Run
cargo build- no errors - Run
cargo test- all tests pass
If your project builds and all tests pass, you've successfully migrated to v0.17.
Need Help?
- Telegram: Build on Miden for technical discussion and support.
- Forum: Miden discussions for longer-form questions and design discussion.
- GitHub issues: file against the relevant repo:
rust-sdk,web-sdk,protocol,miden-vm, orcompiler. - Changelogs: the per-repo
CHANGELOG.mdfiles carry the full list of changes, including non-breaking features and fixes omitted from this guide.