Secure Tree - state trie의 키가 256 bit인 이유

지난번 글 에서 설명했듯이 ethereum의 상태는 modified Merkle Patricia Trie(a.k.a. MPT)에 저장된다. Ethererum에서 값은 nonce, balance 등 account의 상태고, 그 키는 account의 주소다. 이 Account의 주소는 160bit이기 때문에, MPT의 root에서부터 40 nibble 의 경로를 타고 가면 account의 상태가 나와야 한다. 하지만 실제로 ethereum의 상태가 저장된 MPT에서 account의 주소를 키로 가지는 노드를 찾으면, leaf node 가 아닌 branch node 나 extension ndoe 가 나온다. 이는 ethereum이 account를 MPT에 집어넣을 때, account의 주소를 바로 키로 사용하는 것이 아니라, 주소의 keccak-256 hash를 키로 사용하기 때문이다. 즉, 40 nibble의 account 주소를 따라가는 것이 아니라, 64 nibble의 hash를 따라가야 원하는 account를 찾을 수 있다. 이렇게 account의 주소를 바로 경로로 사용하는 것이 아니라, 주소의 hash를 경로로 사용하는 것을 ethereum은 secure tree 라고 부른다. Secure tree 에 대해 자세히 설명하기 전에 ethereum이 사용하는 MPT에 대해서 더 알아야할 것이 있다. Ethereum에 있는 MPT는 state trie만이 아니다. Ethereum은 총 네 종류의 MPT가 있다. 첫 번째는 state trie다. 여기에는 ethereum의 account 정보가 저장된다. 여기서 account 정보는 account의 nonce, balance, storage root의 hash, code의 hash다. 만약 계정이 smart contract라면 storage root에는 smart contract의 state를 가지는 MPT의 root가 저장되고, code에는 evm bytecode의 hash 값이 저장된다. 두 번째는...

2018년 18번째 주

이미지
이 포스팅은 그냥 지난 한 주간 읽었던 것들을 정리하는 포스트입니다. 그냥 예전에 봤던 글 중 나중에 필요한데 뭐였는지 기억 안 나는 글들이 있어서 쓰기 시작했습니다. 보통 하는 일과 관련된 글들이 올라오겠지만 딱히 정해둔 주제는 없고, 그때그때 관심 있었던 것을 읽었기 때문에 지난주에 쓰인 글일 수도 있고 몇 년 전에 쓰인 글일 수도 있습니다. Why would i use @rustlang over C++? Convince me. until now I don't see any reason for me to switch #rustlang — Moustapha Saad (@MoustaphaSaad) 2018년 5월 1일 3개월 전까지 C++을 쓰다가 최근에 회사를 옮기면서 Rust를 쓰고 있다. 개인적으로 느끼기에 Rust가 C++에 비해 가지는 가장 큰 장점은 cargo 라고 생각한다. Cargo 덕분에 C++에 비해서 의존성 관리를 매우 쉽게 할 수 있다. 물론 최근에 나온 언어들은 대부분 패키지 매니저를 가지고 있다. 하지만 그들은 대부분 C++보다 추상화된 메모리 관리를 가정하고 있기 때문에 C++의 대안이 되지는 못한다고 생각한다. 흔히들 말하는 Rust의 메모리 안전성은 딱히 큰 장점으로 느껴지지 않는다. Modern C++에서 제공하는 기능들을 잘 사용하면 C++에서도 메모리 이슈로 문제가 될 일은 많지 않다. 물론 C++을 쓸 때는 잘 써야 한다는 전제가 있어서 Rust를 쓸 때는 때 걱정을 덜 해도 된다는 것은 큰 장점이다. 하지만 Rust가 메모리 안전성은 보장해도 false alarm을 발생하는 일도 자주 있다. Non-lexical lifetime 같은 것이 구현되면서 false alarm을 줄이고 있지만, 아직은 종종 false alarm 때문에 실제로 안전한 코드를 보기 안 좋게 수정해야 하는 경우도 있기 때문에 어느 쪽이 더 좋은지는 취향의 문제라고 생각한다. Date format by count...

Modified Merkle Patricia Trie - ethereum이 상태를 저장하는 방법

이미지
Ethereum 에서 네트워크 부분을 빼고 보면, Ethereum은 하나의 state machine 이고, transaction은 ethereum의 state를 변경시키는 것이다. 이 state는 key-value pair로 표현된다. Key-value pair를 저장하는 방법은 여러 가지 있지만, ethereum에서는 state를 저장하기 위해 Modified Merkle Patricia Trie (a.k.a. MPT)라는 특수화된 방법을 사용하도록 스펙에서 정의하고 있다. MPT는 기본적으로 Patricia trie와 Merkle tree를 합친 것이다. 여기에 추가로 ethereum의 특성에 맞게 몇 가지 최적화를 했다. 따라서 MPT를 쉽게 이해하기 위해서는 Patricia trie와 Merkle tree를 아는 것이 좋다. Patricia Trie Patricia trie는 Prefix tree, radix tree, trie 등 다양한 이름으로 불리는 자료구조다. Trie는 path에 key를 집어넣어 공통된 prefix를 가지는 노드들은 같은 path를 가진다. 공통된 prefix를 찾는데 가장 빠르고, 적은 메모리로 구현할 수 있으며, 구현도 간단하다. 그래서 router 등 낮은 사양의 기계에 들어가는 routing table의 구현체로 많이 사용된다. https://commons.wikimedia.org/wiki/File:Trie_example.svg Merkle Tree Merkle tree 는 hash들의 tree다. Leaf 노드에는 데이터를 보관한다. Leaf의 부모는 leaf의 hash를 가지고, 그 부모는 자식들의 hash의 합을 다시 hash 한 값을 가진다. Merkle tree는 leaf 노드를 제외한 노드들은 전부 hash를 가지고 있기 때문에 hash tree라고도 불린다. https://commons.wikimedia.org/wiki/File:Hash_Tree.svg Merkle tr...

2 phase commit

Two Phase Commit (a.k.a. 2PC)은 distributed system에서 atomic commit 을 보장하는 프로토콜이다. 2PC는 나름 많은 에러 상황을 버티고, 괜찮은 성능을 보이기 때문에 많이 사용된다. 2PC에서 노드는 한 개의 coordinator와 여러 개의 cohort로 나누어진다. Coordinator는 commit 할 transaction을 만드는 노드고, cohort들은 coordinator가 보낸 transaction을 commit 하거나 revert 한다. 2PC는 이때 fail 하지 않은 모든 cohort가 같은 상태를 유지하도록 하는 것이다. 즉, fail 하지 않은 모든 노드는 다 같이 commit 하거나 revert 한다. 이때 coordinator를 어떻게 선정할지는 2PC의 영역이 아니다. 고정된 coordinator를 계속 사용할 수도 있고, 차례대로 돌아가면서 coordinator가 될 수도 있고, 별도의 leader election을 사용하여 coordinator를 선정할 수도 있다. 2PC는 어떻게든 coordinator가 선정된 뒤의 일이다. 2PC는 이름 그대로 2가지 phase로 나누어져 있다. 첫 번째 phase는 voting phase라고 부르고, 두 번째 phase는 commit phase라고 불린다. 각 phase의 시작은 coordinator가 보내는 메시지로 시작한다. Voting phase에서 coordinator는 commit 하고 싶은 transaction을 commit 할지 말지 투표하는 요청을 cohort에게 보낸다. VOTE 메시지를 받은 cohort들은 이 transaction을 바로 commit 하지 않는다. 해당 transaction을 커밋할 수 있으면 YES 메시지를, 없으면 NO 메시지를 coordinator에게 보낸다. Voting phase에서 coordinator가 quorum 이상의 YES 메시지나 NO 메시지를 모으면 commi...

2018년 17번째 주

이 포스팅은 그냥 지난 한 주간 읽었던 것들을 정리하는 포스트입니다. 그냥 예전에 봤던 글 중 나중에 필요한데 뭐였는지 기억 안 나는 글들이 있어서 쓰기 시작했습니다. 보통 하는 일과 관련된 글들이 올라오겠지만 딱히 정해둔 주제는 없고, 그때그때 관심 있었던 것을 읽었기 때문에 지난주에 쓰인 글일 수도 있고 몇 년 전에 쓰인 글일 수도 있습니다. The Configuration Complexity Clock Configuration을 만들다 보면 Rules engine 이나 심할 때는 DSL (Domain Specific Language)까지 만들기도 하는데, 어떨 때는 그냥 하드코딩 하는 것이 가장 적절한 방법일 수 있다는 글이다. Linus's Law given enough eyeballs, all bugs are shallow 리누스의 법칙은 위의 한 줄로 정리된다. 오픈 소스의 근간이 되는 문장이고, peer-review가 필요한 이유로도 많이 언급된다. 문제는 최근의 거대한 소프트웨어서는 버그를 발견하는 데 필요한 enough의 수가 너무 크다는 것이다. 게다가 시스템이 복잡하다면, 그 시스템을 이해하지 못한 개발자는 버그를 발견하기 위한 eyeballs 중 하나가 되지도 못한다. 그렇기 때문에 시스템을 단순하게 유지하는 것이 중요하다. Language Health 각 언어가 오픈 소스에서 얼마나 많이 사용되는지 비교해보는 사이트다. 다만, 어디까지나 오픈소스에서 얼마나 많이 커밋이 있었는지에 대한 비교이지, 얼마나 많은 사람이 사용하는지나, 클로즈드 프로젝트에서 얼마나 많이 사용하는지는 알 수 없다. An introduction to the GNU Core Utilities 리눅스에서 작업하다 보면 필요한 유틸리티 모음. 터미널에서 작업할 때 알면 좋은 것들이다. REST APIs are REST-in-Peace APIs. Long Live GraphQL. GraphQL의 장점에 관해서 쓴 글이다. 근데 ...

Ethereum의 state trie pruning

