0xMiden / 0xMiden/protocol

N-18: Unconditional Nonce Increment in Signature Authentication Lets Empty Transactions Incur Fees

Open
#3,261 0 comments 0 reactions 0 assignees View on GitHub
Dominant language
Rust
Stars
132
Forks
167
Avg merge
1d 23h
Merged PRs (30d)
110

Description

The transaction kernel rejects any transaction that neither changes the account state nor consumes an input note, through the [empty-transaction guard](https://github.com/0xMiden/protocol/blob/2ef8056323df258917d119383a7cdd49b064d88a/crates/miden-protocol/asm/kernels/transaction/lib/epilogue.masm#L453-L470) in `finalize_transaction`, which asserts on `ERR_EPILOGUE_EXECUTED_TRANSACTION_IS_EMPTY` when the account delta commitment is empty and no input notes were present. However, `authenticate_transaction` and the multisig authentication procedures (`multisig`, `multisig_smart`) increment the account nonce unconditionally. The nonce increment makes the account delta commitment non-empty, so the guard can never trigger for accounts using these procedures. As a result, a transaction that consumes no input notes, creates no output notes, and makes no vault or storage change still succeeds and causes the native account to pay a transaction fee, whereas the same transaction submitted by an `auth_no_auth` account, which increments the nonce only when the account state changes, would be rejected.

The impact is limited. A valid signature is required, so only the account owner can trigger this against their own account, and the owner commits to the resulting nonce through the signed transaction summary. The condition is therefore reachable only through a faulty client that assembles an otherwise-empty transaction, in which case the fee is charged silently rather than the transaction failing.

Consider incrementing the nonce only when the transaction performs an observable action, namely when the account state has changed, the account is being created, or the transaction consumes or produces at least one note. Alternatively, if the unconditional increment is intended as a simplification, consider documenting that signature and multisig accounts cannot rely on the kernel's empty-transaction guard.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.