Skip to content
This repository has been archived by the owner on Aug 13, 2024. It is now read-only.

Commit

Permalink
change to code
Browse files Browse the repository at this point in the history
  • Loading branch information
ethan-kr committed Jun 13, 2023
1 parent f7dde3b commit 820636d
Showing 1 changed file with 172 additions and 38 deletions.
210 changes: 172 additions & 38 deletions KIPs/kip-111.md
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ Account 정보는 위와 동일하다.
Diagram-2
Root("acec...e3c5") - Extension0 [ "a7", "72fd...b753"xxx7 ]
|
Branch0 [ 0:N, 1:"7323...25a7"xxx6, 2:N, ..., 7:"945e...f7af"xxx5, 8:N, ..., f:"6c8d...5660"xxx4, val ]
Branch0 [ 0:N, 1:"7323...25a7"xxx5, 2:N, ..., 7:"945e...f7af"xxx6, 8:N, ..., f:"6c8d...5660"xxx4, val ]
/ | \
Leaf0 [ "1355", 45.0 ETH ] Extension1 [ "d3", "127f...6d00"xxx3 ] Leaf1 [ "9365", 1.10 ETH ]
|
Expand Down Expand Up @@ -129,56 +129,190 @@ Hash계산은 아래에서 부터 위로 검사하기 때문에 Leaf3에서 위
Leaf3의 ref_39는 "5597...7d27"xxx1이 되며 Branch1의 9번 child를 "5597...7d27"xxx1으로 업데이트 합니다.
* Leaf2도 Leaf3와 동일하지만 이번에는 random count가 "xxx2"가 됩니다.
Leaf2의 ref_39는 "5597...7d27"xxx2가 되며 Branch1의 3번 child를 "5597...7d27"xxx2로 업데이트 합니다.
* Branch1에는 위 Leaf3, Leaf2에서 업데이트된 2개의 ref_39가 존재합니다. Hash를 계산하기 전에 ref_39를 ref_32로 잠시 변환합니다.
그러면 Branch1의 value는 [ 0:N, ..., 3:"5597...7d27", ..., 9:"5597...7d27", ..., f:N, val ] 이 되며, Diagram-1의 Branch1과 동일한 Value가 되고 Hash를 계산하면 "127f...6d00"가 되고 random count "xxx3"을 붙입니다.


* Leaf3, Leaf2의 계산 결과를 반영하면 아래처럼 표현됩니다.

```go
Diagram-4
Root - Extension0 [ "a7", Branch0 ]
|
Branch0 [ 0:N, 1:Leaf0, 2:N, ..., 7:Extension1, 8:N, ..., f:Leaf1, val ]
/ | \
Leaf0 [ "1355", 45.0 ETH ] Extension1 [ "d3", Branch1 ] Leaf1 [ "9365", 1.10 ETH ]
|
Branch1 [ 0:N, ..., 3:"5597...7d27"xxx2, ..., 9:"5597...7d27"xxx1, ..., f:N, val ]
/ \
Leaf2 [ "7", 1.00 WEI ] Leaf3 [ "7", 1.00 WEI ]
```

* Branch1에는 위 Leaf3, Leaf2에서 업데이트된 2개의 ref_39가 존재합니다. Hash를 계산하기 전에 ref_39를 ref_32로 잠시 변환합니다.
그러면 Branch1의 Value는 [ 0:N, ..., 3:"5597...7d27", ..., 9:"5597...7d27", ..., f:N, val ] 이 되며, Diagram-1의 Branch1과 동일한 Value가 되고 Hash를 계산하면 "127f...6d00"가 되고 random count "xxx3"을 붙입니다.
```go
Diagram-4
Root - Extension0 [ "a7", Branch0 ]
|
Branch0 [ 0:N, 1:Leaf0, 2:N, ..., 7:Extension1, 8:N, ..., f:Leaf1, val ]
/ | \
Leaf0 [ "1355", 45.0 ETH ] Extension1 [ "d3", "127f...6d00"xxx3 ] Leaf1 [ "9365", 1.10 ETH ]
|
Branch1 [ 0:N, ..., 3:"5597...7d27"xxx2, ..., 9:"5597...7d27"xxx1, ..., f:N, val ]
/ \
Leaf2 [ "7", 1.00 WEI ] Leaf3 [ "7", 1.00 WEI ]
```