이미지
MPT를 이용하면 새로 추가되는 노드의 수도 최소화할 수 있다. 예를 들어 위의 그림에서 block N 과 block N + 1 의 차이는 A 의 오른쪽 자식의 값이 10에서 20으로 변경된 것뿐이다. 이 경우 10에서 20으로 변경된 노드의 부모 외의 다른 노드는 전부 기존의 노드를 재활용할 수 있다. 따라서 푸른색으로 그려진 3개의 노드만 새로 추가하면 된다. 그렇다면 더는 접근할 필요가 없는 노드들은 어떻게 되는가? 위의 예제에서 붉은색으로 표시된 3개의 노드는 block N + 1 에서는 필요 없는 노드다. 그렇다면 이 3개의 노드는 3개의 푸른색 노드가 추가되고 나면 바로 지워도 될까? 그랬으면 문제가 쉬웠겠지만 아쉽게도 그렇지 않다. Ethereum은 block의 finality를 보장하지 않는다. 다른 말로 언제든지 block N + 1 이 block N 으로 retract 될 수 있다는 것이다. 게다가 Web3 API 를 통해서 과거의 state에 접근하는 것도 가능하기 때문에 현재 상태에서 안 쓰이는 노드를 바로 지울 수는 없다. 그렇다고 영원히 남겨둘 수는 없다. 현재 ethereum에서 최신 state의 크기는 약 25GB 정도지만, 과거 state를 전부 저장하면 300GB를 넘어간다 . 게다가 이 크기는 점점 커질 것이기 때문에 이를 전부 저장하는 것은 현실적이지 않다. Ethereum은 접근할 수 있는 과거 state를 127개로 제한 하여 그보다 오래된 state에만 포함된 노드는 지워도 되도록 하였다. 하지만 지워도 된다는 것과 지울 수 있다는 것은 별개의 문제다. DB에 저장돼있는 노드 중 최근 127개의 노드에서 접근할 수 없는 노드를 찾아 지우는 것은 쉬운 문제가 아니다. 이 문제는 computer science에서 오랫동안 풀어 온 automatic memory management 문제와 비슷하다. 실제로 Vitalik Buterin 이 쓴 state tree pruning 은 reference counti...

2018년 16번째 주

이 포스팅은 그냥 지난 한 주간 읽었던 것들을 정리하는 포스트입니다. 그냥 예전에 봤던 글 중 나중에 필요한데 뭐였는지 기억 안 나는 글들이 있어서 쓰기 시작했습니다. 보통 하는 일과 관련된 글들이 올라오겠지만 딱히 정해둔 주제는 없고, 그때그때 관심 있었던 것을 읽었기 때문에 지난주에 쓰인 글일 수도 있고 몇 년 전에 쓰인 글일 수도 있습니다. ISO week date 오늘이 올해의 몇 번째 주인지 정하는 기준은 말하는 사람마다 다르다. 그래서 이 요약정리 시리즈는 ISO 8601 기준으로 몇 번째 주인지 표기한다. ISO 8601에 따르면 1월 4일이 포함된 주를 그 해의 첫 번째 주로 취급한다. 다른 말로 한 주의 시작을 월요일로 봤을 때 4일 이상 포함된 첫 번째 주가 그 해의 첫 번째 주인 것이다. TextQL 머신 러닝이나 데이터 마이닝을 할 때 데이터의 경향성을 대강 파악하고 싶을 때가 있다. 이럴 때 사용되는 데이터는 보통 매우 큰 데이터이기 때문에 에디터로 열어서 보는 것은 무리가 있고, 간단하게 스크립트를 짜서 실행하게 된다. 근데 이때 하는 일은 대부분 비슷한 일이기 때문에 꽤나 귀찮은 작업이었는데, 스크립트를 짜지 않고 파일을 SQL 을 실행시켜주는 프로젝트가 있었다. 아직 사용해보지는 않아서 직접 스크립트를 짜는 것과 비교하면 어떨지는 모르겠지만 꽤 많은 사람이 쓰고 있는 것 같다. Writing 수학을 배워야 하는 이유가 사고하는 법을 익히기 위해서이듯이, 글쓰기를 배우는 이유는 무엇을 생각했는지 명확하게 하기 위해서다. 사람은 모든 것을 기억할 수 없기 때문에 자신이 생각한 것을 써서 정리해야 한다는 것이다. 게다가 글을 쓰는 것은 내가 글 쓰는 주제에 대해 나보다 모르는 독자를 가정하고 글을 쓰게 된다. 그래서 평소에는 당연하게 생각하고 넘어갔던 것들에 대해서도 한 번 더 생각하고 넘어갈 시간을 가지게 한다. How quantum computing could wreak havoc on cryptocurren...

이 블로그의 인기 게시물

USB 2.0 케이블의 내부 구조

[C++] enum class - 안전하고 쓰기 쉬운 enum

Log Aggregator 비교 - Scribe, Flume, Fluentd, logstash

[Web] SpeechSynthesis - TTS API

[Python] cache 데코레이터로 최적화하기