EOSIO, 의도하지 않은 RAM 소모 방지

Jeeyong Um
GameXCoin
Published in
6 min readAug 29, 2018

원문: Preventing Unexpected Ram Consumption by Daniel Larimer

이해를 돕기 위해 의역한 부분이 있습니다. 정확한 내용은 원문을 참조하기 바랍니다.

일부 사용자와 EOSIO 기반 스마트 컨트랙트의 RAM 자원을 의도와 다르게 전문적인 스마트 컨트랙트를 작성한 제3자가 소모하는 일이 발생했습니다. 컨트랙트가 다른 컨트랙트에게 ‘이체 받음’ 같은 이벤트를 통지할 수 있도록 설계된 알림(notification) 기능을 잘못 이해했기 때문입니다. 악의적 컨트랙트는 이 알림 기능을 이용하여 고지에 의한 동의(informed consent) 없이 다른 사람의 RAM을 임의의 데이터로 가득 채우고 이 데이터를 해제할 방법도 제공하지 않았습니다.

개요

  1. 토큰은 도난되지 않았습니다.
  2. 적절하게 구현한 스마트 컨트랙트는 이 문제에 취약하지 않습니다.
  3. 거버넌스 절차는 당사자의 의도에 반하여 동작하는 코드를 수정할 수 있습니다.
  4. 블록 생성자 전용의 완화(mitigation) 옵션을 사용하여 보호할 수 있습니다.
  5. 장기적인 업그레이드를 통해 기본 동작은 보다 안전해질 수 있습니다.

토큰은 도난되지 않았습니다

악의적인 컨트랙트는 스마트 컨트랙트 개발자와 사용자들이 스마트 컨트랙트 개발의 모범 사례에 대해 잘못 이해하고 있는 부분을 이용했습니다. 이 공격은 절도보다는 파괴 행위(vandalism)에 가까우며 EOS 거버넌스 절차가 상황을 검토하여 해결할 수 있다면 관련 당사자에게 장기적인 피해는 주지 않을 것입니다.

악용 방지를 위한 모범 사례

각 사용자는 상호작용하는 컨트랙트를 직접 검토하거나 대신 컨트랙트를 검토하는 제3자를 신뢰해야 합니다. 이는 검토자가 알림 기능을 사용하는 스마트 컨트랙트와 상호작용 할 때 주의해야 한다는 뜻입니다. 한 예로 신뢰하지 않는 스마트 컨트랙트에 자신의 CPU와 RAM 자원으로 토큰을 전송하는 것을 들 수 있습니다.

개발자가 프로그램을 작성하여 신뢰하지 않는 제3자가 지정한 계정으로 토큰을 보낼 때는 비어 있는 RAM 자원이 없는 계정을 통해 이체(transfer)를 릴레이 해야 합니다. 이는 사용자 인출을 처리하는 중앙화 거래소 및 스마트 컨트랙트로 같은 기능을 제공하는 분산 거래소 모두에 적용됩니다. 신뢰할 수 있는 릴레이 컨트랙트가 여러 개 있습니다.

이미 많은 지갑 서비스 제공자들이 “트랜잭션이 RAM을 소모할 수 있다”고 경고하는 조치를 취했습니다.

거버넌스 절차를 통해 소모된 RAM 회복

코드의 취지는 사용자와 개발자가 이해한 대로 이행 되어야 한다고 생각합니다. 만약 악의적인 컨트랙트가 사용자의 의도와 코드의 실제 효과 사이의 불일치를 이용하고 있는 것이 분명하다면 블록 생성자는 악의적 컨트랙트의 작성자와 이와 상호작용 하는 사람들 사이에 분쟁이 중재될 때까지 악의적 컨트랙트를 블랙리스트에 올릴 수 있습니다.

중재 결과 코드의 동작이 코드와 상호작용 하는 당사자의 의도에 반하는 경우 선출된 블록 생성자는 결과가 당사자의 원래 의도와 가능한 한 가깝게 일치하도록 자유롭게 코드를 업데이트 할 수 있습니다. 이 경우 의도하지 않게 소모된 RAM을 비우고 앞으로 RAM을 소모하지 않도록 코드가 업데이트 됩니다.