* Leaf1, Leaf0에는 ref_39가 없음으로 그냥 Hash를 계산하고, random count xxx4, xxx5를 붙입니다.
Leaf1 - "6c8d...5660"xxx4, Leaf - "6c8d...5660"xxx5
* Extension1의 Value에는 ref_39가 있어 ref_32로 변환하고 Hash를 계산합니다.
Extension1의 Value는 [ "d3", "127f...6d00" ]이 되고, Hash로 계산한후 xxx6을 붙이면 "945e...f7af"xxx6이 됩니다.
* Leaf1, Leaf0, Extension1의 결과를 반영하면 아래의 그림이 됩니다.
```go
Diagram-5
Root - Extension0 [ "a7", Branch0 ]
|
Branch0 [ 0:N, 1:"7323...25a7"xxx5, 2:N, ..., 7:"945e...f7af"xxx6, 8:N, ..., f:"6c8d...5660"xxx4, val ]
/ | \
Leaf0 [ "1355", 45.0 ETH ] Extension1 [ "d3", "127f...6d00"xxx3 ] Leaf1 [ "9365", 1.10 ETH ]
|
Branch1 [ 0:N, ..., 3:"5597...7d27"xxx2, ..., 9:"5597...7d27"xxx1, ..., f:N, val ]
/ \
Leaf2 [ "7", 1.00 WEI ] Leaf3 [ "7", 1.00 WEI ]
```
* Branch0과 Extension0은 Branch1과 Extention1의 과정을 동일하게 적용하면 Diagram-2와 같은 결과가 나오며, Diagram-1과 동일한 Root Hash를 얻게 되어 호환성이 유지 됩니다.


### Pruning
이제는 삭제과정을 설명합니다.

#### 기존 Hash에서의 Pruning
Diagram-1을 Key : Value 형식으로 표현하면 아래와 같습니다.
```go
KeyValue - 1
"acec...e3c5" : Extension0 - [ "a7", "72fd...b753" ]
"72fd...b753" : Branch0 - [ 0:N, 1:"7323...25a7", 2:N, ..., 7:"945e...f7af", 8:N, ..., f:"6c8d...5660", val ]
"7323...25a7" : Leaf0 - [ "1355", 45.0 ETH ]
"945e...f7af" : Extension1 - [ "d3", "127f...6d00" ]
"6c8d...5660" : Leaf1 - [ "9365", 1.10 ETH ]
"127f...6d00" : Branch1 - [ 0:N, ..., 3:"5597...7d27", ..., 9:"5597...7d27", ..., f:N, val ]
"5597...7d27" : Leaf2 - [ "7", 1.00 WEI ]
```
* a77d397 account의 잔고가 1.00 WEI에서 2.00 WEI로 변경된다면 Diagram-1은 아래처럼 변합니다.
* 새롭게 업데이트된 Hash는 빨간색의 ref_32입니다.
```go
Diagram-6
Root("REDD...e3c5") - Extension0' [ "a7", "REDD...b753" ]
|
Branch0' [ 0:N, 1:"7323...25a7", 2:N, ..., 7:"REDD...f7af", 8:N, ..., f:"6c8d...5660", val ]
/ | \
Leaf0 [ "1355", 45.0 ETH ] Extension1' [ "d3", "REDD...6d00" ] Leaf1 [ "9365", 1.10 ETH ]
|
Branch1' [ 0:N, ..., 3:"5597...7d27", ..., 9:"REDD...7d27", ..., f:N, val ]
/ \
Leaf2 [ "7", 1.00 WEI ] Leaf2' [ "7", 2.00 WEI ]
```
Diagram-6에서 변화된 정보를 Key : Value형식으로 표현하면 아래와 같습니다.
<!-- Diagram-2를 Key : Value형식으로 정리하면 아래처럼 표현할 수 있습니다.
```go
KeyValue - 2
"acec...e3c5" : Extension0 - [ "a7", "72fd...b753" ]
"72fd...b753" : Branch0 - [ 0:N, 1:"7323...25a7", 2:N, ..., 7:"945e...f7af", 8:N, ..., f:"6c8d...5660", val ]
"7323...25a7" : Leaf0 - [ "1355", 45.0 ETH ]
"945e...f7af" : Extension1 - [ "d3", "127f...6d00" ]
"6c8d...5660" : Leaf1 - [ "9365", 1.10 ETH ]
"127f...6d00" : Branch1 - [ 0:N, ..., 3:"5597...7d27", ..., 9:"5597...7d27", ..., f:N, val ]
"5597...7d27" : Leaf2 - [ "7", 1.00 WEI ]
-- ADD NODE --
"REDD...7d27" : Leaf2' - [ "7", 2.00 WEI ]
"REDD...6d00" : Branch1' - [ 0:N, ..., 3:"5597...7d27", ..., 9:"REDD...7d27", ..., f:N, val ]
"REDD...f7af" : Extension1'- [ "d3", "REDD...6d00" ]
"REDD...b753" : Branch0' - [ 0:N, 1:"7323...25a7", 2:N, ..., 7:"REDD...f7af", 8:N, ..., f:"6c8d...5660", val ]
"REDD...e3c5" : Extension0'- [ "a7", "REDD...b753" ]
```
Pruning의 관점에서보면 '(프라임)이 붙은 노드들은 업데이트된 노드이기 때문에 변경전의 노드를 지우고 싶습니다. 그런데 Leaf2'의 원본노드인 Leaf2를 지우면 데이터 유실이 됩니다. 왜냐하면 Branch1에서 Leaf2를 중복으로 참조하고 있었기 때문입니다. 지금은 예제이기 때문에 간단히 표현되었지만, 수십억 노드로 연결되어 있는 MPT에서는 어떤 노드가 새롭게 업데이트 되었을때 과거 노드를 지울수 있는지 판단할 수가 없습니다. 그래서 online puning을 진행할 수 없습니다.

