Skip to content

Commit

Permalink
deploy: 08d3c71
Browse files Browse the repository at this point in the history
  • Loading branch information
tynes committed May 15, 2024
1 parent a0c9718 commit e9fea05
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 92 deletions.
28 changes: 8 additions & 20 deletions interop/messaging.html
Original file line number Diff line number Diff line change
Expand Up @@ -201,7 +201,6 @@ <h1 id="messaging"><a class="header" href="#messaging">Messaging</a></h1>
<ul>
<li><a href="#timestamp-invariant">Timestamp Invariant</a></li>
<li><a href="#chainid-invariant">ChainID Invariant</a></li>
<li><a href="#only-eoa-invariant">Only EOA Invariant</a></li>
<li><a href="#message-expiry-invariant">Message Expiry Invariant</a></li>
</ul>
</li>
Expand Down Expand Up @@ -268,25 +267,27 @@ <h3 id="message-identifier"><a class="header" href="#message-identifier">Message
exact state of the block templates between multiple chains together.</p>
<h2 id="messaging-ends"><a class="header" href="#messaging-ends">Messaging ends</a></h2>
<h3 id="initiating-messages"><a class="header" href="#initiating-messages">Initiating Messages</a></h3>
<p>Each Log (also known as <code>event</code> in solidity) forms an initiating message.
<p>Each <a href="https://github.com/ethereum/go-ethereum/blob/5c67066a050e3924e1c663317fd8051bc8d34f43/core/types/log.go#L29">Log</a> (also known as <code>event</code> in solidity) forms an initiating message.
The raw log data froms the <a href="#message-payload">Message Payload</a>.</p>
<p>Messages are <em>broadcast</em>: the protocol does not enshrine address-targeting within messages.</p>
<p>The initiating message is uniquely identifiable with an <a href="#message-identifier"><code>Identifier</code></a>,
such that it can be distinguished from other duplicate messages within the same transaction or block.</p>
<p>An initiating message may be executed many times: no replay-protection is enshrined in the protocol.</p>
<h3 id="executing-messages"><a class="header" href="#executing-messages">Executing Messages</a></h3>
<p>All the information required to satisfy the invariants MUST be included in the calldata
of the function that is used to execute messages.</p>
<p>An executing message is represented by the <a href="./predeploys.html#executingmessage-event">ExecutingMessage event</a> that is emitted by
the <code>CrossL2Inbox</code> predeploy. This event is coupled to a <code>CALL</code> with the payload that is emitted
within the event, allowing introspection of the data without needing to do call tracing.
All of the information required to satisfy the invariants MUST be included in this event.</p>
<p>Both the block builder and the verifier use this information to ensure that all system invariants are held.</p>
<p>The executing message is verified by checking if there is an existing initiating-message
that originates at <a href="#message-identifier"><code>Identifier</code></a> with matching <a href="#message-payload">Message Payload</a>.</p>
<p>Since an executing message is defined by a log, it means that reverting calls to the <code>CrossL2Inbox</code>
do not count as executing messages.</p>
<h2 id="messaging-invariants"><a class="header" href="#messaging-invariants">Messaging Invariants</a></h2>
<ul>
<li><a href="#timestamp-invariant">Timestamp Invariant</a>: The timestamp at the time of inclusion of the executing message MUST
be greater than or equal to the timestamp of the initiating message.</li>
<li><a href="#chainid-invariant">ChainID Invariant</a>: The chain id of the initiating message MUST be in the dependency set</li>
<li><a href="#only-eoa-invariant">Only EOA Invariant</a>: The executing message MUST be initiated by an externally owned
account such that the top level EVM call frame enters the <code>CrossL2Inbox</code></li>
<li><a href="#message-expiry-invariant">Message Expiry Invariant</a>: The timestamp at the time of inclusion of the executing
message MUST be lower than the initiating message timestamp (as defined in the <a href="#message-identifier"><code>Identifier</code></a>) + <code>EXPIRY_TIME</code>.</li>
</ul>
Expand All @@ -298,19 +299,6 @@ <h3 id="chainid-invariant"><a class="header" href="#chainid-invariant">ChainID I
<p>Without a guarantee on the set of dependencies of a chain, it may be impossible for the derivation
pipeline to know which chain to source the initiating message from. This also allows for chain operators
to explicitly define the set of chains that they depend on.</p>
<h3 id="only-eoa-invariant"><a class="header" href="#only-eoa-invariant">Only EOA Invariant</a></h3>
<p>The <code>onlyEOA</code> invariant on executing a cross chain message enables static analysis on executing messages.
This allows for the derivation pipeline and block builders to reject executing messages that do not
have a corresponding initiating message without needing to do any EVM execution.</p>
<p>It may be possible to relax this invariant in the future if the block building process is efficient
enough to do full simulations to gain the information required to verify the existence of the
initiating transaction. Instead of the <a href="#message-identifier"><code>Identifier</code></a> being included in calldata, it would be emitted
in an event that can be used after the fact to verify the existence of the initiating message.
This adds complexity around mempool inclusion as it would require EVM execution and remote RPC
access to learn if a transaction can enter the mempool.</p>
<p>This feature could be added in a backwards compatible way by adding a new function to the <code>CrossL2Inbox</code>.</p>
<p>One possible way to handle explicit denial of service attacks is to utilize identity
in iterated games such that the block builder can ban identities that submit malicious transactions.</p>
<h3 id="message-expiry-invariant"><a class="header" href="#message-expiry-invariant">Message Expiry Invariant</a></h3>
<p>Note: Message Expiry as property of the protocol is in active discussion.
It helps set a strict bound on total messaging activity to support, but also limits use-cases.
Expand Down Expand Up @@ -392,7 +380,7 @@ <h3 id="bounding-the-graph"><a class="header" href="#bounding-the-graph">Boundin
as per the <a href="#chainid-invariant">ChainID invariant</a>.</li>
<li>Every block cannot depend on future blocks, as per the <a href="#timestamp-invariant">Timestamp invariant</a>.</li>
<li>Every block has a maximum gas limit, an intrinsic cost per transaction,
and thus a maximum inward degree of dependencies, as per the <a href="#only-eoa-invariant">Only-EOA invariant</a></li>
and thus a maximum inward degree of dependencies.</li>
<li>Every block cannot depend on expired messages, as per the <a href="#message-expiry-invariant">Message expiry invariant</a>.</li>
</ul>
<p>The verifier is responsible for filtering out non-canonical parts of the graph.</p>
Expand Down
4 changes: 2 additions & 2 deletions interop/overview.html
Original file line number Diff line number Diff line change
Expand Up @@ -190,7 +190,7 @@ <h1 id="interop"><a class="header" href="#interop">Interop</a></h1>
<tr><td>Source Chain</td><td>A blockchain that includes an initiating message</td></tr>
<tr><td>Destination Chain</td><td>A blockchain that includes an executing message</td></tr>
<tr><td>Initiating Message</td><td>An event emitted from a source chain</td></tr>
<tr><td>Executing Message</td><td>A transaction submitted to a destination chain that corresponds to an initiating message</td></tr>
<tr><td>Executing Message</td><td>An event emitted from a destination chain's <code>CrossL2Inbox</code> that includes an initiating message</td></tr>
<tr><td>Cross Chain Message</td><td>The cumulative execution and side effects of the initiating message and executing message</td></tr>
<tr><td>Dependency Set</td><td>The set of chains that originate initiating transactions where the executing transactions are valid</td></tr>
</tbody></table>
Expand All @@ -199,7 +199,7 @@ <h1 id="interop"><a class="header" href="#interop">Interop</a></h1>
The first transaction is submitted to the source chain and emits an event that can be consumed on a destination chain.
The second transaction is submitted to a destination chain, where the block builder SHOULD only include it if they are
certain that the first transaction was included in the source chain.
There is no strict requirement that the execution message is ever submitted.</p>
There is no strict requirement that the executing message is ever submitted.</p>
<p>The term "block builder" is used interchangeably with the term "sequencer" for the purposes of this document but
they need not be the same entity in practice.</p>
<h2 id="specifications"><a class="header" href="#specifications">Specifications</a></h2>
Expand Down
18 changes: 15 additions & 3 deletions interop/predeploys.html
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ <h1 id="predeploys"><a class="header" href="#predeploys">Predeploys</a></h1>
<li><a href="#_target"><code>_target</code></a></li>
</ul>
</li>
<li><a href="#executingmessage-event"><code>ExecutingMessage</code> Event</a></li>
<li><a href="#reference-implementation">Reference implementation</a></li>
<li><a href="#identifier-getters"><code>Identifier</code> Getters</a></li>
</ul>
Expand Down Expand Up @@ -258,10 +259,19 @@ <h4 id="_target"><a class="header" href="#_target"><code>_target</code></a></h4>
In practice, the <code>_target</code> will be a contract that needs to know the schema of the <code>_msg</code> so that it can be decoded.
It MAY call back to the <code>CrossL2Inbox</code> to authenticate
properties about the <code>_msg</code> using the information in the <code>Identifier</code>.</p>
<h3 id="executingmessage-event"><a class="header" href="#executingmessage-event"><code>ExecutingMessage</code> Event</a></h3>
<p>The <code>ExecutingMessage</code> event represents an executing message. It MUST be emitted on every call
to <code>executeMessage</code>.</p>
<pre><code class="language-solidity">event ExecutingMessage(bytes,bytes);
</code></pre>
<p>The data encoded in the event contains the <code>Identifier</code> and the <code>msg</code>.
The following pseudocode shows the serialization:</p>
<pre><code class="language-solidity">(bytes memory identifier, bytes memory log) = abi.decode(receipt.data, (bytes, bytes));
Identifier id = abi.decode(identifier, (Identifier));
</code></pre>
<h3 id="reference-implementation"><a class="header" href="#reference-implementation">Reference implementation</a></h3>
<p>A simple implementation of the <code>executeMessage</code> function is included below.</p>
<pre><code class="language-solidity">function executeMessage(Identifier calldata _id, address _target, bytes calldata _msg) public payable {
require(msg.sender == tx.origin);
require(_id.timestamp &lt;= block.timestamp);
require(L1Block.isInDependencySet(_id.chainid));

Expand All @@ -280,6 +290,8 @@ <h3 id="reference-implementation"><a class="header" href="#reference-implementat
});

