What’s the role of a nonce in a transaction in A3…?
We can copy Ethereum’s model, and require a tx with nonce N-1 to have been mined before accepting N. Note that we are not enforcing this in the protocol at the moment.
We can just require nonces to be unique, and leave ordering to the account abstraction, thus allowing out-of-order txs at the protocol level if the user wants to.
We can instead use nonces as a salt to hide a tx request. Since we’ll be calculating a tx hash by hashing all the tx fields (see here), an attacker could brute force through common tx requests and compare them to the resulting hash to guess what the user intent was. This is not possible since the attacker would not be able to predict the signature - we just need to make sure the tx signature is not leaked.
We can use the nonce just to let the user differentiate two txs with the same fields. So if the user wants to repeat an action, they just need to tweak the nonce to a different random value. Note that not making the pair (sender, nonce) be unique makes it impossible to replace or cancel in-flight txs, unless we add an explicit API for that.
I think the main reason for a nonce is replay protection, which is linked to 1).
We currently sign over transaction intent, e.g the function signature and arguments, the same signature is potentially valid multiple times. This is different to Aztec connect where we signed over the note commitments / nullifiers, preventing replays.
In my head we need a way to ensure that:
a) a transaction intent can only be used once.
b) enforcing transaction ordering, this is useful for a user / dApp, e.g transaction B is valid only after transaction A. (This would link transactions potentially).
I feel like ordering is not really necessary for private txs because if they would modify the same state there couldn’t be 2 valid proofs. I am not that knowledgeable about nuances of public txs to determine if it’s an issue there.
The catch is that you can only do a replacement if you enforce uniqueness for each (sender, nonce) pair. Otherwise, if you only require uniqueness for tx hashes, you cannot replace a tx with another because its hash changes (unless you add a specific API for that).
Do we want nonces also for public reads since we modify state (add nullifiers)?
Love your idea of letting account abstraction handle it BUT that can only work if we enforce account abstraction on ALL addresses right? Otherwise we would have to also cater to the EOA model.
IIUC a transaction can only be replayed if it doesn’t create any nullifiers, since we won’t verify uniqueness of TX hashes in the rollup contract.
We might need to add a transaction-level nullifier if some TXs might not create any nullifier. I assume this is possible, if the tx:
fee payment is done entirely in that tx using public functions
and tx:
Is a public-only TX (not sure if we’ll allow this) or
Calls private functions that do nothing else than calling public functions
A strategy could be to indeed to have a nonce field in the tx that we hash with the sender address in the base rollup and that the base rollup adds to the nullifier tree?
If we want to enforce tx ordering with nonces in ethereum-style, that would be quite complicated to prove right? at least with the regular nullifier tree.