Flexible and Upgradeable Account Authentication

It is orthogonal to how we do authentication. We could certainly, similarly, add transaction field(s) to specify the fee_payer’s address and authorization.

I think that is maintained here as well. The only decoding of calldata that is happening is for the reconfiguration, the result of which shows up directly in the account state for downstream tooling to make use of.

Thanks for pointing this out. This proposal is focussed on design of the core protocol, but indeed it has to be accompanied by RPC-level changes.

Yes, configs should be exposed via such an RPC method, and events should be emitted from the precompile contract regarding any config changes.

Regarding estimating the gas before any signatures are done, note that in this proposal, the authenticators that we are concerned about are just enshrined cryptographic schemes that will have a fixed gas cost, so it makes the estimation of gas easy. For the signatures supplied to the AuthConfigManager precompile, eth_call should have a skip-auth flag as you point out.

Once we make more progress on crystallizing the core design, we will propose these tooling-related upgrades as well.

1 Like

The proposal deliberately abstracts only the authentication layer. At the same time, the primitives and state model introduced here may shape how the broader account system can be designed later.

So is this MIP intended to be:

a) a self-contained, long-term authentication architecture, or
b) one part of a broader account architecture?

1 Like

Both, but we do wanna do this is individual pieces that can stand for themselves and make sense as building blocks.
In this spirit, let’s focus on how should authentication for an account be done across all flows that involve account authentication while keeping the bigger picture in mind.

  1. As an analogy, we see our proposal as a simple building block that allows one to keep the same “username” (account address), and change their password (“priv key / scheme”) or add passkeys / multi-factor authentication. Taking the analogy further, we view an EOA an object that should not be shared with other people like a username should not be shared with other people. Sharing an account and managing access to it should be an application level concern only. In other words, verifying cryptographic artifacts should happen at the protocol level, verifying whether the authenticated EOA address is authorized for a given task should happen at the application level. Therefore our proposal is only concerned with three objectives: quantum resistance, key management (e.g., recovery and rotation), and user-friendly authentication (e.g., passkeys), all while maintaining the same address on the blockchain. We believe that such a modular approach is better from an architecture point of view.
  2. Regarding making EOAs Post-Quantum safe: IIUC, EIP-8130 does not by itself retire the ECDSA key, neither for signing transactions nor for delegating account to a contract in EIP-7702. In fact, it requires the delegation tuples to still be signed using the ECDSA key even if the account has added other keys. We need to be able to retire the old ECDSA key completely and add a PQ scheme’s key instead. I understand though that EIP-8130 consciously does not want to make changes outside its own path and relies on further EIPs for PQ-safety.
  3. In spirit of point 1, scope authorization (concept of actors) is best delegated at the application layer, unclear why the protocol design has to eat all that complexity (e.g., handling of POLICY and other scopes). In particular, it should not have to verify cryptographic artifacts for authentication. There are many small downstream complexities that arise like account locks, local epochs, etc.
  4. EIP-8130 as written is not friendly for delayed execution. If one were to disable the EVM paths that make changes during execution, so that all authentication functions are determined at consensus time, don’t see why we need all this machinery to begin with. (Side note: we also need to deal with delayed state as of k blocks ago during reconfiguration of account.)
  5. EIP-8130 requires (automatic) delegation for every account. That again makes it unfriendly for delayed execution. For example, when performing reserve balance checks (needed during delayed execution), one has to assume the worst case lower bound of balance for delegated accounts.
  6. We would rather do all of the reconfiguration through a precompile during execution so that existing transaction type (e.g., EIP-1559 tx type) can simply send calldata to the precompile to reconfigure the account. Having a second transport path during consensus (a la account_changes in EIP-8130) is not necessary. Essentially, we would rather do the reconfiguration through execution than worry about it in both consensus/mempool and execution.
  7. There seem to be many other features bundles in EIP-8130, like valid_before, valid_after, 2-D nonces, metadata, introspection of transaction calls, that are at best nice-to-have and so best left out.
  8. In general, EIP-8130 is too complicated, lengthy, and introduces huge tech debt on the protocol design. Just as an example, iiuc consensus now needs to understand how EVM storage is packed in order to understand authenticator contracts so that for example it can validate a PQ signature or a threshold multisig.