#### ExtHash에서의 Pruning

Diagram-2를 Key : Value 형식으로 표현하면 아래와 같습니다.
```go
KeyValue - 3
"acec...e3c5" : Extension0 - [ "a7", "72fd...b753"xxx1 ]
"72fd...b753"xxx1 : Branch0 - [ 0:N, 1:"7323...25a7"xxx2, 2:N, ..., 7:"945e...f7af"xxx3, 8:N, ..., f:"6c8d...5660"xxx4, val ]
"7323...25a7"xxx2 : Leaf0 - [ "1355", 45.0 ETH ]
"945e...f7af"xxx3 : Extension1 - [ "d3", "127f...6d00"xxx5 ]
"72fd...b753"xxx7 : Branch0 - [ 0:N, 1:"7323...25a7"xxx2, 2:N, ..., 7:"945e...f7af"xxx3, 8:N, ..., f:"6c8d...5660"xxx4, val ]
"7323...25a7"xxx5 : Leaf0 - [ "1355", 45.0 ETH ]
"945e...f7af"xxx6 : Extension1 - [ "d3", "127f...6d00"xxx5 ]
"6c8d...5660"xxx4 : Leaf1 - [ "9365", 1.10 ETH ]
"127f...6d00"xxx5 : Branch1 - [ 0:N, ..., 3:"5597...7d27"xxx6, ..., 9:"5597...7d27"xxx7, ..., f:N, val ]
"5597...7d27"xxx6 : Leaf2 - [ "7", 1.00 WEI ]
"5597...7d27"xxx7 : Leaf3 - [ "7", 1.00 WEI ]
``` -->



Hash계산은 아래에서 부터 위로 검사하기 때문에 Leaf3에서 위쪽으로 계산합니다.
* Leaf3의 ref_39에서 마지만 xxx7만 제거하면 원래 Hash("5597...7d27")를 얻을 수 있습니다.
* Leaf2도 Leaf3과 같은 방븝으로 기존 Hash("5597...7d27")을 얻습니다.
* Branch1



