저번 글에 이어 이더리움의 가스라는 놈과 수수료 체계에 대해 알아보려고 합니다.
[이더리움] 블록과 계약의 연결(스마트 컨트랙트)
[이더리움] 계정과 트랜잭션
폭락장에 시세 보러 갈일이 없으니.. 책도 보고 스팀잇도 더 자주 보게 되네요 ㅎ 이렇게 글도 쓰고.ㅎ
이런 걸 반사이익이라고 하나요? ㅎ
이번 글을 이해하기 위해서 저번 글의 요지만 설명드리면, 외부소유계정은 비트코인의 지갑과 같이 이더를 송금하고 전체 계약을 만들 수 있는 상위계정이고, 계약계정은 외부소유계정에서 만든 컨트랙트를 자동실행하는 하위계정이라는 것이었습니다.
자 그럼 GAS라는 놈부터 알아보겠습니다.
저두 그랬고 많은 분들이 혼동하시는 것이 GAS = 이더 라고 생각하는 것입니다.
수수료의 단위로 쓰이는 gas를 이더라는 화폐와 똑같은 개념으로 생각하시는 거죠.
결론적으로, 수수료로 지불되는 화폐는 이더가 맞습니다. 하지만 gas는 다른 개념이죠.
비트코인이나 다른 코인들에서도 수수료를 그 해당 코인으로 지불하다 보니 수수료 = 코인이라고 생각되게 마련입니다.
하지만 이더리움에서 쓰이는 gas라는 단위는 리터(l)나 킬로그램(kg)같은 단위이지 화폐 개념이 아닙니다.
우선 이것을 생각하시고 글을 보시면 편할 거 같아서 적고 넘어가겠습니다.
gas는 이더리움에서 송금이나 스마트 컨트랙트를 실행할 때 수수료를 책정하기 위해 만든 단위입니다.
고기를 살 때 고기의 무게를 재는 kg과 같다고 생각하시면 편합니다.
무게 단위로 파는 고기를 살 때 저희는 저울에 고기의 무게를 재서 몇 g 인지를 알 수 있습니다.
그럼 이더리움에서는 스마트 컨트랙트를 실행시키기 위해 몇 gas가 필요한지는 어떻게 알 수 있을까요?
이건 저희가 어디가서 재고 하는 것이 아닙니다. 이미 정해져있죠.
스마트 컨트랙트에서 한 번의 송금, 혹은 하나의 코드를 실행하기 위해 이 gas가 얼마나 필요한지는 이더리움의 기술 백서인 황서에 나와있습니다.
기술적인 부분은 잘 몰라서 저걸 다 이해할 수는 없지만 저번 글에서 설명 드린 외부소유지갑끼리의 이더 송금(Gtransaction)에는 21,000gas가 쓰인다고 적혀있습니다. 개인지갑끼리나 거래소에서 딴 거래소로 보낼 때 21,000gas가 쓰인다는 거죠. 다른 스마트 컨트랙트에서 쓰는 코드나 저장소 같은 것도 쓰이는 gas의 양이 정해져있습니다.
더 궁금하신 분들을 위해 대략 설명을 해주신 글을 링크하겠습니다.
Andy's blog, 이더리움 설계 근거
중간쯤부터 수수료 관련 설명이 나옵니다.
이렇게 gas는 이더리움 상에서 수수료를 책정하기 위한 단위이며, 사용량은 정해져 있습니다.
따라서, 수수료 = 쓰이는 gas의 총량 x gasprice 가 되고, 트랜잭션을 만드는 유저는 바로 이 gasprice를 설정함으로써 수수료를 조정합니다.
gasprice는 Gwei라고 하는 이더의 하위 단위로 계산됩니다. 비트코인의 사토시같은 개념으로 1Gwei는 0.000000001이더입니다. 1 gas가 50Gwei라고 하면 이더 송금에 쓰이는 수수료는 21,000 x 50 =1,050,000Gwei, 즉 0.00105 이더가 되겠네요..(아 이런 거에 계산기를 써야하다니..머리가..ㅠㅠ)
gasprice는 이더리움 지갑에서 설정할 수 있습니다. 적정 수수료가 얼마인지는 이더스캔에서 다른 트랜잭션을 찾아보셔도 되고 아래 링크에서 적정 gasprice를 알아보셔도 됩니다.
ETH gas station
오른쪽 밑에 빨간 박스 부분이 현재 적정 gasprice를 말해줍니다. 느리지만 안전한 것부터 빠른 것까지.ㅎ
gasprice의 가격이 올라가면 수수료가 비싸지니 수수료를 받아먹는 블록생성자가 빨리 담아주는 것이죠.
gaslimit는 위와 같이 정해진 가스양을 가지고 트랜잭션을 다 실행하기까지, 자신이 쓸 용의가 있는 전체 가스양의 한도를 말합니다. 이 이상은 수수료로 지불하기 싫다는 이야기죠. Startgas라고도 하는데 트랜잭션을 만들어 보낼 때 이 gaslimit를 설정해서 위와 같이 gaslimilt x gasprice 를 한, 지불할 용의가 있는 전체 수수료를 이더로 트랜잭션에 담아서 보냅니다.
자신이 만든 스마트 컨트랙트에서 어느 정도의 가스를 쓸 것인지는 앞의 gas에 관한 표에서와 같은 정보로 알 수 있습니다. 그럼 그에 맞게 gaslimit를 정할 수 있겠죠.
gaslimit를 좀 높게 잡아서 전체 계약이 실행되고 gas가 남은 경우, 남은 gas에 해당하는 이더는 발신자에게 환급됩니다. 위의 이더 송금을 예로 들면 gaslimit를 3만으로 잡아서 9,000gas가 남게 되면 9,000 x 50 해서 450000Gwei가 환급되는 거죠.
이렇게 자신이 모든 컨트랙트를 실행할 시 gas를 얼마 사용할 지 알 수 있습니다. 하지만 다른 사람의 계약계정에 이더를 보내어 그 사람의 컨트랙트를 사용하게 되는 경우, 그 컨트랙트에서 얼마나 많은 gas를 사용할 지 정확히 알 수 없습니다. 그 다른 사람이 정확히 말해주면 좋겠지만 그게 아닌 경우 gaslimit를 넉넉하게 잡아야합니다.
그 이유는 gaslimit보다 gas를 더 사용하게 되면 컨트랙트의 실행이 멈추고 처음 시행되기 전으로 환원되기 때문입니다. 아예 아무것도 안 한게 되어버리죠. 중간에서 뭘 더 넣고 하는 것도 없습니다. gaslimit를 넘기는 즉시 계약실행은 중지되고 모든 실행은 원상 복귀 됩니다.
말로 하는 설명이 넘 길었네요... 이해도 안 되실 거 같고. 꾹 참고 읽으셨으니 이제 예를 들어서 설명해 보겠습니다.
쉽게 단순화한 예이므로 참고하는 정도로 이해하셨으면 좋겠네요 ^^
gas는 우리나라에서는 도시가스나 LPG가스와 같이 정말 기체에만 쓰이지만 미국에서는 차에 넣는 휘발유를 말하는 것으로도 쓰입니다. 차에 기름넣는 곳이 우리나라는 주유소지만 미국에서 gas station이라고 불리니까요.
그래서 이 gas를 설명하기 제일 좋은 예도 자동차에 넣는 기름이 될 수 있습니다.
차에 기름을 넣을 때 몇 리터를 넣어달라고 하고 그 리터당 가격을 곱해서 전체 가격을 계산하죠.
이더리움의 수수료도 마찬가지입니다. 쓴 gas의 양에 gas 하나당 가격을 산정하여 수수료를 계산하는 거죠.
자동차의 기름으로 gas를 설명했으니 그걸로 예를 하나들어보죠.
(너란 놈...갖고싶다..)
제가 BMW 미니(어차피 가정이니 드림카로..)로 서울에서 부산까지 맛집투어를 하려고 합니다.
제 생각에는 기름 7만원치면 부산까지 도착할 거 같습니다. 기름 많이 넣어봐야 차만 무거워지죠.
그래서 주유소에서 리터당 천원 하는 휘발유 7만원치를 넣습니다. 휘발유 70리터를 넣은거죠.
그럼 기름도 채웠으니 신나게 출발합니다.
우선 대전에 가서 친구A를 만나 성심당 빵을 애피타이저로 먹을 겁니다. 그리고 A에게 다음 맛집을 추천받기로 했죠. 대전에서 친구 A와 빵을 먹고, 친구 A는 대구에 뽈찜집으로 제 차를 운전해서 데려갔습니다.
대구에서는 친구 B를 만나 뽈찜을 먹고 부산의 칠성횟집을 소개받았습니다. 이번엔 친구 B가 제 차를 운전하여 부산으로 갑니다. 그런데 가다 보니 기름이 오링... 부산에 가기 전에 기름이 똑 떨어져서 차가 서버렸습니다.
(설명할 내용이 있어서 좀 복잡하게 만들었습니다..이해를...)
위에 과정을 이더리움에서 미술관이 만든 트랜잭션으로 바꿔볼까요? 스마트 컨트랙트가 실행되는 조건은 받은 즉시 만족했다고 가정하겠습니다.(맛난거 사준다면 당연 나가야죠!)
전체적으로 보면
- 미술관의 외부소유계정에서 트랜잭션 생성
- A의 계약계정으로 보냄. A의 계약계정에서 계약내용 자동으로 실행
- B의 계약계정으로 보냄. B의 계약계정에서 계약내용 자동으로 실행.
- B의 계약내용 실행 중 gaslimit 초과, 실행중지.
이렇게 끝나는 트랜잭션이 되겠네요.
세부적으로 gas 개념을 넣어서 바꿔보겠습니다.
제 생각에는 한 7만원치면 부산까지 도착할 거 같습니다
그래서 주유소에서 리터당 천원 하는 휘발유 7만원치를 넣습니다. 휘발유 70리터를 넣은거죠.
gasprice(리터당 가격)를 5wei(천원)로 하고 gaslimit(제 생각에는 한 7만원치면 부산까지 도착할 거 같습니다)를 50,000 gas(70리터)로 설정하고 트랜잭션을 보냅니다(부산으로 출발합니다).
우선 대전에 가서 친구A를 만나 성심당 빵을 애피타이저로 먹을 겁니다. 그리고 A에게 다음 맛집을 추천받기로 했죠.
17000 gas를 소모하는 내용을 실행(대전에 가서 친구 A와 빵을 먹음, 휘발유 25리터 소모)하고 A의 계약계정을 불러옵니다.(A에게 다음 맛집을 추천받음)
친구 A는 대구에 뽈찜집으로 제 차를 운전해서 데려갔습니다.
A의 계약계정의 컨트랙트에 따라 18000 gas를 소모하는 컨트랙트를 자동으로 실행합니다.
대구에서는 친구 B를 만나 뽈찜을 먹고 부산의 칠성횟집을 소개받았습니다.
18000gas를 소모한 A의 컨트랙트는 B의 계약계정에서 새로운 컨트랙트를 불러옵니다.
이번엔 친구 B가 제 차를 운전하여 부산으로 갑니다. 그런데 가다 보니 기름이 오링... 부산에 가기 전에 기름이 똑 떨어져서 차가 서버렸습니다.
B의 계약계정에서 자동으로 이행된 15000gas를 소모하는 컨트랙트를 실행하는 도중, 처음 gaslimit으로 설정한 50000gas가 모두 소진되었습니다.
이것을 위와 같은 그림으로 나타내면,
이렇게 설명됩니다. 이동할 때마다 기름이 나가듯이, 계약내용이 시행될 때 마다 수수료가 나가는 것이죠.
그럼 부산까지의 여정을 저렇게 복잡하게 만든 이유가 나와야겠죠.
처음부터 보시면 이동하는 데 사용한 모든 휘발유는 제가 처음 서울에서 넣은 70리터입니다. A와 B가 맛집을 추천하고 그들이 운전해서 가지만 기름은 제가 넣은 기름을 쓰고 있습니다.
이더리움의 스마트 컨트랙트도 마찬가지입니다. A와 B의 계약계정에 있는 컨트랙트를 실행하지만 그 수수료는 제가 내야합니다. 즉 하나의 스마트 컨트랙트를 끝까지 실행시키는 데 필요한 수수료는 그 트랜잭션에 계약 내용을 담아보낸 유저가 모두 내야합니다. A와 B가 어디를 데려가더라두 그 기름값은 제가 내야하는 거죠.
위의 예는 단순히 서울에서 부산가는 경우지만 이게 Dapp에서 쓰이는 스마트 컨트랙트라고 하면 이야기가 많이 복잡해집니다.
이 수수료시스템의 실례는 제 포스팅 최대출연자 중 한명이신 님의 크립토키티(cryptoKitties) 4편 쉬운 사용과 전망 글 이더리움에 미친 영향에 잘 나와있습니다.
이렇게 사용자가 모든 수수료를 내야한다는 수수료 체계가 이더리움의 큰 문제점이 되고 있죠. 수수료를 댑 개발자가 감당하게 하는 EOS와 비교되는 점이기도 하구요.
두 번째 설명 드려야할 것은 사용한 gas가 gaslimit를 초과한 경우입니다. 위의 예처럼 가다가 서버린 경우, 거기까지 사용한 휘발유는 아무도 돌려주지 않죠. 이더리움도 마찬가지입니다. 거기까지 사용된 gas는 아무도 돌려주지 않습니다. 사용한 gas양에 gasprice를 곱한 수수료, 즉 이더(다 썼으니 gaslimit에 gasprice를 곱한 것과 같겠죠. 그것은 처음 트랜잭션에 넣은 이더의 양이구요)는 그 트랜잭션을 블록에 담은 채굴자가 그냥 꿀꺽합니다.
다른 계약계정을 사용하는 스마트 컨트랙트에서 gaslimit를 넉넉히 잡아야하는 이유가 여기 있습니다. A와 B가 어디로 갈지 모르기 때문에 넉넉히 기름을 채워야 부산까지 갈 수 있는 것처럼, 스마트 컨트랙트에서도 A와 B의 계약계정의 컨트랙트가 gas를 얼마나 사용하는지 정확히 모르면 gaslimit를 넉넉히 잡아야합니다.
위의 예 같은 경우, 저는 견인차를 부르든 기름을 사오든 어떻게든 부산에 갈 수 있겠지만 스마트 컨트랙트의 경우 gaslimit 의 가스를 다 써버리면 실행은 즉각 중지되고 이제까지 실행되었던 것도 원상복귀됩니다. 저를 서울로 다시 날려버리는거죠.
ICO의 경우 gaslimit를 넉넉하게 잡아달라고 하는 것도 이 이유입니다. ICO내에서 소모되는 gas의 양을 유저가 정확히 알 수없으니 원상복구되지 않도록 넉넉히 넣어달라는 것입니다.
처음에 기름을 가득 넣어서 출발하면 이런 문제가 안 생길텐데 굳이 gaslimit라는 건 왜 만들어었을까요?
차도 기름을 많이 넣으면 차가 무거워지듯이 이더리움의 gaslimit도 너무 크게 책정하면 문제가 될 수 있습니다.
바로 이더리움의 블록 구조와 관계된 일인데 이더리움 블록에는 한 블록이 담을 수 있는 gaslimit의 총량이 정해져있습니다. 이 Block gas limit은 채굴자가 설정할 수 있다고 알려져 있지만 한계가 있는 것이 사실입니다.
따라서 수수료가 수입원인 블록 생성자에겐 적절한 gaslimit을 가지고 수수료를 많이 발생시킬 수있는 트랜잭션들이 선호되고 먼저 블록에 담기게 됩니다.
현재 이더스캔에 나오는 블록 하나에서 사용된 가스와 가스리밋입니다. 저렇게 거의 다 사용됩니다.
마지막으로, 이더리움이 가득이나 용량문제가 터져나오고 있는데 수수료에 관한 데이터를 블록에 담으면서까지 수수료체계를 복잡하게 만든 이유는 무엇일까요?
가장 큰 이유는 이더리움의 언어 솔리더티의 튜링완전함과 관계가 있습니다.
튜링 완전하다는 의미는 무한 루프가 가능하다, 즉 하나의 코드를 계속해서 반복 실행할 수 있다는 의미입니다.
쓸데없는 내용을 무한 반복함으로써 전체 네트워크를 공격하는 방법에 대해 모든 실행에 수수료를 부과하는 체계로 막는 것입니다. 반복 실행도 한번 실행마다 gas가 소모되고 gaslimit을 초과하면 모두 원상복구 되므로 저런 공격에 엄청난 수수료가 들어갑니다. 따라서 공격을 하려면 어마어마한 돈을 가지고 소비해야하니 굳이 할 필요가 없어지는 거죠.
글 쓴다고 상당히 오래 걸렸는데 쉽게 써졌는지 잘 모르겠네요.ㅎㅎ
나름 예를 든다고 들었는데 잘못 들었나 하는 생각도 들고 ^^
평소에는 이렇게 열심히 글 쓰고 나면 우리 자식들이 알아서 커주던데..이번 주는 택도 없네요..ㅠㅠ
재미없는 긴 글 읽으신다고 고생하셨습니다~~
고생하신 분들과 오늘 심란하신 분들을 위해 힐링되는 노래 하나 ^^(1분 부터 들으셔도 되요)
제일 좋아하는 건 유희열의 스케치북 버전인데..아무래도 저작권이 걸려서 ㅎ
Ourselves 캠페인
셀프보팅을 하지 않고 글을 올리시고
ourselves 테그를 달아 주시면
많은 분들이 관심 가져 줄꺼에요