As described in this client issue, there are a few obstacles to creating pass-through transactions (tx's which don't modify account state, prev. referred to by me as in-flight transactions) right now in the client's sanity checks, but also in the kernel.
The summary is as follows:
- We determine if the account is new by its nonce (
nonce == 0 is a new account)
- If it's new, we set
INITIAL_ACCOUNT_COMMITMENT to EMPTY_WORD
- The first transaction computes the actual commitment of the account (even if the tx doesn't touch the account state, it will end up with a non-empty final commitment)
- First transactions works fine, at the end of which the global account state now contains the real commitment of the account.
- But nonce hasn't changed
- So the second transaction we issue starts again with
INITIAL_ACCOUNT_COMMITMENT = EMPTY_WORD
- And block building fails because of the local vs. global mismatch
There are at least three options:
Increment account nonce after the auth procedure if nonce == 0
As the headline says: if the auth procedure of the first executed transaction hasn't bumped the nonce (e.g. a certain configuration of AuthRpoFalcon512Acl), then we force the increment.
While this is the simplest approach, it does have the downside of complicating the user docs: we now have to explain a very particular edge case of why the auth procedure might not have the expected effect (but only in the very first tx).
I'm not a fan of this edge-case complexity.
Always increment account nonce if not incremented in the auth procedure
This is a variation of the first approach, where we always increment the account nonce whenever a transaction is executed against it.
Despite it being a state-changing transactions, it's more of a kernel-dictated-change, rather than a user defined one.
If we do this, we might as well completely hide incr_nonce procedure from users, and simply always call it.
Re-define what we mean by new Account; allow zero nonces for existing accounts
Rather than checking nonce == 0, the most reliable check is "is this account already onchain".
Unfortunately, the Account by itself doesn't currently have enough info for this, so Account::is_new() wouldn't work. We could hack this by checking if seed is present (since the client actually erases the seed after it applies the first tx update).
So assuming we can somehow figure out how to properly check is_new(), it would mean we provide the correct INITIAL_ACCOUNT_COMMITMENT for tx creation.
We could then remove the following check from the prologue (process_account_data procedure, account-exists conditional branch)
# assert the nonce of an existing account is non-zero
exec.memory::get_account_nonce neq.0 // <---------- we would now allow zero nonces for existing accounts
assert.err=ERR_PROLOGUE_EXISTING_ACCOUNT_MUST_HAVE_NON_ZERO_NONCE
This last approach effectively means we would allow zero nonces for existing accounts.
As described in this client issue, there are a few obstacles to creating pass-through transactions (tx's which don't modify account state, prev. referred to by me as in-flight transactions) right now in the client's sanity checks, but also in the kernel.
The summary is as follows:
nonce == 0is a new account)INITIAL_ACCOUNT_COMMITMENTtoEMPTY_WORDINITIAL_ACCOUNT_COMMITMENT = EMPTY_WORDThere are at least three options:
Increment account nonce after the auth procedure if
nonce == 0As the headline says: if the auth procedure of the first executed transaction hasn't bumped the nonce (e.g. a certain configuration of
AuthRpoFalcon512Acl), then we force the increment.While this is the simplest approach, it does have the downside of complicating the user docs: we now have to explain a very particular edge case of why the auth procedure might not have the expected effect (but only in the very first tx).
I'm not a fan of this edge-case complexity.
Always increment account nonce if not incremented in the auth procedure
This is a variation of the first approach, where we always increment the account nonce whenever a transaction is executed against it.
Despite it being a state-changing transactions, it's more of a kernel-dictated-change, rather than a user defined one.
If we do this, we might as well completely hide
incr_nonceprocedure from users, and simply always call it.Re-define what we mean by new
Account; allow zero nonces for existing accountsRather than checking
nonce == 0, the most reliable check is "is this account already onchain".Unfortunately, the
Accountby itself doesn't currently have enough info for this, soAccount::is_new()wouldn't work. We could hack this by checking ifseedis present (since the client actually erases the seed after it applies the first tx update).So assuming we can somehow figure out how to properly check
is_new(), it would mean we provide the correctINITIAL_ACCOUNT_COMMITMENTfor tx creation.We could then remove the following check from the prologue (
process_account_dataprocedure, account-exists conditional branch)This last approach effectively means we would allow zero nonces for existing accounts.