지갑 계약 유형
TON 블록체인의 다양한 버전의 지갑에 대해 들어보셨을 것입니다. 하지만 이러한 버전은 실제로 무엇을 의미하며 어떻게 다를까요?
이 글에서는 TON 지갑의 모든 버전과 수정 사항을 살펴보겠습니다.
지갑은 어떻게 다를 수 있을까요?
시작하기 전에 지갑이 어떻게 다른지 먼저 이해해야 합니다.
이더리움, 솔라나 또는 다른 거의 모든 블록체인을 살펴보면 지갑의 종류나 버전이 다양하지 않습니다. 그런데 왜 TON에는 지갑이 존재할까요? TON의 지갑은 스마트 컨트랙트에 의해 만들어지기 때문입니다. 기본적으로 모든 지갑(여러분의 지갑도 포함)은 TON 블록체인에서 실행되는 스마트 컨트랙트이며, 스마트 컨트랙트인 다른 지갑으로 거래를 수락하고 전송할 수 있습니다.
이러한 스마트 컨트랙트는 다양한 방식으로 설정할 수 있으며 다양한 기능을 가질 수 있습니다. 그렇기 때문에 TON에는 여러 버전의 지갑이 있습니다.
기본 지갑
월렛 V1
가장 간단한 방법입니다. 한 번에 하나의 트랜잭션만 전송할 수 있으며 서명과 시퀀스 번호 외에는 아무것도 확인하지 않습니다.
이 버전은 몇 가지 주요 문제가 있기 때문에 일반 앱에서는 사용하지 않습니다:
- 컨트랙트에서 시퀀스 번호와 공개 키를 쉽게 검색할 수 없습니다.
- valid_until` 확인이 없으므로 트랜잭션이 너무 늦게 확인되지 않을지 확신할 수 없습니다.
첫 번째 문제는 V1R2
와 V1R3
에서 수정되었습니다. 이 R
문자는 개정
을 의미합니다. 일반적으로 리비전은 컨트랙트에서 seqno와 공개키를 검색할 수 있는 get-method만 추가하는 작은 업데이트입니다.
하지만 이 버전에는 다음 버전에서 수정되는 두 번째 문제가 있습니다.
지갑 소스 코드:
월렛 V2
이 버전에서는 트랜잭션이 너무 늦게 확인되는 것을 원하지 않을 경우 시간 제한을 설정하는 데 사용되는 valid_until
매개변수가 도입되었습니다. 또한 이 버전에는 V2R2
에 추가된 공개 키에 대한 get-method가 없습니다.
대부분의 경우 사용할 수 있지만 V3
에서 추가된 멋진 기능이 하나 빠져 있습니다.
지갑 소스 코드:
월렛 V3
이 버전에서는 동일한 공개키를 사용해 여러 개의 지갑을 만들 수 있는 subwallet_id
매개변수를 도입했습니다(따라서 하나의 시드 문구와 여러 개의 지갑을 가질 수 있습니다). 그리고 이전과 마찬가지로 V3R2
는 공개 키에 대한 get 메서드만 추가했습니다.
기본적으로 subwallet_id
는 컨트랙트가 배포될 때 컨트랙트 상태에 추가되는 숫자일 뿐입니다. 그리고 TON의 컨트랙트 주소는 상태와 코드의 해시이므로, 지갑 주소는 다른 subwallet_id
로 변경됩니다.
이 버전은 현재 가장 많이 사용되고 있습니다. 대부분의 사용 사례를 지원하며 깔끔하고 단순하게 유지됩니다.
지갑 소스 코드:
월렛 V4
현재 가장 최신 지갑 버전입니다. 이전 버전의 모든 기능을 여전히 가지고 있지만 매우 강력한 기능인 '플러그인'도 도입했습니다.
이 기능을 통해 개발자는 사용자의 지갑과 함께 작동하는 복잡한 로직을 구현할 수 있습니다. 예를 들어, 일부 디앱은 사용자가 일부 기능을 사용하기 위해 매일 소량의 코인을 지불해야 할 수 있으므로 사용자는 트랜잭션에 서명하여 지갑에 플러그인을 설치해야 합니다. 이 플러그인은 외부 메시지에서 코인을 요청할 때 매일 대상 주소로 코인을 전송합니다.
이는 TON 블록체인만의 고유한 사용자 지정 기능입니다.
지갑 소스 코드:
특별 지갑
때로는 기본 지갑의 기능만으로는 충분하지 않을 때가 있습니다. 그렇기 때문에 '고부하', '잠금', '제한' 등 여러 유형의 특수 지갑이 있습니다.
자세히 살펴보겠습니다.
하이로드 월렛 v3
이 지갑은 매우 빠른 속도로 트랜잭션을 전송해야 하는 분들을 위해 만들어졌습니다. 예를 들어 암호화폐 거래소를 들 수 있습니다.
고부하 v3로 전송되는 외부 메시지(전송 요청)에는 다음이 포함됩니다:
- 최상위 셀의 서명(512비트) - 다른 파라미터는 해당 셀의 참조에 있습니다.
- 하위 지갑 ID(32비트)
- 참조로 보낼 메시지(전송될 직렬화된 내부 메시지)
- 메시지 전송 모드(8비트)
- 복합 쿼리 ID - 13 비트의 "시프트"와 10 비트의 "비트 번호"로 구성되지만 비트 번호의 10 비트는 1023이 아닌 1022까지만 올라갈 수 있으며 마지막 사용 가능한 쿼리 ID (8388605)는 비상용으로 예약되어 있으므로 일반적으로 사용해서는 안됩니다.
- 에 생성되었거나 메시지 타임스탬프
- 시간 초과
타임아웃은 하이로드에 매개변수로 저장되며 모든 요청의 타임아웃과 비교하여 확인되므로 모든 요청의 타임아웃은 동일합니다. 메시지는 하이로드 지갑에 도착할 때 타임아웃보다 오래되지 않아야 하며, 코드에서 created_at > now() - timeout
이 필요합니다. 쿼리 ID는 리플레이 보호를 위해 최소 타임아웃, 최대 2 * 타임아웃까지 저장되지만, 타임아웃보다 오래 저장될 것으로 예상해서는 안 됩니다. 하위 지갑 ID는 지갑에 저장된 것과 비교하여 확인됩니다. 지갑의 공개 키에 대한 서명과 함께 내부 참조 해시를 확인합니다.
하이로드 v3는 특정 외부 메시지에서 1 개의 메시지만 보낼 수 있지만 특수 연산 코드를 사용하여 해당 메시지를 자신에게 보낼 수 있으며, 해당 내부 메시지 호출에 액션 셀을 설정할 수 있으므로 외부 메시지 1개당 최대 254 개의 메시지를 효과적으로 보낼 수 있습니다 (이 254 개 중 다른 메시지를 하이로드 월렛으로 다시 보내면 더 많을 수 있습니다).
하이로드 v3는 모든 검사가 통과되면 항상 쿼리 ID(재생 방지)를 저장하지만, 다음과 같은 일부 조건으로 인해 메시지가 전송되지 않을 수 있습니다:
- 상태 초기화 포함 (필요한 경우, 이러한 메시지는 특수 연산 코드를 사용하여 하이로드 지갑에서 자체로 내부 메시지를 보낸 후 액션 셀을 설정할 수 있습니다.)
- 균형이 충분하지 않음
- 잘못된 메시지 구조(외부 아웃 메시지 포함 - 내부 메시지만 외부 메시지에서 바로 보낼 수 있음)
Highload v3는 동일한 query_id
및 created_at
를 포함하는 여러 개의 외부 파일을 실행하지 않습니다. 주어진 query_id
를 잊어버리면 created_at
조건이 이러한 메시지가 실행되지 않도록 합니다. 이렇게 하면 query_id
및 created_at
가 하이로드 v3에 대한 전송 요청의 "기본 키"가 되는 효과가 있습니다.
쿼리 ID를 반복(증분)할 때는 일반 숫자를 증분할 때처럼 비트 수를 먼저 반복한 다음 시프트를 반복하는 것이 수수료 측면에서 더 저렴합니다(TON 사용량 기준). 마지막 쿼리 ID에 도달한 후(긴급 쿼리 ID에 대해 기억하세요 - 위 참조) 쿼리 ID를 0으로 재설정할 수 있지만, 하이로드의 시간 제한 기간이 아직 지나지 않은 경우 재생 보호 사전이 가득 차서 시간 제한 기간이 지나갈 때까지 기다려야 합니다.
하이로드 지갑 v2
레거시 계약의 경우, 고부하 지갑 v3를 사용하는 것이 좋습니다.
이 지갑은 단기간에 수백 건의 트랜잭션을 전송해야 하는 분들을 위해 만들어졌습니다. 예를 들어, 암호화폐 거래소.
한 번의 스마트 컨트랙트 호출로 최대 '254'개의 트랜잭션을 전송할 수 있습니다. 또한 seqno 대신 약간 다른 접근 방식을 사용하여 리플레이 공격을 해결하므로 이 지갑을 한 번에 여러 번 호출하여 초당 수천 개의 트랜잭션을 전송할 수 있습니다.
부하가 많은 지갑을 다룰 때는 다음 제한 사항을 확인하고 고려해야 합니다.
- 스토리지 크기 제한. 현재 컨트랙트 스토리지의 크기는 65535셀 미만이어야 합니다. old_queries의 크기가 이 제한보다 커지면 ActionPhase의 예외가 발생하고 트랜잭션이 실패합니다. 실패한 트랜잭션은 다시 재생될 수 있습니다.
- **현재 가스 한도는 1'000'000개이며, 이는 한 번의 tx에서 삭제할 수 있는 오래된 쿼리의 수에 제한이 있음을 의미합니다. 만료된 쿼리 수가 더 많으면 계약이 중단됩니다.
즉, 만료일을 너무 높게 설정하지 않는 것이 좋습니다: 만료 기간 동안 쿼리 횟수는 1000회를 초과하지 않아야 합니다.
또한 한 트랜잭션에서 정리된 만료된 쿼리의 수는 100개 미만이어야 합니다.
지갑 소스 코드:
잠금 지갑
어떤 이유로 코인을 일정 기간 동안 지갑에 잠가야 하는데 그 시간이 지나기 전에 출금할 수 없다면 잠금 지갑을 살펴보세요.
지갑에서 아무것도 인출할 수 없는 시간을 설정할 수 있습니다. 잠금 해제 기간을 설정하여 설정된 기간 동안 코인을 사용할 수 있도록 사용자 지정할 수도 있습니다.
예를 들어, 총 유효 기간이 10년인 1백만 코인을 보관할 지갑을 만들 수 있습니다. 절벽 기간을 1년으로 설정하면 지갑이 생성된 후 첫 1년 동안 자금이 잠기게 됩니다. 그런 다음 잠금 해제 기간을 한 달로 설정하면 '1'000'000 TON / 120개월 = ~8333 TON'이 매달 잠금 해제됩니다.
지갑 소스 코드:
제한된 지갑
이 지갑의 기능은 일반 지갑처럼 작동하지만 미리 정의한 하나의 목적지 주소로만 이체하도록 제한하는 것입니다. 이 지갑을 만들 때 목적지를 설정하면 해당 지갑에서 해당 주소로만 자금을 이체할 수 있습니다. 하지만 이 지갑으로 유효성 검사기를 실행할 수 있도록 유효성 검사 계약으로 자금을 이체할 수는 있습니다.
지갑 소스 코드:
결론
보시다시피 TON에는 다양한 버전의 지갑이 있습니다. 그러나 대부분의 경우 V3R2
또는 V4R2
만 필요합니다. 주기적인 자금 잠금 해제와 같은 추가 기능을 원한다면 특수 지갑 중 하나를 사용할 수도 있습니다.