TVM 초기화
이 페이지의 이해도를 극대화하려면 TL-B 언어를 숙지하는 것이 좋습니다.
TVM은 일반 및/또는 기타 트랜잭션의 컴퓨팅 단계에서 호출됩니다.
초기 상태
TVM의 새 인스턴스는 스마트 컨트랙트를 실행하기 전에 다음과 같이 초기화됩니다:
원래 cc(현재 연속)는 스마트 컨트랙트의
코드
섹션에서 생성된 셀 슬라이스를 사용하여 초기화됩니다. 계정이 정지되었거나 초기화되지 않은 상태인 경우, 수신 메시지의init
필드에 코드를 제공해야 합니다.cp**(현재 TVM 코드 페이지)는 기본값인 0으로 설정되어 있습니다. 스마트 컨트랙트가 다른 TVM 코드 페이지 x를 사용하려면 코드의 첫 번째 명령어로
SETCODEPAGE
x를 사용하여 해당 코드 페이지로 전환해야 합니다.가스** 값(가스 한도)은 신용 단계 결과에 따라 초기화됩니다.
라이브러리**(라이브러리 컨텍스트) 계산은 아래 설명입니다.
스택** 초기화 프로세스는 트랜잭션을 발생시킨 이벤트에 따라 달라지며, 그 내용은 아래 설명과 같습니다.
제어 레지스터 c0(반환 연속)는 매개변수 0을 가진 특수 연속
ec_quit
에 의해 초기화됩니다. 이 연속이 실행되면 종료 코드 0으로 TVM이 종료됩니다.제어 레지스터 c1(대체 반환 연속)은 파라미터 1을 가진 예외적 연속
ec_quit
에 의해 초기화됩니다. 호출되면 종료 코드 1로 TVM이 종료됩니다. 종료 코드 0과 1 모두 TVM이 성공적으로 종료된 것으로 간주됩니다.제어 레지스터 c2(예외 처리기)는 예외 연속
ec_quit_exc
에 의해 초기화됩니다. 호출되면 스택에서 최상위 정수(예외 번호와 동일)를 가져와 해당 정수와 동일한 종료 코드로 TVM을 종료합니다. 이렇게 하면 기본적으로 모든 예외는 예외 번호와 동일한 종료 코드로 스마트 컨트랙트 실행을 종료합니다.제어 레지스터 c3(코드 사전)은 위에서 설명한 cc(현재 연속)와 같은 스마트 컨트랙트 코드로 셀에 의해 초기화됩니다.
제어 레지스터 c4(영구 데이터의 루트)는 스마트 컨트랙트의 영구 데이터에 의해 초기화되며,
데이터
섹션에 저장됩니다. 계정이 정지되었거나 초기화되지 않은 상태인 경우, 수신 메시지의init
필드에 데이터를 제공해야 합니다. 이 경우 스마트 컨트랙트의 영구 데이터를 입력란에 로드할 필요가 없다는 점에 유의하세요. 대신 루트가 로드되며, TVM은 다른 셀이 액세스될 때만 루트에서 참조하여 다른 셀을 로드할 수 있으므로 일종의 가상 메모리를 제공합니다.제어 레지스터 c5(액션의 루트)는 빈 셀로 초기화됩니다. TVM의 "출력 액션" 프리미티브(예:
SENDMSG
)는 스마트 컨트랙트가 성공적으로 종료될 때 수행될 출력 액션(예: 아웃바운드 메시지)을 이 레지스터에 누적합니다. 직렬화를 위한 TL-B 체계는 아래 설명입니다.제어 레지스터 c7(임시 데이터의 루트)는 튜플로 초기화되며, 그 구조는 아래 설명입니다.
라이브러리 컨텍스트
스마트 컨트랙트의 라이브러리 컨텍스트(라이브러리 환경)는 256비트 셀(표현) 해시를 해당 셀 자체에 매핑하는 해시맵입니다. 스마트 컨트랙트 실행 중에 외부 셀 참조에 액세스하면 라이브러리 환경에서 참조된 셀을 조회하고 외부 셀 참조는 발견된 셀로 투명하게 대체됩니다.
스마트 컨트랙트 호출을 위한 라이브러리 환경은 다음과 같이 계산됩니다:
- 현재 워크체인에 대한 글로벌 라이브러리 환경은 마스터체인의 현재 상태에서 가져옵니다.
- 그런 다음 스마트 컨트랙트의 로컬 라이브러리 환경에 의해 증강되어 스마트 컨트랙트 상태의 '라이브러리' 필드에 저장됩니다. 해당 값 셀의 해시와 동일한 256비트 키만 고려됩니다. 키가 글로벌 및 로컬 라이브러리 환경 모두에 있는 경우, 병합 시 로컬 환경이 우선합니다.
- 마지막으로, 수신 메시지의
init
필드(있는 경우)의library
필드에 의해 보강됩니다. 계정이 동결되었거나 초기화되지 않은 경우 메시지의도서관
필드는 이전 단계의 로컬 라이브러리 환경보다 우선적으로 사용된다는 점에 유의하세요. 메시지 라이브러리는 로컬 및 글로벌 라이브러리 환경보다 우선순위가 낮습니다.
TVM을 위한 공유 라이브러리를 만드는 가장 일반적인 방법은 마스터체인에 라이브러리의 루트 셀에 대한 참조를 게시하는 것입니다.
스택
TVM 스택의 초기화는 TVM의 초기 상태가 형성된 후에 이루어지며, 트랜잭션을 유발한 이벤트에 따라 달라집니다:
- 내부 메시지
- 외부 메시지
- 틱톡
- 분할 준비
- 설치 병합
스택에 푸시되는 마지막 항목은 항상 트랜잭션을 유발한 이벤트를 식별하는 정수인 함수 선택기입니다.
내부 메시지
내부 메시지의 경우 다음과 같이 스마트 컨트랙트의 main()
함수에 인수를 푸시하여 스택을 초기화합니다:
- 스마트 컨트랙트의 잔액 b는 (인바운드 메시지 값을 신용한 후) 나노톤의 정수 양으로 전달됩니다.
- 인바운드 메시지 m의 잔액 _b_m은 나노톤의 정수 양으로 전달됩니다.
- 인바운드 메시지 m은 셀로 전달되며, 여기에는 메시지 X 유형의 직렬화된 값이 포함됩니다(여기서 X는 메시지 본문의 유형입니다).
- 인바운드 메시지의 본문 m-b는 필드 본문 m 값과 동일하며 셀 슬라이스로 전달됩니다.
- 함수 선택기 s는 일반적으로 0과 같습니다.
그 후, 초기 값 c3와 동일한 스마트 컨트랙트의 코드가 실행됩니다. s_에 따라 올바른 함수를 선택하며, 이후 함수에 대한 나머지 인수를 처리하고 종료될 것으로 예상됩니다.
외부 메시지
인바운드 외부 메시지는 위에서 설명한 내부 메시지와 유사하게 처리되지만 다음과 같은 수정 사항이 있습니다:
- 함수 선택기 s가 -1로 설정되어 있습니다.
- 인바운드 메시지의 잔액 _b_m은 항상 0입니다.
- 초기 현재 가스 한도 _g_l은 항상 0입니다. 그러나 초기 가스 크레딧 _g_c는 0을 초과합니다.
스마트 콘트랙트는 _G_C = 0 또는 _G_R ≥ _G_C로 종료되어야 하며, 그렇지 않으면 트랜잭션과 이를 포함하는 블록은 유효하지 않습니다. 블록 후보를 제안하는 검증자 또는 콜레이터는 유효하지 않은 인바운드 외부 메시지를 처리하는 트랜잭션을 포함하지 않아야 합니다.
틱 앤 틱
틱 앤 틱 트랜잭션의 경우, 스택은 다음과 같이 스마트 컨트랙트의 main()
함수에 인수를 푸시하여 초기화됩니다:
- 현재 계정의 잔액 b는 나노톤의 정수 금액으로 전달됩니다.
- 마스터체인 내 현재 계정의 256비트 주소는 서명되지 않은 Integer입니다.
- 틱 트랜잭션의 경우 0, 틱 트랜잭션의 경우 -1에 해당하는 정수입니다.
- 함수 선택기 s는 -2와 같습니다.
분할 준비
분할 준비 트랜잭션의 경우, 스택은 다음과 같이 스마트 컨트랙트의 main()
함수에 인수를 푸시하여 초기화됩니다:
- 현재 계정의 잔액 b는 나노톤의 정수 금액으로 전달됩니다.
- 분할 병합 정보를 포함하는 슬라이스.
- 현재 계정의 256비트 주소입니다.
- 형제 계정의 256비트 주소입니다.
- 현재 계정과 형제 계정의 주소가 다른 유일한 비트의 위치와 같은 정수 0 ≤ d ≤ 63입니다.
- 함수 선택기 s는 -3과 같습니다.
설치 병합
병합 설치 트랜잭션의 경우 다음과 같이 스마트 컨트랙트의 main()
함수에 인수를 푸시하여 스택을 초기화합니다:
- 현재 계좌의 잔액 b(이미 형제 계좌의 나노톤 잔액과 합산됨)는 나노톤의 정수 금액으로 전달됩니다.
- 인바운드 메시지 m에서 가져온 형제 계정의 잔액 b'는 나노톤의 정수 양으로 전달됩니다.
- 병합 준비 트랜잭션에 의해 자동으로 생성된 형제 계정에서 m 메시지가 나타납니다. 이 메시지의
init
필드에는 형제 계정의 최종 상태가 포함됩니다. 메시지는 셀로 전달되며, 이 셀에는 메시지 X 유형의 직렬화된 값이 포함됩니다. 여기서 X는 메시지 본문의 유형입니다. - 형제 계정의 상태(StateInit로 표시됨)입니다.
- 분할 병합 정보를 포함하는 슬라이스.
- 현재 계정의 256비트 주소입니다.
- 형제 계정의 256비트 주소입니다.
- 현재 계정과 형제 계정의 주소가 다른 유일한 비트의 위치와 같은 정수 0 ≤ d ≤ 63입니다.
- 함수 선택기 s는 -4와 같습니다.
제어 레지스터 C5
스마트 컨트랙트의 출력 작업은 제어 레지스터 c5에 저장된 셀에 누적되며, 셀 자체에는 목록의 마지막 작업과 이전 작업에 대한 참조가 포함되어 있어 연결된 목록을 형성합니다.
목록은 OutList n 타입의 값으로 직렬화할 수도 있습니다. 여기서 n은 목록의 길이입니다:
out_list_empty$_ = OutList 0;
out_list$_ {n:#}
prev:^(OutList n)
action:OutAction
= OutList (n + 1);
out_list_node$_
prev:^Cell
action:OutAction = OutListNode;
이에 따라 가능한 작업 목록은 다음과 같이 구성됩니다:
action_send_msg
- 아웃바운드 메시지 전송용action_set_code
- 옵코드 설정용액션_예약_통화
- 통화 컬렉션 저장용액션_변경_라이브러리
- 라이브러리 변경용
해당 TL-B 체계에 설명된 대로:
action_send_msg#0ec3c86d
mode:(## 8)
out_msg:^(MessageRelaxed Any) = OutAction;
action_set_code#ad4de08e
new_code:^Cell = OutAction;
action_reserve_currency#36e6b809
mode:(## 8)
currency:CurrencyCollection = OutAction;
libref_hash$0
lib_hash:bits256 = LibRef;
libref_ref$1
library:^Cell = LibRef;
action_change_library#26fa1dd4
mode:(## 7) { mode <= 2 }
libref:LibRef = OutAction;
제어 레지스터 C7
제어 레지스터 c7에는 임시 데이터의 루트가 시간, 글로벌 구성 등과 같은 몇 가지 기본 블록체인 컨텍스트 데이터를 포함하는 SmartContractInfo 유형으로 구성된 튜플로 포함되어 있습니다. 이는 다음 TL-B 스키마로 설명됩니다:
smc_info#076ef1ea
actions:uint16 msgs_sent:uint16
unixtime:uint32 block_lt:uint64 trans_lt:uint64
rand_seed:bits256 balance_remaining:CurrencyCollection
myself:MsgAddressInt global_config:(Maybe Cell) = SmartContractInfo;
이 튜플의 첫 번째 구성 요소는 Integer 값으로, 항상 0x076ef1ea와 같으며 그 뒤에 9개의 명명된 필드가 이어집니다:
필드 | 유형 | 설명 |
---|---|---|
액션 | uint16 | 원래는 0으로 초기화되지만, 비-ROW 출력 액션 프리미티브에 의해 출력 액션이 설치될 때마다 1씩 증가합니다. |
msgs_sent | uint16 | 전송한 메시지 수 |
유닉스타임 | uint32 | 초 단위의 유닉스 타임스탬프 |
BLOCK_LT | uint64 | 이 계정의 이전 블록의 논리적 시간을 나타냅니다. 논리적 시간에 대해 자세히 알아보기 |
trans_lt | uint64 | 이 계정의 이전 트랜잭션의 논리적 시간을 나타냅니다. |
rand_seed | bits256 | 블록의 rand_seed , 계정 주소, 처리 중인 수신 메시지의 해시(있는 경우), 트랜잭션 논리적 시간 trans_lt 부터 결정론적으로 초기화됩니다. |
balance_remaining | [CurrencyCollection](/개발/데이터 형식/msg-tlb#currencycollection) | 스마트 컨트랙트의 잔액 |
내 자신 | MsgAddressInt | 이 스마트 컨트랙트의 주소 |
글로벌_구성 | (어쩌면 셀) | 글로벌 설정에 대한 정보를 포함합니다. |
곧 있을 TVM 업그레이드에서 c7 튜플이 10개 요소에서 14개 요소로 확장되었음을 참고하세요. 자세한 내용은 여기에서 참조하세요.
참고 항목
- 백서에서 TVM 초기화에 대한 원본 설명 보기