Skip to main content
Version: 0.14 (unstable)

Transaction Changes

Transaction identity, construction, event namespacing, summary stack layout, output accessors, and block signing have all changed in v0.14. These changes affect anyone building, proving, verifying, or signing transactions and blocks.


TransactionId Now Hashes the Fee Asset

Summary

TransactionId::new now requires a fee_asset: FungibleAsset parameter so the fee is included in the transaction hash. The function takes 5 arguments (6 words total) instead of the previous 4.

Affected Code

Rust:

// Before (0.13)
let tx_id = TransactionId::new(init, final_state, input_notes, output_notes);

// After (0.14)
let tx_id = TransactionId::new(init, final_state, input_notes, output_notes, fee_asset);

Migration Steps

  1. Add the fee_asset: FungibleAsset argument to every TransactionId::new call site.
  2. Ensure the fee_asset value matches the fee used in the transaction.
  3. If you compute or verify transaction IDs externally (e.g., in tests), update the hashing logic to include the fee asset.

Common Errors

Error MessageCauseSolution
this function takes 5 arguments but 4 arguments were suppliedMissing fee_asset parameterAdd the FungibleAsset fee as the fifth argument.
Transaction ID mismatch in verificationHash computed without fee assetRecompute the ID with the fee asset included.

ProvenTransactionBuilder Removed in Favor of ProvenTransaction::new

Summary

The ProvenTransactionBuilder has been removed. Instead, construct a TxAccountUpdate and pass it directly to ProvenTransaction::new.

Affected Code

Rust:

// Before (0.13)
let proven_tx = ProvenTransactionBuilder::new(account_id, init_hash, final_hash, proof)
.account_update_details(details)
.add_input_notes(input_notes)
.add_output_notes(output_notes)
.build()?;

// After (0.14)
let account_update = TxAccountUpdate::new(account_id, init_hash, final_hash, details);
let proven_tx = ProvenTransaction::new(
account_update,
input_notes,
output_notes,
ref_block_num,
ref_block_commitment,
fee,
expiration_block_num,
proof,
);

Migration Steps

  1. Remove all ProvenTransactionBuilder usage.
  2. Create a TxAccountUpdate from the account ID, initial hash, final hash, and update details.
  3. Call ProvenTransaction::new with the account update and all remaining fields as positional arguments.
  4. If you previously relied on builder defaults for optional fields, you must now provide them explicitly (e.g., ref_block_num, ref_block_commitment, expiration_block_num).

Common Errors

Error MessageCauseSolution
cannot find struct ProvenTransactionBuilderBuilder removedUse ProvenTransaction::new with TxAccountUpdate.
cannot find struct TxAccountUpdateMissing importAdd use miden_objects::transaction::TxAccountUpdate; (check crate docs for exact path).
Wrong number of arguments to ProvenTransaction::newMissing required positional parametersProvide all 8 arguments: account_update, input_notes, output_notes, ref_block_num, ref_block_commitment, fee, expiration_block_num, proof.

Kernel Events Prefixed with miden::protocol

Summary

All kernel events have been renamespaced under miden::protocol::. The previous miden:: prefix is no longer recognized.

Affected Code

MASM:

# Before (0.13)
event("miden::account::vault_before_add_asset")
event("miden::auth::request")

# After (0.14)
event("miden::protocol::account::vault_before_add_asset")
event("miden::protocol::auth::request")

Migration Steps

  1. Search your MASM files for all event("miden:: occurrences.
  2. Replace miden:: with miden::protocol:: in every event name.
  3. If you have event handlers or listeners matching on event names, update those patterns as well.

Common Errors

Error MessageCauseSolution
Event not firing / handler not triggeredEvent name changed but handler still matches old nameUpdate both the event emission and handler to use miden::protocol:: prefix.
unknown event or silent no-opOld event name no longer existsRename to miden::protocol::....

Transaction Summary Stack Order Reversed

Summary

The 4-word message that authentication procedures sign has its order reversed. Previously SALT was on top of the stack; now ACCOUNT_DELTA_COMMITMENT is on top.

Affected Code

MASM (stack layout for auth signing):

# Before (0.13)
# [SALT, OUTPUT_NOTES_COMMITMENT, INPUT_NOTES_COMMITMENT, ACCOUNT_DELTA_COMMITMENT, PUB_KEY]

# After (0.14)
# [ACCOUNT_DELTA_COMMITMENT, INPUT_NOTES_COMMITMENT, OUTPUT_NOTES_COMMITMENT, SALT, PUB_KEY]

Migration Steps

  1. If you implement a custom authentication procedure that reads or signs the transaction summary, update the expected stack layout.
  2. The new order (top to bottom) is: ACCOUNT_DELTA_COMMITMENT, INPUT_NOTES_COMMITMENT, OUTPUT_NOTES_COMMITMENT, SALT, then PUB_KEY.
  3. Update any manual stack manipulation that assumed the old ordering.

Common Errors

Error MessageCauseSolution
Signature verification failureAuth procedure signing words in old orderUpdate to the new stack order before signing.
FailedAssertion in custom authStack words read in wrong positionsReorder stack reads to match new layout.

TransactionOutputs Fields Private

Summary

Fields on TransactionOutputs are no longer public. Use accessor methods instead.

Affected Code

Rust:

// Before (0.13)
let account = outputs.account;
let fee = outputs.fee;
let expiration = outputs.expiration_block_num;
let notes = outputs.output_notes;

// After (0.14)
let account = outputs.account();
let fee = outputs.fee();
let expiration = outputs.expiration_block_num();
let notes = outputs.output_notes(); // now returns &RawOutputNotes

Migration Steps

  1. Replace all direct field accesses on TransactionOutputs with the corresponding method calls.
  2. Note that output_notes() now returns &RawOutputNotes instead of the previous type. Update downstream code to work with RawOutputNotes.
  3. Since accessors return references, add borrows or clones where ownership was previously obtained via field access.

Common Errors

Error MessageCauseSolution
field account of TransactionOutputs is privateFields no longer publicUse outputs.account().
field fee of TransactionOutputs is privateFields no longer publicUse outputs.fee().
Type mismatch on output notesoutput_notes() returns &RawOutputNotesUpdate code to handle RawOutputNotes instead of the previous type.

SignedBlock Added; BlockSigner Removed

Summary

The BlockSigner trait has been removed. Instead, sign the block header commitment directly and construct a SignedBlock.

Affected Code

Rust:

// Before (0.13)
let signed = signer.sign(&header);

// After (0.14)
let sig = sk.sign(header.to_commitment());
let signed_block = SignedBlock::new(header, body, sig);

Migration Steps

  1. Remove all BlockSigner trait implementations and usages.
  2. Sign header.to_commitment() with your signing key directly.
  3. Construct SignedBlock::new(header, body, signature) with the header, block body, and resulting signature.

Common Errors

Error MessageCauseSolution
cannot find trait BlockSignerTrait removedSign header.to_commitment() directly with your key.
cannot find struct SignedBlockMissing importAdd the appropriate import for SignedBlock from the Miden crate.
Signature verification fails on blockSigning the header directly instead of its commitmentSign header.to_commitment(), not the header itself.