Skip to content

Support for pass-through transactions #1944

@mmagician

Description

@mmagician

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:

  1. We determine if the account is new by its nonce (nonce == 0 is a new account)
  2. If it's new, we set INITIAL_ACCOUNT_COMMITMENT to EMPTY_WORD
  3. 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)
  4. First transactions works fine, at the end of which the global account state now contains the real commitment of the account.
  5. But nonce hasn't changed
  6. So the second transaction we issue starts again with INITIAL_ACCOUNT_COMMITMENT = EMPTY_WORD
  7. 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.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions