You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
This commit was created on GitHub.com and signed with GitHub’s verified signature.
0.17.0
Breaking Changes
[BREAKING][removal][rust] Removed the miden_client::crypto::RandomCoin re-export. Use a rand CSPRNG such as ChaCha20Rng, plus the new miden_client::rng::{draw_felt, draw_word} helpers where a Felt or Word is needed from a generator that does not implement FeltRng (#2414).
[BREAKING][type][rust] ClientBuilder::rng is now only available under the testing feature and requires CryptoRng + Send + Sync; the marker trait ClientFeltRng is renamed to ClientCryptoRng. Outside of tests the client's RNG is always an OS-seeded ChaCha20Rng; drop the rng() call (#2414).
[BREAKING][arch][rust,store] Updated protocol dependencies to 0.17.0, Miden VM to 0.35, miden-debug to 0.18.0 and miden-node-proto-build to 0.17.0-rc.4. Requires a compatible node and a new client database (#2530, #2549, #2562, #2594, #2621, #2651).
[BREAKING][behavior][rust] Keystore::get_account_key_commitments returns an empty set for an account the keystore holds no key for, instead of an error. An account can use keys that are held elsewhere, so this is a valid state. Code that read the error as "this account is unknown" must check for an empty set instead. export --account now exports such an account instead of failing with "No keys found for account" (#2556).
[BREAKING][type][rust] Added the StoreError::DatabaseTransientError and StoreError::DatabasePermanentError variants, so exhaustive matches on StoreError must handle them. The SQLite store returns the first for a busy or locked database and the second for a constraint violation or a corrupt database file, which it previously reported as StoreError::DatabaseError (#2537).
[BREAKING][type][rust] Flattened SyncedNote, it now carries note_id, metadata and inclusion_proof directly, replacing the nested committed: CommittedNote field. Code that read that field can call SyncedNote::into_committed_note to get the sync record back, with the note's resolved attachments included (#2475).
[BREAKING][param][rust] NoteObserver::observe now takes a single &SyncedNote instead of a &CommittedNote and its &NoteAttachments (#2475).
[BREAKING][behavior][rust] Notes fetched from the Note Transport Layer are screened when their tag matches a tracked account's tag, discarding the ones no tracked account can consume (#2474).
[BREAKING][behavior][rust] A Note Transport Layer failure no longer fails Client::sync_state. The error is logged and the chain sync still applies; the transport cursor is left where it was, so the next sync requests the same page again (#2453).
[BREAKING][type][rust] Added the TransactionRequestError::SwapNoteWithZeroAsset variant, so exhaustive matches on TransactionRequestError must handle it (#2459).
[BREAKING][removal][rust] Removed TransactionFilter::to_query. The method emitted SQLite text from the storage-agnostic Store module, so the query now lives in miden-client-sqlite-store next to the NoteFilter queries.
[BREAKING][removal][test] Loose helper functions in miden_client::testing::common are now methods on TestClient. TestClient::keystore() exposes the client's keystore, so ClientConfig::into_client and into_unsynced_client return just the TestClient instead of a client/keystore pair (#2481).
[BREAKING][removal][rust] tokens_to_base_units, base_units_to_tokens and TokenParseError are removed from miden_client::utils. They format and parse fungible amounts for display against a faucet's decimals, which only the CLI needs, so they now live in the CLI crate (#2515).
[BREAKING][arch][rust,rpc] Protocol object messages now come from the canonical miden-objects schemas instead of node-owned copies: proto::account, proto::asset, proto::blockchain, proto::note, proto::primitives, proto::protocol_config and proto::transaction are now re-exports of miden_objects::proto, and primitives.Digest is now primitives.Word. The RPC domain conversions decode a message and then build or verify it, following the miden-objects split. Requires a node that speaks the canonical schemas (#2549).
[BREAKING][removal][rust,rpc] Removed the protobuf conversions for protocol objects from the client: the rpc::domain modules block, digest, merkle and smt are gone, along with the AccountId, AccountHeader, AccountStorageHeader, AccountWitness, NoteId, NoteMetadata, NoteHeader, NoteInclusionProof, NoteScript, TransactionId and Asset conversions in the surviving modules (#2549).
[BREAKING][type][rust] RpcConversionError gained a CanonicalConversion variant that wraps miden_objects::ConversionError, and lost the DeserializationError, NotAValidFelt, NoteTypeError, MerkleError and InvalidInt variants, which the removed conversions were the only source of. ConversionError is re-exported from rpc, so matching on the variant that wraps it needs no direct miden-objects dependency (#2549).
[BREAKING][type][rust] TryFrom<proto::Proof> for ProvenTransaction now reports TransactionProverError instead of DeserializationError, keeping the original error as its source (#2549).
[BREAKING][type][rust] The re-exported NoteExecutionHint gained an Unknown(Felt) variant, so exhaustive matches on it must handle the new variant. NoteExecutionHint::into_parts now returns Option<(u8, u32)>, which is None for Unknown, and the TryFrom<u64> and From<NoteExecutionHint> for u64 conversions are replaced by From<Felt> and From<NoteExecutionHint> for Felt. An unrecognized encoding is now preserved as Unknown instead of being rejected (#2549).
[BREAKING][rename][rust] Renamed the ClientError::TransactionScriptError and StoreError::TransactionScriptError variants to MastForestScriptError, matching the upstream type that now backs both note scripts and transaction scripts (#2530).
[BREAKING][behavior][rust] AccountReader::get_balance now returns an error instead of AssetAmount::ZERO when the stored asset cannot be read as a fungible asset. A missing asset still reports a zero balance (#2530).
[BREAKING][type][rust] NodeRpcClient::get_block_by_number returns a SignedBlock and an optional ExecutionProof instead of a ProvenBlock. The node carries the block and its proof in separate response fields. The proof is None when it is not requested, and also when the node has not proven the block yet (#2530).
[BREAKING][rename][rust] Replaced the ValidatorKeys re-export with ValidatorConfig and ProvingOptions with Prover (#2530).
[BREAKING][removal][rust] Removed the upstream FungibleAssetDelta, NonFungibleAssetDelta, NonFungibleDeltaAction, and SmtForest re-exports (#2530).
[BREAKING][type][rust] TransactionRequest::incoming_assets now returns Vec<Asset> for assets without fungible amounts (#2530).
[BREAKING][removal][rust] The note transport gRPC client now uses the service and message definitions from the node repository, through miden-node-proto-build from crates.io. NoteTransportCursor now stores the node's nonce and sequence, and the unsupported NoteTransportClient::stream_notes API and NoteStream trait were removed (#2594).
[BREAKING][arch][rust] AccountFile and NoteFile moved from miden-protocol and miden-standards to miden-objects. Both are re-exported from miden_client::account and miden_client::note as before (#2594).
[BREAKING][type][rust] AccountFile and NoteFile are encoded as Protobuf, so files written by earlier versions no longer decode. Deserializable::read_from_bytes is replaced by try_from_bytes, which reports the new AccountFileError and NoteFileError (#2594).
[BREAKING][type][rust] The AccountFile fields account and auth_secret_keys are private. Use account(), auth_secret_keys() or into_parts(). NoteSyncHint likewise exposes after_block_num() and tag() (#2594).
[BREAKING][behavior][rust,cli] The client now gets its protocol configuration from the node during Client::sync_state instead of being given one. SyncChainMmr carries the configuration when the client syncs from genesis or when the configuration commitment changed over the synced range, and the client verifies it against the block header before storing it (#2591).
[BREAKING][behavior][rust] State sync now authenticates the chain tip by verifying the block signatures against the validator configuration (#2553).
[BREAKING][param][rust] StateSync::new now takes a validator_config: ValidatorConfig argument, used to authenticate the chain tip block header on every sync. The validator configuration can be retrieved from the client with Client::get_validator_config (#2553).
[BREAKING][type][rust] NodeRpcClient gained a register_account method, which binds an invitation code to an account ID through the node's RegisterAccount endpoint (#2532).
[BREAKING][type][rust] Added NodeRpcClient::is_account_allowed and the ClientError::AccountNotAllowlisted and ClientError::AccountAlreadyAllowed variants (#2550).
[BREAKING][behavior][rust] BatchBuilder::submit returns the new BatchBuilderError::BatchSubmissionOutcomeUnknown when a submission comes back without a definite outcome, instead of ClientError::RpcError. It carries a ProvenBatchSubmission to resend with Client::retry_proven_batch. Rejections the node issues deliberately are unaffected, so code matching ClientError::RpcError still compiles but stops matching these cases (#2508).
[BREAKING][type][rust] Added the BatchBuilderError::BatchSubmissionOutcomeUnknown variant, so exhaustive matches on BatchBuilderError must handle it (#2508).
[BREAKING][param][rust] NodeRpcClient takes the submitted payload by reference instead of by value: submit_proven_transaction takes &ProvenTransaction instead of ProvenTransaction, and submit_proven_batch takes &ProvenBatch and &ProposedBatch instead of ProvenBatch and ProposedBatch. An implementation that needs to own the payload must clone it itself (#2508).
[BREAKING][type][rust] Added the TransactionRequestError::InputNoteBeingProcessed variant, so exhaustive matches on TransactionRequestError must handle it (#2583).
[BREAKING][removal][rust,cli] Removed Client::send_private_note, Client::send_private_note_with_block_hint, NoteTransportClient::send_note and NoteTransportClient::send_note_with_block_hint, which used the note transport network's SendNote endpoint. Use Client::send_private_note_with_proof and NoteTransportClient::send_note_with_proof instead; a private note can only be relayed once its transaction is committed and the sender has synced past it. send_note_with_proof takes a validated TransportNote and is the only send method custom transports implement. miden-client notes --send errors when the stored note has no inclusion proof yet. Pending relay-outbox entries recorded by earlier versions carry no proof and are dropped on load (#2611).
[BREAKING][behavior][rust] Client::add_account and Client::add_address return the new ClientError::AccountTagLimitExceeded when the client already tracks Client::MAX_ACCOUNT_TAGS (128) account tags, the most the note transport accepts in one request (#2627).
[BREAKING][behavior][rust] Client::sync_note_transport and Client::fetch_private_notes return an error when the note transport returns a note that does not decode, whose details do not match its header, or whose tag was not requested. Client::sync_state logs the error and continues the chain sync (#2630).
[BREAKING][type][rust] Added the NoteTransportError::InvalidFetchedNote and NoteTransportError::UnrequestedTag variants (#2630).
[BREAKING][behavior][rust] Added TransactionRequestBuilder::block_numbers so callers can include selected blocks in a transaction's partial blockchain and in anchors captured with Client::chain_anchor_for_request. TransactionRequest now always serializes the block numbers, so request bytes written by earlier versions do not deserialize (#2629, #2625).
[BREAKING][removal][cli] exec now requires --package (-p). Removed --script-path (-s) and in-process MASM compilation. Compile scripts with miden build first. DAP sessions use package debug information and reload the compiled package on restart (#2596).
[BREAKING][type][rust] Sync endpoints now report a FutureBlock error when the requested block is ahead of the node's chain tip. Endpoint errors now match the node's error codes, including new transaction submission errors, and unused error variants were removed (#2623).
[BREAKING][arch][store] The SQLite store writes its structured values as protobuf messages instead of the Serializable encoding: transaction details and status, input and output note states, account code, note and transaction scripts, note assets, attachments, storage and metadata, block headers, partial blockchain peaks, and account witnesses. Requires a new client database (#2624, #2647).
[BREAKING][param][rust] The Store trait requires five account-witness registry methods: track_account_witness, untrack_account_witness, tracked_account_witnesses, get_account_witness and update_account_witness. They have no default bodies, so every out-of-tree implementation must provide them (#2476).
[BREAKING][api][rust,cli] Updated the node, remote prover and note transport clients to the v1 gRPC APIs of node 0.17.0-rc.4 (#2651).
[BREAKING][type][rust] AccountPatch and AccountDelta carry their code as an AccountCodePatch. Code in a patch no longer means that the account is new, because a code upgrade also carries code. AccountPatch::is_full_state and Account::try_from(&AccountPatch) are removed. Use AccountPatch::try_to_new_account to build a new account from a creation patch (#2642).
[BREAKING][behavior][store] Account code, note scripts and transaction scripts use the hashless MAST serialization of protocol 0.17.0. A store that an earlier version created cannot read them and must be recreated (#2642).
[BREAKING][behavior][rust] TransactionRequest serializes the new code of an account code upgrade after its other fields, so request bytes that an earlier version wrote do not deserialize (#2645).
[BREAKING][removal][rust,cli] Removed unused items: the deprecated ClientBuilder::tx_graceful_blocks alias (use tx_discard_delta), the NoteTransportUpdate struct, the AccountProofs type alias, the CliError::Internal variant, and the test helpers FaultyNoteTransportApi::fail_next_n and MockRpcApi::get_private_available_notes (#2661).
Features
[FEATURE][cli] Added a keys command to list, generate, and import authentication keys, manage their account associations, and calculate a key commitment from a public key (#2559).
[FEATURE][cli] export --account accepts a --no-keys flag, which leaves the account secret keys out of the exported .mac file. The file still carries the account seed while the account is undeployed (#2556).
[FEATURE][rust] The committed note passed to the OnNoteReceived callback now always reports the note's resolved attachment content, whether the SyncNotes response carried it verbatim or a GetNotesById follow-up resolved it (#2475).
[FEATURE][rust] Re-exported the fee pricing and note checking types that the client API already surfaces, so downstream crates no longer need a direct miden-tx dependency to price note consumption: NetworkNotePricer, NotePricingError and NoteCheckerError at the crate root, TransactionFee and TransactionFeeError from transaction, NoteCost and NoteConsumptionCost from note, and MastForestStore and TransactionMastStore from testing (#2475).
[FEATURE][rust] Added Client::get_validator_config, which returns the validator configuration committed by the locally stored block header at the current sync height (#2553).
[FEATURE][rust] Added Endpoint::mainnet(), ClientBuilder::for_mainnet(), MAINNET_PROVER_ENDPOINT and NOTE_TRANSPORT_MAINNET_ENDPOINT. The mainnet RPC endpoint maps to NetworkId::Mainnet, so addresses derived from it use the mm prefix (#2569).
[FEATURE][cli] init --network mainnet configures the client for the Miden mainnet, including its note transport endpoint (#2569).
[FEATURE][cli] Added the optional network_id setting under [rpc] and the init --network-id <HRP> flag. They set the bech32 prefix the CLI renders and accepts for a node that is not one of the built-in endpoints, which otherwise maps to mcst (#2569).
[FEATURE][rust] Client::retry_proven_batch resends a batch whose outcome was never confirmed, sealing the transaction inputs again on every attempt so nothing is executed or proven twice. It takes the ProvenBatchSubmission from BatchBuilderError::BatchSubmissionOutcomeUnknown, which has no public constructor, so that error is the only way to obtain one (#2508).
[FEATURE][cli] Added account --register <ID> --invitation-code <CODE>, which registers a tracked account on the network allowlist. When the network funds registered accounts, the command tells the user to sync and consume the funding note the node paid the account, which creates the account on chain (#2545).
[FEATURE][rust] Added Client::register_account, which binds an invitation code to a tracked new account that is not a network account (#2545).
[FEATURE][rust] Added Client::is_account_allowed. Submitting a transaction or batch that creates an account the network allowlist does not accept now fails with ClientError::AccountNotAllowlisted (#2550).
[FEATURE][cli] Added a --package option to exec so a compiled transaction script package (.masp) can be run instead of MASM source. A path without an extension is resolved in the package directory, as with call --package (#2470).
[FEATURE][cli] Added the mutually exclusive authentication scheme flags --ecdsa-k256-keccak [PUBLIC_KEY] and --falcon512-poseidon2 (aliases --ecdsa, --falcon) to new-wallet and new-account. With an ECDSA public key, the account commits to the external key and stores no secret key. ECDSA accepts a 0x-prefixed compressed or uncompressed SEC1 key. Without a public key, the CLI generates and stores a key of the selected scheme. keys --commitment now also accepts the 65-byte uncompressed SEC1 encoding (#2590).
[FEATURE][rust,cli] Added Client::send_private_note_with_proof and NoteTransportClient::send_note_with_proof, which relay a private note together with its inclusion proof through the note transport network's SendNoteWithProof endpoint. The gRPC service verifies the proof before it stores the note, and recipients receive the exact commitment block instead of a hint. miden-client notes --send relays the stored note's proof (#2611).
[FEATURE][rust] Added support for account code upgrades. The store saves the new code when a local transaction or a synced public account update changes the code of an account, also when a large public account syncs through incremental patches. The store rejects a patch whose code does not match the new code commitment. Re-exported AccountCodePatch, AccountCodeUpgrade, UpgradeNote, AccountCodeUpgradeAttachment, AccountCodeUpgradeAttachmentError and UpgradeManager (#2642).
[FEATURE][rust] Added MockRpcApi::add_pending_executed_transaction, which commits an executed transaction on the mock chain with a dummy proof (#2642).
[FEATURE][rust] Added TransactionRequestBuilder helpers for account code upgrades. account_code_upgrade gives the new code to a transaction whose custom script upgrades the executing account. build_account_code_upgrade builds a request that upgrades the code of an account with UpgradeManager and Authority::AuthControlled. TransactionRequest::account_code_upgrade returns the new code of a request (#2645).
Enhancements
[rust] Client::sync_state fetches a Note Transport Layer page and the node's chain update concurrently, instead of running a full note transport sync before the chain sync. The transport notes are imported first and their records join the chain sync's note updates, so a note delivered and committed within the same sync is reported by that sync (#2453).
[FEATURE][cli] call now takes an account-id argument as a bech32 address as well as a hex id, matching the spellings the rest of the CLI accepts for an account. This applies to the account-id type itself and to the faucet half of an asset token (#2179).
[test] The testing node is installed from the node crates on crates.io instead of a git revision. Its genesis is built with that release's miden-validator genesis flags: the native faucet, a new funding account, the fee and the timestamp are passed on the command line and the remaining accounts through --accounts-config (#2594).
[test] CI uses smaller runners for short jobs and cancels superseded pull request runs. Pull requests skip specialty system tests when unrelated files change, while pushes to main and next still run every test (#2610).
[FEATURE][cli] The CLI logs the .miden directory it loaded the configuration from, and whether it is the local or the global one, at debug level. Run a command with RUST_LOG=debug to see it (#2648).
[FEATURE][arch][rust] Added the miden-client-proto crate with the protobuf schemas and conversions of the miden-client types. decode runs all checks and decode_unchecked may skip the expensive ones for bytes from a trusted source. Output note states can include their note scripts or omit them when a store keeps scripts separately. miden-client-sqlite-store uses it for its stored values (#2652).
[FEATURE][rust] Added Client::track_account_witness, Client::untrack_account_witness and Client::tracked_account_witnesses to register accounts whose account witness the sync keeps fresh in the store (new account_witnesses table). A transaction using a registered account as a foreign account builds its inputs from the store instead of issuing a GetAccount request, moving the cost from once per transaction to once per sync (#2476).
Fixes
[FIX][cli] new-account and new-wallet accept a composite storage slot given as a single slot-level value in the init data file, instead of prompting for each field and then failing with a conflict (#2534).
[FIX][rust] Refreshed tracked input notes after transport imports so the same sync detects their consumption (#2453).
[FIX][rust] A private note fetched from the Note Transport Layer whose nullifier is already on chain is now imported as consumed instead of committed, so get_consumable_notes no longer reports notes the node will reject (#2453).
[FIX][rust] Added validation of cached transaction encryption keys during deserialization. Unsupported encryption schemes and empty or oversized key IDs are rejected before reading the key ID bytes (#2411).
[FIX][cli] notes --list consumable now respects the --account-id filter (#2449).
[FIX][store] Every write transaction of the SQLite store begins as IMMEDIATE. A transaction that read before it wrote could fail the write-lock upgrade with SQLITE_BUSY_SNAPSHOT, which the busy timeout does not retry.
[FIX][cli] A bech32 address encoded for a different network is now rejected, instead of being used as the account ID it carries on the configured network. This covers every account argument (send, mint, consume-notes, call, export, account), the recipient of notes --send, the faucet in an <AMOUNT>::<FAUCET_ADDRESS> asset, and the token symbol map, which no longer loads if an entry names an address of another network (#2546).
[store] Simplified SqliteStore::get_setting to take &Connection directly without opening an unnecessary transaction (#2449).
[FIX][cli] miden-client import now rejects invocations without a file path instead of silently succeeding (#2450).
[FIX][rust] TransactionRequestBuilder::build_swap and build_pswap_create now reject a zero-amount asset on either side of the exchange. A zero requested asset produced a payback P2ID note carrying nothing, and a zero offered asset produced a note whose consumer pays and receives nothing (#2459).
[FIX][test] The integration tests run again on a chain that charges no fee. A --funders path (MIDEN_FUNDER_ACCOUNTS_DIR) that is unset, empty, missing, or holds no .mac file now leaves the run without funders instead of failing, which is all a fee-free genesis needs, since it declares no wallets for the path to hold. A .mac file that is present but unusable stays a hard error (#2481).
[FIX][rust] VerifyingRpcClient::sync_nullifiers now rejects an update stamped outside the requested block_from/block_to window with RpcError::InvalidResponse, in the same pass that checks the nullifier prefixes. GrpcClient rejects a page whose cursor ends past the requested block_to with RpcError::PaginationError, which covers every block-paginated method. Note blocks and transaction records were already range-checked by the sync (#2503).
[FIX][store] set_setting and remove_setting return an error when the number of affected rows does not match the expected count (#2537).
[FIX][rust] A request that consumes a note already held by a pending local transaction is now rejected with TransactionRequestError::InputNoteBeingProcessed before it is executed. Previously the transaction was executed, proven and submitted to the node, and only the local store update failed, leaving a submitted transaction without a local record (#2583).
[FIX][cli] new-account and new-wallet now reject a package that exports procedures without an @account_procedure or @auth_script attribute. They also reject packages whose target kind is not account-component and packages without an account component metadata section (#2542).
[FIX][rust] TransactionRequestBuilder::expiration_delta is now applied to requests without own output notes, such as build_consume_notes or a bare build(). Such a request runs the standard ExpirationTransactionScript with the delta as its script argument, where the delta was previously dropped and the transaction never expired (#2580).
[FIX][store] SqliteStore::update_account keeps the seed of an account whose nonce is still zero, so overwriting an undeployed account (for example with import --overwrite) no longer leaves it undeployable (#2541).
[FIX][cli] Packages resolved from the package directory are read with the trusted package reader (#2568).
[FIX][rust] Missing block headers are fetched together with their MMR proof, avoiding a second node request for the same block while building transaction inputs or a chain anchor (#2634).
[FIX][rust] State sync matches an included transaction to a local pending transaction by its ID only. An included transaction with an unknown ID from the same account and initial state no longer marks the local transaction as committed and is handled as an external transaction (#2661).