require(success);

emit ExecutingMessage(abi.encode(_id), _msg);
}
</code></pre>
<p>Note that the <code>executeMessage</code> function is <code>payable</code> to enable relayers to earn in the gas paying asset.</p>
Expand Down Expand Up @@ -359,15 +371,15 @@ <h4 id="relaying-messages"><a class="header" href="#relaying-messages">Relaying
tstore(CROSS_DOMAIN_MESSAGE_SOURCE_SLOT, _source)
}

sentMessages[messageHash] = true;

bool success = SafeCall.call({
_target: _target,
_value: msg.value,
_calldata: _message
});

require(success);

sentMessages[messageHash] = true;
}
</code></pre>
<p>Note that the <code>relayMessage</code> function is <code>payable</code> to enable relayers to earn in the gas paying asset.</p>
Expand Down
49 changes: 29 additions & 20 deletions interop/sequencer.html
Original file line number Diff line number Diff line change
Expand Up @@ -218,13 +218,13 @@ <h2 id="sequencer-policy"><a class="header" href="#sequencer-policy">Sequencer P
without adding additional state-transition complexity or cross-chain synchronicity to the protocol.</p>
<h2 id="block-building"><a class="header" href="#block-building">Block Building</a></h2>
<p>The goal is to present information in a way where it is as efficient as possible for the block builder to only include
executing messages that have a corresponding initiating message.</p>
executing messages that have a corresponding initiating message. It is not possible to enforce the ability to
statically analyze a transaction, so execution MAY be required to determine the information required to include
executing messages.</p>
<h3 id="static-analysis"><a class="header" href="#static-analysis">Static analysis</a></h3>
<p>The block builder SHOULD use static analysis on executing messages to determine the dependency of the message.</p>
<p>When a transaction has a top level <a href="https://github.com/ethereum/execution-specs/blob/1fed0c0074f9d6aab3861057e1924411948dc50b/src/ethereum/frontier/fork_types.py#L52">to</a> field that is equal to the <code>CrossL2Inbox</code>
and the 4-byte selector in the calldata matches the entrypoint interface,
the block builder should use the chain-ID that is encoded in the <code>Identifier</code> to determine which chain includes
the initiating transaction.</p>
<p>Note that static analysis is never reliable because even if the top level <code>transaction.to</code>
is equal to the <code>CrossL2Inbox</code>, it is possible that there is a reentrant <code>CALL</code>. The block
builder SHOULD NOT rely on static analysis for building blocks.</p>
<h3 id="dependency-confirmations"><a class="header" href="#dependency-confirmations">Dependency confirmations</a></h3>
<p>The sequencer MAY include an executing message in a block with any desired level
of confirmation safety around the dependency of the message.</p>
Expand Down Expand Up @@ -260,26 +260,35 @@ <h4 id="direct-dependency-confirmation"><a class="header" href="#direct-dependen
that the identifier points to, if it trusts the remote canonical chain but not its RPC server.</p>
<p>The block builder MAY also trust a remote RPC and use the following algorithm
to verify the existence of the log.</p>
<p>The following pseudocode represents how to check existence of a log based on an <code>Identifier</code>.</p>
<pre><code class="language-python">target, message, id = abi.decode(calldata)
<p>The following pseudocode represents how to check existence of a log based on an <code>Identifier</code>.
If the value <code>True</code> is returned, then it is safe to include the transaction.</p>
<pre><code class="language-python">success, receipt = evm.apply_transaction(tx)

eth = clients[id.chainid]
if not success:
return True

if eth is None:
return False
for log in receipt.logs:
if is_executing_message(log):
id, message = abi.decode(log.data)

logs = eth.getLogs(id.origin, from=id.blocknumber, to=id.blocknumber)
log = filter(lambda x: x.index == id.logIndex &amp;&amp; x.address == id.origin)
if len(log) == 0:
return False
# assumes there is a client for each chain in the dependency set
eth = clients[id.chainid]

if message != encode(log[0]):
return False
if eth is None:
return False

block = eth.getBlockByNumber(id.blocknumber)
logs = eth.getLogs(id.origin, from=id.blocknumber, to=id.blocknumber)
log = filter(lambda x: x.index == id.logIndex &amp;&amp; x.address == id.origin)
if len(log) == 0:
return False

if id.timestamp != block.timestamp:
return False
if message != encode(log[0]):
return False

block = eth.getBlockByNumber(id.blocknumber)

if id.timestamp != block.timestamp:
return False

return True
</code></pre>
Expand Down
Loading

0 comments on commit e9fea05

Please sign in to comment.