왜 EOSIO에 이런 기능이 있습니까?

RAM 소모에 악용된 이 기능을 유효하게 사용한 예가 많이 있습니다. 가장 기본적인 사용 예는 사용자의 자금을 입금할 수 있는 게임 컨트랙트입니다. 거래소는 토큰 컨트랙트가 보낸 이체 알림을 처리하는 코드를 구현하여 발신자에게 거래소 상의 잔액을 더합니다. 이 경우 거래소와 입금한 사용자는 사용자의 RAM을 소모하여 잔액을 저장할 권한을 거래소 컨트랙트에 합리적으로 부여할 수 있습니다. 거래소는 사용자의 잔액을 거래소의 RAM 안에 저장하길 원하지 않는데, 이는 다수의 계정에서 먼지 잔액(dust balances, 받은 액수보다 처리 비용이 더 큰 작은 금액)을 보내는 다른 공격이 가능하기 때문입니다.

EOSIO에는 컨트랙트가 다른 컨트랙트의 코드를 현재 트랜잭션의 일부로 호출 할 수 있게 해주는 인라인 액션(inline action)이란 관련 기능이 있습니다. 액션 알림 기능과 다르게 인라인 액션은 인라인 액션을 생성한 컨트랙트의 자원만 할당하도록 제한되어 있습니다. 액션 알림은 원본 액션의 자원 할당 권한을 전달 받습니다.

의도하지 않은 동작 방지를 위한 계획

기존의 설계에서 적법하게 사용한 많은 예가 있지만 우리는 이제 코드의 기본 동작이 사용자나 개발자의 직관과 다르게 작동한다고 생각합니다. 악용 방지를 위해 취해야 하는 단계들이 덜 흔한 사용 예를 단순하게 하기 위해 일반적인 사용 예를 더 복잡하게 만들고 있습니다.

앞으로는 알림 처리자(notification handler)가 알림을 받은 컨트랙트의 RAM을 소모할 권한만 갖도록 제안합니다. 이를 통해 예상치 못한 RAM 소모에 대한 걱정 없이 아무 컨트랙트로나 토큰을 보낼 수 있습니다. 거래소는 사용자의 인출 요청이 있는 경우 사용자 계정에 배포(deploy)된 컨트랙트 확인 없이 안전하게 인출을 처리할 수 있습니다.

제안된 변경 사항이 적용되면, 기존 컨트랙트는 사용자의 가용 RAM 일부를 소모하기 위해 직접 승인을 받아야만 합니다. 거래소 컨트랙트는 사용자에게 예금을 받기 전, “계정을 만들어 잔액을 저장하기 위한 공간을 예약” 하도록 요청합니다. 입금 수신에 대한 알림은 새로 RAM을 할당하는 대신 단순히 사전에 할당된 RAM을 증가시킵니다.

제안된 업그레이드 경로

우리는 액션 알림(예, 토큰 이체 알림)의 수신자가 의도치 않게 발신자의 RAM을 소모하지 않도록 기본 동작을 변경하는 블록 생성자 전용 업그레이드를 준비중입니다. 모든 블록 생성자가 이 업그레이드를 채택하면 악용 완화 계획은 필요 없게 됩니다. 안타깝게도 이 완화 조치는 액션 알림 처리자(action notification handler)가 사용자 계정의 RAM 할당에 의존하지 않도록 업데이트 할 때까지 유효한 컨트랙트를 파기합니다.

다행스러운 것은, 새로운 모범 사례를 채택하기 위해 컨트랙트를 업그레이드하는 과정이 상대적으로 단순할 것이라는 점입니다.

블록 생성자 전용 업그레이드는 다음 투표의 일부로 모든 노드에서 채택됩니다.

결론

EOSIO는 설계대로 작동 중이며 올바르게 사용하면 안전합니다. 우리는 대부분의 사용 사례에서 EOSIO 사용을 적절히 더 쉽게 만들 수 있다고 믿으며, 가능한 가장 강력한 전체 솔루션을 개발하기 위해 EOS 커뮤니티와 함께 노력하고 있습니다.

--

--