Edit

Amazon Managed Blockchain

220.Blockchain 블로그 이더리움 ethereum aws qldb 티스토리

11/28일, AWS 에서 AWS Blockchain Template 에 이어 Amazon Managed Blockchain 서비스와 QLDB 를 소개하였다. 지금 시점에는 Preview 상태인데 이마저도 Sign Up 을 해야 하기는 하다.

일단 Preview Signup 을 하고나면 시간이 좀 지났더니 아래 처럼 메일이 온다

위 메일이 왔다고 해서 Preview Applicant 가 되었다는게 아니다. 기다려야 한다..
Apply 를 했지만 이틀 째 아직 회신이 오거나 하지 않는다 그냥 계속 기다려야 한다.

혹시나 사용 가능해지면 써보고 바로 다시 글을 올려보겠다

어디에 있나

AWS Console 에 들어가면 아래 처럼 Amazon Managed Blockchain 이 있는걸 볼 수 있다

마치 될 것 같은 느낌이지만 클릭하면 다시 Preview sign up 페이지로 넘어간다

현재 AMB Preview 가 지원되는 Region 은 US East (Virginia) 뿐이다
현 시점에 QLDB 메뉴는 어디에 있는지 발견하지 못하였다

Amazon Managed Blockchain

아직은 들어가보지도 못하고 자료도 거의 전무한 상태이므로, AWS 상의 서비스 소개 페이지를 참고하여 어떤것인가 정리해놓겠다

전체 구성

AMB 는 독립된 Member 별로 Peer Node 를 구성하게 하고, Ordering Service 와 Client 를 Fabric Network 으로 연결해주기 위한 VPC Endpoint Service 등은 공용할 수 있는 컴포넌트 형태로 제공하는 것으로 보인다.

아래 가격표를 보아도 알겠지만, Ordering Service 를 위한 별도의 Node 는 구매하지 않는다. 이부분은 AWS 에서 제공하는 것으로 보이며, 대신 Membership 금액을 시간당으로 받는 것으로 생각된다

Benefits (&Features)

Fully Managed

  • 여러 AWS 계정에 걸쳐 Blockchain Network 을 쉽게 생성
  • 멤버 그룹과 Account 의 Transaction 실행, 데이터 공유를 설정
  • Infra 와 S/W 설치 등이 필요 없다
  • 모니터링 기능 제공한다
  • 멤버 추가와 삭제를 위한 투표 기능 API를 제공한다

Fabric 과 Ethereum 중 선택

  • Privacy 와 Permission 중요한 곳에 Fabric 추천
  • Transparency 와 분산화 중요한 곳에 Ethereum 추천
  • Ethereum 은 Public / Private Network 지원할 것으로 보임

Scalable and Secure

  • Peer node 추가를 위한 API 를 제공
  • 원하는 H/W spec 을 조합
  • AWS KMS(Key Management System)를 통한 Key 관리로 안전

Easily analyze Blockchain Activity (향후 예정)

  • Blockchain network 활동을 QLDB 에 저장할 수 있음
  • 변경되거나 삭제될 수 없는 형태로 영구히 남게됨
  • 누가 Transaction 을 발생하였는지, Transaction Rate 이 어떻게 되는지 등 Query 가능

Reliability

  • Ordering service 에 QLDB 를 접목, Transaction 의 Full History 를 조회 가능하도록 함

가격

N. Virginia Region 에 대한 가격만 나와있는 상황으로, 아래와 같이 가격표가 나온다

Membership

  • Starter Edition : $0.30/h (337원/시간)
    • 네트워크 상 최대 5개 멤버
    • 멤버 당 최대 2개 Peer Node
    • bc.t3.small 또는 medium 타입 Peer Node 가능
    • 최대 1 TB 의 Peer node storage
    • Orderer 성능 제약(Standard 에 비해 떨어짐. 수치는 안나옴)
  • Standard Edition : $0.55/h (617원/시간)
    • 네트워크 상 최대 30개 멤버
    • 멤버 당 최대 10개 Peer Node
    • bc.t3, bc.m5, bc.c5 타입 Peer Node 가능
    • 최대 15 TB 의 Peer node storage

On Demand peer node pricing

  • 38 원 ~ 1,220 원 / 시간

Peer node storage
최소 10GB 부터 최대 15TB 까지 선택할 수 있음

  • $0.10 / 월 (112원/월)

Data Written
Fabric Network 에 Write 되는 모든 Transaction Payload 를 포함한 Data 총량

  • $0.10 / GB (112원/GB)

가격 예시

✸ Starter Edition 기준으로 아래와 같이 세팅 한다고 하자

2 개 Starter Member
각 멤버가 bc.t3.small 1개씩 운영
20GB Storage
시간당 9MB 의 Network 사용

위 Spec 이면 간단한 내부 PoC 정도가 가능한 사양이라고 봐야 하겠다. 음.. 사실 PoC 를 위한 개발 정도?

✸ Standard Edition 으로 가보자. 상용에서는 자신의 Org 에 대한 비용만 내는 경우가 많은것이므로 아래와 같이 구성했다고 가정한다

1 개 Standard Member
3 개 Peer Node (m5.2xlarge)
Node 당 1TB Storage
시간당 200MB Network 사용

위 Spec 이면 상용 서비스를 위한 구성 으로 알맞는다고 본다. Offchain 시스템을 위한 부분은 추가로 갖추어져야 한다.

이상이 AMB(Amazon Managed Blockchain) 의 소개 이다. 대략 어떤 서비스가 가능한지 감이 온다. 설치와 설정을 위한 노가다가 줄어들고, 모니터링 기능이 추가될 것이고, Key 저장을 안전하게 해주고, QLDB 를 활용하여 모든 Transaction 과 Activity 가 저장되니 의미있는 데이터를 QLDB 에서 뽑아쓸 수 있다 정도가 핵심일듯 싶다.

그리고 소개 페이지나 Guide 등에 보면 대부분 Fabric 중심으로 설명되어 있어서 사실 Ethereum 은 기존의 Blockchain Template 기능 정도를 재탕하여 해주지 않을까 생각이 든다

사용 가능한 상태가 되면 실제 사용해보고 (설마 돈내라는건 아니겠지..) 추가로 글을 써보도록 하겠다

%23%20Amazon%20Managed%20Blockchain%20%0A@%28220.Blockchain%29%5B%uBE14%uB85C%uADF8%2C%20%uC774%uB354%uB9AC%uC6C0%2C%20ethereum%2C%20aws%2C%20qldb%2C%20%uD2F0%uC2A4%uD1A0%uB9AC%5D%0A%0A11/28%uC77C%2C%20AWS%20%uC5D0%uC11C%20AWS%20Blockchain%20Template%20%uC5D0%20%uC774%uC5B4%20Amazon%20Managed%20Blockchain%20%uC11C%uBE44%uC2A4%uC640%20QLDB%20%uB97C%20%uC18C%uAC1C%uD558%uC600%uB2E4.%20%uC9C0%uAE08%20%uC2DC%uC810%uC5D0%uB294%20Preview%20%uC0C1%uD0DC%uC778%uB370%20%uC774%uB9C8%uC800%uB3C4%20Sign%20Up%20%uC744%20%uD574%uC57C%20%uD558%uAE30%uB294%20%uD558%uB2E4.%0A%0A%21%5BAlt%20text%5D%28./1543543140559.png%29%0A%21%5BAlt%20text%5D%28./1543542273179.png%29%0A%0A%uC77C%uB2E8%20Preview%20Signup%20%uC744%20%uD558%uACE0%uB098%uBA74%20%uC2DC%uAC04%uC774%20%uC880%20%uC9C0%uB0AC%uB354%uB2C8%20%uC544%uB798%20%uCC98%uB7FC%20%uBA54%uC77C%uC774%20%uC628%uB2E4%0A%0A%21%5BAlt%20text%5D%28./1543543183836.png%29%0A%0A%uC704%20%uBA54%uC77C%uC774%20%uC654%uB2E4%uACE0%20%uD574%uC11C%20Preview%20Applicant%20%uAC00%20%uB418%uC5C8%uB2E4%uB294%uAC8C%20%uC544%uB2C8%uB2E4.%20**%uAE30%uB2E4%uB824%uC57C%20%uD55C%uB2E4..**%0AApply%20%uB97C%20%uD588%uC9C0%uB9CC%20%uC774%uD2C0%20%uC9F8%20%uC544%uC9C1%20%uD68C%uC2E0%uC774%20%uC624%uAC70%uB098%20%uD558%uC9C0%20%uC54A%uB294%uB2E4%20%uADF8%uB0E5%20%uACC4%uC18D%20%uAE30%uB2E4%uB824%uC57C%20%uD55C%uB2E4.%0A%3E%20%uD639%uC2DC%uB098%20%uC0AC%uC6A9%20%uAC00%uB2A5%uD574%uC9C0%uBA74%20%uC368%uBCF4%uACE0%20%uBC14%uB85C%20%uB2E4%uC2DC%20%uAE00%uC744%20%uC62C%uB824%uBCF4%uACA0%uB2E4%0A%0A%23%23%20%uC5B4%uB514%uC5D0%20%uC788%uB098%0AAWS%20Console%20%uC5D0%20%uB4E4%uC5B4%uAC00%uBA74%20%uC544%uB798%20%uCC98%uB7FC%20Amazon%20Managed%20Blockchain%20%uC774%20%uC788%uB294%uAC78%20%uBCFC%20%uC218%20%uC788%uB2E4%0A%0A%21%5BAlt%20text%5D%28./1543543250433.png%29%0A%0A%uB9C8%uCE58%20%uB420%20%uAC83%20%uAC19%uC740%20%uB290%uB08C%uC774%uC9C0%uB9CC%20%uD074%uB9AD%uD558%uBA74%20%uB2E4%uC2DC%20Preview%20sign%20up%20%uD398%uC774%uC9C0%uB85C%20%uB118%uC5B4%uAC04%uB2E4%0A%0A%3E%20%uD604%uC7AC%20AMB%20Preview%20%uAC00%20%uC9C0%uC6D0%uB418%uB294%20Region%20%uC740%20**US%20East%20%28Virginia%29**%20%uBFD0%uC774%uB2E4%0A%3E%20%uD604%20%uC2DC%uC810%uC5D0%20QLDB%20%uBA54%uB274%uB294%20%uC5B4%uB514%uC5D0%20%uC788%uB294%uC9C0%20%uBC1C%uACAC%uD558%uC9C0%20%uBABB%uD558%uC600%uB2E4%0A%0A%23%23%20Amazon%20Managed%20Blockchain%0A%uC544%uC9C1%uC740%20%uB4E4%uC5B4%uAC00%uBCF4%uC9C0%uB3C4%20%uBABB%uD558%uACE0%20%uC790%uB8CC%uB3C4%20%uAC70%uC758%20%uC804%uBB34%uD55C%20%uC0C1%uD0DC%uC774%uBBC0%uB85C%2C%20%5BAWS%20%uC0C1%uC758%20%uC11C%uBE44%uC2A4%20%uC18C%uAC1C%20%uD398%uC774%uC9C0%5D%28https%3A//aws.amazon.com/ko/managed-blockchain/%29%uB97C%20%uCC38%uACE0%uD558%uC5EC%20%uC5B4%uB5A4%uAC83%uC778%uAC00%20%uC815%uB9AC%uD574%uB193%uACA0%uB2E4%0A%0A%23%23%23%20%uC804%uCCB4%20%uAD6C%uC131%0A%21%5BAlt%20text%5D%28./1543623032865.png%29%0A%0AAMB%20%uB294%20%uB3C5%uB9BD%uB41C%20Member%20%uBCC4%uB85C%20Peer%20Node%20%uB97C%20%uAD6C%uC131%uD558%uAC8C%20%uD558%uACE0%2C%20Ordering%20Service%20%uC640%20Client%20%uB97C%20Fabric%20Network%20%uC73C%uB85C%20%uC5F0%uACB0%uD574%uC8FC%uAE30%20%uC704%uD55C%20VPC%20Endpoint%20Service%20%uB4F1%uC740%20%uACF5%uC6A9%uD560%20%uC218%20%uC788%uB294%20%uCEF4%uD3EC%uB10C%uD2B8%20%uD615%uD0DC%uB85C%20%uC81C%uACF5%uD558%uB294%20%uAC83%uC73C%uB85C%20%uBCF4%uC778%uB2E4.%20%0A%0A%uC544%uB798%20%uAC00%uACA9%uD45C%uB97C%20%uBCF4%uC544%uB3C4%20%uC54C%uACA0%uC9C0%uB9CC%2C%20Ordering%20Service%20%uB97C%20%uC704%uD55C%20%uBCC4%uB3C4%uC758%20Node%20%uB294%20%uAD6C%uB9E4%uD558%uC9C0%20%uC54A%uB294%uB2E4.%20%uC774%uBD80%uBD84%uC740%20AWS%20%uC5D0%uC11C%20%uC81C%uACF5%uD558%uB294%20%uAC83%uC73C%uB85C%20%uBCF4%uC774%uBA70%2C%20%uB300%uC2E0%20Membership%20%uAE08%uC561%uC744%20%uC2DC%uAC04%uB2F9%uC73C%uB85C%20%uBC1B%uB294%20%uAC83%uC73C%uB85C%20%uC0DD%uAC01%uB41C%uB2E4%0A%0A%23%23%23%20Benefits%20%28%26Features%29%0A**Fully%20Managed**%0A-%20%uC5EC%uB7EC%20AWS%20%uACC4%uC815%uC5D0%20%uAC78%uCCD0%20Blockchain%20Network%20%uC744%20%uC27D%uAC8C%20%uC0DD%uC131%0A-%20%uBA64%uBC84%20%uADF8%uB8F9%uACFC%20Account%20%uC758%20Transaction%20%uC2E4%uD589%2C%20%uB370%uC774%uD130%20%uACF5%uC720%uB97C%20%uC124%uC815%0A-%20Infra%20%uC640%20S/W%20%uC124%uCE58%20%uB4F1%uC774%20%uD544%uC694%20%uC5C6%uB2E4%0A-%20%uBAA8%uB2C8%uD130%uB9C1%20%uAE30%uB2A5%20%uC81C%uACF5%uD55C%uB2E4%0A-%20%uBA64%uBC84%20%uCD94%uAC00%uC640%20%uC0AD%uC81C%uB97C%20%uC704%uD55C%20%uD22C%uD45C%20%uAE30%uB2A5%20API%uB97C%20%uC81C%uACF5%uD55C%uB2E4%0A%0A**Fabric%20%uACFC%20Ethereum%20%uC911%20%uC120%uD0DD**%0A-%20Privacy%20%uC640%20Permission%20%uC911%uC694%uD55C%20%uACF3%uC5D0%20Fabric%20%uCD94%uCC9C%0A-%20Transparency%20%uC640%20%uBD84%uC0B0%uD654%20%uC911%uC694%uD55C%20%uACF3%uC5D0%20Ethereum%20%uCD94%uCC9C%0A-%20Ethereum%20%uC740%20Public%20/%20Private%20Network%20%uC9C0%uC6D0%uD560%20%uAC83%uC73C%uB85C%20%uBCF4%uC784%0A%0A**Scalable%20and%20Secure**%0A-%20Peer%20node%20%uCD94%uAC00%uB97C%20%uC704%uD55C%20API%20%uB97C%20%uC81C%uACF5%0A-%20%uC6D0%uD558%uB294%20H/W%20spec%20%uC744%20%uC870%uD569%0A-%20AWS%20KMS%28Key%20Management%20System%29%uB97C%20%uD1B5%uD55C%20Key%20%uAD00%uB9AC%uB85C%20%uC548%uC804%0A%0A**Easily%20analyze%20Blockchain%20Activity**%20%28%uD5A5%uD6C4%20%uC608%uC815%29%0A-%20Blockchain%20network%20%uD65C%uB3D9%uC744%20QLDB%20%uC5D0%20%uC800%uC7A5%uD560%20%uC218%20%uC788%uC74C%0A-%20%uBCC0%uACBD%uB418%uAC70%uB098%20%uC0AD%uC81C%uB420%20%uC218%20%uC5C6%uB294%20%uD615%uD0DC%uB85C%20%uC601%uAD6C%uD788%20%uB0A8%uAC8C%uB428%0A-%20%uB204%uAC00%20Transaction%20%uC744%20%uBC1C%uC0DD%uD558%uC600%uB294%uC9C0%2C%20Transaction%20Rate%20%uC774%20%uC5B4%uB5BB%uAC8C%20%uB418%uB294%uC9C0%20%uB4F1%20Query%20%uAC00%uB2A5%0A%0A**Reliability**%0A-%20Ordering%20service%20%uC5D0%20QLDB%20%uB97C%20%uC811%uBAA9%2C%20Transaction%20%uC758%20Full%20History%20%uB97C%20%uC870%uD68C%20%uAC00%uB2A5%uD558%uB3C4%uB85D%20%uD568%0A%0A%23%23%23%20%uAC00%uACA9%0AN.%20Virginia%20Region%20%uC5D0%20%uB300%uD55C%20%uAC00%uACA9%uB9CC%20%uB098%uC640%uC788%uB294%20%uC0C1%uD669%uC73C%uB85C%2C%20%uC544%uB798%uC640%20%uAC19%uC774%20%5B%uAC00%uACA9%uD45C%5D%28https%3A//aws.amazon.com/ko/managed-blockchain/pricing/%29%uAC00%20%uB098%uC628%uB2E4%0A%0A**Membership**%0A-%20Starter%20Edition%20%3A%20%240.30/h%20%28337%uC6D0/%uC2DC%uAC04%29%0A%09-%20%uB124%uD2B8%uC6CC%uD06C%20%uC0C1%20%uCD5C%uB300%205%uAC1C%20%uBA64%uBC84%0A%09-%20%uBA64%uBC84%20%uB2F9%20%uCD5C%uB300%202%uAC1C%20Peer%20Node%0A%09-%20bc.t3.small%20%uB610%uB294%20medium%20%uD0C0%uC785%20Peer%20Node%20%uAC00%uB2A5%0A%09-%20%uCD5C%uB300%201%20TB%20%uC758%20Peer%20node%20storage%0A%09-%20Orderer%20%uC131%uB2A5%20%uC81C%uC57D%28Standard%20%uC5D0%20%uBE44%uD574%20%uB5A8%uC5B4%uC9D0.%20%uC218%uCE58%uB294%20%uC548%uB098%uC634%29%0A-%20Standard%20Edition%20%3A%20%240.55/h%20%28617%uC6D0/%uC2DC%uAC04%29%0A%09-%20%uB124%uD2B8%uC6CC%uD06C%20%uC0C1%20%uCD5C%uB300%2030%uAC1C%20%uBA64%uBC84%0A%09-%20%uBA64%uBC84%20%uB2F9%20%uCD5C%uB300%2010%uAC1C%20Peer%20Node%0A%09-%20bc.t3%2C%20bc.m5%2C%20bc.c5%20%uD0C0%uC785%20Peer%20Node%20%uAC00%uB2A5%0A%09-%20%uCD5C%uB300%2015%20TB%20%uC758%20Peer%20node%20storage%0A%0A**On%20Demand%20peer%20node%20pricing**%0A%0A%21%5BAlt%20text%5D%28./1543623968662.png%29%0A%0A-%2038%20%uC6D0%20%7E%201%2C220%20%uC6D0%20/%20%uC2DC%uAC04%0A%0A**Peer%20node%20storage**%0A%uCD5C%uC18C%2010GB%20%uBD80%uD130%20%uCD5C%uB300%2015TB%20%uAE4C%uC9C0%20%uC120%uD0DD%uD560%20%uC218%20%uC788%uC74C%0A-%20%240.10%20/%20%uC6D4%20%28112%uC6D0/%uC6D4%29%0A%0A**Data%20Written**%0AFabric%20Network%20%uC5D0%20Write%20%uB418%uB294%20%uBAA8%uB4E0%20Transaction%20Payload%20%uB97C%20%uD3EC%uD568%uD55C%20Data%20%uCD1D%uB7C9%0A-%20%240.10%20/%20GB%20%28112%uC6D0/GB%29%0A%0A**%uAC00%uACA9%20%uC608%uC2DC**%0A%0A%u2738%20Starter%20Edition%20%uAE30%uC900%uC73C%uB85C%20%uC544%uB798%uC640%20%uAC19%uC774%20%uC138%uD305%20%uD55C%uB2E4%uACE0%20%uD558%uC790%0A%3E%202%20%uAC1C%20Starter%20Member%0A%3E%20%uAC01%20%uBA64%uBC84%uAC00%20bc.t3.small%201%uAC1C%uC529%20%uC6B4%uC601%0A%3E%2020GB%20Storage%20%0A%3E%20%uC2DC%uAC04%uB2F9%209MB%20%uC758%20Network%20%uC0AC%uC6A9%0A%0A%21%5BAlt%20text%5D%28./1543627868394.png%29%0A%0A%uC704%20Spec%20%uC774%uBA74%20**%uAC04%uB2E8%uD55C%20%uB0B4%uBD80%20PoC%20%uC815%uB3C4**%uAC00%20%uAC00%uB2A5%uD55C%20%uC0AC%uC591%uC774%uB77C%uACE0%20%uBD10%uC57C%20%uD558%uACA0%uB2E4.%20%uC74C..%20%uC0AC%uC2E4%20PoC%20%uB97C%20%uC704%uD55C%20%uAC1C%uBC1C%20%uC815%uB3C4%3F%0A%0A%u2738%20Standard%20Edition%20%uC73C%uB85C%20%uAC00%uBCF4%uC790.%20%uC0C1%uC6A9%uC5D0%uC11C%uB294%20%uC790%uC2E0%uC758%20Org%20%uC5D0%20%uB300%uD55C%20%uBE44%uC6A9%uB9CC%20%uB0B4%uB294%20%uACBD%uC6B0%uAC00%20%uB9CE%uC740%uAC83%uC774%uBBC0%uB85C%20%uC544%uB798%uC640%20%uAC19%uC774%20%uAD6C%uC131%uD588%uB2E4%uACE0%20%uAC00%uC815%uD55C%uB2E4%0A%0A%3E%201%20%uAC1C%20Standard%20Member%0A%3E%203%20%uAC1C%20Peer%20Node%20%28m5.2xlarge%29%0A%3E%20Node%20%uB2F9%201TB%20Storage%0A%3E%20%uC2DC%uAC04%uB2F9%20200MB%20Network%20%uC0AC%uC6A9%0A%21%5BAlt%20text%5D%28./1543628282848.png%29%0A%0A%uC704%20Spec%20%uC774%uBA74%20**%uC0C1%uC6A9%20%uC11C%uBE44%uC2A4%uB97C%20%uC704%uD55C%20%uAD6C%uC131**%20%uC73C%uB85C%20%uC54C%uB9DE%uB294%uB2E4%uACE0%20%uBCF8%uB2E4.%20Offchain%20%uC2DC%uC2A4%uD15C%uC744%20%uC704%uD55C%20%uBD80%uBD84%uC740%20%uCD94%uAC00%uB85C%20%uAC16%uCD94%uC5B4%uC838%uC57C%20%uD55C%uB2E4.%0A%0A%uC774%uC0C1%uC774%20AMB%28Amazon%20Managed%20Blockchain%29%20%uC758%20%uC18C%uAC1C%20%uC774%uB2E4.%20%uB300%uB7B5%20%uC5B4%uB5A4%20%uC11C%uBE44%uC2A4%uAC00%20%uAC00%uB2A5%uD55C%uC9C0%20%uAC10%uC774%20%uC628%uB2E4.%20**%uC124%uCE58%uC640%20%uC124%uC815%uC744%20%uC704%uD55C%20%uB178%uAC00%uB2E4%uAC00%20%uC904%uC5B4%uB4E4%uACE0%2C%20%uBAA8%uB2C8%uD130%uB9C1%20%uAE30%uB2A5%uC774%20%uCD94%uAC00%uB420%20%uAC83%uC774%uACE0%2C%20Key%20%uC800%uC7A5%uC744%20%uC548%uC804%uD558%uAC8C%20%uD574%uC8FC%uACE0%2C%20QLDB%20%uB97C%20%uD65C%uC6A9%uD558%uC5EC%20%uBAA8%uB4E0%20Transaction%20%uACFC%20Activity%20%uAC00%20%uC800%uC7A5%uB418%uB2C8%20%uC758%uBBF8%uC788%uB294%20%uB370%uC774%uD130%uB97C%20QLDB%20%uC5D0%uC11C%20%uBF51%uC544%uC4F8%20%uC218%20%uC788%uB2E4**%20%uC815%uB3C4%uAC00%20%uD575%uC2EC%uC77C%uB4EF%20%uC2F6%uB2E4.%20%0A%0A%uADF8%uB9AC%uACE0%20%uC18C%uAC1C%20%uD398%uC774%uC9C0%uB098%20Guide%20%uB4F1%uC5D0%20%uBCF4%uBA74%20%uB300%uBD80%uBD84%20Fabric%20%uC911%uC2EC%uC73C%uB85C%20%uC124%uBA85%uB418%uC5B4%20%uC788%uC5B4%uC11C%20%uC0AC%uC2E4%20Ethereum%20%uC740%20%uAE30%uC874%uC758%20%20Blockchain%20Template%20%uAE30%uB2A5%20%uC815%uB3C4%uB97C%20%uC7AC%uD0D5%uD558%uC5EC%20%uD574%uC8FC%uC9C0%20%uC54A%uC744%uAE4C%20%uC0DD%uAC01%uC774%20%uB4E0%uB2E4%0A%0A%uC0AC%uC6A9%20%uAC00%uB2A5%uD55C%20%uC0C1%uD0DC%uAC00%20%uB418%uBA74%20%uC2E4%uC81C%20%uC0AC%uC6A9%uD574%uBCF4%uACE0%20%28%uC124%uB9C8%20%uB3C8%uB0B4%uB77C%uB294%uAC74%20%uC544%uB2C8%uACA0%uC9C0..%29%20%uCD94%uAC00%uB85C%20%uAE00%uC744%20%uC368%uBCF4%uB3C4%uB85D%20%uD558%uACA0%uB2E4%0A%0A

반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,
Edit

Multisig Wallet #1

Ethereum multisigwallet ethereum

Multisig Wallet 을 구현해보자. 블록체인의 응용을 이야기 하거나 할 때 빠지지 않는 단골 메뉴이기도 한 Multi Signature 를 활용하는 Wallet 을 만들어 보고, gnosis, consensys 애들이 만든 Multisign Wallet 은 어떤 구조를 갖고 있는지도 봐보는 재미진 시간을 가져보자

Blockchain 의 Wallet

일단 Wallet 의 개념은 다 알것이다. 특히 Blockchain 의 Wallet 또한 모두 잘 알 것이다. Blockchain 의 Wallet 은

  • Key Pair (Private / Public Key) 를 생성하여 안전하게 보관
  • Transaction 을 생성하고 여기에 본인의 전자서명을 첨부 (보통 Transaction 의 Hash 값을 원문으로 함)
  • Account 기반의 State Model 인 경우, Account Nonce 를 관리

를 기본 기능으로 가지며, 추가적으로

  • 복수의 계좌(Account)를 생성/관리 하는 HD Wallet 의 경우 KDF(Key Derivation Function)를 통한 루트 키와 Derived Key 관리
  • Mnemonic 기반의
  • Web 기반 dApp 실행을 위한 Web View 와 web3.js 등의 JS Injection
  • (Ethereum) ERC 20 기반의 Token 및 기타 EIP 제안 중 널리 쓰이는 ERC 지원(ERC721 등)

등의 기능을 가지는 Wallet 들이 많아지고 있다.

Wallet 에 관해서는 이번 주제 끝나고 다음에 한번 상세히 다루어 보도록 하겠다
HD Wallet 이나 Cold Wallet 에 대해서도 재미난 것들이 많이 있으니 그때 또~

일반 Crypto Wallet 의 Transfer Transaction

Multisig Wallet 은 Crypto Wallet 자체에서 지원하는 기능은 아니다. UTXO 내의 Script 혹은 Smart Contract 의 코드로 Blockchain 내에 존재한다.

일단 아래는 단순화 된 일반적인 Wallet 의 Transfer 과정이다

그림을 단순화 해서 그렇지 Wallet 내부에서는 아래와 같은 과정을 거친다

  1. (secp256k1 으로 Private Key 는 이미 생성 되었다고 가정한다. 즉, 주소는 이미 생성 되었다고 가정한다)
  2. ECDSA 전자서명이 붙지 않은, 100 Ether 를 Value 로 하는 Raw Transaction 을 구성한다
  3. Raw Transaction 의 keccak256 Hash 를 원문으로 한 ECDSA 전자서명 값 r,s,v 를 추가하여 Transaction 을 만든다
  4. Wallet 서비스를 하는 Gateway 를 거치거나 혹은 직접 Node 에게(이런경우는 흔치 않다) Transaction 을 Submit 한다
  5. 100 Ether 는 to address 에 해당하는 Account 의 State 에 더해진다

UTXO 기반 모델의 Blockchain 도 Wallet 의 기능은 마찬가지이다

Multisig Wallet 의 Transfer Transaction

일반적으로 Multisig Wallet 은 2개 이상의 서명이 있어야 실제 Token 의 이체가 일어나게 할 수 있는 기능을 갖는 Wallet 을 말한다.

Bitcoin Wallet 개발하시는 분들은 Multisig Wallet 하면, Wallet 에서 생성한 Tx(Transaction) 내 Output 의 Locking Script(Pubkey Script) 부분에 OP_CHECKMULTISIG 를 포함하도록 만드는 것을 생각 할 수 있겠다.

Ethereum 과 같이 Smart Contract 를 지원하는 블록체인의 경우는 좀더 세련된 방식으로 Multisig Wallet 을 만든다. 또한, Token Asset 의 이체를 위한 Transfer Transaction 뿐만이 아니라 Smart Contract 실행을 위한 Message Transaction 또한 조건을 만족하는 복수개의 서명이 Submit 되었을때에만 실행되게 할 수 있다(보통 이렇게 만든다).

왜 갑자기 Wallet 얘기를 하는데 Smart Contract 얘기가 나오는가 할 수도 있다. 예전부터 많은 사람들이 이부분을 헷갈려 한다는걸 느꼈다. Multisig Wallet 은 결국 내가 제출한 Transaction 에 대해, 미리 지정된 복수의 Account Owner 가 전자서명을 통해 허락해야지만 실제로 그 Transaction 이 실행되어야 하는 규칙 이다.

이러한 규칙은 Wallet App 에 구현되고 저장되는 경우 충분히 위변조 될 수 있으며 중요한 돈거래의 경우 보안성과 범용성의 측면에서 뭐하나 이로울게 없다. 그 얘기는, 블록체인 기술과 Smart Contract 의 필요성이 가장 강한 형태의 dApp 중 하나가 바로 Multisig Wallet 인 것이다.

아래의 Diagram 은 Multisig Wallet 의 동작을 단순화 해본 그림이다
상황은 0xa0c9… 주소를 갖는 EOA 가 0x039b… 에게 100 Ether 를 이체하려고 하며, 이때 미리 지정한 0x0248… EOA 의 최종 승인 이 있어야지만 실제로 100 Ether 가 0x039b… 에게 이체되는 Transaction 이 실행되게 해야 한다.

구성요소

  • Wallet - Account 소유자가 설치한 Browser Plug-in, Desktop, Mobile 용의 Wallet App (Metamask, MEW, Jaxx, Exodus …) 이거나 Smart Contract 실행을 위한 Message Transaction 을 만들어낼 수 있는 어떠한 dApp 도 될 수 있다
  • Multisig Wallet Contract
    • 이체하고자 하는 Token 을 보관
    • 제출 된 Transaction 실행 요건 지정 (n of m 개의 전자서명 요구와 같은)
    • 전자서명 주체가 되는 Wallet Owner 들의 등록 및 관리
    • Transaction 제출 알림
    • 요건을 만족한 경우 Transaction 의 실제 실행

이외에도 Wallet 앱을 개발하고 서비스 하는 회사의 경우, 아무나 자신들이 운영하는 Node 에 수많은 Transaction 을 날려 DoS Attack 을 하거나 부하를 일으키지 않도록 하고 부가적인 서비스를 제공하기위한 목적으로 Wallet Service Gateway 를 둘 수도 있겠지만 Offchain 시스템은 모두 생략하였다

위 구성요소의 설명을 보면 알겠지만 핵심은 Multisig Wallet Contract 이다. Multisig Wallet의 모든 핵심 기능은 이 Contract 에서 이루어진다. 예전에 문제가 된 Parity 의 Multisig Wallet 도 물론 Smart Contract 이다.

흐름

위 Multisig Wallet Contract 를 사용하는 흐름을 보면 간단하다 하지만 이전 글에서는 다루지 않았던 새로운 요소가 하나 등장한다

  1. submitTransaction
    submitTranaction() 을 실행하기 위한 Message Transaction 의 Parameter 를 이용하여 실제 Token(Ether) 을 받을 주소를 넣어준다

    이때, Token 을 받을 대상이 다른 Smart Contract 이고 Transaction 종류가 Message Transaction 인 경우, submitTransaction() 의 파라미터 중 하나에 실행해야 하는 Smart Contract 의 Method 와 파라미터를 포함하는 Data Payload 를 넣어준다 (web3 의 .getData() 사용)

    추가적으로, 예의상 submitTransaction() 이 되면 Event 로 transaction 이 submit 되었다고 알려주는 센스 정도는 설명하지 않아도 구현 되어야 한다고 느낌이 올 것이다

이부분은 구현 부분에서 설명하겠다. 향후 CALL, CALLCODE, DELEGATECALL 과 관련 있는 부분이니 그때 또 설명 하겠다 (음.. 오랜만이 시작하려니 설명할게 산더미같다..)

  1. confirmTransaction
    위 submitTransaction() 으로 제출 된 Transaction 을 승인 하는 단계이다. Contract 에 등록된 승인 권한이 있는 EOA 가 confirmTransaction() 을 통해 confirm 해주면 된다. 이때, 각 confirm 시 마다 등록된 조건(최소 n 개의 confirm 필요)을 만족하는 confirm 을 받았는지 check 한다

  2. executeTransaction
    confirmTransaction() 실행 시 만족하는 confirm 수가 채워졌으면 submitTransaction() 시에 제출 된 token 의 양 만큼을 원래 보내고자 했던 주소로 보내주도록 Transaction 의 value 값을 채우며, submitTransaction() 단계에서 제출 된 Message Transaction 이 있었다면 Wallet Contract 가(msg.sender == Wallet Contract) 해당 Message Transaction 을 실행한다

Multisig 인데, 서명은 언제하는가?

전에 Multisig Wallet 에 대해 차분히 설명 해주고 나서 들었던 질문이 있었다. “그런데 다른사람들(EOA)이 전자서명은 언제 해줘요?” 전자서명은 이미 Smart Contract 를 실행하는 submitTransaction(), confirmTransaction() 단계에서 Message Transaction 을 보내기 위해 Raw Transaction 에 대고 다 했다. 그래야 Transaction 이 submit 되었지 않겠는가..요.. 라고 답을 해줬던 기억이 난다.

(단, Smart Contract 이 internal call 을 하는 구간에는 전자서명이 당연히 없다. EOA 에서 이미 했지않은가. Smart Contract 는 서명할 수 있는 놈이 아니다. Smart Contract 을 실행한 놈이 이미 전자서명을 해서 Message Transaction 을 보낸 것이다)

이름이 문제다. Multisig.. 사실 confirmTransaction() 단계에서 파라미터로 메시지와 전자서명값 r,s,v 를 넣어줄 수도 있다. 그러나 다른 EOA 의 전자서명을 전달하는 상황이 아니고 confirmTransaction() 을 실행하는 주체 자체가 승인 권한을 가진 EOA 이므로 이미 transaction 내에 들어있는 전자서명을 Multisig Wallet Contract 의 파라미터로 보낼 이유가 없는 것이다

마치며

오랜만에 올리는 글 치고는 매우 기본적인 주제를 올려본다. 사실 0xProtocol, Plasma, Raiden, ERC20 Token 기반으로 돌아가는 dApp 만들기, plasma-mvp … 또는 Enterprise Blockchain, Quorum 등등 무엇부터 시작할까를 많이 고민해보았다.

그리고 이전에 올렸던 글들을 다시 훑어보다가, 블로그의 흐름이 갑자기 끊기는것 보다는 이전의 Context 를 이어나아가면서 좀더 빠르게 진행해보는 것으로 일단 마음을 먹어본다. (그래도 기본은 기본대로 가고, 중간중간 발표자료도 좀 올리고, 이런저런 구현 샘플들도 짬짬이 올리겠다^^;;)

다음은 Multisig Wallet 구현 예제를 1회 정도 올리고 퀵하게 마무리 하고 또 그 다음으로 넘어가 보도록 하는걸 목표로 해보겠다

%23%20Multisig%20Wallet%20%231%0A@%28220.Blockchain%29%5B%uC774%uB354%uB9AC%uC6C0%2C%20Ethereum%2C%20%uD2F0%uC2A4%uD1A0%uB9AC%2C%20multisigwallet%2C%20ethereum%5D%0A%0A%3Cimg%20src%3D%22./1543316979811.png%22%20width%3D%22300%22%20align%3D%22middle%22%20/%3E%0A%0AMultisig%20Wallet%20%uC744%20%uAD6C%uD604%uD574%uBCF4%uC790.%20%uBE14%uB85D%uCCB4%uC778%uC758%20%uC751%uC6A9%uC744%20%uC774%uC57C%uAE30%20%uD558%uAC70%uB098%20%uD560%20%uB54C%20%uBE60%uC9C0%uC9C0%20%uC54A%uB294%20%uB2E8%uACE8%20%uBA54%uB274%uC774%uAE30%uB3C4%20%uD55C%20Multi%20Signature%20%uB97C%20%uD65C%uC6A9%uD558%uB294%20Wallet%20%uC744%20%uB9CC%uB4E4%uC5B4%20%uBCF4%uACE0%2C%20gnosis%2C%20consensys%20%uC560%uB4E4%uC774%20%uB9CC%uB4E0%20Multisign%20Wallet%20%uC740%20%uC5B4%uB5A4%20%uAD6C%uC870%uB97C%20%uAC16%uACE0%20%uC788%uB294%uC9C0%uB3C4%20%uBD10%uBCF4%uB294%20%uC7AC%uBBF8%uC9C4%20%uC2DC%uAC04%uC744%20%uAC00%uC838%uBCF4%uC790%20%0A%0A%23%23%20Blockchain%20%uC758%20Wallet%0A%uC77C%uB2E8%20Wallet%20%uC758%20%uAC1C%uB150%uC740%20%uB2E4%20%uC54C%uAC83%uC774%uB2E4.%20%uD2B9%uD788%20Blockchain%20%uC758%20Wallet%20%uB610%uD55C%20%uBAA8%uB450%20%uC798%20%uC54C%20%uAC83%uC774%uB2E4.%20Blockchain%20%uC758%20Wallet%20%uC740%20%0A-%20Key%20Pair%20%28Private%20/%20Public%20Key%29%20%uB97C%20%uC0DD%uC131%uD558%uC5EC%20%uC548%uC804%uD558%uAC8C%20%uBCF4%uAD00%0A-%20Transaction%20%uC744%20%uC0DD%uC131%uD558%uACE0%20%uC5EC%uAE30%uC5D0%20%uBCF8%uC778%uC758%20%uC804%uC790%uC11C%uBA85%uC744%20%uCCA8%uBD80%20%28%uBCF4%uD1B5%20Transaction%20%uC758%20Hash%20%uAC12%uC744%20%uC6D0%uBB38%uC73C%uB85C%20%uD568%29%0A-%20Account%20%uAE30%uBC18%uC758%20State%20Model%20%uC778%20%uACBD%uC6B0%2C%20Account%20Nonce%20%uB97C%20%uAD00%uB9AC%0A%0A%uB97C%20%uAE30%uBCF8%20%uAE30%uB2A5%uC73C%uB85C%20%uAC00%uC9C0%uBA70%2C%20%uCD94%uAC00%uC801%uC73C%uB85C%0A-%20%uBCF5%uC218%uC758%20%uACC4%uC88C%28Account%29%uB97C%20%uC0DD%uC131/%uAD00%uB9AC%20%uD558%uB294%20HD%20Wallet%20%uC758%20%uACBD%uC6B0%20KDF%28Key%20Derivation%20Function%29%uB97C%20%uD1B5%uD55C%20%uB8E8%uD2B8%20%uD0A4%uC640%20Derived%20Key%20%uAD00%uB9AC%20%0A-%20Mnemonic%20%uAE30%uBC18%uC758%20%0A-%20Web%20%uAE30%uBC18%20dApp%20%uC2E4%uD589%uC744%20%uC704%uD55C%20Web%20View%20%uC640%20web3.js%20%uB4F1%uC758%20JS%20Injection%0A-%20%28Ethereum%29%20ERC%2020%20%uAE30%uBC18%uC758%20Token%20%uBC0F%20%uAE30%uD0C0%20EIP%20%uC81C%uC548%20%uC911%20%uB110%uB9AC%20%uC4F0%uC774%uB294%20ERC%20%uC9C0%uC6D0%28ERC721%20%uB4F1%29%0A%0A%uB4F1%uC758%20%uAE30%uB2A5%uC744%20%uAC00%uC9C0%uB294%20Wallet%20%uB4E4%uC774%20%uB9CE%uC544%uC9C0%uACE0%20%uC788%uB2E4.%0A%0A%3E%20Wallet%20%uC5D0%20%uAD00%uD574%uC11C%uB294%20%uC774%uBC88%20%uC8FC%uC81C%20%uB05D%uB098%uACE0%20%uB2E4%uC74C%uC5D0%20%uD55C%uBC88%20%uC0C1%uC138%uD788%20%uB2E4%uB8E8%uC5B4%20%uBCF4%uB3C4%uB85D%20%uD558%uACA0%uB2E4%0A%3E%20HD%20Wallet%20%uC774%uB098%20Cold%20Wallet%20%uC5D0%20%uB300%uD574%uC11C%uB3C4%20%uC7AC%uBBF8%uB09C%20%uAC83%uB4E4%uC774%20%uB9CE%uC774%20%uC788%uC73C%uB2C8%20%uADF8%uB54C%20%uB610%7E%0A%0A%23%23%23%20%uC77C%uBC18%20Crypto%20Wallet%20%uC758%20Transfer%20Transaction%0AMultisig%20Wallet%20%uC740%20Crypto%20Wallet%20%uC790%uCCB4%uC5D0%uC11C%20%uC9C0%uC6D0%uD558%uB294%20%uAE30%uB2A5%uC740%20%uC544%uB2C8%uB2E4.%20UTXO%20%uB0B4%uC758%20Script%20%uD639%uC740%20Smart%20Contract%20%uC758%20%uCF54%uB4DC%uB85C%20Blockchain%20%uB0B4%uC5D0%20%uC874%uC7AC%uD55C%uB2E4.%0A%0A%uC77C%uB2E8%20%uC544%uB798%uB294%20%uB2E8%uC21C%uD654%20%uB41C%20%uC77C%uBC18%uC801%uC778%20Wallet%20%uC758%20Transfer%20%uACFC%uC815%uC774%uB2E4%0A%0A%3Cimg%20src%3D%22./multisig00.png%22%20width%3D%22600%22/%3E%0A%0A%uADF8%uB9BC%uC744%20%uB2E8%uC21C%uD654%20%uD574%uC11C%20%uADF8%uB807%uC9C0%20Wallet%20%uB0B4%uBD80%uC5D0%uC11C%uB294%20%uC544%uB798%uC640%20%uAC19%uC740%20%uACFC%uC815%uC744%20%uAC70%uCE5C%uB2E4%0A1.%20%28secp256k1%20%uC73C%uB85C%20Private%20Key%20%uB294%20%uC774%uBBF8%20%uC0DD%uC131%20%uB418%uC5C8%uB2E4%uACE0%20%uAC00%uC815%uD55C%uB2E4.%20%uC989%2C%20%uC8FC%uC18C%uB294%20%uC774%uBBF8%20%uC0DD%uC131%20%uB418%uC5C8%uB2E4%uACE0%20%uAC00%uC815%uD55C%uB2E4%29%0A2.%20ECDSA%20%uC804%uC790%uC11C%uBA85%uC774%20%uBD99%uC9C0%20%uC54A%uC740%2C%20100%20Ether%20%uB97C%20Value%20%uB85C%20%uD558%uB294%20Raw%20Transaction%20%uC744%20%uAD6C%uC131%uD55C%uB2E4%0A3.%20Raw%20Transaction%20%uC758%20keccak256%20Hash%20%uB97C%20%uC6D0%uBB38%uC73C%uB85C%20%uD55C%20ECDSA%20%uC804%uC790%uC11C%uBA85%20%uAC12%20r%2Cs%2Cv%20%uB97C%20%uCD94%uAC00%uD558%uC5EC%20Transaction%20%uC744%20%uB9CC%uB4E0%uB2E4%0A4.%20Wallet%20%uC11C%uBE44%uC2A4%uB97C%20%uD558%uB294%20Gateway%20%uB97C%20%uAC70%uCE58%uAC70%uB098%20%uD639%uC740%20%uC9C1%uC811%20Node%20%uC5D0%uAC8C%28%uC774%uB7F0%uACBD%uC6B0%uB294%20%uD754%uCE58%20%uC54A%uB2E4%29%20Transaction%20%uC744%20Submit%20%uD55C%uB2E4%0A5.%20100%20Ether%20%uB294%20**to**%20address%20%uC5D0%20%uD574%uB2F9%uD558%uB294%20Account%20%uC758%20State%20%uC5D0%20%uB354%uD574%uC9C4%uB2E4%0A%0AUTXO%20%uAE30%uBC18%20%uBAA8%uB378%uC758%20Blockchain%20%uB3C4%20Wallet%20%uC758%20%uAE30%uB2A5%uC740%20%uB9C8%uCC2C%uAC00%uC9C0%uC774%uB2E4%0A%0A%23%23%20Multisig%20Wallet%20%uC758%20Transfer%20Transaction%0A%uC77C%uBC18%uC801%uC73C%uB85C%20Multisig%20Wallet%20%uC740%202%uAC1C%20%uC774%uC0C1%uC758%20%uC11C%uBA85%uC774%20%uC788%uC5B4%uC57C%20%uC2E4%uC81C%20Token%20%uC758%20%uC774%uCCB4%uAC00%20%uC77C%uC5B4%uB098%uAC8C%20%uD560%20%uC218%20%uC788%uB294%20**%uAE30%uB2A5**%uC744%20%uAC16%uB294%20Wallet%20%uC744%20%uB9D0%uD55C%uB2E4.%20%0A%0ABitcoin%20Wallet%20%uAC1C%uBC1C%uD558%uC2DC%uB294%20%uBD84%uB4E4%uC740%20Multisig%20Wallet%20%uD558%uBA74%2C%20Wallet%20%uC5D0%uC11C%20%uC0DD%uC131%uD55C%20Tx%28Transaction%29%20%uB0B4%20Output%20%uC758%20Locking%20Script%28Pubkey%20Script%29%20%uBD80%uBD84%uC5D0%20OP_CHECKMULTISIG%20%uB97C%20%uD3EC%uD568%uD558%uB3C4%uB85D%20%uB9CC%uB4DC%uB294%20%uAC83%uC744%20%uC0DD%uAC01%20%uD560%20%uC218%20%uC788%uACA0%uB2E4.%20%0A%0AEthereum%20%uACFC%20%uAC19%uC774%20Smart%20Contract%20%uB97C%20%uC9C0%uC6D0%uD558%uB294%20%uBE14%uB85D%uCCB4%uC778%uC758%20%uACBD%uC6B0%uB294%20%uC880%uB354%20%uC138%uB828%uB41C%20%uBC29%uC2DD%uC73C%uB85C%20Multisig%20Wallet%20%uC744%20%uB9CC%uB4E0%uB2E4.%20%uB610%uD55C%2C%20Token%20Asset%20%uC758%20%uC774%uCCB4%uB97C%20%uC704%uD55C%20Transfer%20Transaction%20%uBFD0%uB9CC%uC774%20%uC544%uB2C8%uB77C%20Smart%20Contract%20%uC2E4%uD589%uC744%20%uC704%uD55C%20Message%20Transaction%20%uB610%uD55C%20%uC870%uAC74%uC744%20%uB9CC%uC871%uD558%uB294%20**%uBCF5%uC218%uAC1C%uC758%20%uC11C%uBA85**%uC774%20Submit%20%uB418%uC5C8%uC744%uB54C%uC5D0%uB9CC%20%uC2E4%uD589%uB418%uAC8C%20%uD560%20%uC218%20%uC788%uB2E4%28%uBCF4%uD1B5%20%uC774%uB807%uAC8C%20%uB9CC%uB4E0%uB2E4%29.%0A%0A%uC65C%20%uAC11%uC790%uAE30%20Wallet%20%uC598%uAE30%uB97C%20%uD558%uB294%uB370%20Smart%20Contract%20%uC598%uAE30%uAC00%20%uB098%uC624%uB294%uAC00%20%uD560%20%uC218%uB3C4%20%uC788%uB2E4.%20%uC608%uC804%uBD80%uD130%20%uB9CE%uC740%20%uC0AC%uB78C%uB4E4%uC774%20%uC774%uBD80%uBD84%uC744%20%uD5F7%uAC08%uB824%20%uD55C%uB2E4%uB294%uAC78%20%uB290%uAF08%uB2E4.%20Multisig%20Wallet%20%uC740%20%uACB0%uAD6D%20**%uB0B4%uAC00%20%uC81C%uCD9C%uD55C%20Transaction%20%uC5D0%20%uB300%uD574%2C%20%uBBF8%uB9AC%20%uC9C0%uC815%uB41C%20%uBCF5%uC218%uC758%20Account%20Owner%20%uAC00%20%uC804%uC790%uC11C%uBA85%uC744%20%uD1B5%uD574%20%uD5C8%uB77D**%uD574%uC57C%uC9C0%uB9CC%20%uC2E4%uC81C%uB85C%20%uADF8%20Transaction%20%uC774%20%uC2E4%uD589%uB418%uC5B4%uC57C%20%uD558%uB294%20**%uADDC%uCE59**%20%uC774%uB2E4.%0A%0A%uC774%uB7EC%uD55C%20**%uADDC%uCE59**%uC740%20Wallet%20App%20%uC5D0%20%uAD6C%uD604%uB418%uACE0%20%uC800%uC7A5%uB418%uB294%20%uACBD%uC6B0%20%uCDA9%uBD84%uD788%20%uC704%uBCC0%uC870%20%uB420%20%uC218%20%uC788%uC73C%uBA70%20%uC911%uC694%uD55C%20%uB3C8%uAC70%uB798%uC758%20%uACBD%uC6B0%20%uBCF4%uC548%uC131%uACFC%20%uBC94%uC6A9%uC131%uC758%20%uCE21%uBA74%uC5D0%uC11C%20%uBB50%uD558%uB098%20%uC774%uB85C%uC6B8%uAC8C%20%uC5C6%uB2E4.%20%uADF8%20%uC598%uAE30%uB294%2C%20%uBE14%uB85D%uCCB4%uC778%20%uAE30%uC220%uACFC%20Smart%20Contract%20%uC758%20%uD544%uC694%uC131%uC774%20%uAC00%uC7A5%20%uAC15%uD55C%20%uD615%uD0DC%uC758%20dApp%20%uC911%20%uD558%uB098%uAC00%20%uBC14%uB85C%20Multisig%20Wallet%20%uC778%20%uAC83%uC774%uB2E4.%0A%0A%uC544%uB798%uC758%20Diagram%20%uC740%20Multisig%20Wallet%20%uC758%20%uB3D9%uC791%uC744%20%uB2E8%uC21C%uD654%20%uD574%uBCF8%20%uADF8%uB9BC%uC774%uB2E4%0A%uC0C1%uD669%uC740%200xa0c9...%20%uC8FC%uC18C%uB97C%20%uAC16%uB294%20EOA%20%uAC00%200x039b...%20%uC5D0%uAC8C%20100%20Ether%20%uB97C%20%uC774%uCCB4%uD558%uB824%uACE0%20%uD558%uBA70%2C%20%uC774%uB54C%20%uBBF8%uB9AC%20%uC9C0%uC815%uD55C%200x0248...%20EOA%20%uC758%20%uCD5C%uC885%20**%uC2B9%uC778**%20%uC774%20%uC788%uC5B4%uC57C%uC9C0%uB9CC%20%uC2E4%uC81C%uB85C%20100%20Ether%20%uAC00%200x039b...%20%uC5D0%uAC8C%20%uC774%uCCB4%uB418%uB294%20Transaction%20%uC774%20%uC2E4%uD589%uB418%uAC8C%20%uD574%uC57C%20%uD55C%uB2E4.%0A%0A%3Cimg%20src%3D%22./multisig01.png%22%20width%3D%22600%22%20/%3E%0A%0A%23%23%23%20%uAD6C%uC131%uC694%uC18C%0A-%20**Wallet**%20-%20Account%20%uC18C%uC720%uC790%uAC00%20%uC124%uCE58%uD55C%20Browser%20Plug-in%2C%20Desktop%2C%20Mobile%20%uC6A9%uC758%20Wallet%20App%20%28Metamask%2C%20MEW%2C%20Jaxx%2C%20Exodus%20...%29%20%20%uC774%uAC70%uB098%20Smart%20Contract%20%uC2E4%uD589%uC744%20%uC704%uD55C%20Message%20Transaction%20%uC744%20%uB9CC%uB4E4%uC5B4%uB0BC%20%uC218%20%uC788%uB294%20%uC5B4%uB5A0%uD55C%20dApp%20%uB3C4%20%uB420%20%uC218%20%uC788%uB2E4%0A-%20**Multisig%20Wallet%20Contract**%0A%09-%20%uC774%uCCB4%uD558%uACE0%uC790%20%uD558%uB294%20Token%20%uC744%20%uBCF4%uAD00%0A%09-%20%uC81C%uCD9C%20%uB41C%20Transaction%20%uC2E4%uD589%20%uC694%uAC74%20%uC9C0%uC815%20%28n%20of%20m%20%uAC1C%uC758%20%uC804%uC790%uC11C%uBA85%20%uC694%uAD6C%uC640%20%uAC19%uC740%29%0A%09-%20%uC804%uC790%uC11C%uBA85%20%uC8FC%uCCB4%uAC00%20%uB418%uB294%20Wallet%20Owner%20%uB4E4%uC758%20%uB4F1%uB85D%20%uBC0F%20%uAD00%uB9AC%0A%09-%20Transaction%20%uC81C%uCD9C%20%uC54C%uB9BC%0A%09-%20%uC694%uAC74%uC744%20%uB9CC%uC871%uD55C%20%uACBD%uC6B0%20Transaction%20%uC758%20%uC2E4%uC81C%20%uC2E4%uD589%0A%0A%3E%uC774%uC678%uC5D0%uB3C4%20Wallet%20%uC571%uC744%20%uAC1C%uBC1C%uD558%uACE0%20%uC11C%uBE44%uC2A4%20%uD558%uB294%20%uD68C%uC0AC%uC758%20%uACBD%uC6B0%2C%20%uC544%uBB34%uB098%20%uC790%uC2E0%uB4E4%uC774%20%uC6B4%uC601%uD558%uB294%20Node%20%uC5D0%20%uC218%uB9CE%uC740%20Transaction%20%uC744%20%uB0A0%uB824%20DoS%20Attack%20%uC744%20%uD558%uAC70%uB098%20%uBD80%uD558%uB97C%20%uC77C%uC73C%uD0A4%uC9C0%20%uC54A%uB3C4%uB85D%20%uD558%uACE0%20%uBD80%uAC00%uC801%uC778%20%uC11C%uBE44%uC2A4%uB97C%20%uC81C%uACF5%uD558%uAE30%uC704%uD55C%20%uBAA9%uC801%uC73C%uB85C%20Wallet%20Service%20Gateway%20%uB97C%20%uB458%20%uC218%uB3C4%20%uC788%uACA0%uC9C0%uB9CC%20Offchain%20%uC2DC%uC2A4%uD15C%uC740%20%uBAA8%uB450%20%uC0DD%uB7B5%uD558%uC600%uB2E4%0A%0A%uC704%20%uAD6C%uC131%uC694%uC18C%uC758%20%uC124%uBA85%uC744%20%uBCF4%uBA74%20%uC54C%uACA0%uC9C0%uB9CC%20%uD575%uC2EC%uC740%20**Multisig%20Wallet%20Contract**%20%uC774%uB2E4.%20Multisig%20Wallet%uC758%20%uBAA8%uB4E0%20%uD575%uC2EC%20%uAE30%uB2A5%uC740%20%uC774%20Contract%20%uC5D0%uC11C%20%uC774%uB8E8%uC5B4%uC9C4%uB2E4.%20%uC608%uC804%uC5D0%20%uBB38%uC81C%uAC00%20%uB41C%20Parity%20%uC758%20Multisig%20Wallet%20%uB3C4%20%uBB3C%uB860%20Smart%20Contract%20%uC774%uB2E4.%20%0A%0A%23%23%23%20%uD750%uB984%0A%uC704%20Multisig%20Wallet%20Contract%20%uB97C%20%uC0AC%uC6A9%uD558%uB294%20%uD750%uB984%uC744%20%uBCF4%uBA74%20%uAC04%uB2E8%uD558%uB2E4%20%uD558%uC9C0%uB9CC%20%uC774%uC804%20%uAE00%uC5D0%uC11C%uB294%20%uB2E4%uB8E8%uC9C0%20%uC54A%uC558%uB358%20%uC0C8%uB85C%uC6B4%20%uC694%uC18C%uAC00%20%uD558%uB098%20%uB4F1%uC7A5%uD55C%uB2E4%0A1.%20**submitTransaction**%20%0AsubmitTranaction%28%29%20%uC744%20%uC2E4%uD589%uD558%uAE30%20%uC704%uD55C%20Message%20Transaction%20%uC758%20Parameter%20%uB97C%20%uC774%uC6A9%uD558%uC5EC%20%uC2E4%uC81C%20Token%28Ether%29%20%uC744%20%uBC1B%uC744%20%uC8FC%uC18C%uB97C%20%uB123%uC5B4%uC900%uB2E4%0A%0A%20%uC774%uB54C%2C%20Token%20%uC744%20%uBC1B%uC744%20%uB300%uC0C1%uC774%20%uB2E4%uB978%20Smart%20Contract%20%uC774%uACE0%20Transaction%20%uC885%uB958%uAC00%20Message%20Transaction%20%uC778%20%uACBD%uC6B0%2C%20submitTransaction%28%29%20%uC758%20%uD30C%uB77C%uBBF8%uD130%20%uC911%20%uD558%uB098%uC5D0%20**%uC2E4%uD589%uD574%uC57C%20%uD558%uB294%20Smart%20Contract%20%uC758**%20Method%20%uC640%20%uD30C%uB77C%uBBF8%uD130%uB97C%20%uD3EC%uD568%uD558%uB294%20**Data%20Payload**%20%uB97C%20%uB123%uC5B4%uC900%uB2E4%20%28web3%20%uC758%20.getData%28%29%20%uC0AC%uC6A9%29%20%0A%0A%20%uCD94%uAC00%uC801%uC73C%uB85C%2C%20%uC608%uC758%uC0C1%20submitTransaction%28%29%20%uC774%20%uB418%uBA74%20Event%20%uB85C%20transaction%20%uC774%20submit%20%uB418%uC5C8%uB2E4%uACE0%20%uC54C%uB824%uC8FC%uB294%20%uC13C%uC2A4%20%uC815%uB3C4%uB294%20%uC124%uBA85%uD558%uC9C0%20%uC54A%uC544%uB3C4%20%uAD6C%uD604%20%uB418%uC5B4%uC57C%20%uD55C%uB2E4%uACE0%20%uB290%uB08C%uC774%20%uC62C%20%uAC83%uC774%uB2E4%0A%0A%3E%20%uC774%uBD80%uBD84%uC740%20%uAD6C%uD604%20%uBD80%uBD84%uC5D0%uC11C%20%uC124%uBA85%uD558%uACA0%uB2E4.%20%uD5A5%uD6C4%20CALL%2C%20CALLCODE%2C%20DELEGATECALL%20%uACFC%20%uAD00%uB828%20%uC788%uB294%20%uBD80%uBD84%uC774%uB2C8%20%uADF8%uB54C%20%uB610%20%uC124%uBA85%20%uD558%uACA0%uB2E4%20%28%uC74C..%20%uC624%uB79C%uB9CC%uC774%20%uC2DC%uC791%uD558%uB824%uB2C8%20%uC124%uBA85%uD560%uAC8C%20%uC0B0%uB354%uBBF8%uAC19%uB2E4..%29%0A%0A%0A2.%20**confirmTransaction**%0A%uC704%20submitTransaction%28%29%20%uC73C%uB85C%20%uC81C%uCD9C%20%uB41C%20Transaction%20%uC744%20**%uC2B9%uC778**%20%uD558%uB294%20%uB2E8%uACC4%uC774%uB2E4.%20Contract%20%uC5D0%20%uB4F1%uB85D%uB41C%20%uC2B9%uC778%20%uAD8C%uD55C%uC774%20%uC788%uB294%20EOA%20%uAC00%20confirmTransaction%28%29%20%uC744%20%uD1B5%uD574%20confirm%20%uD574%uC8FC%uBA74%20%uB41C%uB2E4.%20%uC774%uB54C%2C%20%uAC01%20confirm%20%uC2DC%20%uB9C8%uB2E4%20%uB4F1%uB85D%uB41C%20%uC870%uAC74%28%uCD5C%uC18C%20n%20%uAC1C%uC758%20confirm%20%uD544%uC694%29%uC744%20%uB9CC%uC871%uD558%uB294%20confirm%20%uC744%20%uBC1B%uC558%uB294%uC9C0%20check%20%uD55C%uB2E4%0A%0A3.%20**executeTransaction**%0AconfirmTransaction%28%29%20%uC2E4%uD589%20%uC2DC%20%uB9CC%uC871%uD558%uB294%20confirm%20%uC218%uAC00%20%uCC44%uC6CC%uC84C%uC73C%uBA74%20submitTransaction%28%29%20%uC2DC%uC5D0%20%uC81C%uCD9C%20%uB41C%20token%20%uC758%20%uC591%20%uB9CC%uD07C%uC744%20%uC6D0%uB798%20%uBCF4%uB0B4%uACE0%uC790%20%uD588%uB358%20%uC8FC%uC18C%uB85C%20%uBCF4%uB0B4%uC8FC%uB3C4%uB85D%20Transaction%20%uC758%20value%20%uAC12%uC744%20%uCC44%uC6B0%uBA70%2C%20submitTransaction%28%29%20%uB2E8%uACC4%uC5D0%uC11C%20%uC81C%uCD9C%20%uB41C%20Message%20Transaction%20%uC774%20%uC788%uC5C8%uB2E4%uBA74%20**Wallet%20Contract%20%uAC00%28msg.sender%20%3D%3D%20Wallet%20Contract%29**%20%uD574%uB2F9%20Message%20Transaction%20%uC744%20%uC2E4%uD589%uD55C%uB2E4%0A%0A%23%23%23%20Multisig%20%uC778%uB370%2C%20%uC11C%uBA85%uC740%20%uC5B8%uC81C%uD558%uB294%uAC00%3F%0A%uC804%uC5D0%20Multisig%20Wallet%20%uC5D0%20%uB300%uD574%20%uCC28%uBD84%uD788%20%uC124%uBA85%20%uD574%uC8FC%uACE0%20%uB098%uC11C%20%uB4E4%uC5C8%uB358%20%uC9C8%uBB38%uC774%20%uC788%uC5C8%uB2E4.%20**%22%uADF8%uB7F0%uB370%20%uB2E4%uB978%uC0AC%uB78C%uB4E4%28EOA%29%uC774%20%uC804%uC790%uC11C%uBA85%uC740%20%uC5B8%uC81C%20%uD574%uC918%uC694%3F%22**%20%uC804%uC790%uC11C%uBA85%uC740%20%uC774%uBBF8%20Smart%20Contract%20%uB97C%20%uC2E4%uD589%uD558%uB294%20submitTransaction%28%29%2C%20confirmTransaction%28%29%20%uB2E8%uACC4%uC5D0%uC11C%20Message%20Transaction%20%uC744%20%uBCF4%uB0B4%uAE30%20%uC704%uD574%20Raw%20Transaction%20%uC5D0%20%uB300%uACE0%20%uB2E4%20%uD588%uB2E4.%20%uADF8%uB798%uC57C%20Transaction%20%uC774%20submit%20%uB418%uC5C8%uC9C0%20%uC54A%uACA0%uB294%uAC00..%uC694..%20%uB77C%uACE0%20%uB2F5%uC744%20%uD574%uC92C%uB358%20%uAE30%uC5B5%uC774%20%uB09C%uB2E4.%0A%0A%28%uB2E8%2C%20Smart%20Contract%20%uC774%20internal%20call%20%uC744%20%uD558%uB294%20%uAD6C%uAC04%uC5D0%uB294%20%uC804%uC790%uC11C%uBA85%uC774%20%uB2F9%uC5F0%uD788%20%uC5C6%uB2E4.%20EOA%20%uC5D0%uC11C%20%uC774%uBBF8%20%uD588%uC9C0%uC54A%uC740%uAC00.%20Smart%20Contract%20%uB294%20%uC11C%uBA85%uD560%20%uC218%20%uC788%uB294%20%uB188%uC774%20%uC544%uB2C8%uB2E4.%20Smart%20Contract%20%uC744%20%uC2E4%uD589%uD55C%20%uB188%uC774%20%uC774%uBBF8%20%uC804%uC790%uC11C%uBA85%uC744%20%uD574%uC11C%20Message%20Transaction%20%uC744%20%uBCF4%uB0B8%20%uAC83%uC774%uB2E4%29%0A%0A%uC774%uB984%uC774%20%uBB38%uC81C%uB2E4.%20Multisig..%20%uC0AC%uC2E4%20confirmTransaction%28%29%20%uB2E8%uACC4%uC5D0%uC11C%20%uD30C%uB77C%uBBF8%uD130%uB85C%20%uBA54%uC2DC%uC9C0%uC640%20%uC804%uC790%uC11C%uBA85%uAC12%20r%2Cs%2Cv%20%uB97C%20%uB123%uC5B4%uC904%20%uC218%uB3C4%20%uC788%uB2E4.%20%uADF8%uB7EC%uB098%20%uB2E4%uB978%20EOA%20%uC758%20%uC804%uC790%uC11C%uBA85%uC744%20%uC804%uB2EC%uD558%uB294%20%uC0C1%uD669%uC774%20%uC544%uB2C8%uACE0%20**confirmTransaction%28%29%20%uC744%20%uC2E4%uD589%uD558%uB294%20%uC8FC%uCCB4%20%uC790%uCCB4%uAC00%20%uC2B9%uC778%20%uAD8C%uD55C%uC744%20%uAC00%uC9C4%20EOA%20%uC774%uBBC0%uB85C%20%uC774%uBBF8%20transaction%20%uB0B4%uC5D0%20%uB4E4%uC5B4%uC788%uB294%20%uC804%uC790%uC11C%uBA85%uC744%20Multisig%20Wallet%20Contract%20%uC758%20%uD30C%uB77C%uBBF8%uD130%uB85C%20%uBCF4%uB0BC%20%uC774%uC720%uAC00%20%uC5C6%uB294%20%uAC83**%uC774%uB2E4%0A%0A%21%5BAlt%20text%5D%28./1543506496329.png%29%0A%0A%0A%23%23%20%uB9C8%uCE58%uBA70%0A%uC624%uB79C%uB9CC%uC5D0%20%uC62C%uB9AC%uB294%20%uAE00%20%uCE58%uACE0%uB294%20%uB9E4%uC6B0%20%uAE30%uBCF8%uC801%uC778%20%uC8FC%uC81C%uB97C%20%uC62C%uB824%uBCF8%uB2E4.%20%uC0AC%uC2E4%200xProtocol%2C%20Plasma%2C%20Raiden%2C%20ERC20%20Token%20%uAE30%uBC18%uC73C%uB85C%20%uB3CC%uC544%uAC00%uB294%20dApp%20%uB9CC%uB4E4%uAE30%2C%20plasma-mvp%20...%20%uB610%uB294%20Enterprise%20Blockchain%2C%20Quorum%20%uB4F1%uB4F1%20%uBB34%uC5C7%uBD80%uD130%20%uC2DC%uC791%uD560%uAE4C%uB97C%20%uB9CE%uC774%20%uACE0%uBBFC%uD574%uBCF4%uC558%uB2E4.%0A%0A%uADF8%uB9AC%uACE0%20%uC774%uC804%uC5D0%20%uC62C%uB838%uB358%20%uAE00%uB4E4%uC744%20%uB2E4%uC2DC%20%uD6D1%uC5B4%uBCF4%uB2E4%uAC00%2C%20%uBE14%uB85C%uADF8%uC758%20%uD750%uB984%uC774%20%uAC11%uC790%uAE30%20%uB04A%uAE30%uB294%uAC83%20%uBCF4%uB2E4%uB294%20%uC774%uC804%uC758%20Context%20%uB97C%20%uC774%uC5B4%uB098%uC544%uAC00%uBA74%uC11C%20%uC880%uB354%20%uBE60%uB974%uAC8C%20%uC9C4%uD589%uD574%uBCF4%uB294%20%uAC83%uC73C%uB85C%20%uC77C%uB2E8%20%uB9C8%uC74C%uC744%20%uBA39%uC5B4%uBCF8%uB2E4.%20%28%uADF8%uB798%uB3C4%20%uAE30%uBCF8%uC740%20%uAE30%uBCF8%uB300%uB85C%20%uAC00%uACE0%2C%20%uC911%uAC04%uC911%uAC04%20%uBC1C%uD45C%uC790%uB8CC%uB3C4%20%uC880%20%uC62C%uB9AC%uACE0%2C%20%uC774%uB7F0%uC800%uB7F0%20%uAD6C%uD604%20%uC0D8%uD50C%uB4E4%uB3C4%20%uC9EC%uC9EC%uC774%20%uC62C%uB9AC%uACA0%uB2E4%5E%5E%3B%3B%29%0A%0A%uB2E4%uC74C%uC740%20Multisig%20Wallet%20%uAD6C%uD604%20%uC608%uC81C%uB97C%201%uD68C%20%uC815%uB3C4%20%uC62C%uB9AC%uACE0%20%uD035%uD558%uAC8C%20%uB9C8%uBB34%uB9AC%20%uD558%uACE0%20%uB610%20%uADF8%20%uB2E4%uC74C%uC73C%uB85C%20%uB118%uC5B4%uAC00%20%uBCF4%uB3C4%uB85D%20%uD558%uB294%uAC78%20%uBAA9%uD45C%uB85C%20%uD574%uBCF4%uACA0%uB2E4%0A%0A%23%23%20References%0Ahttps%3A//medium.com/haechi-labs/parity-multisig-wallet-%25EB%258F%2599%25EA%25B2%25B0%25EA%25B3%25BC-eip999-4dc303cd8e27%0A%0Ahttps%3A//medium.com/hellogold/ethereum-multi-signature-wallets-77ab926ab63b%0A


반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,
지난번에 이어 이번에는 Smart Contract 의 응용 예시를 일단 마무리 할 단계이다. 
휴가와 개인사정으로 정말 오랜만의 글이 되었다 ^^;;

▌Crowd Funding 서비스 구성요소

이번 간단한 Crowd Funding 서비스의 컴포넌트 구성은 아래 그림과 같다.


 매우 간단하다. Smart Contract 만을 사용하므로 Server 도 필요 없으며, 사용자 편의를 위한 HTML + JavaScript 기반의 UI 코드 정도만 있으면 된다. 웹서버도 필요 없고 HTML 파일을 Browser 로 열기만 해도 된다.

▪ Browser

 Browser 에서는 새로운 Campaign 을 만들기 위한 간단한 FORM Element 한두개와 투자자가 Contract 로 보낼 투자금을 입력하기 위한 Input 1개, 달성 여부를 점검하기 위한 Text 한줄 정도면 충분하다

▪ web3.js

 Contract 를 Deploy 하고 Contract 내의 함수를 실행하는 부분(Message Transaction, Call)은 web3.js 를 통해서 할 예정이다.
(향후에는 Web App 형태 말고 Go Native App 형태로도 한번 설명해볼 예정이다)
 web3.js 는 내부적으로 RPC 나 IPC 를 사용하여 JSON 형태의 데이터 포맷으로 API 를 호출한다. 이번에는 간단하게 JSON RPC (HTTP) 로 호출하는 기본 동작을 해본다.

▪ Geth (Miner)

 개발환경이므로 Geth 를 띄우고 직접 Mining 을 하도록 구성한다. 다음 글부터 이야기 하겠지만 사실 Geth 대신 TestRPC 를 사용하는게 개발할 때에는 더 편하기도 하다. 여유가 된다면 물론 여러 Miner 나 Node 들을 연결해서 사용하면 된다. 

▪ CrowdFund (Contract)

 Smart Contract Code 이다. Creation Transaction 으로 Blockchain 에 Contract 가 Deploy 된 상태의 그림이다.


: 이렇게 Smart Contract 와 Static Resource 만을 갖고 서버 없는 응용 개발이 가능한게 Smart Contract 의 큰 매력이며, Swarm 이 완성되면 Static Resource 의 배포 방식 또한 완전한 P2P 로 변화 될 것이다. 또한 Whisper 가 완성되면 이러한 응용(Dapp) 간의 Interaction 과 Communication 이 매우 빠르게 다양한 방법으로 가능해지므로 DApp 의 확산이 매우 급속화 될것이라고 믿는다.

▌Crowd Funding 의 동작 흐름

 일단 Smart Contract 를 배포하는 프로세스가 반드시 필요하다. Solidity 로 개발한 Code 를 컴파일하여 Byte Code 와 ABI 를 얻어내고 (이 과정들은 향후 상세히 소개하겠다), 이후 부터는 web3.js 를 응용하거나 RPC API, Go Native Binding 을 사용하여 Smart Contract 의 함수를 실행하게 된다.

▪ UI 소개
 이쁜 UI 에는 소질도 없고, 이해에 집중하기 위한 목적도 추가하여, 최대한 한단한 UI 를 만들어서 소개한다.

 위 HTML Code 를 치는 귀챦음이 두려운 분들을 위해 Gist 에 코드를 올려놓았다.


▪ Contract Creation(Deploy)


 화면의 Create 버튼을 누르면 저장 된 Contract Code (Byte Code) 를 이더리움에 Deploy 한다. 이걸 Contract Creation Transaction 이라고 부르며, 이렇게 Contract 가 정상적으로 Deploy 되면, 그 즉시 ABI 를 통해 생성한 JavaScript 객체를 활용하거나 JSON RPC API 를 통해 Contract 를 사용할 수 있다.

 Contract Code 를 Compile 한 Byte Code 는 HTML 의 JavaScript Code 에 대략 아래 처럼 정의해놓았다.

 코드가 너무 긴 관계로 한줄의 일부만 캡춰 했다. 이렇게 정의해놓은 Byte Code 는 "Create" 버튼을 누르면 아래와 같은 web3.js 를 사용한 JavaScript 코드로 Deploy 된다. (코드와 개발에 대한 설명은 다음에 자세히 할 예정이니 너무 깊게 생각 안해도 된다)

    $('#btnCreate').click(function(){
            crowd = Contract.new({
            data:code,
            gas:2000000,
            from:web3.eth.accounts[0]
        }, function (error, contract) {
            if (!error) {
                if (!contract.address) {
                    _log("Creating Contract : " + contract.transactionHash);
                } else {
                    address = contract.address;
                    _log("Contract Deployed : " + contract.address);
                }
            } else
                console.error(error);
        });
    });

 위에 보면 data:code 부분이 보이는데, 이 부분에 바로 Byte Code 를 넣어서 Transaction 을 발생시키는 것이다.
 Create 를 하면 아래와 같이 화면 상단의 TextArea 에 Contract 를 Deploy 한 Transaction 의 TxHash 가 출력되게 했고, Deploy 가 완료 되었다면 Deploy 된 Contract 의 주소를 출력하도록 했다.


 한번 Deploy 된 Contract 는 Transaction Receipt 를 통해 Contract Address 를 가져올 수 있으며, 이 Contract Address 가 있으면 이후 부터는 이 Address 를 통해 바로 Contract 를 "사용" 하기만 하면 된다. 위 UI 에서는 At 버튼을 만들어서 주소를 써주고 At 을 누르면 ABI 를 통해 Contract 를 사용하기 위한 JavaScript 객체를 만든다.



▪ 신규 캠패인 시작

 신규 캠페인을 시작하기 위해서는 Beneficiery 의 Address 와 목표 금액을 넣기로 했다. 현재 내 Morden-Net 의 Account 는 아래와 같이 두개가 있고, Campaign 의 beneficiery 는 두 개의 계좌 중 두번째 계좌로 지정하여 신규 캠페인을 생성하도록 하겠다. 목표 금액은 100 Ether 로 설정 한다.

 현재 두번째 계좌에는 712 Ether 가 들어있는것을 알 수 있다. 이제 신규 Campaign 을 UI 를 통해 해본다.


 New Campaign 버튼을 누르면 브라우져의 console 로그에 TxHash 를 찍도록 했다.


 그리고 Transaction 이 처리 되었는지 보려면, web3.eth.getTransactionReceipt() 를 사용하는 방법과 etherscan.io 와 같은 Explorer 사이트를 활용하는 방법이 있다.

 만약 Transaction 이 처리되어 Block 으로 묶였다면, 아래와 같이 Transaction 의 Receipt 정보가 보인다.


 혹은 etherscan.io 와 같은 Explorer 사이트에서 확인해보면 아래와 같이 Transaction 이 처리되었음을 알 수 있다.



▪ 목표 달성여부 점검

 특정 캠페인이 목표 투자금액을 달성하였는지를 확인해보도록 한다. 신규 캠페인을 만들거나 투자를 하는 경우와는 달리 달성이 되었는지 확인만 하는 작업은 궂이 Transaction 을 발생시켜 Gas 를 소모시킬 이유가 없다. 이럴 때에는 Local Blockchain 에서 CALL 을 통해 Gas 를 소모하는 Transaction 발생 없이 값을 확인할 수 있다.

 정확히는, Global State 의 변경이 필요한 함수를 실행하는 경우는 SendTransaction 을 통해 Message Transaction 을 발생시켜야 하며, 나의 Local State 만을 임시로 변경하는 테스트 작업을 하거나 State 를 읽어들이기만 하는 작업(Solidity 에서 constant 함수)을 하는 경우에는 CALL 을 사용하도록 하는 것이다.


위와 같이 campaign ID 를 입력하고 check(call) 을 click 하면, 달성 여부와 목표 금액, 현재 모금된 금액이 즉시 표시된다.



▪ 투자 하기

 이번에는 투자를 해보겠다. 나의 1 번 계좌에서 위에서 생성한 0 번 Campaign 에 150 이더를 투자 해 보겠다.

 

 0번 Campaign 에 120 Ether 를 투자하도록 하고, 돈을 지불하는 쪽은 나의 Morden-Net 계좌 중 1번 계좌가 하도록 했다.

 Transaction 이 처리되었는지 위의 "신규 캠페인 시작" 때와 동일한 방법으로 체크를 하고, Transaction 이 처리되었다면 목표 달성 여부를 다시한 번 check 해본다.

 

 120 이더가 0 번 Campaign 에 전달되었다. Contract 의 전체 잔고도 120 Ether 가 된다. 이를 etherscan.io 를 통해 확인해본다.


 위 처럼, Contract 로 120 Ether 가 이체 된 것을 볼 수 있으며, 102,147 Gas 가 소모 되었고, Input Data 는 4바이트의 NewCampaign() 함수의 Signature 인 함수 정의의 SHA-3 해쉬값 중 4바이트가 들어간 것을 볼 수 있다.

 아래는 현재 Contract 의 상태 정보 중 일부이다.



▪ 목표달성 시 펀드 전달

 이제 목표금액이 달성되었다는 사실을 확인 했으니 실제로 달성 금액이 Beneficiery 에게 이체 되도록 해보자. 여기서 한가지 주의해야 할 것이 있다. Smart Contract 는 스스로 함수를 실행할 수 없다는 것이다. 즉, 시스템 시각이 지정한 시각이 되거나 외부 시스템과 주기적으로 인터페이스 하여 조건을 만족하면 함수를 실행하도록 하는 등의 행위는 불가하다.

 Smart Contract 는 반드시
1) 외부의 EOA 에 의해 발생한 Transaction 에 의해 실행되거나
2) 다른 Contract 의 호출에 의해 실행되거나
의 방법으로 호출된다.

 그래서 우리의 Crowd Funding Contract 의 펀드 전달 기능 또한 누군가가 혹은 어떤 시스템이 Smart Contract 를 실행하여 Global State 를 변이하도록 Transaction 을 발생시켜야 한다. 아마도 이 상황에서는 Beneficiery 가 해당 Transaction 을 발생시키는게 합리적이긴 하겠다. 그러나 현재 Contract 는 다른 어떠한 EOA 나 Contract 도 함수를 실행시킬 수 있다.


 UI 의 Check(send) 버튼을 누르면 Check(call) 때와 똑같은 함수를 실행한다 하지만 CALL 이 아니고 Message Transaction 을 발생 시킨다. 그러면 실제 아래 Contract Code 의 c.beneficiary.send(c.amount) 함수가 모든 Node 에서 실행되어 Global State 를 변경하게 된다.

  function checkGoalReached(uint campaignID) returns (bool reached_, uint goal_, uint amount_) {
    Campaign c = campaigns[campaignID];
    goal_ = c.fundingGoal;
    amount_ = c.amount;
    if (c.amount < c.fundingGoal) {
      reached_ = false;
      return;
    }
    c.beneficiary.send(c.amount);
    reached_ = true;
    c.amount = 0;
  }

 Transaction 이 실행되고 난 후 Etherscan.io 를 통해 보면, Contract 가 120 Ether 를 Beneficiery 계좌로 보낸것을 볼 수 있다.


 그리고 다시 0번 캠페인의 상태를 Check 해보면 돈이 빠져나간 것을 확인할 수 있다. 또한 2번째 계좌의 이전 Balance 가 712 Ether 에서 832 Ether 로 변경된 것을 확인할 수 있다.



▌결론

 이번 2회에 걸친 글은 기술적인 글 보다는 "Smart Contract 로 이런게 가능하고, 매우 간단한 예시로는 이런게 있다" 를 전달하기 위한 목적의 글이다. 

 "저장" 뿐만이 아닌 "실행" 가능한 블록체인 기술로, 앞으로 매우 다양한 서비스를 개발하는 사례가 생겨날 것이라고 생각한다. 이러한 사례를 만들어 내기 위한 기술적인 글들을 다음 부터 또 올려보도록 하겠다.


반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,
지난 글에서는 Smart Contract 를 처음 접하는 분들의 이해를 돕기 위한 글을 올렸다. 이번에도 약간 그러한 연장선상에서 Smart Contract 의 응용 예시에 대해 글을 올려보도록 하겠다. 다음 글 정도 부터는 본격적인 개발 이야기로 들어가보도록 하고, 우선 Overview 형태로 Smart Contract 가 돌아서 무엇을 할 수 있는지에 대해 이야기 해보도록 한다.


▌Crowd Funding 의 예시

 Smart Contract 를 이해하기에 가장 좋은 첫 예시는 Crowd Funding 이라고 생각한다. 돈도 들어가고, modifier 를 예로 들기에도 좋고, 코드도 간결하니 사람들이 이해하기에도 쉽고, event 도 넣기 좋고, 좀더 확장하면 DAO 를 이해하기에도 좋고, Contract 간의 Interface 로 확장해 나아가기에도 참 좋은 예시이다.

 일단 Smart Contract 로 가칭 Quick Starter 라는 어디서 많이 들어본것 같은 느낌의 크라우드 펀딩 Contract 가 갖는 기능을 보자.

[Quick Starter]

  ▶ 누구나 캠페인을 만들 수 있다 (캠페인 = 신규 펀딩 유치)
  ▶ 누구나 Ether 를 보내 펀딩할 수 있다
  ▶ 캠페인의 모금액이 목표 모금액보다 크면 수혜자에게 펀드를 전달한다
  ▶ 펀드 전달과 동시에 캠페인은 종료된다
  ▶ [확장] 캠페인 종료와 함께 캠페인 투자자의 지분(토큰)을 기록한다
  ▶ [확장] 수혜자는 매 년 수익을 이더로 공유하면 지분에 따라 수익이 분배된다
  ▶ [확장] 지분 보유자는 Quick Starter 컨트랙트를 통해 지분 거래가 가능하다

대략 이러한 시나리오(계약내용이라고 하지 않으나 시나리오의 구현 내용이 즉 계약 내용이라고 보면 이해가 빠르겠다)를 갖는 Contract 를 조금 도식화 해 보면 아래와 같다.


Smart Contract 에 대해 잘 모르고 비트코인만 접했던 사람들은 두어번 의문을 가지게 된다.

   Contract 에 송금을 한다고?
   지분 부여, 수익 분배, 지분 매도/매수를 Contract 가 한다고?

Bitcoin 의 Transaction 중심의 응용 방법으로는 이해가 가지 않는 부분이며, 동시에 Smart Contract 가 존재하는 가장 큰 이유이기도 하다. 

 비트코인이 처음 나오고 블록체인 기술이 소개될 때 항상 따라다니는 유행어 같은게 있었다. "중개자 없는 P2P 거래" 라는 말이다. 그리고 기업들은 고민한다. "P2P 는 전통적으로 기업이 참여할 시장이 아니야, 거기에다가 중애자 없이라고? 그럼 더 할 이유가 없네!'. 뭐 그런 회사가 있다.. 아니 많이 있다. P2P 가상화폐 이체P2P Digital Asset 발행 및 거래, Transaction 내에 증명데이터(Proof of Existence) 저장 이라는 틀에 갇혀있고 안그래도 복잡한데, 그 이상으로는 이해하고 싶지 않은 노력을 하는 기업들이다. (아 쫌 안티했나..^^;;)

 그러나 위 처럼 Smart Contract 가 끼면서 Blockchain 의 기존 관념에 큰 변화가 생긴다. 바로 "중개자" 가 Blockchain 내에 생기게 되는 것이다. 좀더 정확히 말하자면 "응용 서비스 제공자/가상기업" 이 생기게 된다. 기업이나 개인은 사람들에게 충분한 가치를 제공할 수 있는 서비스라면 Smart Contract 로 그러한 가치를 제공하는 가상기업을 운영하고 수익을 낼 수 있다. 


■ 번외  Smart Contract 현황

 현재 Ethereum 에는 93,711 개의 Smart Contract 가 Deploy 되어있으며, 이러한 Smart Contract Account 에는 총 16,921,390.231 이더가 담겨있다. 한화로 따지면 약 2,115억원 (1 ether 12,500 원 기준) 규모이다. DAO Smart Contract 또한 이 Contract 들 중 하나이며, 이번에 문제가 된 TheDarkDAO 가 이중 21.5% (454억)를 갖고있다. 조만간 무용지물 되겠지만 큰 규모의 악행 이었다. (아 왜 갑자기 이야기가 DAO 로 가나...^^;;)


 위 http://etherscan.io 사이트에서 Contract Account Address 를 클릭하면 Contract 의 Internal Transaction (Contract 간 호출) 과 Contract 의 Byte Code 를 볼 수 있다. 만약, 소스가 공개된 Smart Contract 의 Source Code 까지 보고싶다면, http://etherchain.org 에서 해당 기능을 제공하고있다.

 오늘 카페(http://cafe.naver.com/decentral) 어느분께서 Byte Code 를 Solidity 로 Disassemble 하여 Reverse 가능하냐고 하셨는데, 아직 그런툴은 없다고 답변드렸다. 물론 OPCode 로는 가능하지만 Solidity 로 변환해주는 툴은 아직 없다.

 만약 어느정도 퀄리티가 된다 싶은 공개 Smart Contract 기반의 Dapp 들을 보고 싶다면, http://dapps.ethercasts.com/ 에서 하나씩 눌러보는것들도 재미지다.


 깔끔하게 https://docs.google.com/spreadsheets/d/1VdRMFENPzjL2V-vZhcc_aa5-ysf243t5vXlxC2b054g/edit?usp=sharing 를 통해 엑셀로 정리된 버전을 볼 수도 있다.



▌Smart Contract Code 구조

 이제부터는 Code 로 가보자. 저 위의 Quick Starter 컨셉의 매우 핵심 기능만을 하는 Crowd Funding Contract 를 보자. 지분 개념이나 거래개념은 없으며

  ▶ 누구나 캠페인을 만들 수 있다 (캠페인 = 신규 펀딩 유치)
  ▶ 누구나 Ether 를 보내 펀딩할 수 있다
  ▶ 캠페인의 모금액이 목표 모금액보다 크면 수혜자에게 펀드를 전달한다
  ▶ 펀드 전달과 동시에 캠페인은 종료된다
 
위 기능만을 하는 Contract Code 를 보자. 지금은 그 구조만을 눈여겨 본다. 이 다음 글 부터는 본격적인 Smart Contract 개발환경 설명을 시작으로 개발에 대한 상세한 방법을 써볼 예정이니 일단 참고 보도록 하자. 이후로도 계속 사용할 언어는 Solidity 이다. 작년에는 Serpent 도 섰었지만 이제는 Solidity 가 대세이므로 앞으로도 계속 Solidity 중심으로만 설명한다.

contract CrowdFunding {
  struct Funder {
    address addr;
    uint amount;
  }
  struct Campaign {
    address beneficiary;
    uint fundingGoal;
    uint numFunders;
    uint amount;
    mapping (uint => Funder) funders;
  }
  uint numCampaigns;
  mapping (uint => Campaign) campaigns;
  function newCampaign(address beneficiary, uint goal) returns (uint campaignID){
    campaignID = numCampaigns++
    campaigns[campaignID] = Campaign(beneficiary, goal, 00);
  }
  function contribute(uint campaignID) {
    Campaign c = campaigns[campaignID];
    c.funders[c.numFunders++] = Funder({addr: msg.sender, amount: msg.value});
    c.amount += msg.value;
  }
  function checkGoalReached(uint campaignID) returns (bool reached) {
    Campaign c = campaigns[campaignID];
    if (c.amount < c.fundingGoal)
      return false;
    c.beneficiary.send(c.amount);
    c.amount = 0;
    return true;
  }
}

코드 분석을 위한 글은 아니므로, 코드에 대한 설명을 간단히만 해본다.

contract CrowdFunding {

Contract 를 선언한다. Contract 의 이름은 CrowdFunding 으로 하였다. Library 나 상속, 참조 없이 하나의 Contract 만으로 개발한 코드이므로 1개의 Contract 만 보인다.

 struct Funder {

Funding 을 한 EOA(Externally Owned Account / 사람소유계정)의 정보를 담을 구조체이다. 간단하게 Address 와 투자한 Ether (Wei) 의 양을 저장하고 있다.
Solidity 에서는 이 struct, mapping, dynamic array 를 매우 자주 사용한다. 여러 Account 를 대상으로 하거나 내부적인 데이터를 여럿 갖고있어야 하는 경우가 대부분이므로 이는 매우 중요하다.

  uint numCampaigns;

State 변수를 uint 타입으로 하나 선언한다. uint 는 uint256 과 동일하다. 32바이트 변수이다. 

  mapping (uint => Campaign) campaigns;

앞으로도 매우 자주 보게 될 mapping 변수이다. (괄호) 안의 uint => Campaign 은, Key 를 uint 타입으로 하고, Value 를 Campaign 구조체로 갖는 Mapping 을 만든다는 이야기 이며, 이러한 Map 을 campaigns 라는 이름의 State 변수로 선언한 예이다. Key 는 위의 numCampaigns 의 증가값을 ID 로 사용할 예정이다.

  function newCampaign(address beneficiary, uint goal) returns (uint campaignID){

새로운 Campaign 을 만드는 함수이다. address 타입과 uint 타입으로 파라미터를 받으며, uint 타입을 리턴한다. 수혜자의 EOA Address 와 목표금액을 넣는 함수이다. 그리고 신규 campaign ID 를 리턴하도록 되어있다. 그런데, 이 return 값은 Smart Contract 로 Transaction 을 발생시켜서는 받을 수 없다. 리턴값을 받으려면 CALL 을 해야 한다. 그래서 이 함수는 CALL 로 실행해서 새로운 campaignID 를 받아보는 용도로도 쓰일 수 있으며 실제 Transaction 을 발생해서 신규 캠페인을 등록하는 용도로도 사용할 수 있다. 이 부분에 대해서는 차츰 이해가 가게 될 것이다.

  function contribute(uint campaignID) {

투자자는 이 contribute 함수로 Message Transaction 을 발생시키면서 동시에 투자할 ether 를 Transaction 의 value 로 담아서 보내면 된다. 그러면 해당 campaignID 의 캠페인에 투자를 하게되고, campaigns Map 의 Campaign 내의 funders Map 에 신규 Funder 를 추가하도록 되어있다.

  function checkGoalReached(uint campaignID) returns (bool reached) {

특정 캠페인의 모금액이 목표금액에 도달하였는지를 점검하고, 도달하였다면 실제로 자금을 이체하도록 하는 함수이다. 이 함수 내용을 보면 Smart Contract 의 특징이 하나 보인다. 바로 "Smart Contract 는 스스로 실행될 수 없다" 는 특징이다. 그래서 특정 EOA 나 Contract 가 이 함수에 Message Transaction 을 보냈을 때에만 목표 도달 시 실제 이체를 실행하게 된다. 그러므로 CALL 을 통해 수시로 체크를 하다가 실제 목표 금액에 도달하였을 때 수혜자 혹은 누군가가(수혜자가 해야겠지요?) Message Transaction 을 보내면서 이 함수를 실행시키는것이 비용적으로 타당한 동작 방식이다. 

 짧은 설명이었고, 더 깊고 많은 설명은 점차 기술 설명으로 들어가면서 해 나아가겠다.


▌1/2 끝에

 오늘도 시간이 빨리간다. 사실 오늘 아예 허접하지만 UI 붙이고 돌아가는 흐름과 캡춰 까지 올리려고 하였으나 반만 쓴다.. 졸려서~ ^^;; 

 이제부터는 조금씩 잘라서 여러번 올려야겠다. 코드가 들어가니 괜히 페이지가 길어질 듯 하다.

 다음 글에는 동작 흐름, 실행 결과, 개발로 들어가기 전의 결론에 대해 말해볼 예정이다.


반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,
이제부터는 Smart Contract 로 들어가기로 한다.
Ethereum 이 비트코인과 가장 크게 차별화되는 특징이기도 하며, Public/Consortium/Private Blockchain 에 공통으로 적용되어 기존 C/S 환경 대비 가장 큰 변화를 가져다줄 수 있는 기술이기도 하다.

일단 얼마전에, 블록체인의 응용방법을 주제로 한 Blockchain 초급 개발자를 대상으로 생각하여 만든 자료를 사용하여 설명 해보겠다.

▌Smart Contract 의 개요

쉽고 멋들어지게 일반화된 용어로 Smart Contract 를 표현한 뉴스기사나 글들이 참 많다. 그래서일까, 사람들이 Smart Contract (스마트 계약)이라는 용어를 나름 머릿속으로 해석하여 정말 무슨 계약 문서같은것이 블록체인에 담겨있다는 생각을 하는 이들도 많다. 그도 그럴것이, Blockchain 을 응용한 매우 낮은 수준의 응용 방법 중 대표적인 것이 "Proof of Existence" 였고, "진본증명" 이나 "외부거래증명" 같은 Use-Case 를 다수 접해온 Blockchain 초심자들이 상상해내기 딱 좋은 용어의 조합이기 때문이라고 생각한다.

Nick Szabo (닉 싸보)

Smart Contract 의 최초 발안자는 Nick Szabo 이다. 이양반은 Computer Scientist 이며 암호학과 법학에 조회가 깊고 경제학에도 관심이 많은, 보통 사람이 대하기에는 힘겨운 그런 사람이다.

1994년, Smart Contract 라는 개념에 대해 처음으로 발표하게 되고
1997년, The Idea of Smart Contract 라는 글로 실제로 이러한 Smart Contract 를 어디에 적용하면 좋을지에 대한 아이디어를 낸다

▌Smart Contract 키워드

Nick Szabo 가 말하는 Smart Contract 의 목적은, "신뢰할 수 없는 컴퓨터 네트워크환경" 에서 "(Machine 간에)고도로 발달된 자동 계약 이행 방법" 을 제시하는 것이다. 이러한 개념은 블록체인 기술을 만나면서 빛을 발하게 되었고, Ethereum 이 "Turing Complete Blockchain" 이라는 개념으로 Blockchain 을 진화시켜가며 Nick Szabo 의 아이디어를 실현시켜 준다.

Nick Szabo 는 블록체인 내의 Smart Contract 를 아래와 같이 이야기한다.
 
    ▪  코드 조각 이다
    ▪  공유장부와 상호작용할 수 있는 인터페이스
    ▪  Transaction 을 보내면 코드조각의 함수를 실행
    ▪  실행된 함수는 장부에서 값을 읽거나 씀

그리고, 금융을 의식해서인지, 어느 강연에서는 이렇게 이야기한다.


이제 조금 감이 왔을 것이라고 믿는다. 조금만 더 이해를 돕기 위한 이야기를 해보자.

▌Smart Contract 의 정체

Nick 이 말한대로이다. Smart Contract 는 계약가 아니라 코드 조각이다. 

아래는 실제 Solidity 언어로 구현 한 Smart Contract (Code) 이다.

contract CrowdFunding {
  struct Funder {
    address addr;
    uint amount;
  }
  struct Campaign {
    address beneficiary;
    uint fundingGoal;
    uint numFunders;
    uint amount;
    mapping (uint => Funder) funders;
  }
  uint numCampaigns;
  mapping (uint => Campaign) campaigns;
  function newCampaign(address beneficiary, uint goal) returns (uint campaignID){
    campaignID = numCampaigns++; 
    campaigns[campaignID] = Campaign(beneficiary, goal, 0, 0);
  }
 
...

이러한 Smart Contract Code 는 Ethereum 의 경우, Solidity, Serpent, LLL, Mutan 의 언어로 쓰여질 수 있는데, 현재는 Solidity 를 주로 밀고 있으며 문법은 JavaScript-Like 하다. Serpent 는 Frontier 가 Release 되기 전까지만 해도 C 언어와 유사한 문법이고 Solidity 의 완성도가 많이 떨어져서 두루두루 함께 썼지만 지금은 Solidity 의 승이다. Mutan 은 접은지 꽤 됐고, LLL 은 아직도 Assembly-Like 하게 Low Level 로 개발하고 Debug 하는데에 일부 해외 개발자들이 사용한다.

위에 보이는대로, Smart Contract 는 "변수"도 있고 "구조체"도 있고 "함수"도 있는 코드 이다. 물론 좀더 들어가면 'Storage 변수와 Memory 변수'로 변수의 종류가 나뉘고 Contract 간의 Address 기반 호출과 DELEGATECALL 등이 들어가면서 기존 프로그래밍 방식과 다른 점들이 많이 튀어나오긴 하지만 그래도 코드이다.

이러한 Smart Contract Code 는 Compile 과정을 거쳐 Byte Code 로 변환된다.


위 Bytecode 는 Solidity Realtime Compiler 를 통해 컴파일된 결과이다(도구 등에 대해서도 다음번에 다룰 것이다). 모두 16진수로 된 코드이며, 이 Bytecode 를 to: 주소가 없이 Payload (data: ) 로 할당하여 Blockchain 에 Transaction 을 날리면, Miner 에 의해 Block 이 생성되고, 이러한 Transaction은 Contract Creation Transaction 으로 간주되어 Transaction Receipt 의 contractAddress: 필드에 생성(배포)된 Contract 의 주소를 넣어서 리턴해주게 되어있다.

다음은 이러한 Smart Contract 의 응용 흐름에 대해 간략히 이해 해보자

▌Smart Contract 의 응용 흐름

Smart Contract Code 는 크게 [Creation/Deployment] [Invoke by Message] [Call] 의 응용방식으로 나뉜다.
우선 아래 그림을 보면서 해당 Smart Contract의 응용 흐름을 이해 해보자.


▪   Smart Contract 개발환경
 Smart Contract 개발환경은 개발도구와 Compiler 까지를 포함한 범위를 표시한다. Code 를 작성하고 컴파일 하면 모든 컴파일러는 [Byte Code] 와 [Function Signature], [ABI] 를 최소한 벹어낸다. 

  Byte Code 는 이미 위에서 설명한 것 처럼 Smart Contract Code 를 컴파일 한 결과이며, Blockchain 에 Contract Creation Transaction 을 발생시켜 배포하거나 Contract 로의 Message Tx 이나 Call 을 통해 EVM 위에서 실행된다.

  Function Signature 는 Contract 내의 함수 이름의 SHA3 한 Hash 값의 4바이트 값으로, Contract 의 함수를 실행시킬 때 Transaction 의 to: 주소에는 Contract Address 를, data: 부분에는 이 method signature 4바이트와 함께 파라미터 값이 payload 로 들어간다. JSON RPC API 를 통해 직접 실행시킬때에는 신경써야 하지만 web3.js 를 통해 contract 를 실행할때에는 신경 쓸 필요 없다. 아래 ABI 때문에 가능하다.

  ABI(Application Binary Interface) 는 특정 언어나 플랫폼에 종속되지 않은 방식으로 기술된 Application Interface 에 대한 정의이다. 쉽게 말하면, 이 ABI 정의를 컴파일러 혹은 ABI Generator 가 벹어내는데, 이 ABI 에는 Smart Contract 의 함수와 Parameter 에 대한 Metadata 가 정의되어있다. 이 ABI 를 갖고 JavaScript 언어 기반의 어플리케이션을 만들 때 객체를 만들게 할 수 있고, 쉽게 그 객체의 Method를 호출하는것 만으로 Contract 의 함수가 호출되도록 할 수 있는 것이다. 현재 Ethereum 은 web3.js 와 함께 JavaScript 응용에서 쉽게 ABI 로 객체를 만들어 사용하도록 지원하며, 1.4.0 이후의 go-ethereum 에서는 Go Native 언어 기반의 응용에서 Smart Contract 를 쉽게 Binding 가능하도록 ABI 기반으로 Go Code 를 생성 해주는 ABIGen 을 제공하고있다.

▪   Blockchain Engine
 geth 나 parity, eth 와 같은 Ethereum Node 를 의미한다. 결국 모든 Smart Contract 와 관련한 Transaction 처리와 Contract 실행을 위한 EVM 은 Node 가 갖고있다.

▪   Applications
 Smart Contract 는 Logic 만을 갖고있을 뿐이다. 사용자나 외부 시스템과의 상호작용을 위해서는 당연히 Application 이 필요하다. HTML+CSS+JavaScript 가 되었건 Application Server 가 되었건 Wallet 이건 간에, Ethereum 과의 Interface 를 통해 Smart Contract 와 상호작용하는 Application 에 해당하는 부분이다. Contract 파트를 뺀 Dapp 부분 정도로 봐도 된다.


[1] Contract Creation/Deployment

 일단 bytecode 가 생성되면, ABI 기반의 객체를 통하건 RPC API 를 통하건 Ethereum Network 으로 Contract Creation Transaction 을 날릴 수 있다. 이때 Transaction 에서 to: 주소는 빼고 payload 에 bytecode 를 넣고, 충분한 Gas 를 넣어 보내면(Gas Estimation 기능을 잘 활용해야 한다. 아니면 좀 과하게 넣고 남기면 된다) Contract 가 생성되게 된다.

 ABI 를 통해 생성한 객체의 new() 를 통해 Contract 를 Create 했다면 생성이 완료된 시점(Transaction 이 처리되고 블록으로 묶여서 Import 된 시점)에 callback 이 호출되며 그때 Transaction Receipt 를 보면 contractAddress 에 생성된 Contract 의 주소가 들어가 있게 된다. 이후 부터는 이 주소를 통해 Contract 를 사용하면 되는것이다.

[2] Message Transaction

 위에서 생성한 Contract 의 함수를 실행하는 Transaction 이다. JSON RPC API 로 호출할때에는 payload 에 4바이트의 Function Signature 를 제일 먼저 쓰고 그 다음부터 32바이트 단위의 파라미터 값들을 넣어서 보내게 된다. ABI 를 통한 Contract 객체는 단순히 객체의 Method 를 호출하듯 하면 된다. 

 이 Message Transaction 은 단순히 모든 함수 호출에 사용하면 낭패를 볼 수 있다. Message Transaction 또한 Transaction 이며, Transaction 을 발생시키면 당연히 Gas 가 소모된다. 단순히 현재 상태값을 조회하는 함수를 호출하거나 테스트 목적으로 함수를 호출한다면 Message Transaction 을 발생하면 안된다. 이때는 다음 설명하는 Call 방식을 사용해야 하며, Message Transaction 은, Smart Contract 를 통해 Global State 를 변경해야하는 경우 즉, 값이 변경되어야 하는 경우에만 사용하여야 한다. 나중에 상세히 설명하겠지만, Contract 개발자도 이러한 상태변화가 없는 함수는 constant 로 선언하여야 ABI 로 아무생각없이 함수를 호출하는 응용 사용자들이 Gas 를 소모당하지 않게할 수 있다.

[3] Call

 Contract 의 함수를 호출하는 두번째 방법이다. [2] 에서도 잠깐 언급했지만, Ethereum 의 Global State 에 변화를 주지 않는 함수를 Gas 소모 없이 호출하려면 이 call 을 사용해야 한다. Contract 함수를 Call 하게 되면, Transaction 을 발생시키지 않고 자기 Node 내에 이미 저장되어있는 Smart Contract 를 Local 에서 실행시킨다. constant 함수가 아니더라도 Transaction 발생 없이 함수를 실행시킬 수 있으나 Global State 에는 영향을 주지 않고, call 이 끝난 시점에 모든 state 는 원상복귀된다. 


아.. 오늘은 그냥 "이해" 인데 또 글이 길어졌다.. 더이상 쓰다가는 내일 출근에 지장을 줄 터, 이만 줄이고 앞으로도 많은 내용을 올려야 할 듯 하니 다음 글로 미루어 두도록 하겠다~ ^^;;


▌그래서..

Smart Contract 는, 보이는 대로 블록체인에 배포되는 Code 이다. 그래서 IBM 의 경우, OBC-Peer 를 만들 때 부터 Smart Contract 라는 개념을 가져다 쓰지만 용어는 좀더 Clear 하게, "Chain Code" 라고 부른다. Nick Szabo 에게는 좀 미안하긴 하지만, Contract 라는 표현 보다는 좀더 직관적이지 않나 싶다.

그러나 앞으로의 글들을 보다보면 무조건 Chain Code 라고 하기 보다는 어떤 때는 Contract 라는 용어가 더 맞는것 같다는 느낌이 종종 들 것이다. Public Blockchain 과 Private Blockchain 에서 Smart Contract 가 가져야할 특징과 역할이 약간 다르기 때문인데, 이건 앞으로의 글을 이해하면서 느껴보면 되겠다.

아.. 이젠 졸립다.. 그럼 이만..


반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,
요 몇달 간 회사일에 치어 글쓰기에 너무 소홀했던 듯 하다. 각성하고, 이제 진도를 뽑아보자~

얼마전, Vitalik Buterin 과 Martin이 한국에 다녀갔다. 국내 블록체인 업체인 코인플러그도 퍼블릭 블록체인 기반의 사업성과가 기대에 못미쳐서인지 기업용 블록체인에 눈을 돌린 듯 하다. 자체 블록체인을 발표하고, Ethereum 과 협업을 하고있는 모습이 국내 블록체인 기술의 업그레이드를 위해 노력하는 모습인것 같아 다행이라고 생각한다.

너무 오랜만의 글이라 갈길이 머니 마지막 글에 이어 일단 web3.js 를 사용하는 방법에 대해 본격적으로 이야기 해보자.

▌web3.js 소개


github.com/ethereum 의 repository 목록에서 보이는 내용이다. web3.js 는 Ethereum Compatible JavaScript API 이다. 
일단 아래 그림을 보자.

예전에 외부에서 이더리움을 소개할 때 Ethereum 의 응용 구조에 대해 썼던 자료이다.현재 go Ethereum 의 경우, JSON RPC, IPC 외에도 그림에는 안나와있지만 WebSocket 을 지원한다.

위 구조를 보면 알겠지만, 이전 글까지는 Ethereum 의 JSON RPC 를 통해 어플리케이션이 Ethereum 을 사용하는 방법에 대해 소개 한 것이다.
그런데 JSON RPC 를 사용해서도 충분히 Ethereum 을 사용할 수 있겠지만, 응용 만드는 입장에서는 좀더 편하게 JSON RPC 를 호출해주는 라이브러리가 필요함을 느낀다. 특히 기본적인 Transaction 기반의 응용이 아니라 Smart Contract 를 사용하게 되면, Event 를 처리하거나 Smart Contract 에서 Return 되는 타입을 처리하여야 하는데, 이때 이러한 타입처리 또한 web3.js 라이브러리를 사용하면 편리하다.

web3.js 는 JavaScript 기반으로 Dapp 이나 서비스를 구현할 때 매우 유용하며, 현재는 EthereumJ 도 web3.js 를 지원하는 작업을 하고있다. 실질적으로 JSON RPC API 와 함께 Ethereum 의 표준 API 로 보면 되겠다. web3.js 는 내부적으로 HTTP 나 IPC 를 통해 JSON RPC API 를 호출하도록 되어있다.

▌JavaScript 코드에 web3.js 사용하기

web3.js 는 github/ethereum/web3.js 의 dist 내에 있는 web3.js 를 받아도 되지만,
Browser 에서 사용하려면 bower 를 사용하거나
Node.JS 를 사용한다면 npm 을 사용하면 된다.

이번에는 간단히 bower 로 install 한다.
[goodjoon eth_basic]$  bower install --save web3
crypto-js 와 bignumber.js 에 Dependency 가 걸려있으므로 두개를 추가로 받는다.
(npm 도 마찬가지로 web3 모듈을 설치하면 된다.)

이제 실제로 이전에 JSON RPC API 로 Transaction 보내기 했던 것을 web3.js 로 보내보도록 하고, 보너스로 블록 생성되는 이벤트를 받아보기 위한 Filter 를 하나 설치해보도록 하겠다.
화면은 간단히 아래와 같이 만들어 봤다.


일단 HTML 에서 web3.js 를 import 한다.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script type="text/javascript" src="../bower_components/web3/dist/web3.js"></script>
    <title>Simple Wallet</title>

그다음, web3.js 를 사용하여 Ethereum Node 에 접속하려면, 아래와 같이 Provider를 지정 해주어야 한다.
var Web3 = require('web3');
var web3 = new Web3();
web3.setProvider(new Web3.providers.HttpProvider('http://localhost:8551'));

위 예제에서는 HttpProvider 를 지정해주었으나, IpcProvider 도 존재한다. Ethereum Node 와 같은 Machine 에서 동작한다면 IPC 로 Interface 하는것이 성능 측면에서 매우 유리하다.


▌Account 의 Balance 가져오기

Account 의 Balance 를 가져오기 위해서는 web3.eth.accounts 프로퍼티를 조사하면 된다. 
function updateBalance() {
    var address = web3.eth.accounts[0];
    var balance = web3.fromWei(web3.eth.getBalance(address), 'ether');

    $('#address').val(address);
    $('#balanceAmount').val(balance);
}

web3.eth.accounts[0]
web3.js API 들은 web3 라는 이름의 객체에 var web3 = new Web3(); 를 통해 할당하였다.
web3.eth 객체 내의 accounts 는 현재 Ethereum Node 에 생성된 계정들의 목록을 배열로 저장하고있다. 현재 내 Node 에 2개의 계정이 있으며, 이중 0 번 계정의 주소를 address 변수에 저장하였다.

web3.eth.getBalance(address)
특정 주소의 Balance 를 가져오는 함수이다. getBalance() 의 리턴값은 Wei 단위의 Balance 이다. address 의 Balance 를 가져와서 web3.fromWei() 함수를 통해 Wei 단위를 Ether 단위로 변경해서 balance 변수에 저장한다. 'ether' 를 지정하지 않아도 fromWei(), toWei() 함수의 기본 변환 단위는 'ether' 이다.

값을 가져와서 화면의 #address 와 #balanceAmount INPUT 필드의 value 로 표현한다.


▌Synchronous vs Asynchronous API

아마 위 함수들이 호출될 때 마다 브라우져나 Node.JS의 Console 에는 Synchronous XHR 은 deprecate 되었다고 경고가 출력될 것이다. 
web3.js 에는 Synchronous 함수와 Property 들이 있으며, 이에 상응하는 Asynchronous 함수들이 있다. 원칙적으로는 Asynchronous API 를 호출해야 한다. accounts 프로퍼티 대신 web3.eth.getAccounts(address, callback) 을 주도록 되어있으며, web3.eth.getAccounts(address, function(err, addresses) { console.log(addresses)}); 처럼 Callback 을 통해 결과를 받아야 한다.
(RPC API 는 deprecate 된 Synchronous 호출을 아직 실행 해주지만, IPC 방식은 아예 호출이 불가능하다)

▌Transaction 보내기

Ether 의 이체, Smart Contract 의 Deploy (Creation), Smart Contract 의 함수 실행 (Message) 모두 하나의 Transaction 발생 함수를 통해 실행한다. 바로 web3.eth.sendTransaction() 함수이다.
sendTransaction() 함수는 앞으로 지속적으로 사용할 것이며 사용법은 매우 간단하다.

web3.personal.unlockAccount(web3.eth.accounts[0],'1111');

일단, Page 가 로드되는 시점 즈음에서 account 를 unlock 해두도록 한다. 이전 RPC API 편에서도 이야기 했듯이, Account 를 사용하기 전에는 Account 를 Unlock 해주어야 한다. 만약 Ethereum 실행 시에 --unlock 옵션을 주고 --password <패스워드파일> 을 주어서 Node 의 BootUp 시에 Unlock 을 이미 하였다면 unlockAccount() 를 실행 할 필요는 없다.

Send 버튼을 눌렀을 때에 실행되는 코드는 아래와 같다.
var toAddress = $('#toAddress').val();
var sendAmount = web3.toWei($('#sendAmount').val(), 'ether');

var txHash = web3.eth.sendTransaction({
    from: web3.eth.accounts[0],
    to: toAddress,
    value: sendAmount
});

console.log(txHash);

web3.eth.sendTransaction(object) 함수에서 object 는 보낼 Transaction 의 내용이 정의 된 Object 이다.
     - from : Transaction 을 보내는 from 주소
     - to : Transaction 의 Destination 주소. 만약 Smart Contract Creation Transaction 인 경우, to 를 지정하지 않는다.
     - value : 보낼 Balance 의 양 (Wei 단위)
     - gas : 이번에는 Gas 양을 지정하지는 않았지만, Ethereum 은 기본적으로 90,000 Gas 를 적어 보내게 되어있다. data 필드를 사용하지 않는 기본 이체 Transaction 의 소모 Gas 는 현재 21,000 Gas 이다.

이 sendTransaction() 함수의 리턴값은 Transaction 의 Hash 값이다. Transaction 의 Hash 값은 Transaction 의 형식 자체에 오류만 없다면 Node 에서 즉시 리턴이 오는 값이다. Miner 나 타 Node 의 Validation 작업과는 무관하다. 

Transaction 이 Block 에 잘 묶여졌는지 확인하기 위해서는 
web3.eth.getTransactionReceipt(txHash) 로 Receipt 를 확인해야 한다. 만약 null 이 리턴되었다면 Transaction 은 Block 에 묶이지 않는 것이다.


▌Block Filter 

Ethereum 에서 새로운 블록이 나오거나 Smart Contract 의 Method 내에서 Event 를 실행(Trigger) 시켰을 때, 특정 Address 나 Topic 에 해당하는 Log 를 알림 받으려고 할 때 사용할 수 있는 기능이 바로 Filter 객체이다. 그중 기본적으로 최신 블록이 생성되어 Mined/Import 되었을 때 이벤트를 받을 수 있도록 하여 좀더 동적인 느낌이 나도록 해보겠다.

var blockFilter = web3.eth.filter('latest');
blockFilter.watch(function(error, blockHash) {
    var block = web3.eth.getBlock(blockHash);
    appendLog('New Block('+block.number+')['+block.hash+'] / ' + block.transactions.length + ' TXs');
});

위 처럼 web3.eth.filter() 함수를 통해 Block 에 대한 Filter 를 걸 수 있다. 'latest' 를 넣어주면 최신 생성된 블록이 있는 경우 Filter 로 잡히게 되며, 'pending' 을 적어주면 Pending 중인 블록 (마이닝 대상)을 보여준다. 또한 Smart Contract 의 Transaction Receipt 내의 Log 에 한하여 Address 나 Topic 을 옵션으로 하여 Filter 할 수도 있는데, 이건 다음번 Smart Contract 하면서 이야기 해보도록 하겠다.

이렇게 코드를 만들고 나면 최종 아래와 같은 화면을 볼 수 있다.


▌결과화면


이처럼 web3.js 를 사용하는 방법은 매우 간단하고 쉽다. 만약 Transaction 에 Custom 한 데이터를 포함하고 싶다면 sendTransaction() 시에 { data : '<HEX값>'} 을 추가하여 보내기만 하면 된다. Bitcoin 이 OP_RETUN 코드 실행으로 가져올 수 있는 40 Byte 의 임의의 데이터 공간만을 제공하는것에 비해 Gas 만 충분하다면 (1 Byte 당 5 Gas) 큰 데이터를 넣는것도 문제 없다. 실제로 수십KB 이상의 이미지 Binary 를 Homestead 와 같은조건으로 놓고 테스트해 본 결과 잘 들어간다. 

다음은 Smart Contract 에 대한 개념과 개발 방법을 시작으로, Smart Contract 에 대하여 본격적으로 연재 해보도록 하겠다.



반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,
이전의 JSON RPC API 기본의 연장이다.
이번에는 JSON RPC 를 통해 실제 Ether 를 이체시키는 Transaction 을 발생시켜보자.

▌Unlock Account
Geth 와 Eth 모두 Account 로 부터 Transaction 을 발생시키기 위해서는 From 이 되는 Account 를 unlock 해야 한다. 
Account 를 Unlock 하기 위해서는 Account 를 생성했을 당시 입력한 패스워드를 반드시 알고 있어야 한다.

일단, 아래와 같이 Request 를 한다.
{
    "jsonrpc":"2.0",
    "method":"personal_unlockAccount",
    "params": [
        "0x2c6191a4792a3a33cbd2f8b7b7e583a61fb33b23",
        "1111",
        0
        ],   
    "id":100
}
"params" Object 의
1번째 파라미터는 "Unlock 을 하고자 하는 자기 Account 의 주소"이다
  Wallet 안에 해당 Account 가 존재해야 하며, Wallet 의 위치는 datadir 에 따라 다르므로, geth account list 나 JSConsole 또는 RPC 로 현재 자신의 Wallet 내의 account 를 확인한 후 입력하자
2번째 파라미터는 "Account 의 Password" 이다
3번째 0 은 Unlock 의 Timout 을 "초" 단위로 입력한다.
  0 으로 지정하면, 이번 Session (Geth 의 Instance 가 살아있는) 동안은 계속 unlock 하게 된다.

성공 했다면 아래와 같은 response 가 온다
{
  "id"100,
  "jsonrpc""2.0",
  "result"true
}


▌Ether 보내기
일단 다른 Node 에 Account 를 하나 추가하였다. Address 는 "0xd33cbaced7b3990554667391708350cbbe3083a6" 로 EOA 를 생성했고, 아직 balance 는 0 이다.
2c6191a4792a3a33cbd2f8b7b7e583a61fb33b23 계좌에서 위 계좌로 150 ether 를 이체 해보겠다. 
Transaction 을 보낼때는 Wei 단위를 쓰며, 150 이더는 150,000,000,000,000,000,000 Wei 이다. 이걸 HEX 값으로 바꾸면 0x821ab0d4414980000 이 된다.

{
    "jsonrpc":"2.0",
    "method":"eth_sendTransaction",
    "params": [{
      "from""0x2c6191a4792a3a33cbd2f8b7b7e583a61fb33b23",
      "to""0xd33cbaced7b3990554667391708350cbbe3083a6",
      "value""0x821ab0d4414980000"
    }],   
    "id":100
}

위 처럼 Request 를 보내면, 정상적인 Transaction 이 발생 되었다면 아래와 같은 응답이 온다.

{
  "id"100,
  "jsonrpc""2.0",
  "result""0x265be2659d440ccd894370a9354bb189123f71ad17fea55f3b7dc2f8900d1664"
}

Result 로 보내준 값은 Transaction 의 Hash 이다.

▌Receipt 조사하기
Ethereum 은 Miner 가 생성한 Block 을 Import할 때 Transaction 을 처리하였다면, Receipt 를 만들어서 저장한다. 그래서, Transaction 이 정상적으로 Block 으로 묶여서 처리되었다면 Receipt 가 생기게 되어있다. Receipt 에는 해당 Transaction 처리에 소모된 Gas 와 Transaction 이 묶인 Block 의 번호 등이 포함되며, Smart Contract 를 Create 한 경우, Contract Account 의 Address 도 들어가게 된다.

Receipt 요청
{
    "jsonrpc":"2.0",
    "method":"eth_getTransactionReceipt",
    "params":[
        "0x265be2659d440ccd894370a9354bb189123f71ad17fea55f3b7dc2f8900d1664"
        ],
    "id":100
}

Receipt 결과
{
  "id"100,
  "jsonrpc""2.0",
  "result": {
    "transactionHash""0x265be2659d440ccd894370a9354bb189123f71ad17fea55f3b7dc2f8900d1664",
    "transactionIndex""0x0",
    "blockNumber""0x7a7",
    "blockHash""0xb760b2d919227cf557f7289c3a5181f09fb0deda669df35b50c510af189cdc5a",
    "cumulativeGasUsed""0x5208",
    "gasUsed""0x5208",
    "contractAddress"null,
    "logs": []
  }
}

해당 Transaction 이 Mining 되어 Block 들어갔고, Block Hash 도 보여준다.

이제 잔고를 확인해보면 된다.

▌잔고 확인하기
위 이체 작업이 잘 되었는지 잔고를 확인해보도록 하겠다.

Balance 확인 요청
{
    "jsonrpc":"2.0",
    "method":"eth_getBalance",
    "params": [
        "0xd33cbaced7b3990554667391708350cbbe3083a6"
        ],   
    "id":100
}

Balance 확인 응답
{
  "id"100,
  "jsonrpc""2.0",
  "result""0x0821ab0d4414980000"
}

위 처럼 150 ether 가 잘 이체되었음을 알 수 있다.


이렇게 JSON RPC API 를 사용한 방법은 아주 간결하다. 다만 Bitcoin 과 프로세스 상 다른부분들이 있어서 까다로워 보일 뿐이다.
이제 기본적인 Transaction 발생까지 해보았으니, 다음부터는 Web3 API 나 RPC 를 사용한 Smart Contract 로 들어가볼까 한다.

반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,
블록체인 기술을 공부하는 가장 기본적인 목표인 Transaction 발생을 해보도록 하겠다.
이 Transaction 발생은 어떤 블록체인이건 개념이해 후 가장 첫 걸음을 떼는 단계이므로 잘 따라해보도록 하자.

Transaction 을 발생하는것을 포함하여 Ethereum 과 Interaction 을 할 수 있는 방법에 대한 설명과 실제 간단한 Transaction 을 JSON-RPC 를 통해 발생시키는 방법을 알아보겠다.

이후 모든 Ethereum 과 관련한 내용은 Geth 를 기준으로 하겠다.
Eth 만 있는 기능인 경우 Eth 를 언급하겠으나 별도 언급이 없으면 모두 Geth 환경이다.

▌Ethereum 에서 개발하는 방법
이더리움을 블록체인 플랫폼의 코어 엔진으로 생각했을 때, 이 코어 엔진을 활용하여 응용을 개발할 수 있는 방법에는 아래 세가지가 있다.

  1. HTTP 기반 JSON RPC API 사용
    REST API Test 프로그램이나 Curl 등으로 즉시 테스트해볼 수 있으며, 원격 응용 프로그램과 통신하기에 적합한 인터페이스.
  2. JavaScript 기반의 web3.js API 를 사용
    Ethereum 이 Dapp 개발을 위해 기본으로 제공하는 JavaScript API 로, Browser, Node.JS, Mist 등으로 실행할 수 있는 인터페이스 이다. 내부적으로는 JSON RPC 를 사용한다.
  3. 응용에 엔진을 라이브러리 형태로 활용하는 방법
    소스코드 형태로 Ethereum 을 사용하며, 가장 응용과 Tight 하게 동작할 수 있다. 그러나 그래야 할 확실한 이유가 있지않는 한 추천하고싶지 않은 방법이다.

위 세가지 방법 중 1,2 번은 비교적 쉬운 방법이나, 3번의 경우 Ethereum 의 코드 분석 없이는 활용이 거의 불가능하다고 봐야하며, 이 코드를 분석하는 데만도 수개월 이상의 노력이 필요하다.
나도 C++ Ethereum 을 3번 형태로 응용하는것을 목표로 한적이 있으나, 200,000 라인에 육박하는 코드에, 난무하는 Template Class 와 상호 Dependency 가 높고 boost 로 발라놓은 C++ 11 스펙의 코드를 해석하기에는 시간이 매우 부족하였다.

따라서, 1,2번 방법이 Ethereum 을 "활용"하기 가장 적합한 방법이라고 생각되며, Transaction 발생과 같은 매우 간단한 API 사용부터 시작하는게 응용을 위한 이해의 첫걸음이라 하겠다.

▌JSON RPC 인터페이스 기본 이해
ETH 와 GETH 모두 HTTP 기반의 JSON RPC 2.0 스펙을 지원한다. JSON RPC API 는 여기 에서 확인할 수 있으며 사용법은 매우 간단한 편이다.

Listen Port : JSON RPC 의 기본 Listen Port 는 8545 번이다. (Geth, Eth 공통)
실행 옵션
     --rpc : rpc 를 사용함
     --rpcaddr : RPC 를 Listen 하는 IP Address Bining (기본: 127.0.0.1)
     --rpcport : RPC Listen Port (기본:8545)
     --rpcapi : RPC 를 통해 사용 가능한 API 셋 (기본: db, eth, net, web3) (이외에 admin, debug, miner, shh, txpool, personal 을 , 로 구분하여 추가 가능)
     --rpccorsdomain : Browser 에서 web3.js 사용 시 Cross Domain 문제가 생기지 않도록 Accept 할 Document 의 Origin Domain.

테스트 환경을 위해 두개의 Node Instance 를 아래와 같이 구성하였다
[Node 1]
  1. Miner 동작
  2. RPC Listen Address Binding : ALL
  3. RPC Listen Port : 8541
  4. RPC API : admin, db, eth, debug, miner, net, shh, txpool, personal, web3
  5. Geth Listen Port : 3031
  6. JavaScript Console 켜기

일단, 아래 커맨드로 Account 를 하나 생성한다
$ geth --datadir $ETH_HOME/db/p1_net_node1 account new

그리고 나서 Miner 인 Node 1을 실행시킨다
$ geth --datadir $ETH_HOME/db/p1_net_node1 --genesis $ETH_HOME/res/p1_net/genesis.json --rpc --rpcaddr "0.0.0.0" --rpcport "8541" --rpcapi "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" --port 3031 --nodiscover --mine console


[Node 2]
  1. Miner 동작 안함
  2. RPC Listen Address Binding : ALL
  3. RPC Listen Port : 8542
  4. RPC API : Node 1 과 동일
  5. Geth Listen Port : 3032
  6. JavaScript Console 켜기

Node 2 용 Account 도 하나 생성한다
$ geth --datadir $ETH_HOME/db/p1_net_node2 account new

$ geth --datadir $ETH_HOME/db/p1_net_node2 --genesis $ETH_HOME/res/p1_net/genesis.json --rpc --rpcaddr "0.0.0.0" --rpcport "8542" --rpcapi "admin,db,eth,debug,miner,net,shh,txpool,personal,web3" --port 3032 --nodiscover $@

[genesis.json]
 {
 "alloc": {
    "d1c8b6e81af8ef16a7dbcd410234f12e10f1579d": {
      "balance""5000000000000000000000000000"
    },

    "2c6191a4792a3a33cbd2f8b7b7e583a61fb33b23": {
      "balance""5000000000000000000000000000"
    }
  },

  "nonce""0x0000000000000000",
  "difficulty""0x010000",
  "mixhash""0x0000000000000000000000000000000000000000000000000000000000000000",
  "coinbase""0x0000000000000000000000000000000000000000",
  "timestamp""0x00",
  "parentHash""0x0000000000000000000000000000000000000000000000000000000000000000",
  "extraData""0x",
  "gasLimit""0x1000000000"
}

위 alloc 의 Account Address 는 각 Node 1, 2 를 위해 생성한 Account 들이다

[static-nodes.json]
위 CLI 옵션에서 보이듯 --nodiscover 옵션을 주었으므로 자동으로 Peer 를 찾지 않을것이다. Node 2 의 <datadir>/static-nodes.json 파일에 static node 로 Node 1 을 추가해준다.
[
    "enode://258a9b4558c163fdaa48f4f7111b8479d87360bc61c77680269b34204dadc293fccdf2c915acb446953712c12ab8a040d2f7b79ef1e066da60b65a88a7bb382d@[::]:3031"
]

두 Peer 를 실행시키면 Node 1 은 DAG 파일을 생성한 후 Mining 을 시작하고, Node 2 를 띄우면 Node 1 에 접속하여 Block 을 sync 하기 시작한다.
이제 테스트할 환경이 만들어졌다.

▌JSON RPC 테스트환경 만들기
JSON RPC API 를 테스트하기 전에 curl 대신 좀더 쉽게 테스트할 수 있는 환경을 만들어보자. 
Chrome 을 사용하고있다면, Post Man 이라는 REST 테스트 도구를 사용할 수 있다. Plugin 을 설치하고 실행하면 아래와 같은 화면이 보인다.

JSON RPC 로 테스트 하여 성공한다면, 이후 어떠한 언어로든 Ethereum Blockchain 을 사용하는 응용을 만들 수 있게 되는것이다.


위 화면에서, Collection 을 하나 만들어두자


이름은 Geth 로 해 두고, 이제 화면 우측 상단의 "Manage Environment" 를 클릭한다.


Add 버튼을 눌러 Environment 이름을 적당히 준다.


key 에 "url" 이라고 입력하고, value 에 Geth 의 JSON RPC Listen IP 주소와 Port 를 입력한다
나는 node 2 (Miner 아닌 Node) 를 대상으로 해보겠다.

이렇게 등록한 Environment Variable 은 향후에 {{url}} 과 같이 사용할 수 있다.



▌Client Version 가져오기

위 모든 과정들을 마쳤다면 이제 JSON RPC 테스트 환경이 끝난것이다. 아주 간단한 Client Version 을 요청하는 API 부터 사용해본다.
Client 의 Version 을 가져오는 API 이름은 web3_clientVersion 이다.

Spec 상, Parameter 는 없고, Return 은 현재 Client 의 버전을 담은 정보가 들어오게 되어있다.


위 처럼 새로운 요청을 만들고, Request Type 은 "raw" 로 하고, 데이터 포맷은 "JSON (application/json)" 으로 한다.
Send 를 누르면, 아래와 같은 응답이 온다.
{
  "id"100,
  "jsonrpc""2.0",
  "result""Geth/v1.3.5-cab802b4/linux/go1.6"
}

성공이다. 이제 원하는 API 를 무엇이든 응용하여 사용할 수 있다.

▌JSON RPC 를 통한 Block 정보 가져오기

하나만 더 해보자. Node 1 에서 Miner 가 돌고 있으므로, Block 이 계속 생성되고 있을 것이다. Difficulty 가 매우 낮으므로 빠른 속도로 생성되고 있을 것이다.
Node 2 가 Import 한 최신 Block 의 정보를 가져와보도록 하겠다.

[Request]
{
    "jsonrpc":"2.0",
    "method":"eth_getBlockByNumber",
    "params":["latest",true],
    "id":100
}

params 의 첫번째 파라미터는 "최신 블록"을 가져오란 이야기 이고,
params 의 두번째 파라미터 true 는, Transaction 데이터 전체를 가져오겠다는 이야기이다. (그러나 Transaction 을 발생시키지 않았으므로, 이 배열값은 비어있다)

[Response]
{
  "id"100,
  "jsonrpc""2.0",
  "result": {
    "number""0x1ff",
    "hash""0x1c9dd4d3191be60a30a01cd8423f05ee203617a03c60d330f76805be2d8df0de",
    "parentHash""0x267128da87431da30d30bf280efa1ef41f5c5e7a2dee846f3d2c94b89947adfd",
    "nonce""0x7652646a68725a33",
    "sha3Uncles""0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347",
    "logsBloom""0x00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
    "transactionsRoot""0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
    "stateRoot""0x9ad2a3c192a39ec9653915f6935c3502fd46d9e6e2805309d80408ea3227e1b4",
    "receiptRoot""0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421",
    "miner""0xd1c8b6e81af8ef16a7dbcd410234f12e10f1579d",
    "difficulty""0x27be0",
    "totalDifficulty""0x4788d6e",
    "size""0x219",
    "extraData""0xd583010305844765746885676f312e36856c696e7578",
    "gasLimit""0x9b62bb0db",
    "gasUsed""0x0",
    "timestamp""0x56ed6d1b",
    "transactions": [],
    "uncles": []
  }
}

Block Number 는 0x1ff (511) 이다.
sha3Uncles, logsBloom, stateRoot, receiptRoot, totalDifficulty, extraData, gasLimit, gasUsed, uncles 등이 기존 Bitcoin 을 했던 사람들은 생소하게 보일것이다. 이건 차츰 알아가보도록 하고, 일단 정보가 잘 왔다면 가장 기본적인 API 를 성공적으로 실행 한 것이니 박수를 치자.

반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,

우리는 흔히 시스템의 처리 성능을 TPS 로 나타낸다. 말 그대로 초당 몇개의 "Transaction" 을 "처리"할 수 있느냐를 나타내는 수치이다. 

이번에 블록체인의 TPS 성능에 대해 이야기 해보고자 한다. 사람들이 많이 궁굼해 하지만 답변하는 사람들의 답변 내용을 들어봐도 딱히 맞다는 생각이 들지는 않더라.

Blockchain 이 널리 쓰이는 중요한 인프라소프트웨어 가 되려면 반드시 당면하게 될 문제 중 하나가 바로 “Transaction 처리 성능” 이다.


▌Bitcoin Blockchain PoW 방식 에서의 TPS 한계성

현재 Blockchain 은 1MB 의 블록 크기와 10분의 블록 생성을 근거로, 1 트랜잭션의 크기를 1 Input, 1 Output 만을 포함하는 최소한의 Size 로 잡더라도,
(1MB/600초)/약260바이트 = 약 7TPS
가 채 안나오게 된다.

이 7 TPS 라는 수치를 계산해내는 방법을 보았듯이, 우리가 생각하는 일반적인 TPS 와는 그 개념이 다르다. TPS 는 시스템의 "성능"을 측정하는 단위이지만, 블록체인은 그 성능 보다는 "10분 후 전파되는 블록에 담긴 Transaction 수"이다.

아래는 C/S 환경에서의 Transaction 처리를 간략히 표현해본 그림이다.

그림에서 처럼 클라이언트는 서버를 바라보며 요청을 하고, 해당 요청이 처리된 즉시 응답을 받는다. 이러한 요청은 여러 클라이언트가 동시에 할 수 있으며, 서버는 이러한 요청을 초당 몇개 처리할 수 있는지를 TPS 수치로 표현할 수 있다.

그러나, 아래와 같은 Blockchain 환경에서 보면, 이러한 TPS의 의미가 다르게 해석되어야 함을 알 수 있다.


Node 들 중에는 Miner 도 있고, Lightweight Client 들도 있다. SPV 라고 표현하던 것들이다. 이중 일반 Node 가 처리를 요청하면, 요청을 Transaction 메시지로 자신과 연결된 (1)Peer 들에게 전파된다. 모든 Node 들은 이러한 Transaction 에 대해 (2)검증 을 해야 한다. 또한 Transaction 을 검증한 Node 는, 해당 Transaction 을 자신의 Peer 들에게 (3)(4)전파 해야 한다. 그러면 그 트랜잭션은 Miner 에 의해 (5)검증 되며, Transaction Pool 에 담겨있던 Transaction 은 (6)Pow 를 통해 최소 10분 후 블록에 묶이게 된다. 이 블록은 Miner 의  Peer 들에게 (7)전파 되며 해당 Peer 는 받은 블록에 대해 (8)블록검증 을 수행하고, 검증된 블록은 다시 (9)전파 된다. 최종적으로 Transaction 처리에 대한 응답을 확인하고자 하는 Peer 는 이 블록을 받았을 때 (10)응답을 확인 할 수 있게 된다. 그리고 그 블록에는 최대 약 7*60초*10분 = 약4,200 개의 Transaction 이 포함되어있을 수 있다. 

위 시나리오는 매우 정상적인 Case 에서의 동작이며, 이론상 최대한 희망적인 상황에서의 상황이다. 실제로는
A. 여러 Input 과 Output 이 1 트랜잭션에 포함되어 Transaction 크기가 커진다
B. Miner 의 Transaction Pool 에 들어가도, 이미 Mining 중인 Block 이 있다면 트랜잭션은 가장 빨리 블록을 생성해낸 마이너의 다음 마이닝 작업에 대상이 된다. 그러므로 최대 19.9분 후에 블록을 받을 수도 있다
C. 어떤 Node 들은 6 Confirm 이상을 최종 Commit 으로 간주 하므로 약 1시간 뒤에 해당 Transaction 이 최종 “처리” 됨을 인정받을 수 있다.

이렇게 “처리”의 개념이 일반적인 C/S 아키텍쳐와 다르며, 그 이유는 “합의” 라는 과정과 “P2P” 라는 환경으로 인해 발생하는 것이다. 이 두가지 과정으로 인해 “처리 Latency" 가 높아지게 되며, 이것은 전체적인 시스템의 처리 성능이 매우 늦어지게 되는 결과를 초래한다.

아래 흐름을 보자. 우선, 설명을 위해 매우 단순한 CS 구성에서의 Transaction 처리 시나리오이다.

그림 처럼, client_1 과 client_2 는 Transaction 을 "직접 서버로" 전달한다. Client 3,4,5,6,... 모두 Server 에게 직접 Transaction 을 전달하며, 서버는 Transaction 을 처리하고 처리된 결과나 처리되었음을 알리는 Notification 을 Client 에게 전달한다. Client 에게 1 TX 처리에는 0.001초가 걸린 것이며, 서버의 입장에서는 1초에 1,000 TPS 를 처리한 것이 된다.

다음은 Blockchain 의 경우이다. 설명을 위해 node2 가 Miner 역할을 하며, node1,3,4 등은 SPV 로 간주하면 되겠다.

node 들은 P2P 환경으로 구성되어있다. node1 이 운 좋게 miner 인 node_2 를 peer 로 직접 추가하고 있거나, node1 자체가 miner 인 경우에도 최소 1 Transaction 이 처리되어 처리된 결과를 자신의 State 에 반영할 수 있는데 까지는 최소 10분 이상이 소요된다. node4 의 경우, node3 의 peer 인 경우로, 이 경우 node3 으로의 TX 전파와 node3 의 TX 검증 단계를 거친 후 miner 에게 전달될 수 있다. 만약 node1 이 Miner 라고 하더라도 Block 이 나오는데 까지는 10분이 소요되므로 사실상 "의미있는" Transaction 의 완전한 처리는 최소 10분이 되는 것이다.
이 경우, Miner 는 최대 7 TPS 로 10분 만에 Transaction 을 Commit 을 하게 된 것이며, Client 의 입장에서는 1 TX 를 처리하는데 10분이 걸린 것이다.

“처리”를 어디까지 볼것인가. 1:1 상황에서의 “전달” 과 "Transaction 검증", “(블록없이 Transaction 만만으로의)State 전이 완료 (Pre-Mined State)” 까지를 Transaction 처리 완료 시점이라고 정한다면 상당히 높은 성능의 시스템 구현이 가능하겠지만, 다수가 참여해야 하는 P2P 환경에서는 이러한 기준은 무의미 하다시피 하다. 

위 그림의 Pending TX 범위안에 있는 Transaction 들로 Miner 는 Block 을 만들게 되는데, 만약 Transaction 의 합이 Block Header 를 포함하여 총 1MB 를 넘게 되면, 1MB 내에서 Pending TX 를 잘라내고 잘라낸 만큼만을 Block 으로 만들게 된다. Mike Hearn 이 이야기 했던 1MB 의 블록 용량의 한계는 바로 이때문이다. 만약 비트코인 거래가 더 활발해져서 Transaction 수가 더 많아진다면, 저 Pending TX 의 용량은 조만간 1MB 를 넘을 것이다. 아래 그림을 보자.


노란색 그래프가 Block 의 평균 크기 이며, 이미 700KB 선이다. 7 TPS 의 트랜잭션도 안되며, 만약 700KB 로 계산해보면, 4~5 TPS 정도의 트랜잭션 발생에 블럭의 크기가 저렇게 된 것이다.

C/S 환경에서는 서버의 DB 에 최종 Commit 만 되었다면 이 즉시 모든 클라이언트가 전이된 State 를 기반으로 다음 작업을 할 수 있다. 그러나 Blockchain 의 경우, Block 이 적어도 다음 Transaction 을 발생시켜야 하는 Client 에게는 전달되었고 그 Block 에 의해 변이된 State 가 “옳다” 라는 “합의”가 되어지지 않는다면 다른 Peer 들은 내 Transaction 을 무시하게 될 것이다.

Pending Transaction 을 기반으로 작업을 한다면 Double Spending 을 막을 수 없다. 내가 매우 빠른속도로 어떤 네트워크에서 잔고 1,000 원에서 100원을 이체시키고, 다른 네트워크(또는 다른 멀리 있는 피어)로 이체 이전 상태인 1,000 원 상태에서 다시 500원을 이체하도록 한다면, 10분 뒤 블록이 나오기 이전에 Pending Transaction 을 기반으로 거래를 확정한 상대 시스템은 10분 후에나 문제가 있었음을 알 수 있으며, 어쩌면 그 다음 블럭인 20분 후에 이 사실을 알게된다.

Bitcoin 에서 최종 거래확정에 6 Confirm 을 권고하는 이유도, 1 Confirm 으로 들어온 블록이 Best Blockchain 이라고 말하기 어렵기 때문이며, 이후 들어온 블록을 기반으로 뒤따라 마이너들이 지속적으로 블록을 연결했다면, 결국 이전에 받은 1 Confirm 블록 내에 Double Spending 중 하나가 섞여있었을 수도 있기 때문이다.

"만약, Bitcoin 으로 한사람이 편의점에서 담배를 결재한 후 10분 이내에 라이터를 추가결재 하려 한다면, 이 거래는 현재 Bitcoin 내에서는 불가해야 한다" 왜냐하면, 아직 1 Confirm 도 떨어지지 않았을 것이기 때문이다. 물론 작은 금액의 거래에 대해서는 1 Confirm, 심지어 Pending Transaction 에 있어도 인정하는 추세이기는 하지만 어디까지나 이건 위험하다.

▌블럭을 크게, 생성 주기를 빠르게 하면? 

블럭 생성을 빠르게 한다면 Bitcoin 보다 더 빠른 응답속도가 가능해지며, Block 의 사이즈가 커진다면 블록에 더 많은 Transaction 을 담을 수 있게된다. Ethereum 의 경우, 0x0D (13초)를 블록 생성주기로 맞추어 놓고 있으며, 아직까지는 Block 의 사이즈를 제한하지는 않고, 대신 Block 의 Gas Limit 을 두어 Gas Limit 내에서 Transaction 을 담을 수 있게 하였다.

이러한 방식은 Bitcoin Blockchain (이제 Blockchain 1.0 이라고 하겠다) 에 적용했을 때 문제가 발생하게 되는데, 바로 다수의 Miner 가 동시에 생성해내는 Block 이 많아지는 문제가 생기는 것이다. Stale Block, Ethereum 에서는 Uncle 이라고 불리우는 Fork 들인데, 이러한 Fork 가 많아지게 되면 발생하는 문제는 State 의 불안정성이다.

Fork 를 인정하지 않는 Blockchain 1.0 방식으로 가게되면, Best Block Chain 이 바뀌는 순간 State 가 출렁일 수 있다. 특정 Account 의 Nonce 가 100 까지 올라간 Block을 받아서 State 가 올라갔는데, 새로 들어온 같은 Block Number의 Block 에는 이 State 변이를 실행했던 Transaction 이 제외되어 있으나 새로들어온 Block 의 Chain Total Difficulty 가 이전의 Difficulty 보다 높았다면 Best Blockchain 이 버뀌면서 State 가 Nonce 100 에서 99로 다시 바뀔 수 있다.

Ethereum 은 이러한 상황을 예상하여 GHOST(Greedy Heaviest Observed Subtree) 라는 프로토콜을 응용하여 자신들의 State Tree 인 Patricia Tree 를 구성할 때 Uncle Block 을 포함하도록 하였으며, 새로운 Block 이 생성될 때 자신이 참고하는 Uncle Block 을 포함시키도록 하였다. Uncle Block 에 대해서도 93.75% 의 Reward 를 주며, 이를 포함하는 Block 이 Best Block 이 되었을 때에는 각 Uncle Block 의 Reward 의 3.125% 를 Best Block 의 Coinbase 에 추가하도록 하였다.

이외에도 많은 부분을 생각해야 한다. 사이즈가 큰 블록은 네트워크 전파 속도가 느려지게되어 결국 더 많은 Uncle Block 들이 생기게 되고, 너무 작은 블록도 오버헤드를 높여 전체적인 성능을 저하시킨다. 특히나 시간이 짧아질수록 평균 Hashrate 를 기반으로한 블록 생성속도의 오차율은 커지게 되는데, 아래 그림(블록생성시간)처럼 블록생성시간의 오차범위는 매우 커지게 된다.


Ethereum 의 지금 시각 평균 Hashrate 는 etherstat 리포팅을 하고있는 node 들 기준으로 1.4TH/s 정도 되며, Difficulty 는 14~15초 정도 되는 20.34 TH 정도로 맞추어져있다.


빨라지는 주기를 PoW 로 때우기 위해서는 Block 생성 시간이 안정적이어야 하고 ASIC 같은 돈버러지를 떼어내야 하는데, 이때문에 Ethereum 은 DAG (Dagger Hashimoto)와 같은 방법을 썼고, 현재는 ethash 알고리즘으로 약1GB 정도의 Hash Cache 를 위한 Seed Table 을 생성하게 해놨으며, 100시간 정도 되는 30,000 블럭 주기로 이 DAG 를 전체 재생성 하도록 해놓았다. 이게 생성되는 것만도 십수분은 걸린다.

▌Authority 기반 블록 생성은?

권한 기반의 블록체인은 이미 작년 부터 Private Blockchain 과 Consorthium Blockchain의 필요성이 나오면서 구현체들이 나왔고, Ethereum 조차도 C++ eth 에서 이 PoA 를 flu 라는 CLI 를 통해 제공했었다. 현재는 Homestead 런칭으로 기능을 삭제한 상태이며 이전에 구현했던 방식도 그다지 세련되지 않은 방식이었다.

Authority 기반의 블록체인의 기본적인 핵심은 "블록을 생성할 수 있는 권한을 부여"하는 것부터 출발하는 것이다. PoW 를 하건, PoS 를 하건 최종 블록을 만들어내는건 "권한"을 가진 Node 가 만들어내게 하는 것이다. 

권한이 있고 이 권한을 신뢰하여 Blockchain 을 구성한다면 궂이 Nonce 를 찾을 이유도 없다. 전제조건은 경제관념이 없어야 제대로 돌아갈 수 있으며 권한이 있는 모든 노드들은 모두 신뢰된 관계여야 한다는 것이다. 경제관념이 생긴다면 그중 어떤 Node 는 더 많은 Token 을 얻으려 할 것이며, 이러다 보면 다시 권한이 있는 노드들 간에 합의가 필요하게 된다.

신뢰된 관계 또한 매우 중요하다. 권한이 있는 Node 이더라도 악의적 행위를 할 수 있다라고 판단되는 경우 이는 다시 합의가 필요한 상황으로 치닫게 된다. 또한 이러한 신뢰관계를 어떻게 시스템 간에 구현 할 것이냐는 것에 대해서도 충분히 고민하여야 한다. 

아무생각 없이 Genesis 에 Key 박아두거나 권한 Key 를 누군가 관리하며 추가 발급한 후에 "응용 업데이트 됐습니다. 다운받으세요." 하는거나 "신뢰는 별도의 보안솔루션이 있쟎아" 라고 하는거면 고개를 몇번 갸우뚱~ 해봐야 하지 않겠나 싶다.

▌Proof of Stake 에서는?

Proof of Stake 는 자신의 지분이 곧 블록생성권 지분율이 되는 형태이다. Public Blockchain 에서는 자신의 Balance 가 크면 블록을 생성할 수 있는 권한이 생기게 되며 블록을 Accept 할 때에도 Miner 의 지분율을 보아야 한다. PoW 대비 블록 생성 주기가 매우 짧아질 수 있으나 가장 지분이 큰 Miner 가 꺼져있거나 하는 상황에서는 전체 네트워크의 Node 상태를 알지 못하는 이상 어떤 블록이 Best Block 인지 판단하기 쉽지 않다는 단점와 빈익빈 부익부 현상이 나타날 수 있다는 부작용이 있다.
이러한 부분을 개선하는 노력들을 많이 해왔으며 Coin Ages Selection 방식이나 Random 방식, PoSV (Velocity) 방식, Voting 방식 등이 블록 채택을 위한 PoS 알고리즘으로 나와있다.

대량의 Transaction이 빠르게 처리되어야 한다면 고려해야하는 모델이며, 특히나 Consortium Blockchain 의 경우 고려할 필요가 있는 방식이 아닐까 생각한다. 

Eris 의 경우, PoS 의 Voting 방식을 채택하고있는데, 모든 권한있는 Node 가 Voting 을 하게 되어있다. Voting Message 를 통해서 Block Proposal 에 대해서 투표하고, 최종 Confirm 은 2/3 의 Token (Voting Power)이 확인되고 Signature 로 Voter 가 확인하면 최종 Step 에서는 Precommit 후 Commit 하여 해당 Transaction List 를 승인하도록 되어있다.

이러한 방식은 블록 생성과 전파 대비 효율적이긴 하나 Public 에서 사용하기에는 효율성이 떨어질 수 있으며, Voting Power 에 해당하는 Token 을 무엇에 맵핑할것인지 생각해야 한다. Eris 는 이러한 Token 을 Genesis 에 Key 와 함께 부여할 수 있도록 하였다. 좀 문제이긴 하다.

그러나 PoW 대비 Transaction 처리의 Confirm 속도는 확연히 차이가 나며 Eris 를 실제 구동해보면 1~3초 이내에 Commit 이 되는것을 볼 수 있다. (Node 3대로 테스트라 좀 그렇긴 하다).


▌그래서 ?

그래서 결론은,
  1. Blockchain 에서의 TPS 를 이야기 할 때에는 부디 C/S 아키텍쳐에서의 TPS 잣대를 들이대지 말자.
  2. 합의 방식에 따라 Transaction 처리 방법과 시스템 전체 성능은 달라진다.
  3. 합의 필요 없고 완전 믿을 수 있는 네트워크라면 그냥 합의하지 말아라. (블록체인 불필요)
  4. 높은 TPS 성능만 필요한거라면, 차라리 성능 좋은 분산 DB 와 Messaging M/W 를 쓰고 참여자 간 인터페이스 통일해라. 

Blockchain 이 풀어낸 가장 큰 문제는 "신뢰" 를 증명하는 방법이다. 
스티븐 코비의 "신뢰의 속도" 라는 책이 떠오른다. 어떠한 일이든 가장 빠른 방법은 "신뢰"를 바탕으로 했을 때이지, 신뢰할 수 없는 환경에서가 아니다.
보안, 위변조, 합의, 정합성, ... 믿을 수 있다면 무엇이든 빠르고 좋은걸 해라. 그리고 다른것에 더 힘을 쏟아라.

(이상 책상에 앉아서 계획없이 생각나는대로 함 써봤다.. 훑어보니 내용이 좀 산으로 갔네요.. 졸려서 이만..^^)


반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,
Smart Contract 는 1994년 암호학, 법학에 일가견이 있는 컴퓨터 과학자인 Nick Szabo 에 의해 소개된 개념이다. 신뢰할 수 없는 컴퓨터 인터넷 환경에서 "고도로 발달된" 계약을 준수하도록 하는 프로토콜이다.

혹 처음 "스마트 계약" 이라는 말을 처음 듣는 사람들은, 블록체인에 "계약" 이라 불리울만한 "문서"를 업로드 하고 이를 준수하도록 "약속"하는 것이라는 막연한 상상을 하고는 한다(실제로 있었다). Contract 라는 용어가 그러한 오해를 살 수도 있는게 사실이긴 하다.

말을 약간 바꿔보자. "스마트 계약"은 블록체인에 모든 Node가 접근할 수 있는 "코드" 를 업로드 하고, 이를 "실행" 하도록 하는 "프로토콜" 이라고 한다면 좀더 이해하기 편할 수 있을 것이다.


▌사전 이해 필요항목
일단 이 Smart Contract 에 대하여 기술적으로 이해하기 전에 Ethereum 의 기본적인 아래 사항에 대해 이해하고 있는게 좋다.

  1. EOA/Contract Account
  2. Account / Global State
  3. Create/Message/Transfer Transaction, Call
  4. Transaction Receipt
  5. Gas, GasPrice
  6. Ethereum Virtual Machine
  7. Turing Complete

(위 개념들은 시간나는대로 정리하여 블로그로 올리기로 한다)

▌Bitcoin 의 Contract Code

Contract 는 마치 Assembly 코드를 연상시키는 듯한 Byte Code 형태의 코드로 구성해왔다. OP_CODE 로 불리우는 1바이트 크기의 명령인 Operation Code 들은 Stack 에 쌓이며 실행된다. 

Bitcoin 의 경우, Script 라고 부르고 있으며 기본적인 Balance Transfer Transaction 의 경우 Client 가 Transaction 의 Script 파트에 Pubkey, PubKeyHash, Private Key Signature 를 연산하여 UTXO 를 소비하려는 현재 Transaction 이 정당한지를 검증하는 Script 를 자동으로 추가하도록 되어있다.

좀더 자세히는, UTXO 의 Public Key Hash 가  Transaction 의 INPUT 파트에 있는 Unlocking Script 내의 Public Key 의 HASH160 OPCODE 연산 결과와 같은지를 비교하며 최종 CHECKSIG OPCODE 를 통해 Private Key 의 Signature 를 Public Key 로 검증하여 TRUE 를 리턴하는지를 검사한다.

이러한 Script 파트에는 원하는 OPCODE 들을 구성하여 Transaction 을 만들어낼 수 있는데, 쌍방 혹은 여러 “신뢰되지 않은” Peer 들 간에 특정한 OPCODE Script를 실행시켰을 때 값이 정상이라면 그 Transaction 을 "정상으로 인정한다”라는 “계약적인 조건”을 명시하고 실행 가능하므로, 이러한 개념으로  Contract Code 라고 표현하고 있다.

Bitcoin 의 OPCODE 는 Constants, Flow Control, Stack, String 의 Splice, Bitwise, Arithmetic, Crypto, Locktime, Pseudo-Words 의 카테고리에 해당하는 85개 정도의 명령어를 제공하고있다.

▌Ethereum 의 Smart Contract 차이점 

Bitcoin 이 선보인 이 Contract Script 는 매우 획기적인 방식이며 신뢰할 수 없는 환경에서 신뢰를 기반으로 해야하는 중요한 거래가 가능하도록 하는 핵심적인 요소로서 동작한다. Ethereum 의 Vitalik Buterin 은 어린나이에 이러한 Bitcoin Blockchain 에 대해 이해하고 Contract Code 를 더 확장하면 무한한 확장성을 가진 탈 중앙화 된 컴퓨팅 환경, 더 나아가서는 Global/World Computer 를 실현시킬 수 있다고 믿고 Gavin Wood 박사는 그의 사상을 구현하기위해 함께하며 개발언어에 독립적인 Yellow Paper 를 만든다.

Ethereum 은 Bitcoin 의 Contract 에 비해 매우 고도로 발전된 형태의 Contract Code 라고 말할 수 있으며, 단순한 “검증” 과 “연산” 을 뛰어넘는 ”상태”와 “함수”를 정의하고 “상태변이”와 “데이터 저장”이 가능한  Turing Complete 코드 개발을 가능하도록 하였다.

APPLY(S)=S’
(APPLY: 상태변이 함수, S:현재상태, S’: 변이된 상태)
 
라는 상태변이 함수과계에서,
Bitcoin 의 S와 S' 는 UTXO 의 Balance 만이 가능하지만,
Ethereum 의 S 는 EOA(Externally Owned Account)의 Balance 는 물론, Account의 Nonce, Contract Account 의 Storage 에 저장된 데이터의 값들도 포함된다.

즉, “잔고” 뿐만이 아니라 “데이터” 또한 상태변이 함수로 변이 가능한 상태의 대상이 된다는 것이다.
또한 이러한 상태변이 함수를 Smart Contract 라고 부르며, Smart Contract 는 EVM(Ethereum Virtual Machine) 이 실행시키고, 여기에서 실행되는 이러한 Smart Contract 함수를 정의한 Code 를 EVM Code 또는 Smart Contract Code (줄여서 Contract Code) 라고 부른다.

Loop 지원, Contract Account, (Contract 의) Block 과 Transaction 정보에의 접근, Statefull, Gas 개념 등은 Ethereum Smart Contract 의 큰 특징이다.

Bitcoin 대비 별것 아닌 변화일것이라 생각될 수 있지만 이것은 Blockchain 기술의 적용 가능 분야를 무한히 확장할 수 있는 큰 변화이다. 복잡한 금융 파생상품에서 부터 지능형 머신/IoT 디바이스의 자율적 협업,  슈퍼컴퓨터를 초월하는 강력한 컴퓨팅 까지 가능하게 하는 중요한 열쇠가 바로 이 Smart Contract 라고 할 수 있다.

Ethereum 은 Dapp (Decentralized Application) 이라는 개념을 Smart Contract 를 중심으로 하여 실현하고 있으며, 이는 기존의 중앙 집중식의 시스템의 단점(DoS 취약, 보안 취약, Single Point of Failure, Scalability 한계성, Privacy 침해, 외부 인터페이스 표준화 문제 등)으로 부터 자유로워질 수 있는 탈중앙화된 Appication 아키텍쳐가 가능해지는 기술이라고 할 수 있으며, 전통적인 P2P 로는 풀 수 없었던 “신뢰할 수 없는 환경에서의 신뢰성 있는 서비스 운영”이 가능하게 하는 핵심적인 기술이 아닐까 생각한다.

▌EVM

Ethereum 은 Smart Contract Code 구현을 위해 4가지의 언어를 구현한다. 

Mutan, LLL, Serpent, Solidity 가 현재 Ethereum 의 Smart Contract 를 구현할 수 있는 Code 이다. 이중 Mutan 은 C 언어와 유사한 구조를, LLL 은 Low-Level 의 OPCODE 형태를 가지며, Serpent 는 Python 과 유사하다고 할 수 있고, Solidity 는 JavaScript 와 매우 닮았다.

Mutan 은 Deprecated 되었으며, LLL 은 더이상 Develop 하지 않으나 여전히 지원하고는 있으며 Serpent 와 Solidity 가 주요 언어라고 볼 수 있으며 그 중 Ethereum 은 Solidity 를 Main 언어로 주력하고있다.

EVM(Ethereum Virtual Machine) 은 이러한 상위레벨 언어로 만들어진 코드가 컴파일되어 생성되는 Byte  Code 를 실행하기 위한 Runtime 으로, OPCODE, Stack 외에 Ethereum 에서 추가된 Memory, Storage 를 사용하는 주체이기도 하다.

Smart Contract 실행 (Create, Message Transaction)은 모든 Block 검증을 수행하는 Node 에서 동일하게 일어난다. 또한 Contract 를 실행하는데에는 현재 Homestead 에서도 아래와 같은 Gas 를 소모해야 한다.

Operation Name Gas Cost Remark
step 1 default amount per an execution cycle
stop 0 free
suicide 0 free
sha3 20  
sload 20 get from permanent storage
sstore 100 put into permanent storage
balance 20  
create 100 contract creation
call 20 initiating a read only call
memory 1 every additional word when expanding memory
txdata 5 every byte of data or code for a transaction
transaction 500 base fee transaction
contract creation 53000
changed in homestead from 21000

Gas 는 Gas * GasPrice 만큼의 Wei 비용으로 지불되며, 이는 Turing Complete Machine 인 이더리움이 무한루프와 같은 Attack 으로 부터 자유롭기 위함과 Contract 실행과 Storage 사용에 대한 자원비용 보상을 지불하는 목적이다.

Gas 가 생각보다 많이 나올 수 있는데, Code 실행과  sstore 등 뿐만 아니라, Transaction 의 size 에도 비용이 비례하여 증가하게 되기 때문이며, 최소 Gas Price 보다 크지 않으면 아예 Transaction 이 발생하지 못하는 비극이 발생한다. 결론적으로 돈이 있어야 한다.

▌Storage, Memory, Stack

모든 Contract Account 는 Storage 라고 불리는 Persistent 저장소를 갖고있다. Key-Value 맵 구조로 32바이트 키를 32바이트 값으로 맵핑하도록 되어있다. Contract 는 자기 자신 이외의 Contract 의 Storage 를 읽거나 쓸 수 없다.

Memory 는 Contract 가 Message Call 이 있을 때 마다 최신의 Instance 를 얻을 수 있는 공간으로, Byte 레벨로 읽고 쓸 수 있으나 32바이트 단위 Chunk로 저장된다. 즉, 1 이라는 값을 저장하면 32바이트 (256비트) 공간에 저장된다.

EVM 은 총 1024개의 Instruction Set (OPCODE) 를 담을 수 있는 Stack 을 갖으며, 256비트의 word (값) 을 갖는다. 

이러한 특성으로 Message Call 시에도 몇가지 제약사항들이 있는데, 그중 하나는 32바이트를 넘는 문자열을 하나의 파라미터로 보낼 수는 없다는 것이다. 

▌Message Call

Contract 는 다른 Contract 를 Call 하거나 EOA 로 Ether 를 보낼 수 있으며, 이때 Message Call 을 사용하게된다. 일반 이체 Transaction 과 매우 유사하지만 호출할 Contract 의 주소, Method 의 주소, 함수  파라미터(옵션)를 넣는것이 다르다.

Sub Contract Call 이 실행되어야 하는 경우, 연쇄적인 Message Call 이 Contract 에 의해 일어나게 되며, 이러한 연속된 Contract 실행을 위한 충분한 Gas 를 포함시켜야만 나중에 Contract 실행이 끝까지 될 수 있다. Call 은 최대 1024 Depth 까지 호출될 수 있다.

Message Call 의 결과는 Block 내의 Transaction Receipt 를 참고하여 조회할 수 있다.

Contract 실행 전, EVM 은 Transaction Sender 의 잔고가 충분한지 검토하고 실행하며, 실행 중 Gas 가 모두 소진되었으나 실행이 완료되지 않은 경우에는 그때까지의 Gas 는 지출되고 모든 State 는 Contract 실행 이전 단계로 돌아간다.

▌Delegate Call, Callcode, 라이브러리

Message Call 중에, Delegatecall 이라는 방식이 있는데, 이건 Contract 가 실행될 때 Contract 를 실행시킨 Contract 의 Context 를 사용한다는 것이다. 그리고, Message Sender 와 Value 가 변경되지 않고 Caller Contract 의 것을 그대로 사용한다.

이러한 특성을 활용하여 Library 형태의 Contract 를 만들 수 있다.

▌Create Contract Transaction

Contract 를 Byte Code 로 컴파일 하여 Blockchain 에 Upload 하여야 Contract 를 실행할 수 있다. Contract Create 는 EOA 가 Create 하는것이 일반적이나, Contract 가 다른 Contract 를 Create 할 수도 있다. 

▌Self Destruct

Contract 를 삭제할 수 있는 유일한 방법은 Contract Address 에서 (자신이) SELFDESTRUCT 명령을 수행하는 것이다. 이때 Contract Account 의 Ether 잔고는 지정된 Account 로 이체되고 Contract 의 모든 State 는 소멸된다.

위 기본적인 개념들 말고도 설명해야 하는 것들이 많다. 앞으로 조금씩 써보도록 하고, 예제도 종종 올려보도록 하겠다. 


반응형
블로그 이미지

Good Joon

IT Professionalist Since 1999

,