내멋대로 블록체인 #3 - 블록 및 계좌 데이터 구조 설계

    주의


    해당 포스팅은 자바로 블록체인(Blockchain)을 구현해 나가는 장기간의 프로젝트로서 초반에는 매우 강력한 삽질을 할 수 있다는 점 양해 바랍니다. 자바 자체가 블록체인에 적합한 언어가 아니기 때문에 본 포스팅은 완전한 퍼블릭 블록체인을 추구하는 것은 아니라, DPOS(Delegated Proof of Stake)와 프라이빗 블록체인(Private Blockchain) 정도를 포커스로 잡고 구현해 나갈 생각입니다. 다만 가능하다면, 퍼블릭 블록체인(Public Blockchain) 도 설계는 계속 해볼 생각입니다(사토시 빙의)


    어제 영상을 찍으면서도 깨닫는 것이 있고, 아침에 샤워를 하면서도 깨닫는 것들이 있기 때문에 포스팅이 오락가락할 수 있지만, 그럴때마다 포스팅에서 정정해 나가도록 하겠습니다. 이번 편은 데이터 구조를 설계하는 것입니다. 프로그래밍을 하려면, 어떤 데이터 타입으로 구현해 나가야 될 것인가가 매우 중요하기에 클래스 설계까진 아니더라도 블록에 어떤 데이터들이 들어가 있어야 하는지 설계를 해보았습니다.




    비트코인(Bitcoin)의 구조는 어떨까?


    제가 만들 코인의 구조를 만들기에 앞서, 비트코인의 구조는 어떨것인가?를 먼저 살펴보고자 합니다. 사실 모든 코인들이 비트코인의 큰 틀에서 벗어나지는 않고, 몇몇가지 기능만 추가를 한 정도가 대다수라서 (이더리움같은 플랫폼 코인은 좀 예외입니다. 플랫폼 코인들은 이더리움을 따라했겠죠) 비트코인만 제대로 분석한다면 왠만한 코인은 제작이 가능할거라 생각하고 있습니다.



    이 그림은 비트코인의 논문에 나와있는 비트코인 거래 구조입니다. 모든 거래들이 해시(Hash)로 이어지고 있으며, 단 하나의 거래만 변경해도 해시값이 바뀌기 때문에 조작을 했다는 사실을 다른 노드가 쉽게 검증할 수 있을 것입니다. 다만, 제 눈에는 모든 거래를 저렇게 이을 필요까진 있었을까? 라는 생각이 있습니다.


    여기서 참고해야 될 부분은 공개키(Public Key)와 개인키(Private Key)를 이용한 전자서명(Digital Signature) 같은 경우는 해당 사용자가 정말로 보낸 것인지 검증하기 위한 방안입니다. 사실 암호화폐(Cryptocurrency)라고 하는 가장 큰 이유가 바로 이 전자서명으로 인한 거래의 신뢰성입니다. 이 부분은 추후, 구현을 하되 속도를 위해 동일하게 구현은 하지 않을 생각입니다. 아직 거래 구조를 봤을 때, 비트코인은 데이터 구조가 어떤지 명확하게 보이지는 않습니다.




    이 그림은 비트코인의 작업증명(PoW) 구조입니다. 블록 하나에는 이전 블록의 해시 정보와 임시값 그리고 거래들로 이루어져 있습니다. 바로 이 범위가 해시를 만드는 값으로 볼 수 있는데 블록하나에 들어있는 데이터가 어느정도 윤곽이 잡힙니다


    확실한건 이전블록의 해시와 그리고 장부 거래 기록들, 그리고 블록을 채굴 했을 때 성공한 임시값이 있다는 것이죠. 일단 이 정도의 데이터와 이더리움의 디앱(Dapp)을 만들면서, 최소한으로 필요한 데이터를 접목하여 데이터를 설계를 해보았습니다.



    블록체인 데이터 설계


    우선, 이 설계는 지극히 제 개인적인 설계이고 추후 변경될 수 있다는 점을 우선 아셨으면 좋겠습니다. 일단 최소한으로 구성을 해보았고, 데이터 구조가 많으면 블록의 크기가 커지기 때문에 장부의 사이즈가 커지는 것도 문제가 있을 것입니다.



    우선 계좌 구조를 설계를 해보았습니다. 복수의 계좌를 생성할 수 있다는 사실은 다들 알고 있을 것입니다. 그러니 거래소 같은 곳에서 사람들마다 계좌를 생성할 수 있게 만들어 주는 것이겠죠. 그리고 계좌는 어떤 노드에서 생성이 되었는지를 알아야 할텐데, 그 값을 id라고 지정하였습니다.


    id는 노드 하나당 하나만 존재할 수 있습니다. 가상을 돌려서 여러개의 노드를 만드는 것을 방지하기 위해서, 노드는 맥어드레스를 기반으로 생성을 할 생각입니다. 사실 프라이빗으로 만들면, ID는 고민할 필요는 딱히 없겠죠



    계좌에는 잔고와 계좌가 생성한 날짜, 활성화 여부, 그리고 계좌 주소가 있습니다. AddressVO에는 계좌 키가 보이지 않는데 그 이유는 이 AddressVO를 HashMap 형태로 감쌌기 때문에, HashMap의 Key에 Address 주소(40글자의 난수)를 저장합니다.




    블록 구조는 비트코인의 작업증명을 참고 했습니다. 이전 블록의 해시값과 그리고 임시값, 장부들 그리고 이 내용들을 토대로 만들어진 해당 블록의 해시값 마지막으로 블록을 생성한 아이디값입니다. 블록을 생성한 아이디 경우, 혹여나 해커가 악의적으로 채굴 작업을 수행하게 되는 것을 파악하기 위함입니다.



    하나의 블록에 여러개의 거래 기록이 있을 수 있기 때문에, List 형태로 거래 기록을 담아야 합니다. 그래서 거래 기록을 하나의 Value Object로 생성하여 관리를 하는 것으로 설계를 해보았습니다.


    하나의 거래 기록에는 타임스탬프, 송신자, 수신자, 전달된 코인개수, 비고란, 거래일들이 있습니다. 여기에 타임스탬프는 거래 기록에 순서를 생성하는 구조라고 생각하면 될 것 같습니다. 분산화된 장부는 어느 기록이 우선인지 아는 것이 그 무엇보다 중요할 것입니다. 데이터베이스가 하나일 경우, 해당 데이터베이스에 넣는 순서대로 기록의 순위를 산정하면 되지만, 분산 데이터는 그것을 알수가 없습니다.



    타임스탬프(Timestamp) 서버 활용



    그래서 거래 기록을 들고, 타임스탬프 서버에게 해당 기록의 순서를 배당 받은 후, 작업을 하는 걸로 설계를 하였습니다. 각각의 거래기록을 가지고 있는 노드들은 타임스탬프에게 할당받은 시퀀스(순서값)로 순서를 재정렬하게 됩니다. 


    사실 이 부분에서 SPOF(Single Point of Failure) 구조가 발생할 가능성이 매우 높습니다 타임스탬프 서버가 맛이 가서 제대로 운영이 안된다면 혹은 DDoS(Distributed Denial of Service attack) 공격을 받게 된다면 전체 성능이 죽어버릴 수 있는 문제가 있습니다.



    블록에 처리할 장부의 기준


    장부 하나하나에 타임스탬프를 찍어서, 이제 순서를 산정하여 모든 장부가 뒤엉켜도 어떤 거래가 먼저 했는지 알아낼 수는 있지만, 어떤 데이터까지를 블록으로 생성해야 될지가 상당히 힘이 듭니다. 마스터노드에서 타임스탬프 어디까지를 기반으로 블록을 만들어봐!! 라고 명령을 때리면 편하겠지만, 이러면 마스터 노드의 부하도 심하고, 탈중앙화 방식과 전혀 상관 없는 완전 중앙화 방식일 겁니다.


    타임스탬프에는 이런식으로 데이터를 넣을 것입니다. 예를 들어 현재 시간이 2018년 8월 28일 오전 10시 38분 22초일 경우, 해당 초에 제일 처음 타임스탬프 작업 요청을 한 거래는 201808281038221 이라는 값을 주는 것이죠. 이 숫자를 사실 크게 보면, 20180828103822-1 이런 느낌입니다. 



    여기에 그림처럼, 마스터노드가 노드들에게 5초 단위로 블록을 생성해라라는 식의 명령을 내렸다고 한다면, 타임스탬프 값 기준으로 0~4초까지 거래내용, 5~9초까지의 거래 내역을 블록에 만들면 되는 것이겠죠. 그러나, 각각의 블록 생성 시작 시간이 다를텐데 이 시작은 최근에 블록을 생성한 노드가 바로 연결된 노드에게 블록을 생성하라고 명령을 하게 되는 걸로 설계를 해봤습니다.


    이렇게 설계한 이유는 블록을 생성한 노드가 연속적으로 블록을 생성할 수 없게 방지하며, 이런식으로 작업이 되어야 공평하게 순서가 갈것으로 판단을 했습니다. 참고로 순서를 어떻게 할지는 아직 완벽하게 설계하진 않았습니다.


    이상 블록 및 데이터 구조 설계를 해보았습니다만 소스를 보지 않으면 갸우뚱 할 수 있을 거라, 다음 포스팅은 이 설계로 만들어진 별거 아닌 소스 코드를 보여드리도록 하겠습니다.



    유튜브 영상


    영상이 포스팅보다 진도가 빠르기 때문에, 이 포스팅이 관심이 있으신 분들은 유튜브를 구독하시면 감사하겠습니다. :)



    댓글

    Designed by JB FACTORY