Стандартная библиотека FunC
Эта страница переведена сообществом на русский язык, но нуждается в улучшениях. Ес ли вы хотите принять участие в переводе свяжитесь с @alexgton.
В этом разделе обсуждается библиотека stdlib.fc со стандартными функциями, используемыми в FunC.
В настоящее время библиотека является просто оберткой для наиболее распространенного ассемблера команд TVM, которые не являются встроенными. Описание каждой команды TVM, используемой в библиотеке, можно найти в разделе документация TVM. Некоторые описания были взяты для этого документа.
Некоторые функции в файле закомментированы. Это означает, что они уже стали встроенными в целях оптимизации. Однако сигнатура типа и семантика остаются прежними.
Обратите внимание, что некоторые менее распространенные команды не представлены в stdlib. Они также будут добавлены в будущем.
Примитивы для манипулирования кортежами
Имена и типы в основном говорят сами за себя. См. полиморфизм с forall для получения дополнительной информации о полиморфных функциях.
Обратите внимание, что в настоящее время значения атомарного типа tuple
не могут быть преобразованы в составные типы кортежей (например, [int, cell]
) и наоборот.
Списки в стиле Lisp
Списки могут быть представлены как вложенные кортежи из 2 элементов. Пустой список традиционно представляется как значение TVM null
(его можно получить, вызвав null()
). Например, кортеж (1, (2, (3, null)))
представляет список [1, 2, 3]
. Элементы списка могут быть разных типов.
cons
forall X -> tuple cons(X head, tuple tail) asm "CONS";
Добавляет элемент в начало списка в стиле lisp.
uncons
forall X -> (X, tuple) uncons(tuple list) asm "UNCONS";
Извлекает начало и конец списка в стиле lisp.
list_next
forall X -> (tuple, X) list_next(tuple list) asm( -> 1 0) "UNCONS";
Извлекает начало и конец списка в стиле lisp. Может использоваться как (не)модифицирующий метод.
() foo(tuple xs) {
(_, int x) = xs.list_next(); ;; get the first element, `_` means do not use tail list
int y = xs~list_next(); ;; pop the first element
int z = xs~list_next(); ;; pop the second element
}
car
forall X -> X car(tuple list) asm "CAR";
Возвращает начало списка в стиле lisp.
cdr
tuple cdr(tuple list) asm "CDR";
Возвращает конец списка в стиле lisp.
Другие примитивы кортежа
empty_tuple
tuple empty_tuple() asm "NIL";
Создает кортеж из 0 элементов.
tpush
forall X -> tuple tpush(tuple t, X value) asm "TPUSH";
forall X -> (tuple, ()) ~tpush(tuple t, X value) asm "TPUSH";
Добавляет значение x
к Tuple t = (x1, ..., xn)
, но только если полученный Tuple t' = (x1, ..., xn, x)
не длиннее 255 символов. В противном случае выдается исключение проверки типа.
single
forall X -> [X] single(X x) asm "SINGLE";
Создает одиночку, т. е. кортеж длиной один.
unsingle
forall X -> X unsingle([X] t) asm "UNSINGLE";
Распаковывает одиночку.
pair
forall X, Y -> [X, Y] pair(X x, Y y) asm "PAIR";
Создает пару.
unpair
forall X, Y -> (X, Y) unpair([X, Y] t) asm "UNPAIR";
Распаковывает пару.
triple
forall X, Y, Z -> [X, Y, Z] triple(X x, Y y, Z z) asm "TRIPLE";
Создает тройку.
untriple
forall X, Y, Z -> (X, Y, Z) untriple([X, Y, Z] t) asm "UNTRIPLE";
Распаковывает тройку.
tuple4
forall X, Y, Z, W -> [X, Y, Z, W] tuple4(X x, Y y, Z z, W w) asm "4 TUPLE";
Создает кортеж из 4 элементов.
untuple4
forall X, Y, Z, W -> (X, Y, Z, W) untuple4([X, Y, Z, W] t) asm "4 UNTUPLE";
Распаковывает кортеж из 4 элементов.
first
forall X -> X first(tuple t) asm "FIRST";
Возвращает первый элемент кортежа.
second
forall X -> X second(tuple t) asm "SECOND";
Возвращает второй элемент кортежа.
third
forall X -> X third(tuple t) asm "THIRD";
Возвращает третий элемент кортежа.
fourth
forall X -> X fourth(tuple t) asm "3 INDEX";
Возвращает четвертый элемент кортежа.
pair_first
forall X, Y -> X pair_first([X, Y] p) asm "FIRST";
Возвращает первый элемент пары.
pair_second
forall X, Y -> Y pair_second([X, Y] p) asm "SECOND";
Возвращает второй элемент пары.
triple_first
forall X, Y, Z -> X triple_first([X, Y, Z] p) asm "FIRST";
Возвращает первый элемент тройки.
triple_second
forall X, Y, Z -> Y triple_second([X, Y, Z] p) asm "SECOND";
Возвращает второй элемент тройки.
triple_third
forall X, Y, Z -> Z triple_third([X, Y, Z] p) asm "THIRD";
Возвращает третий элемент тройки.
Примитивы, специфичные для домена
Извлечение информации из c7
Некоторые полезные сведения о вызове смарт-контракта можно найти в специальном регистре c7. Эти примитивы служат для удо бного извлечения данных.
now
int now() asm "NOW";
Возвращает текущее время Unix как целое число
my_address
slice my_address() asm "MYADDR";
Возвращает внутренний адрес текущего смарт-контракта как срез с MsgAddressInt
. При необходимости его можно проанализировать далее с помощью примитивов, таких как parse_std_addr
.
get_balance
[int, cell] get_balance() asm "BALANCE";
Возвращает оставшийся баланс смарт-контракта в виде tuple
, состоящего из int
(оставшийся баланс в nanotoncoin) и cell
(словарь с 32-битными ключами, представляющими баланс "дополнительных валют"). Поскольку это произойдет в фазе вычислений, баланс контракта будет включать входящее сообщение value
, вычитать storage_fee
и import_fee
.
Необработанные примитивы, такие как send_raw_message
, не обновляют это поле.
cur_lt
int cur_lt() asm "LTIME";
Возвращает логическое время текущей транзакции.
block_lt
int block_lt() asm "BLOCKLT";
Возвращает начальное логическое время текущего блока.
config_param
cell config_param(int x) asm "CONFIGOPTPARAM";
Возвращает значение глобального параметра конфигурации с целочисленным индексом i
как cell
или null
значение.
Хэши
cell_hash
int cell_hash(cell c) asm "HASHCU";
Вычисляет хэш представления cell c
и возвращает его как 256-битное беззнаковое целое число x
. Полезно для подписи и проверки подписей произвольных сущностей, представленных деревом ячеек.
slice_hash
int slice_hash(slice s) asm "HASHSU";
Вычисляет хэш slice s
и возвращает его как 256-битное целое число без знака x
. Результат такой же, как если бы была создана обычная ячейка, содержащая только данные и ссылки из s
, и ее хэш был вычислен cell_hash
.
string_hash
int string_hash(slice s) asm "SHA256U";
Вычисляет sha256 бит данных slice s
. Если длина бит s
не делится на восемь, выдается исключение потери значимости ячейки. Значение хэша возвращается как 256-битное целое число без знака x
.
Проверка подписи
check_signature
int check_signature(int hash, slice signature, int public_key) asm "CHKSIGNU";
Проверяет signature
Ed25519 для hash
(256-битное беззнаковое целое число, обычно вычисляемое как хэш некоторых данных) с помощью public_key
(также представленного 256-битным беззнаковым целым числом). Подпись должна содержать не менее 512 бит данных; используются только первые 512 бит. Если подпись действительна, результат равен -1
; в противном случае это 0
. Обратите внимание, что CHKSIGNU
создает 256-битный срез с хешем и вызывает CHKSIGNS
. То есть, если hash
вычисляется как хеш некоторых данных, эти данные хешируются дважды, второе хеширование происходит внутри CHKSIGNS
.
check_data_signature
int check_data_signature(slice data, slice signature, int public_key) asm "CHKSIGNS";
Проверяет, является ли signature
допустимой подписью Ed25519 части данных slice data
, используя public_key
, аналогично check_signature
. Если длина бит data
не делится на восемь, выдается исключение переполнения ячейки. Проверка подписей Ed25519 является стандартной, с использованием sha256 для сокращения data
до 256-битного числа, которое фактически подписано.
Вычисление размера boc
Приведенные ниже примитивы могут быть полезны для расчета платы за хранение предоставленных пользователем данных.
compute_data_size?
(int, int, int, int) compute_data_size?(cell c, int max_cells) asm "CDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT";
Возвращает (x, y, z, -1)
или (null, null, null, 0)
. Рекурсивно вычисляет количество отдельных ячеек x
, битов данных y
и ссылок на ячейки z
в DAG с корнем cell c
, фактически возвращая общее хранилище, используемое этим DAG, с учетом идентификации равных ячеек. Значения x
, y
и z
вычисляются путем обхода в глубину этого DAG с хэш-таблицей хэшей посещенных ячеек, используемых для предотвращения посещений уже посещенных ячеек. Общее количество посещенных ячеек x
не может превышать неотрицательного max_cells
; в противном случае вычисление прерывается до посещения (max_cells + 1)
-й яч ейки и возвращается нулевой флаг, указывающий на ошибку. Если c
равно null
, возвращается x = y = z = 0
.
slice_compute_data_size?
(int, int, int, int) slice_compute_data_size?(slice s, int max_cells) asm "SDATASIZEQ NULLSWAPIFNOT2 NULLSWAPIFNOT";
Аналогично compute_data_size?
, но принимает slice s
вместо cell
. Возвращаемое значение x
не учитывает ячейку, содержащую сам срез s
; однако биты данных и ссылки на ячейки s
учитываются в y
и z
.
compute_data_size
(int, int, int) compute_data_size(cell c, int max_cells) impure asm "CDATASIZE";
Не тихая версия compute_data_size?
, которая выдает исключение переполнения ячейки (8) при сбое.
slice_compute_data_size
(int, int, int) slice_compute_data_size(slice s, int max_cells) impure asm "SDATASIZE";
Не тихая версия slice_compute_data_size?
, которая выдает исключение переполнения ячейки (8) при сбое.
Сохранение и загрузка постоянного хранилища
get_data
cell get_data() asm "c4 PUSH";
Возвращает ячейку постоянного хранилища контракта. Позже ее можно проанализировать или изменить с помощью примитивов среза и конструктора.
set_data
() set_data(cell c) impure asm "c4 POP";
Устанавливает ячейку c
как постоянные данные контракта. Вы можете обновить постоянное хранилище контракта с помощью этого примитива.
Примитивы продолжения
get_c3
cont get_c3() impure asm "c3 PUSH";
Обычно c3
имеет продолжение, инициализированное всем кодом контракта. Оно используется для вызовов функций. Примитив возвращает текущее значение c3
.
set_c3
() set_c3(cont c) impure asm "c3 POP";
Обновляет текущее значение c3
. Обычно используется для обновления кода смарт-контракта во время выполнения. Обратите внимание, что после выполнения этого примитива текущий код (и стек рекурсивных вызовов функций) не изменится, но любой другой вызов функции будет использовать функцию из нового кода.
bless
cont bless(slice s) impure asm "BLESS";
Преобразует slice s
в простое обычное продолжение c
с c.code = s
, пустым стеком и списком сохранения.