I acknowledge that I may have misunderstood things despite reading EIP-8130 for many hours as it is not easy to get one’s hands around it let alone understand fully, so would be happy to discuss further.

1 Like

A few patterns still seem useful here while staying inside the current MIP scope:

  • expected_config_version on every reconfiguration, using the existing config_version, so the update is explicitly bound to the exact effective auth state it was authorized against and becomes stale if that state has already changed.

  • deterministic conflict semantics for multiple reconfigurations targeting the same config generation, where the first valid transition advances the version and any other update against the old generation becomes stale.

  • explicit recovery conflict semantics, defining what happens when a recovery reconfiguration competes with a normal reconfiguration or with another valid recovery attempt against the same auth state.

1 Like

Thanks for the detail Kushal! A few things:

8130 does retire the key if you use the keystore fully. I should update the EIP to explain that a chain MUST do that to be PQ. We are doing this at Base (revoking means 7702, 1559 tx wont land via the k1 key). The second step is re-enabling these tx to use any valid keystore signature.

Actor-config layout is normative so a node can resolve it without hitting any EVM code. Base is fully native code for example.

2D nonces can be disallowed (or just nonceless tx), but understand it is a large spec / number of things to add.

Monad could have an alternative default account that isnt applied just present when the transaction is running for example (similar to 8141 default account). We wanted it as default at Base so we can lean into other things the default account can provide (policy driven session keys most importantly). Happy to jam on this one!

As for authorization, its actually possible to convert any general app layer approval scheme into authenticators if you wanted them to be able to be written. Ie { authenticate + authorize} in a single contract means it would then basically do if authenticated (actor) and context = a then approve. 8130 just says make that authenticate external and the context = a is external. If you need that to be stateful then you can always bake the check into the authenticator itself again.

8130 has the decision that we want to push the stateful authentication into execution (ie session keys) and keep the regular validation paths protocol visible and enabling pure native code.

It feels like if validation has to be decided on at consensus time then you need authorization to be protocol visible! Monad can not have app code being responsible for authz because that can easily change n blocks into the future.

Would love to work on this though! Sounds like a very interesting problem space

Thanks Chris for the points.

Yes, while having native execution for auth as opposed to evm execution is the right direction, dependence on evm layout is not the ideal abstraction.

Wondering why not allow value to be passed in the calls at the transaction level as done currently, rather than requiring value to flow through a contract? I assume this is the reason 8130 is requiring every account to have code (by delegating to a default contract).

This is possible, but in our view directionally incorrect, and we should be separating auth from authorization. As you mentioned, 8130 makes the auth external, but it still keeps it at the contract level. Is that because a change in the account trie was undesirable for some reason? This was also my question on the call the other day: why not have authentication configs be stored in the account object in the account trie (which then allows us to do validation without depending on evm execution / storage layout at all) as opposed to the contract-based authentication in 8130 (which as mentioned above depends on storage layout at least)? I dont think this breaks EVM compatibility if that’s the fear, because raw account object by itself is never made available (as an opcode) to the app layer—only light clients / bridges / eth_getProof verifiers would be affected.

What kind of state is used for these “stateful authentication”? Perhaps concrete examples of usecases will help. While “session keys” is a misnomer, I understand that to refer to the usecase of giving a dapp limited authorization for the account. As mentioned in my previous comment, we view the solution a bit differently: instead of having the dapp’s keys added to the user account, the dapp’s account should simply receive authorization at the smart contract layer (e.g., via EIP-7702).

Not really. In this flexible auth design, we do authentication validity at the consensus time, and leave authorization for execution-time. If authorization changed during the consensus-execution delay in Monad, then the concerned transaction will just revert at execution time.

Looking forward to our call next week :slight_smile: