라벨이 ethereum인 게시물 표시

2018년 22번재 주 - P2P Network

이 포스팅은 그냥 지난 한 주간 읽었던 것들을 정리하는 포스트입니다. 그냥 예전에 봤던 글 중 나중에 필요한데 뭐였는지 기억 안 나는 글들이 있어서 쓰기 시작했습니다. 보통 하는 일과 관련된 글들이 올라오겠지만 딱히 정해둔 주제는 없고, 그때그때 관심 있었던 것을 읽었기 때문에 지난주에 쓰인 글일 수도 있고 몇 년 전에 쓰인 글일 수도 있습니다. 지난주 에 이어 이번 주는 P2P를 주제로 발표 했다. 이번에도 발표자료를 만들면서 참고한 자료를 공유하도록 하겠다. Chord: a scalable peer-to-peer lookup protocol for internet applications Tapestry: A Resilient Global-scale Overlay for Service Deployment Pastry: Scalable, decentralized object location and routing for large-scale peer-to-peer systems A Scalable Content-Addressable Network P2P 네트워크 중에서도 네트워크 토폴로지가 특정한 규칙에 의해서 구성되는 네트워크를 structured 네트워크라고 말한다. Structured network는 unstructured network에 비해 특정 노드에 부하가 걸리거나 의존하는 것을 방지하면서 잘 분산된 네트워크를 구성할 수 있다. 위의 4 논문은 각기 Chord , Tapestry , Pastry , Content Addressable Network (a.k.a. CAN)라는 대표적인 structured 네트워크 오버레이를 제시하는 논문이다. Kademlia: A Peer-to-Peer Information System Based on the XOR Metric Kademlia는 위의 네 논문을 개선하는 네트워크 오버레이를 제시한다. BitTorrent , eDonkey , 이더리움 등 많은 P2P 시스템이 kademl...

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 값이 저장된다. 두 번째는...

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...

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...

이더리움 샤딩

현재 이더리움이 겪고 있는 가장 큰 문제는 scalability다. 이더리움이 인기를 끌면서 트랜잭션의 양도 늘어나고 참여하고 있는 노드의 수도 늘고 있는데 PoW를 쓰는 이더리움의 특성상 초당 트랜잭션 처리 수는 늘지 못한다. 그래서 지금 이더리움 코어 개발자들이 초점을 맞춰서 개발하고 있는 것이 ethereum sharding 이다. 이더리움 샤딩을 간단히 설명하면 샤드별로 merkle patricia tree 를 만들고 그 샤드의 root들로 만들어진 merkle partricia tree의 root만을 블록체인에 올리는 것이다. 이렇게 하면 모든 miner가 모든 트랜잭션을 실행할 필요 없이 각 샤드별로 miner를 분산시켜 실행할 수 있기 때문에 전체 실행 속도가 올라간다는 내용이다. 설명은 간단하지만 구현은 간단하지 않다. 이더리움은 replay attack 을 막기 위해서 account nonce라는 것을 도입했다. 현재 state에서 account가 가지는 nonce보다 1 큰 nonce를 가지는 트랜잭션만 유효한 transaction이기 때문에, 같은 account에서 보내는 2개 이상의 트랜잭션은 동시에 처리될 수 없다. 즉, 한 account의 트랜잭션이 두 개 이상의 샤드에서 실행되면 안전하지 못하다는 것이고, account는 샤드에 종속돼야 한다. 또한, 샤드는 독립적으로 실행돼야 한다. 이 말은 한 샤드에서 실행된 트랜잭션이 다른 샤드에 영향을 주지 못 한다는 것이고, 다른 샤드에 존재하는 account 사이에서는 트랜잭션을 주고받을 수 없다는 것이다. 현재 제안된 샤드 간 통신은 receipt tree를 이용하는 것이다. 예를 들어 shard N 의 account A 에서 shard M 의 account B 로 송금하는 상황을 생각해보자. 이때 N 은 account A 의 계좌를 차감하는 transaction T1 을 실행한다. T1 은 M 의 state를 변경할 수 없기 때문에 B 에게 바로 입금할 수 없다. 따라서 T1...

이더리움과 Eclipse attack

p2p 네트워크는 많은 취약점을 가지고 있는데 대표적인 것이 Eclipse attack 이다. Eclipse attack은 네트워크 전체를 공격하는 것이 아니라 목표로 하는 노드의 Routing table을 공격하여 목표로 하는 노드와 전체 네트워크 사이에 악의적인 노드를 집어넣는 공격이다. Routing table을 공격하는 방법이기 때문에 routing-table poisoning이라고도 불린다. 이더리움도 p2p 네트워크를 사용하여 메시지를 주고받기 때문에 eclipse attack이 가능하리라 생각은 했는데 지난 3월 1일 발표 된 페이퍼 에 따르면 단 2개의 노드만으로 하나의 노드를 완전히 고립시키는 것이 가능하다고 한다. 이 페이퍼는 올해 1월 진행됐던 바운티 프로그램에서 나온 문제점들을 정리한 페이퍼로 크게 세 가지 공격방법으로 나눌 수 있다. 우선 첫 번째 문제는 이해하기 위해 이더리움이 p2p 네트워크를 어떻게 관리하는지 이해해야 한다. 네트워크 그래프 구성에 가장 중요한 것은 다른 노드를 어떻게 찾을 것인가 하는 것이다. 이를 흔히 node discovery라고 하는데 이더리움은 node discovery를 위해 DHT( Distributed Hash Table ) 프로토콜 중 하나인 Kademlia 의 일부를 수정해서 사용한다. Kademlia가 다른 DHT와 다른 가장 큰 특징은 노드 간의 거리를 XOR distance로 측정한다는 것이다. XOR distance의 거리는 symmetric 하므로 노드 아이디만 알고 있으면, 노드 A가 생각하는 노드 B까지의 거리나, 노드 B가 생각하는 노드 A까지의 거리나, 노드 C가 생각하는 노드 A와 노드 B 사이의 거리가 같다. 따라서 각 노드는 자신이 알고 있는 노드 중에서 자신과 가까운 노드들과만 통신하면 적은 연결 수로도 큰 네트워크를 구성할 수 있다는 장점이 있다. Kademlia 페이퍼에는 대략 노드의 개수를 N 이라고 할 때 각 노드는 O(log(N)) 개의 연결만 유지하면 된...

이 블로그의 인기 게시물

USB 2.0 케이블의 내부 구조

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

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

[Web] SpeechSynthesis - TTS API

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