---
# System prepended metadata

title: Verkle tree 実装詳細

---

# Verkle tree 実装詳細

## key-value 型 DB に対する Verkle tree

- [Verkle tree integration - HackMD](https://notes.ethereum.org/@vbuterin/verkle_tree_eip)
- [gballet/go-verkle](https://github.com/gballet/go-verkle)

key, value が 32 bytes ずつのテーブルの中身について inclusion proof したい. これができると stateless client の実装に役立つ.

Verkle tree の作成手順を図, 及び python コードで示した.

vector commitment では基本的に楕円曲線を用いるので, key, value が 32 bytes ずつのテーブル $d = \{(k_{\lambda}, v_{\lambda})\}_{\lambda \in \Lambda}$ に関する Verkle tree を作成したい場合に, 最下層を若干工夫する必要がある. この部分を extension (Verkle) tree として構成し, $d^{\prime} = \{(\mathrm{stem}, D^{(\mathrm{stem})})\}_{\mathrm{stem} \in \mathsf{Stems}}$ というテーブルに帰着させる. ただし $\mathsf{Stems}$ とは, 任意の $k_{\lambda} \ (\lambda \in \Lambda)$ を $256^{31}$ で割った余りを含み, かつそのようなもののみを含む集合とする.

$$\mathsf{Stems} := \{ p \in [0, 256^{31}) \mid k_{\lambda} = p + s \cdot 256^{31} \text{ for some } s \in [0, 256), \lambda \in \Lambda \}$$

extension Verkle tree と $d^{\prime}$ から構成した Verkle suffix tree とを合わせて, $d$ の Verkle tree が構成される. 深さの最大値は root node を含めなければ 33 (= 2 + 31) であるが, テーブルの key $k_{\lambda}$ たちが十分に散らばっているほど小さくなる. 理想的な例としては, $256^2$ 個のデータがあって, それらの key の suffix 2 bytes が全て異なれば, 深さ 4 の Verkle tree になる.

![vercle_tree_construction](https://i.imgur.com/kZA0Bqh.jpg)
<!-- 
下記コード中の compute_vector_commitment 関数は単なる hash 関数として実装している. Merkle proof よりも短い proof を作成したいという目的のためには, より良い commitment scheme を選ぶ必要がある.

```python
import hashlib
from typing import Dict, List

bytes32 = bytes
bytes31 = bytes
byte = bytes

VERKLE_NODE_WIDTH = 256
EXTENSION_MARKER = 1

def compute_vector_commitment(children: List[int]) -> int:
    # pseudo code
    digest = hashlib.sha3_256(b"".join([value.to_bytes(32, 'little')
                              for value in children])).hexdigest()
    return int(digest, 16)

def compute_extension_tree_root(stem: bytes31, values: Dict[byte, bytes32]) -> int:
    sub_leaves = [0] * 512
    for suffix, value in values.items():
        suffix_int = int.from_bytes(suffix, 'little')
        sub_leaves[2 * suffix_int] = \
            int(2**128) + int.from_bytes(value[:16], 'little')
        sub_leaves[2 * suffix_int + 1] = \
            int.from_bytes(value[16:], 'little')
    C0 = compute_vector_commitment(sub_leaves[:256])
    C1 = compute_vector_commitment(sub_leaves[256:])
    main_leaves = [
        int(EXTENSION_MARKER),
        int.from_bytes(stem, 'little'),
        C0,
        C1
    ] + [0] * 252
    return compute_vector_commitment(main_leaves)

def compute_main_tree_root(data: Dict[bytes32, int], prefix: bytes) -> int:
    if len(data) == 0:
        return 0
    elif len(data) == 1:
        return list(data.values())[0]
    else:
        sub_commitments = [
            compute_main_tree_root(
                {
                    key: value for key, value in
                    data.items() if key[:len(prefix) + 1] == prefix + bytes([i])
                },
                prefix + bytes([i])
            ) for i in range(VERKLE_NODE_WIDTH)
        ]
        return compute_vector_commitment(sub_commitments)

def compute_verkle_commitment(data: Dict[bytes32, bytes32]) -> int:
    stems = set(key[:-1] for key in data.keys())
    data_as_stems = dict()
    for stem in stems:
        commitment_data = dict()
        for i in range(VERKLE_NODE_WIDTH):
            key = stem + bytes([i])
            if key in data:
                commitment_data[bytes(i)] = data[key]
        data_as_stems[stem] = compute_extension_tree_root(
            stem, commitment_data)
    return compute_main_tree_root(data_as_stems, bytes([]))

if __name__ == '__main__':
    data = {0: 2, 1: 15, 2: 209, 256: 83}
    table = {}
    for key, value in data.items():
        table[key.to_bytes(32, 'little')] = value.to_bytes(32, 'little')
    root = hex(compute_verkle_commitment(table))
    assert root == '0x70dbdb60678021614a6d5455c5c6e4dfd69fdc8d2a53790947c60f5dea3d7dcd'
``` -->

<!-- ## Verkle Proof の実装

proof の構築方法は下記などを参考にしたが, 実装の細部まで理解できたわけではない.

[research/verkle_trie.py](https://github.com/ethereum/research/blob/master/verkle_trie_eip/verkle_trie.py)

この実装では, vector commitment として pedersen commitment なるものを用いている.

そこでは bandersnatch という楕円曲線が用いられている.

[bandersnatch/bandersnatch](https://github.com/zhenfeizhang/bandersnatch/tree/65823a69d6c4c7612d2f2d3d21ce87f2b319fcf0/bandersnatch)

かなり複雑な実装に見えるが, セキュリティ要件の都合で必要になるのだろうか? -->

## コード

### CreateIPAProof

![Figure 9](https://hackmd.io/_uploads/rJX_u9QKK.jpg)
![Figure 10](https://hackmd.io/_uploads/B1mOu9mYY.jpg)

### CheckMultiProof

![Figure 11](https://hackmd.io/_uploads/r1DOdcmtF.jpg)
![Figure 12](https://hackmd.io/_uploads/HkD_dqQtt.jpg)

### Insert

![Figure 14](https://hackmd.io/_uploads/HkZeDroFY.jpg)
![Figure 15](https://hackmd.io/_uploads/Sy-xwHsKF.jpg)
![Figure 16](https://hackmd.io/_uploads/HyZeProKt.jpg)

### ComputeCommitment

![Figure 17](https://hackmd.io/_uploads/Bk-gProFK.jpg)
![Figure 18](https://hackmd.io/_uploads/ryZgwriFK.jpg)

## Non-inclusion proof

non-inclusion proof も行える Verkle SMT にしたいならば, $E^{(\mathrm{suffix})}$ が empty node のときに値 0 を結びつけるのではなく, $(0, \mathrm{stem}, 0, \ldots, 0)$ から構成した node $D^{(\mathrm{stem})}$ の commitment を結びつけるなどすれば良さそうである. さらに, extension tree の各 leaf にも non-inclusion flag を含めておく必要がある.

![extension_tree_for_non_inclusion_proof](https://i.imgur.com/KWpKF71.png)
