or
or
By clicking below, you agree to our terms of service.
New to HackMD? Sign up
Syntax | Example | Reference | |
---|---|---|---|
# Header | Header | 基本排版 | |
- Unordered List |
|
||
1. Ordered List |
|
||
- [ ] Todo List |
|
||
> Blockquote | Blockquote |
||
**Bold font** | Bold font | ||
*Italics font* | Italics font | ||
~~Strikethrough~~ | |||
19^th^ | 19th | ||
H~2~O | H2O | ||
++Inserted text++ | Inserted text | ||
==Marked text== | Marked text | ||
[link text](https:// "title") | Link | ||
![image alt](https:// "title") | Image | ||
`Code` | Code |
在筆記中貼入程式碼 | |
```javascript var i = 0; ``` |
|
||
:smile: | Emoji list | ||
{%youtube youtube_id %} | Externals | ||
$L^aT_eX$ | LaTeX | ||
:::info This is a alert area. ::: |
This is a alert area. |
On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?
Please give us some advice and help us improve HackMD.
Syncing
xxxxxxxxxx
Block roots permanent cache (EIP-4788 plugin)
Preface
A buffer of beacon block roots proposed in EIP-4788 has a limited capacity. At the moment, it is designed to keep 8191 values. There are 7200 roots generated daily. It means there are about 27 hours to use a proof against any beacon block root. In some situations, it can be insufficient or might affect the reliability of the methods relying on beacon root usage. Hence, a separate solution is required to retrieve the required beacon block root in a trustless manner.
Proposed solution
A storage cache with (timestamp, root) permanent "checkpoints" is proposed. The cache is populated by calling the EIP-presented contract via a permissionless method.
Additionally, anyone can bring proof of any arbitrary beacon block root against the closest available checkpoint in the cache, effectively adding a new checkpoint to the cache.
The contract interface may look like this:
Roots for blocks added after EIP-4788
For any block after the hardfork with EIP-4788 enabled it's possible to bring a Merkle Patricia Trie proof[1] of the EIP buffer storage at the given block. To verify this proof,
state_root
of the block should be known, and it could be retrieved from the execution payload of the corresponding beacon block.Currently, block structure looks like this:
, and
executionPayload
includesstate_root
field:It means, one can provide a proof of the
state_root
against a beacon block root of a "checkpoint". It effectively gives an ability to bring a proof for any timestamp existed in the EIP buffer.Since the EIP buffer stores just a limited amount of roots, the storage trie of the buffer is compact. It means it's pretty cheap to prove any root within the buffer and fulfill the historical roots in hops of
HISTORY_BUFFER_LENGTH
length.Pseudocode
Roots for blocks before EIP-4788
Since there was no EIP buffer, an alternative approach should be used, like zk-STARK. However, the naive approach of using plain Merkle proofs described below is applicable despite the high cost of including aged roots.
Given that
parentRoot
in a beacon block is a merkle tree root of the merkleizedBeaconBlock
structure corresponding to the preceding block in the beacon chain.Since a
parentRoot
field is a bytes32 value, the result of merkleization of this field is the field value itself. It means twoBeaconBlock
Merkle trees corresponding to adjacent beacon blocks can be combined one on top of the other:It means we can use this tree to prove the Nth root down the tree. The only thing we need is the index[2] of the root in the tree.
By knowing how many blocks down the tree located the root we want to prove to the contract, we can then determine the index[3].
Pseudocode
The following pseudocode describes the idea of proving a
parentRoot
with the correspondingslot
against a "checkpoint", i.e., aparentRoot
known to the contract. Since it's required to check proofs for two fields of theBeaconBlock
structure, the method below does it in two phases:slot
andparentRoot
of this header against the header root accepted previously.Considerations
What to do with changing generalized indices?
Hard forks can alter the beacon block structure, causing changes in generalized indices. These generalized indices are not directly given by the network on the execution layer, so they need a reliable source of truth.
This becomes an issue when we attempt to provide proof for beacon blocks corresponding to different hard forks with altered indices.
To ensure that the stored roots in the contract match a single fork, the maximum acceptable timestamp may be set, via a permissioned method, to the timestamp of the next fork as soon as it becomes known. Alternatively if the execution number could return a number of the current hard fork, the contract could rely on this data instead. To preserve the contract state it's possible to delegate the global indices storage to a dedicated contract.
How much costs proving blocks roots before EIP-4788
We can roughly estimate gas usage for the proposed solution to store 24 hours old missing root:
Verifying of a proof has O(N) gas complexity and depends on the depth of the tree, hence the cost grows linearly.
see curve-merkle-oracle ↩︎
i.e. generalized index ↩︎
see concat_generalized indices ↩︎