Leaf3의 ref_39는 "5597...7d27"xxx7 이며, Leaf2의 ref_39는 "5597...7d27"xxx6 입니다.





"127f...6d00"xxx3 : Branch1 - [ 0:N, ..., 3:"5597...7d27"xxx6, ..., 9:"5597...7d27"xxx7, ..., f:N, val ]
"5597...7d27"xxx2 : Leaf2 - [ "7", 1.00 WEI ]
"5597...7d27"xxx1 : Leaf3 - [ "7", 1.00 WEI ]
```

* a77d397 account의 잔고가 1.00 WEI에서 2.00 WEI로 변경된다면 Diagram-2는 아래처럼 변합니다.
a77d397에 관련된 ref_39는 모두 새로 계산되어야 하며, 붉은색 처럼 표현됩니다.
```go
Diagram-7
Root("REDD...e3c5") - Extension0 [ "a7", "REDD...b753"xxxb ]
|
Branch0 [ 0:N, 1:"7323...25a7"xxx5, 2:N, ..., 7:"REDD...f7af"xxxa, 8:N, ..., f:"6c8d...5660"xxx4, val ]
/ | \
Leaf0 [ "1355", 45.0 ETH ] Extension1 [ "d3", "REDD...6d00"xxx9 ] Leaf1 [ "9365", 1.10 ETH ]
|
Branch1 [ 0:N, ..., 3:"5597...7d27"xxx2, ..., 9:"REDD...7d27"xxx8, ..., f:N, val ]
/ \
Leaf2 [ "7", 1.00 WEI ] Leaf3 [ "7", 2.00 WEI ]
```

Diagram-2에서 Diagram-6으로 변경된 내용을 Key : Value 형식으로 표현하면 아래와 같습니다.
```go
KeyValue - 4
-- OLD NODE --
"acec...e3c5" : Extension0 - [ "a7", "72fd...b753"xxx1 ]
"72fd...b753"xxx7 : Branch0 - [ 0:N, 1:"7323...25a7"xxx2, 2:N, ..., 7:"945e...f7af"xxx3, 8:N, ..., f:"6c8d...5660"xxx4, val ]
"7323...25a7"xxx5 : Leaf0 - [ "1355", 45.0 ETH ]
"945e...f7af"xxx6 : Extension1 - [ "d3", "127f...6d00"xxx5 ]
"6c8d...5660"xxx4 : Leaf1 - [ "9365", 1.10 ETH ]
"127f...6d00"xxx3 : Branch1 - [ 0:N, ..., 3:"5597...7d27"xxx6, ..., 9:"5597...7d27"xxx7, ..., f:N, val ]
"5597...7d27"xxx2 : Leaf2 - [ "7", 1.00 WEI ]
"5597...7d27"xxx1 : Leaf3 - [ "7", 1.00 WEI ]
-- ADD NODE --
"REDD...7d27"xxx8 : Leaf3' - [ "7", 2.00 WEI ]
"REDD...6d00"xxx9 : Branch1' - [ 0:N, ..., 3:"5597...7d27"xxx2, ..., 9:"REDD...7d27"xxx8, ..., f:N, val ]
"REDD...f7af"xxxa : Extension1'- [ "d3", "REDD...6d00"xxx9 ]
"REDD...b753"xxxb : Branch0' - [ 0:N, 1:"7323...25a7"xxx5, 2:N, ..., 7:"REDD...f7af"xxxa, 8:N, ..., f:"6c8d...5660"xxx4, val ]
"REDD...e3c5" : Extension0'- [ "a7", "REDD...b753"xxxb ]
```
* Leaf3의 Balance가 변경됨으로 인해 Leaf3', Branch1' Extention1', Branch0', Extension0'으로 새롭게 업데이트 되었고, Pruning의 목적처럼 최신데이터만 유지 한다면 "OLD NODE"에 있던 Leaf3, Branch1, Extention1, Branch0, Extension0를 삭제하면 됩니다.
* 추가된 7바이트로 인해 중복 참조하는 노드가 존재할 수 없기 때문입니다.
* 따라서 "5597...7d27"xxx1, "127f...6d00"xxx3, "945e...f7af"xxx6, "72fd...b753"xxx7, "acec...e3c5"를 삭제할 수 있습니다.

#### Pruning을 위해 도입한 ExtHash로 인한 변화

* 데이터 관점에서 보기 위해 KeyValue-1KeyValue-3을 이곳에서 다시 보고 비교해봅니다.
```go
KeyValue - 1
"acec...e3c5" : Extension0 - [ "a7", "72fd...b753" ]
"72fd...b753" : Branch0 - [ 0:N, 1:"7323...25a7", 2:N, ..., 7:"945e...f7af", 8:N, ..., f:"6c8d...5660", val ]
"7323...25a7" : Leaf0 - [ "1355", 45.0 ETH ]
"945e...f7af" : Extension1 - [ "d3", "127f...6d00" ]
"6c8d...5660" : Leaf1 - [ "9365", 1.10 ETH ]
"127f...6d00" : Branch1 - [ 0:N, ..., 3:"5597...7d27", ..., 9:"5597...7d27", ..., f:N, val ]
"5597...7d27" : Leaf2 - [ "7", 1.00 WEI ]
```

아래 그림은 기존 MPT에서 value에서 Hash를 구하고 서로를 참조하는 Root Node, Child Node, Leaf Node간의 연결 관계를 나타낸 그림이다.
![Legacy Merkle Patricia Trie diagram](../assets/kip-111/legacy_trie_diagram.png)

아래 그림은 ExtHash를 사용한 MPT의 연결 관계를 나타낸 그림이다.
* Root Node에서 Child Node, Leaf Node를 참조할때는 ExtHash를 사용해서 연결된다.
* 노드의 정합성을 검증하기 위한 Hash를 구할때는 ExtHash의 마지막 7자리를 제외하고 Hash를 계산해서 기존 MPT와 동일한 Hash를 얻을 수 있다.
![ExtHash Merkle Patricia Trie diagram](../assets/kip-111/extHash_trie_diagram.png)


```go
KeyValue - 3
"acec...e3c5" : Extension0 - [ "a7", "72fd...b753"xxx1 ]
"72fd...b753"xxx7 : Branch0 - [ 0:N, 1:"7323...25a7"xxx2, 2:N, ..., 7:"945e...f7af"xxx3, 8:N, ..., f:"6c8d...5660"xxx4, val ]
"7323...25a7"xxx5 : Leaf0 - [ "1355", 45.0 ETH ]
"945e...f7af"xxx6 : Extension1 - [ "d3", "127f...6d00"xxx5 ]
"6c8d...5660"xxx4 : Leaf1 - [ "9365", 1.10 ETH ]
"127f...6d00"xxx3 : Branch1 - [ 0:N, ..., 3:"5597...7d27"xxx6, ..., 9:"5597...7d27"xxx7, ..., f:N, val ]
"5597...7d27"xxx2 : Leaf2 - [ "7", 1.00 WEI ]
"5597...7d27"xxx1 : Leaf3 - [ "7", 1.00 WEI ]
```

* KeyValue - 1, 3은 같은 데이터를 표현하고 있습니다.
* 하지만 추가된 7바이트로 인해 2가지 변화가 있습니다.
* MPT의 모든 Hash32 byte에서 39 byte로 증가했으며, Key, Value모두에 적용됩니다. 이로 인해 39/32 만큼 증가해서 최대 21.8%정도의 용량이 증가될 수 있습니다.
* KeyValue - 3에는 KeyValue - 1에 없던 Leaf3이 추가되었습니다. 중복 참조로 인해 데이터를 효율적으로 사용할 수 없게 되었습니다. 이는 각 블록체인의 상황에따라 많이 다를 수 있으나, 클레이튼 내부 조사 결과는 2% 이하로 증가되는 것으로 조사되었습니다.
* 결과적으로 ExtHash를 도입함으로 인해 23% 정도의 데이터가 증가하게 되는 것으로 보고 있습니다.



Expand Down

0 comments on commit 820636d

Please sign in to comment.