EIP-7685 General purpose execution layer requests

Discussion for Add EIP: General purpose execution layer requests by lightclient · Pull Request #8432 · ethereum/EIPs · GitHub

3 Likes

I’ve started a draft implementation of this EIP for ethereumjs and have a question regarding the Intra-type ordering.

The EIP states:

Within the same type, order is not defined. This is because the data of the request is opaque as far as this EIP is concerned. The only valid ordering scheme would be lexicographical ordering of the opaque byte data.

If we don’t define any intratype order and make it exogenous to this EIP, doesn’t that make the requestsRoot non-deterministic where we have multiple requests of the same type since you could reorder them arbitrarily? I suppose we can just create arbitrary test vectors and say we’re assuming the order of requests within a type is lexicographical for now?

My perspective is that if a EIP uses 7685 and doesn’t define it’s intra-type ordering, it’s incomplete. Therefore I’m not sure how the ordering would be non-deterministic. Do you have an example maybe?

Ah, ok, that makes more sense. It might be clearer in the EIP to say something like

Within the same type, order is not defined. This is because the data of the request is opaque as far as this EIP is concerned. Intra-type order should be determined by each request type.

instead of the comment about lexicographical ordering since that made me thing we needed to code that as a fallback in case an order was not otherwise defined.

I’ll create a simple request type and ordering mechanism in my work to use as a proof of concept.

I made the clarification in the EIP Update EIP-7685: clarify intra-type ordering by lightclient · Pull Request #8501 · ethereum/EIPs · GitHub

Then at this point, 7002 and 6110 are incomplete, right? They define the encoding of the request but not the ordering :thinking:

Hmm 6110 does specifically say the ordering:

Each deposit accumulated in the block must appear in the EIP-7685 requests list in the order they appear in the logs

However it isn’t said explicitly in 7002. It should be in the order it is pulled out of the queue (FIFO). I can make that explicit.

Ah right, sorry, I did not see that part of 6110. Thanks :slight_smile:

If you could make the order for 7002 more explicit that would be great! :smiley:

1 Like

About “Opaque byte array rather than an RLP array” rationale, it also means that it becomes challenging to upgrade existing schemes later on.

For example, EIP-6110 adds more RLP cruft, if it uses EIP-7685 it means that that RLP component cannot easily be replaced with SSZ or a SNARK friendly representation later on.

Also, the proposal attempts to be generic, but is not completely generic. For example, some operations may be desirable to execute at start of the block, some at end of the block, and so on.

It’s also a bit weird, to have deposits follow a completely different scheme than withdrawals. What’s the advantage of mixing different concepts into one tree, instead of continuing the existing scheme of simply using separate lists for separate operations? How many operations do we expect there to be? Is it more than 2-3? Do they thematically overlap, as in, would something as in EIP-6493 work out for these validator dependent operations?

I’m not sure why it is harder to replace. It seems equally as challenging as replacing, say, the withdrawals root with a hash tree root.

Withdrawals are CL → EL communication, whereas deposits, exits, and partial withdrawals are EL → CL communication (a request).

My understanding is that there are many more possibilities for EL → CL requests to manage validators. We’re even discussing another one potentially for Prague: consolidations.

Withdrawals are CL → EL communication, whereas deposits, exits, and partial withdrawals are EL → CL communication (a request).

Makes sense, thanks for the clarification.

Considering that it gets transformed to a deposit_receipts list in the CL ExecutionPayload, maybe still simpler to just match that in the EL block header, as in, make it a deposit_receipts list there as well, instead of the list of prefixed opaque blocks.

How would JSON-RPC look for these? Would it return the prefixed opaque data, or something sensible (as is the case for withdrawals/receipts/transactions atm)?

I have a couple of questions regarding the statement about processing the requests in process_execution_payload. I want to make sure that this EIP does not block completely ePBS.

  1. The outcome of processing these requests can affect the beacon state right? (Eg deposits, withdrawals etc).
  2. are the requests located in the CL ExecutionPayloadHeader or within the ExecutionPayload?

In ePBS these are processed at different times and the header may be present and processed with the full payload never be revealed. A situation that becomes difficult and even impossible in ePBS would be if some request that is forced to be processed during header processing (with the CL block) then forces the payload to have specific information. An example of this is withdrawals, which can be processed with the header in the CL block, and then the next payload is forced to fulfill them in the EL or it’s not valid. This doesn’t break ePBS because withdrawals are completely beacon state deterministic but if these requests require knowledge of the EL state that would be quite difficult.

If on the other hand the requests can be processed in the CL side when the payload is processed, this won’t be any problem.

Hey you might be reading an old version. I ended up removing the wording around when / where the CL should process requests.

The EIP defines how requests should be saved in the EL. It is agnostic to how the CL stores requests.

1 Like

An overview of EIP#132: EIP-7685:General purpose execution layer requests with @matt

Why does this proposal use sha256 instead of keccak256?

It’s SHA2-256 for compatibility with the CL (via ethereum/consensus-specs#612.)

1 Like

A requests object consists of a request_type prepended to an opaque byte array request_data. The request_data contains zero or more encoded request objects.

requests = request_type ++ request_data

I would like to know the size of request_type, I cannot find it in the EIP.

Hi Ethereum magicians! The team at 2077 Research recently published a deep dive on EIP-7685 for interested readers: EIP-7685: General Purpose Execution Requests. All feedback and comments are welcome.

Requests root is not longer computed as merkle tree root, but just hash of a list of hashes, so this part of the article is outdated.

@matt What is the rationale for the root being hash of hashes instead of just a hash of concatenation of requests? Seems like unnecessary extra work for double-hashing.