출처: Beosin
블록체인 기술의 급속한 발전 속에서 효율성과 유연성이 뛰어난 블록체인 플랫폼인 TON(The Open Network)이 개발자들의 주목을 받고 있습니다.
TON의 독특한 아키텍처와 기능은 탈중앙화 애플리케이션 개발을 위한 강력한 도구와 풍부한 가능성을 제공합니다. 그러나 기능과 복잡성이 증가함에 따라 스마트 컨트랙트의 보안은 점점 더 중요해지고 있습니다. TON의 스마트 컨트랙트 프로그래밍 언어인 FunC는 유연성과 효율성으로 유명하지만 잠재적인 위험과 과제도 많습니다. 안전하고 신뢰할 수 있는 스마트 컨트랙트를 작성하려면 개발자는 FunC 언어의 기능과 잠재적 위험에 대해 깊이 이해해야 합니다.
이 글에서는 TON 블록체인의 스마트 컨트랙트와 관련된 몇 가지 기능과 간과하기 쉬운 TON 스마트 컨트랙트의 취약점에 대해 자세히 분석해 보겠습니다.
TON 비동기 기능 및 계정 메커니즘 분석
스마트 컨트랙트 비동기 호출
네트워크 샤딩과 비동기 통신
Ton 블록체인은 마스터체인, 워킹체인, 샤드체인의 세 가지 유형으로 구분되도록 설계되었습니다.
마스터체인은 전체 네트워크의 핵심으로, 전체 네트워크의 메타데이터와 합의 메커니즘을 저장하는 역할을 담당합니다. 모든 워킹체인과 샤드체인의 상태를 기록하고 전체 네트워크의 일관성과 보안을 보장합니다. 워킹 체인은 특정 유형의 트랜잭션과 스마트 컨트랙트 처리를 담당하는 최대 2^32개의 항목으로 구성된 독립적인 블록체인입니다. 각 작업 체인은 다양한 애플리케이션 요구 사항을 충족하기 위해 고유한 규칙과 기능을 가질 수 있습니다. 분할 체인은 작업 체인의 하위 체인으로, 처리 능력과 확장성을 개선하기 위해 작업 체인의 부하를 더 분할하는 데 사용됩니다. 각 작업 체인은 최대 2^60개의 샤드 체인으로 분할되며, 샤드 체인은 일부 트랜잭션을 독립적으로 처리하여 효율적인 병렬 처리를 달성합니다.
이론적으로 각 계정은 하나의 샤드 체인을 차지할 수 있고, 각 계정은 자체 코인/토큰 잔액을 독립적으로 유지하며, 각 계정 간의 거래는 완전히 병렬화될 수 있습니다. 계정은 비동기 메시지를 통해 전달되며, 샤드 체인 간의 메시지 경로는 log_16(N) - 1이며, 여기서 N은 샤드 체인의 수입니다.
그림 출처: https:// frontierlabzh.medium.com/ton-web3world-weixin-e1d3ae3b3574
톤에서 스마트 컨트랙트는 메시지를 주고받으며 상호 작용합니다. 이러한 메시지는 내부 메시지(일반적으로 서로 상호작용하는 스마트 컨트랙트가 보내는 메시지) 또는 외부 메시지(외부 소스에서 보내는 메시지)일 수 있습니다. 메시지 전달 프로세스는 대상 콘트랙트의 즉각적인 응답을 기다릴 필요가 없으며, 발신자는 나머지 로직 코드를 계속 실행할 수 있습니다. 이러한 비동기 메시징 메커니즘은 이더리움의 동기식 호출에 비해 유연성과 확장성이 뛰어나 응답 대기로 인한 성능 병목 현상을 줄여주는 동시에 동시성 및 경쟁 조건을 처리하는 데 어려움을 겪을 수 있습니다.
메시지 형식 및 구조
톤에서 메시지는 일반적으로 발신자, 수신자, 금액, 메시지 본문과 같은 정보를 포함합니다. 메시지 본문은 함수 호출, 데이터 전송 또는 기타 사용자 정의 콘텐츠일 수 있습니다.
톤에서 사용하는 메시지 형식은 유연하게 정의하고 확장할 수 있어 서로 다른 컨트랙트 간에 다양한 유형의 정보를 효율적으로 전송할 수 있습니다.
메시지 큐 및 상태 처리
각 컨트랙트는 아직 처리되지 않은 메시지를 저장하는 메시지 큐를 유지합니다. 컨트랙트는 실행 중에 큐에 있는 메시지를 기반으로 하나씩 처리됩니다. 메시지 처리는 비동기식이기 때문에, 컨트랙트의 상태는 메시지가 수신될 때까지 즉시 업데이트되지 않습니다.
비동기 메시징의 장점
-효율적인 슬라이싱 메커니즘: 톤의 비동기 메커니즘은 슬라이싱 설계와 호환성이 높습니다. 각 슬라이스는 컨트랙트 메시지와 상태 변경을 독립적으로 처리하므로 슬라이스 간 동기식 통신과 관련된 지연 문제를 피할 수 있습니다. 이 설계는 전체 네트워크의 처리량과 확장성을 향상시킵니다.
-리소스 소비 감소: 비동기 메시지는 즉각적인 응답이 필요하지 않으므로 톤의 컨트랙트 실행을 여러 블록에 분산하여 단일 블록 내에서 과도한 리소스 소비를 피할 수 있습니다. 이를 통해 톤은 더 복잡하고 리소스 집약적인 스마트 컨트랙트를 지원할 수 있습니다.
-내결함성 및 안정성: 비동기 메시징은 시스템의 내결함성을 높여줍니다. 예를 들어, 리소스 제약이나 기타 이유로 인해 컨트랙트가 적시에 메시지에 응답할 수 없는 경우에도 발신자는 다른 로직 작업을 계속할 수 있으며, 개별 컨트랙트의 지연으로 인해 시스템이 멈추지 않습니다.
비동기 컨트랙트 설계의 과제
-상태 일관성 문제: 메시징은 비동기적이기 때문에 컨트랙트의 상태가 순간마다 다른 메시지를 받을 수 있으므로 개발자는 상태 일관성 문제에 특별한 주의를 기울여야 합니다. 컨트랙트를 설계할 때는 다양한 메시지 시퀀스로 인해 발생할 수 있는 상태 변화를 고려하여 시스템이 어떤 상황에서도 일관성을 유지할 수 있도록 하는 것이 중요합니다.
-경쟁 조건과 가드: 비동기 메시지 처리에는 여러 메시지가 동시에 컨트랙트 상태를 수정하려고 시도하는 경쟁 조건의 잠재적 문제가 발생합니다. 개발자는 상태 충돌을 방지하기 위해 적절한 잠금 메커니즘을 도입하거나 트랜잭션 작업을 사용해야 합니다.
-보안 고려사항: 비동기 컨트랙트는 컨트랙트 간 통신을 처리할 때 중간자 공격이나 리플레이 공격에 취약합니다. 따라서 비동기식 컨트랙트를 설계할 때는 이러한 잠재적인 보안 위험을 고려하고 타임스탬프, 난수 또는 다중 서명 사용과 같은 보안 위험을 방지할 수 있는 조치를 취하는 것이 중요합니다.
원장 모델
Ton(오픈 네트워크)은 블록체인 인프라를 설계할 때 고유한 계정 추상화 및 원장 모델을 사용합니다. 이 모델의 유연성은 계정 상태, 메시징, 컨트랙트 실행을 처리하는 방식에 반영되어 있습니다.
계정 추상화
톤의 계정 모델은 각 계정을 하나의 계약으로 간주할 수 있는 계약 기반 추상화를 사용하며, 이는 이더의 계정 추상화 모델과 일부 유사점을 공유하지만 더 유연하고 일반적입니다. 톤에서 계정은 단순히 자산을 보관하는 컨테이너가 아니라 컨트랙트 코드와 상태 데이터도 포함합니다. 각 계정은 코드, 데이터, 메시지 처리 로직으로 구성됩니다.
계정 구조: 각 Ton 계정에는 계정 코드의 해시, 배포 시 초기 데이터 및 기타 여러 매개변수의 조합인 고유 주소가 있습니다. 즉, 동일한 코드와 초기 데이터를 다른 환경(예: 다른 블록체인 또는 샤드)에 배포하면 다른 주소가 생성될 수 있습니다.
유연성: 각 계정은 자체 컨트랙트 코드를 실행할 수 있기 때문에 톤의 계정은 매우 복잡한 로직을 구현할 수 있습니다. 계정은 단순한 잔고 보유자를 넘어 복잡한 상태 전송, 계정 간 메시지 통신, 특정 조건에 따른 자동화된 작업까지 처리할 수 있습니다. 따라서 톤의 계정 모델은 기존 블록체인의 계정보다 훨씬 더 확장성과 유연성이 뛰어납니다.
원장 아키텍처
톤의 원장 아키텍처는 비동기 메시징과 멀티슬라이스 작업을 지원하여 대규모 동시 트랜잭션을 효율적으로 처리하도록 설계되었습니다. 각 계정의 상태는 머클 트리 구조에 저장되어 톤의 원장에 효율적인 상태 검증 기능을 제공합니다.
상태 저장소
계정 상태 정보는 영구 저장소에 저장되고 머클 트리를 통해 정리되어 상태 무결성과 보안을 보장합니다. 이 설계는 특히 교차 분할 트랜잭션 시나리오에서 상태의 효율적인 쿼리 및 유효성 검사를 지원합니다.
계정 또는 스마트 콘트랙트 상태에는 일반적으로 다음이 포함됩니다.
1. 기본 통화의 잔액
2. 다른 통화의 잔액
3. 스마트 콘트랙트 코드(또는 해시)
4. 스마트 콘트랙트의 영구 데이터(또는 머클 해시)
5. 영구 저장 장치 수에 대한 통계 및 원시 바이트 수에 대한 사용된 원시 바이트 수에 대한 통계
6. 스마트 컨트랙트에 의해 유지된 가장 최근 결제 시간(실제로는 메인체인 블록 번호)
7. 이 계정에서 통화를 전송하고 메시지를 보내는 데 필요한 공개 키(선택 사항, 기본적으로 계정_id 자체와 같음)
8. 경우에 따라 비트코인 트랜잭션 출력과 유사하게 더 복잡한 서명 확인 코드를 여기에서 찾을 수 있으며, 계정_id는 이 코드의 해시값과 같을 것입니다.
이 모든 정보가 모든 계정에 필요한 것은 아닙니다. 예를 들어 스마트 컨트랙트 코드는 스마트 컨트랙트에만 적용되며 '단순' 계정에는 적용되지 않습니다. 또한 모든 계정은 기본 통화(예: 기본 작업 체인의 메인 체인 및 샤드 체인의 경우 그램)의 잔액이 0이 아니어야 하지만, 다른 통화는 잔액이 0일 수 있습니다. 사용하지 않은 데이터가 남는 것을 방지하기 위해, 작업 체인 생성 시 서로 다른 태그가 붙은 바이트를 사용해 서로 다른 '충분한 기능'을 구분하는 합계-제품 유형이 정의됩니다. 궁극적으로 계정 상태 자체는 TVM 퍼시스턴트 저장소에 단위 모음으로 저장됩니다.
메시징 및 처리
Ton의 원장 구조는 각 계정이 수신 메시지를 독립적으로 처리하고 상태를 업데이트할 수 있는 비동기 메시징을 기본적으로 지원합니다. 이 비동기 메시징 메커니즘은 한 작업의 지연이 다른 계정의 정상적인 작동에 영향을 미치지 않고 계정 간의 복잡한 상호작용을 가능하게 합니다.
가스 모델
톤(오픈 네트워크) 블록체인은 스마트 컨트랙트 실행에 소비되는 리소스의 양을 측정하고 제한하기 위해 블록체인에서 사용되는 고유한 가스 수수료 모델을 통해 스마트 컨트랙트 실행의 효율성을 극적으로 최적화합니다. 톤의 모델은 이더와 같은 기존 블록체인의 가스 모델보다 더 정교하고 효율적으로 설계되었으며, 계약 실행 중 리소스 소비를 보다 정확하게 관리할 수 있습니다.
정교한 가스 소비량 측정
톤의 가스 모델은 스마트 컨트랙트가 실행되는 동안 소비되는 컴퓨팅 리소스, 스토리지 운영, 메시징 비용을 정확하게 측정합니다. 톤의 가스 모델은 컴퓨팅, 스토리지, 메시징 리소스를 세밀하게 측정하여 지나치게 복잡한 특정 작업이 너무 많은 리소스를 소비하는 것을 방지합니다. 톤은 가스 소비를 제한함으로써 네트워크의 각 노드가 컴퓨팅 리소스를 공평하게 분배하고 단일 컨트랙트나 작업으로 인해 네트워크 리소스가 과도하게 소비되는 것을 방지합니다.
병렬 처리 및 가스 최적화
톤은 스마트 컨트랙트의 병렬 처리를 지원하여 여러 컨트랙트가 서로를 차단하지 않고 서로 다른 샤드에서 동시에 실행될 수 있도록 합니다. 이러한 설계에서 가스 모델은 병렬 실행 및 샤딩 메커니즘과 긴밀하게 결합되어 있습니다. 여러 샤드에서 계약을 병렬로 처리함으로써 톤은 가스 계산과 결제를 여러 노드와 체인에 분산하여 네트워크 정체를 방지하고 리소스 활용을 극대화할 수 있습니다.
동적 가스 조정 메커니즘
톤의 가스 모델에는 실시간 네트워크 부하에 따라 가스 요금을 조정할 수 있는 동적 조정 메커니즘이 포함되어 있습니다. 즉, 네트워크 부하가 낮을 때 사용자는 더 낮은 가스 요금으로 계약을 체결할 수 있으므로 부하가 낮은 시간대에 운영을 장려하고 네트워크의 리소스 사용량을 균형 있게 조정할 수 있습니다. 이 메커니즘은 사용자 경험을 개선할 뿐만 아니라 시장 기반 접근 방식을 통해 리소스의 피크 사용량을 제어합니다.
Ton 스마트 컨트랙트는 쉽게 무시되는 취약점을 가지고 있습니다
< href="https://www.jinse.cn/blockchain/3693214.html" target="_blank" textvalue="previous TON의 보안 분석 기사">에서 톤 생태계의 일반적인 보안 취약점에 대해 자세히 설명했으며,
이 기사에서는 우리 팀이 요약한 TON 컨트랙트에서 간과하기 쉬운 취약점을 집중적으로 살펴봅니다.
(1) 코드 가독성 최적화
TON의 스마트 컨트랙트에서는 메시지를 저장하는 데 숫자가 사용됩니다. 예를 들어, 다음 코드에서는 해당 로고와 데이터 저장 길이를 나타내기 위해 숫자가 여러 번 사용되어 코드의 가독성과 유지보수성을 크게 떨어뜨립니다. 다른 개발자가 코드를 읽을 때 이러한 숫자의 의미와 용도를 이해하기 어렵기 때문에 코드의 가독성과 유지보수성이 떨어집니다. 코드의 가독성과 유지보수성을 높이려면 주요 숫자 값을 명명된 상수로 정의하는 것이 좋습니다(예: 0x18은 NON_BOUNCEABLE로 정의).
check_std_addr(address);var msg = begin_cell()&. nbsp; store_uint(0x18, 6) ;;; nobounce store_slice(address) store_coins (금액) store_uint(0, 1 + 4 + 4 + 64 + 32 + 1 +  1) end_cell();send_raw_message(msg, 1);
또한 오류 메시지의 컨트랙트 판단 조건에서 오류 코드를 대체할 해당 변수를 정의하는 것도 동일하게 권장합니다.
이미지 src="https://img.jinse.cn/7293285_image3.png" title="7293285" alt="Spt0xg4c3qeRweqNIVusRoWj5TrX0LUyVjz5eMJl.jpeg">
(2) end_parse()를 사용하여 데이터 무결성 보장
TON 컨트랙트에서 데이터 파싱은 정해진 순서를 따라 원시 데이터에서 지정된 유형의 데이터를 점진적으로 로드합니다. 이 구문 분석은 데이터 일관성과 정확성을 보장합니다. 아래 그림과 같이:
이미지 src="https://img.jinse.cn/7293286_image3.png" title="7293286" alt="6X01fhbPAcVmA1Qn13Z4qn43rN9VxnNDsbSFl0qi.jpeg"> p>
여기에서 end_parse()는 데이터 슬라이스(슬라이스)가 비어 있는지 확인하는 데 사용되며, 슬라이스가 비어 있지 않으면 이 함수는 예외를 던집니다. 이렇게 하면 데이터의 형식과 내용이 예상과 일치하는지 확인할 수 있습니다. end_parse() 함수가 데이터 슬라이스에 아직 데이터가 남아 있는 것을 발견하면 데이터 구문 분석이 예상대로 정확하게 진행되지 않았거나 데이터 형식에 문제가 있음을 나타낼 수 있습니다. 따라서 end_parse()를 호출하여 구문 분석 중에 데이터에 누락이나 이상이 있는지 확인할 수 있습니다.
(3) 데이터 레코드와 저장 타입의 불일치로 인한 예외
여기서 주로 설명해야 할 것은 int와 uint의 접근 타입의 일치입니다. 아래 코드에서는 int 타입의 값을 -42로 저장하기 위해 store_int()를 사용하여 데이터를 저장하고 있는데, 값을 로드할 때 load_uint()를 사용했기 때문에 여기서 예외가 발생할 수 있습니다. 예외가 발생할 수 있습니다.
(4) 인라인_ref와 인라인 수정자의 현명한 사용
우선, 인라인_ref와 인라인 수정자의 차이점을 설명해야 합니다.
l인라인: 인라인 수정자를 사용하는 함수는 호출할 때마다 호출 위치에 코드가 직접 삽입됩니다. 즉, 함수가 호출될 때마다 일반 함수처럼 함수 본문으로 이동하여 실행되는 것이 아니라 함수의 실제 코드가 호출된 위치로 복사됩니다.
linline_ref: inline_ref 수정자를 사용하는 함수는 코드가 별도의 셀에 저장됩니다. 함수가 호출될 때마다 TVM은 호출 위치에 함수 코드를 삽입하는 대신 CALLREF 명령을 통해 셀에 저장된 코드를 실행합니다.
따라서 인라인 수정자는 단순한 함수에 적용되어 함수 호출 오버헤드를 줄이지만 잠재적으로 계약 코드 중복을 유발할 수 있는 반면, 인라인_ref 수정자는 보다 복잡한 함수나 여러 번 호출되는 함수에 적용되어 효율성을 높이고 함수 코드를 별도의 셀에 저장하여 코드 중복을 방지할 수 있습니다. 따라서 함수가 크거나 여러 곳에서 호출되는 경우, 또는 그 반대의 경우에도 inline_ref를 권장한다고 요약할 수 있습니다.
(5) 올바른 작업 체인 결정
톤은 최대 2^32개의 작업 체인을 생성할 수 있으며, 각 체인은 2^60개까지 세분화할 수 있다. 1)과 기본 체인(0). 컨트랙트에서 목적지 주소를 계산할 때, 생성된 지갑 주소가 올바른 작업 체인에 있는지 확인하기 위해 목적지 주소가 속한 체인 ID를 명시적으로 지정해야 합니다. 잘못된 주소가 생성되는 것을 방지하기 위해 force_chain()을 사용하여 체인 ID를 지정하는 것이 좋습니다.
(6) 에러 코드 충돌 방지
계약 설계에서 에러 코드 관리는 정상성을 보장하고 혼란을 피하기 위해 매우 중요합니다. TON 스마트 컨트랙트의 경우 첫째, 에러 코드에 대한 혼란과 불명확한 정보를 방지하기 위해 각 에러 코드가 컨트랙트에서 고유하도록 하고 동일한 컨트랙트에 중복 에러 코드를 정의하지 않아야 하며 둘째, TON 플랫폼 또는 기반 시스템이 일부 표준 에러 코드를 정의했으며 이러한 시스템 에러 코드와의 충돌(예: 333 에러 코드가 나타내는 체인 ID의 불일치)을 피해야 합니다. 따라서 컨트랙트의 오류 코드는 400에서 1000 사이가 바람직합니다.
(7) 연산이 완료된 후 데이터를 저장하고 반환()을 호출해야 합니다.
TON 스마트 컨트랙트에서 메시지 처리는 연산 코드에 따라 다른 로직을 선택합니다. 해당 연산 코드 로직이 완료된 후 두 가지 연산을 더 완료해야 합니다. 첫째, 데이터 변경이 포함된 경우 save_data()를 호출하여 데이터가 저장되었는지 확인해야 하며, 그렇지 않으면 변경이 무효화되고 둘째, 반환()을 호출하여 연산이 완료되었음을 나타내야 하며, 그렇지 않으면 throw(0xffff) 예외가 트리거됩니다.
() recv_internal(int my_balance, int msg_value, cell in_msg_full, slice in_msg_body) impure {
int flags = cs~load _uint(4);
if (flags & 1) {
; 반송된 모든 메시지 무시
return ();
} 코드><코드>슬라이스 발신자 주소 = cs~load_msg_addr();코드><코드>load_data();코드><코드>int op = in_msg_body~load_op();코드><코드> if ((op == op::op_1())) {
handle_op1();
save_data();
return ();
} code>if ((op == op::op_2())) {
handle_op2();
save_data();
return ();
}
if ((op == op::op_3())) {
handle_op3();
save_data();
return ( );
}
throw(0xffff);
}
요약하자면, TON 블록체인은 혁신적인 아키텍처와 유연한 개발 환경 덕분에 탈중앙화 애플리케이션 개발자들에게 이상적인 플랫폼으로 점차 자리잡아가고 있습니다. 그러나 스마트 컨트랙트가 TON 생태계에서 점점 더 중요한 역할을 하고 있기 때문에 컨트랙트 보안 문제도 무시할 수 없습니다. 개발자는 TON 생태계의 특성을 이해하고 엄격한 모범 사례를 따르며 보안 감사 프로세스를 강화하여 계약의 견고성과 보안을 보장해야 합니다. 이렇게 해야만 TON 플랫폼의 장점을 최대한 활용하고, 더욱 안전하고 신뢰할 수 있는 탈중앙화 애플리케이션을 구축하고, 전체 생태계의 건전한 발전을 보호할 수 있습니다.
TON 생태계는 현재 많은 자본과 적극적인 사용자를 유치하며 빠르게 발전하고 있습니다. 그러나 그에 따른 보안 문제도 무시할 수 없습니다.