This proposal defines a general purpose framework for storing contract-triggered
requests. It extends the execution header and body with a single field each to
store the request information. This inherently exposes the requests to the
consensus layer, which can then process each one.
Motivation
The proliferation of smart contract controlled validators has caused there to be
a demand for additional EL triggered behaviors. By allowing these systems to
delegate administrative operations to their governing smart contracts, they can
avoid intermediaries needing to step in and ensure certain operations occur.
This creates a safer system for end users.
Specification
Execution Layer
Request
A request consists of a request_type prepended to an opaque byte array
request_data:
request = request_type ++ request_data
Let requests be the list of all request objects in the block in ascending
order by type. For example:
The ordering of requests within a type is to be defined by each request type.
Block structure
The block body is appended with a list of requests. RLP encoding of the extended
block body structure is computed as follows:
block_body_rlp=rlp([field_0,...,# Latest block body field before `requests`
field_n,[request_0,...,request_k],])
Block Header
Extend the header with a new 32 byte value requests_root.
Let requests_root be the root of a Merkle-Patricia trie keyed by the index in
the list of requests. This is equivalent to how the transaction trie root is
computed.
The requests_root field value is therefore computed as follows:
Each proposal may choose how to extend the beacon chain types to include the new
EL request.
Rationale
Opaque byte array rather than an RLP array
By having the second byte on be opaque bytes, rather than an RLP (or other
encoding) list, we can support different encoding formats for the transaction
payload in the future such as SSZ, LEB128, or a fixed width format.
Request source and validity
This EIP makes no strict requirement where a request may come from nor when/how
a request must be validated. This is to provide future protocol designers
maximum flexibility.
The authors’ recommendations on source and validity of requests are:
The source of requests should be from the execution of transactions. More
specifically, transactions which make calls to designated system contracts
that store the request in account. The storage would later be retrieved by a
post-block system call to the contract. Alternatively, if the system call does
not need to be inherently concerned with rate limiting, it could rely simply
on emitting an event which is later parsed post-block by the system and
converted into a request.
A request’s validity can often not be fully verified at the execution layer.
This is why they are referred to merely as “requests”; they do not carry the
authority on their own unilaterally catalyze and action. We expect the system
contracts to perform whatever validation is possible by the EL and then pass
it on to the CL for further validation.
Ordering
The ordering across types is ascending by type. This is to simplify the process
of verifying that all requests which were committed to in requests_root were
found in the block.
An alternative could be to order by when the request was generated within the
block. Since it’s expected that many requests will be accumulated at the end of
the block via system calls, this would be difficult to enforce. Therefore,
ordering by type is the most straightforward ordering which ensures integrity.
Intra-type
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. Therefore, it is to be
determined by each request type individually.