cryptobro
New member
- Сообщения
- 23
- Реакции
- 10
Для начала у вас должен быть собран Light Client TON и интерпретатор языка Fift
Адреса и аккаунты в TON
Структура блокчейна TON состоит из основного мастерчейна и множества воркчейнов, которые идентифицируются 32-битным числом. Мастерчейн имеет идентификатор -1, кроме него так же может использоваться базовый воркчейн с идентификатором 0. У каждого воркчейна может быть своя конфигурация. Далее каждый воркчейн дробится на шардчейны и затем шардчейны на блоки. В пределах одного воркчейна хранится множество аккаунтов, у которых есть свои идентификаторы account_id. Для мастерчейна и нулевого воркчейна они имеют длину 256 бит.
Идентификатор аккаунта (адреса) записывается так:
Это «сырой» формат: сначала идентификатор воркчейна, затем двоеточие, и идентификатор аккаунта в шестнадцатеричной записи.
Также есть короткий формат записи — номер воркчейна и адрес аккаунта кодируются в бинарном виде, к ним дописывается контрольная сумма и всё это кодируется в Base64:
Зная этот формат записи, мы можем запросить текущее состояние какого-нибудь аккаунта через тестовый клиент с помощью команды
Обратно приходит следующий ответ
Видим структуру, которая хранится в DHT указанного воркчейна. Например, в поле storage.balance находится текущий баланс аккаунта, в storage.state.code — код смарт-контракта, а в storage.state.data — его текущие данные. Обратите внимание, что хранилище данных TON — Cell, ячейки — является древовидным, у каждой ячейки могут быть как свои данные, так и дочерние ячейки. Это показано в виде отступов в последних строчках.
Сборка смарт-контракта в TON
Создадим такую структуру самостоятельно (она называется BOC — bag of cells) с помощью языка Fift. В папке crypto/block из архива с исходниками есть файл new-wallet.fif, который поможет создать новый кошелёк. Скопируем его в папку с собранным клиентом. Как собрать клиент TON
Выполняем этот файл следующим образом:
Здесь <source-directory> надо заменить на путь к распакованным исходникам (символ "~" тут, к сожалению, использовать нельзя, нужен полный путь). Вместо использования ключа -I можно определить переменную окружения FIFTPATH и поместить этот путь в неё. Так как Fift мы запустили с именем файла new-wallet.fif, он выполнит его и завершится. Если имя файла опустить, то можно поиграть с интерпретатором в интерактивном режиме.
В консоли после выполнения будет следующее:
Это означает, что кошелёк с идентификатором -1:4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2 (или, что то же самое, 0f9PzVILj8yglrVn1zS-NSjtxr7QBfaTCp7JrBqnFPIR8nhZ) успешно создан. Соответствующий ему код окажется в файле new-wallet-query.boc, его адрес — в new-wallet.addr, а приватный ключ — в new-wallet.pk (будьте осторожны — повторный запуск скрипта перезапишет эти файлы).
Пока сеть TON не знает ничего об этом адресе. Его нужно загрузить в блокчейн TON. Также стоит понимать что для создания смарт-контракта нужно заплатить комиссию, а баланс у вашего аккаунта пока нулевой. В основной сети вы сможете для этого приобрести Gram на бирже или в обменниках или перевести с другого кошелька. В тестовой сети TON существует специальный кран (TON faucet), это смарт-контракт который даёт 20 GRAM на аккаунт при обращении к нему.
Формирование запроса к смарт-контракту TON faucet
Запрос к смарт-контракту TON faucet выполняется следующим образом. Во всё той же папке crypto/block находим файл testgiver.fif:
Его тоже сохраним в папку с собранным клиентом, но поправим пятую строчку — перед строчкой "constant dest_addr". Заменим её на адрес того кошелька, который вы создали до этого (полный, не сокращённый). "-1:" в начале писать не нужно, вместо этого в начале поставьте "0x". Ещё можно поменять строку 6.666 Gram*/ constant amount — это сумма в Gram, которую вы запрашиваете (не больше 20). Даже если указываете целое число, оставьте десятичную точку.
Наконец, нужно поправить строку 0x00000011 constant seqno. Первое число тут — это текущий sequence number, который хранится в аккаунте, выдающем токены Gram. Откуда его взять? Как говорилось выше, запустите клиент и выполните:
В самом конце в данных смарт-контракта будет:
Число 0000000D (у вас оно будет больше) и есть sequence number, который надо подставить в testgiver.fif.
Всё, сохраняем файл и запускаем (./crypto/fift testgiver.fif). На выходе получим файл wallet-query.boc. Это и есть сформированное сообщение к чужому смарт-контракту которая выглядит как запрос «перевод столько-то Gram на такой-то аккаунт».
С помощью TON Light Client загружаем файл wallet-query.bo в сеть:
Если теперь вызвать команду last, а затем снова запросить статус аккаунта, у которого были запрошены Grams, то его sequence number увеличится на единицу — это значит, что смарт-контракт отправил токены на наш адрес
Остался последний шаг — загружаем код нашего кошелька (баланс его уже пополнен, но без кода смарт-контракта им нельзя управлять). Выполняем команду sendfile new-wallet-query.boc — теперь у вас есть собственный кошелёк (аккаунт) в тестовой сети TON.
Создание исходящих транзакций
Чтобы переводить деньги с баланса созданного аккаунта, есть файл crypto/block/wallet.fif, который тоже нужно поместить в папку с собранным клиентом.
Аналогично предыдущим шагам, в нём нужно поправить сумму, которую вы переводите, адрес получателя (dest_addr), и seqno вашего кошелька (он равен 1 после инициализации кошелька и увеличивается на 1 после каждой исходящей транзакции — вы сможете увидеть его, запросив состояние своего аккаунта). Для тестов можете использовать, например, мой кошелёк — 0x4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2.
При запуске (./crypto/fift wallet.fif) скрипт возьмёт адрес вашего кошелька (откуда вы переводите) и его приватный ключ из файлов new-wallet.addr и new-wallet.pk, а полученное сообщение запишет в new-wallet-query.boc.
Как и раньше, чтобы непосредственно выполнить транзакцию, вызываем sendfile new-wallet-query.boc в клиенте. После этого не забываем обновить состояние сети командой last и проверяем, что баланс и seqno нашего кошелька изменились (getaccount <account_id>).

Выше вы увидели пример создания смарт-контракта в TON и взаимодействия с ним
За подготовку материала спасибо пользователю deNULL и порталу habr.com
Адреса и аккаунты в TON
Структура блокчейна TON состоит из основного мастерчейна и множества воркчейнов, которые идентифицируются 32-битным числом. Мастерчейн имеет идентификатор -1, кроме него так же может использоваться базовый воркчейн с идентификатором 0. У каждого воркчейна может быть своя конфигурация. Далее каждый воркчейн дробится на шардчейны и затем шардчейны на блоки. В пределах одного воркчейна хранится множество аккаунтов, у которых есть свои идентификаторы account_id. Для мастерчейна и нулевого воркчейна они имеют длину 256 бит.
Идентификатор аккаунта (адреса) записывается так:
-1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0d
Это «сырой» формат: сначала идентификатор воркчейна, затем двоеточие, и идентификатор аккаунта в шестнадцатеричной записи.
Также есть короткий формат записи — номер воркчейна и адрес аккаунта кодируются в бинарном виде, к ним дописывается контрольная сумма и всё это кодируется в Base64:
Ef+BVndbeTJeXWLnQtm5bDC2UVpc0vH2TF2ksZPAPwcODSkb
Зная этот формат записи, мы можем запросить текущее состояние какого-нибудь аккаунта через тестовый клиент с помощью команды
getaccount -1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0d
Обратно приходит следующий ответ
Код:
[ 3][t 2][1558746708.815218925][test-lite-client.cpp:631][!testnode] requesting account state for -1:8156775B79325E5D62E742D9B96C30B6515A5CD2F1F64C5DA4B193C03F070E0D
[ 3][t 2][1558746708.858564138][test-lite-client.cpp:652][!testnode] got account state for -1:8156775B79325E5D62E742D9B96C30B6515A5CD2F1F64C5DA4B193C03F070E0D with respect to blocks (-1,8000000000000000,72355):F566005749C1B97F18EDE013EBA7A054B9014961BC1AD91F475B9082919A2296:1BD5DE54333164025EE39D389ECE2E93DA2871DA616D488253953E52B50DC03F and (-1,8000000000000000,72355):F566005749C1B97F18EDE013EBA7A054B9014961BC1AD91F475B9082919A2296:1BD5DE54333164025EE39D389ECE2E93DA2871DA616D488253953E52B50DC03F
account state is (account
addr:(addr_std
anycast:nothing workchain_id:-1 address:x8156775B79325E5D62E742D9B96C30B6515A5CD2F1F64C5DA4B193C03F070E0D)
storage_stat:(storage_info
used:(storage_used
cells:(var_uint len:1 value:3)
bits:(var_uint len:2 value:539)
public_cells:(var_uint len:0 value:0)) last_paid:0
due_payment:nothing)
storage:(account_storage last_trans_lt:74208000003
balance:(currencies
grams:(nanograms
amount:(var_uint len:7 value:999928362430000))
other:(extra_currencies
dict:hme_empty))
state:(account_active
(
split_depth:nothing
special:nothing
code:(just
value:([email protected]^Cell
x{}
x{FF0020DDA4F260D31F01ED44D0D31FD166BAF2A1F80001D307D4D1821804A817C80073FB0201FB00A4C8CB1FC9ED54}
))
data:(just
value:([email protected]^Cell
x{}
x{0000000D}
))
library:hme_empty))))
x{CFF8156775B79325E5D62E742D9B96C30B6515A5CD2F1F64C5DA4B193C03F070E0D2068086C000000000000000451C90E00DC0E35B7DB5FB8C134_}
x{FF0020DDA4F260D31F01ED44D0D31FD166BAF2A1F80001D307D4D1821804A817C80073FB0201FB00A4C8CB1FC9ED54}
x{0000000D}
Видим структуру, которая хранится в DHT указанного воркчейна. Например, в поле storage.balance находится текущий баланс аккаунта, в storage.state.code — код смарт-контракта, а в storage.state.data — его текущие данные. Обратите внимание, что хранилище данных TON — Cell, ячейки — является древовидным, у каждой ячейки могут быть как свои данные, так и дочерние ячейки. Это показано в виде отступов в последних строчках.
Сборка смарт-контракта в TON
Создадим такую структуру самостоятельно (она называется BOC — bag of cells) с помощью языка Fift. В папке crypto/block из архива с исходниками есть файл new-wallet.fif, который поможет создать новый кошелёк. Скопируем его в папку с собранным клиентом. Как собрать клиент TON
Выполняем этот файл следующим образом:
./crypto/fift -I"<source-directory>/crypto/fift" new-wallet.fif
Здесь <source-directory> надо заменить на путь к распакованным исходникам (символ "~" тут, к сожалению, использовать нельзя, нужен полный путь). Вместо использования ключа -I можно определить переменную окружения FIFTPATH и поместить этот путь в неё. Так как Fift мы запустили с именем файла new-wallet.fif, он выполнит его и завершится. Если имя файла опустить, то можно поиграть с интерпретатором в интерактивном режиме.
В консоли после выполнения будет следующее:
Код:
StateInit: x{34_}
x{FF0020DDA4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54}
x{0000000055375F730EDC2292E8CB15C42E8036EE9C25AA958EE002D2DE48A205E3A3426B}
new wallet address = -1 : 4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2
0f9PzVILj8yglrVn1zS-NSjtxr7QBfaTCp7JrBqnFPIR8nhZ
signing message: x{00000000}
External message for initialization is x{89FEE120E20C7E953E31546F64C23CD654002C1AA919ADD24DB12DDF85C6F3B58AE41198A28AD8DAF3B9588E7A629252BA3DB88F030D00BC1016110B2073359EAC3C13823C53245B65D056F2C070B940CDA09789585935C7ABA4D2AD4BED139281CFA1200000001_}
x{FF0020DDA4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED54}
x{0000000055375F730EDC2292E8CB15C42E8036EE9C25AA958EE002D2DE48A205E3A3426B}
B5EE9C724104030100000000D60002CF89FEE120E20C7E953E31546F64C23CD654002C1AA919ADD24DB12DDF85C6F3B58AE41198A28AD8DAF3B9588E7A629252BA3DB88F030D00BC1016110B2073359EAC3C13823C53245B65D056F2C070B940CDA09789585935C7ABA4D2AD4BED139281CFA1200000001001020084FF0020DDA4F260810200D71820D70B1FED44D0D31FD3FFD15112BAF2A122F901541044F910F2A2F80001D31F3120D74A96D307D402FB00DED1A4C8CB1FCBFFC9ED5400480000000055375F730EDC2292E8CB15C42E8036EE9C25AA958EE002D2DE48A205E3A3426B6290698B
(Saved to file new-wallet-query.boc)
Пока сеть TON не знает ничего об этом адресе. Его нужно загрузить в блокчейн TON. Также стоит понимать что для создания смарт-контракта нужно заплатить комиссию, а баланс у вашего аккаунта пока нулевой. В основной сети вы сможете для этого приобрести Gram на бирже или в обменниках или перевести с другого кошелька. В тестовой сети TON существует специальный кран (TON faucet), это смарт-контракт который даёт 20 GRAM на аккаунт при обращении к нему.
Формирование запроса к смарт-контракту TON faucet
Запрос к смарт-контракту TON faucet выполняется следующим образом. Во всё той же папке crypto/block находим файл testgiver.fif:
Код:
// "testgiver.addr" file>B 256 B>[email protected]
0x8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0d
dup constant wallet_addr ."Test giver address = " x. cr
0x4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2
constant dest_addr
-1 constant wc
0x00000011 constant seqno
1000000000 constant Gram
{ Gram swap */ } : Gram*/
6.666 Gram*/ constant amount
// b x --> b' ( serializes a Gram amount )
{ -1 { 1+ 2dup 8 * ufits } until
rot over 4 u, -rot 8 * u, } : Gram,
// create a message (NB: 01b00.., b = bounce)
<b b{010000100} s, wc 8 i, dest_addr 256 u, amount Gram, 0 9 64 32 + + 1+ 1+ u, "GIFT" $, b>
<b seqno 32 u, 1 8 u, swap ref, b>
dup ."enveloping message: " <s csr. cr
<b b{1000100} s, wc 8 i, wallet_addr 256 u, 0 Gram, b{00} s,
swap <s s, b>
dup ."resulting external message: " <s csr. cr
2 boc+>B dup Bx. cr
"wallet-query.boc" B>file
Наконец, нужно поправить строку 0x00000011 constant seqno. Первое число тут — это текущий sequence number, который хранится в аккаунте, выдающем токены Gram. Откуда его взять? Как говорилось выше, запустите клиент и выполните:
Код:
last
getaccount -1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0d
Код:
...
x{FF0020DDA4F260D31F01ED44D0D31FD166BAF2A1F80001D307D4D1821804A817C80073FB0201FB00A4C8CB1FC9ED54}
x{0000000D}
Всё, сохраняем файл и запускаем (./crypto/fift testgiver.fif). На выходе получим файл wallet-query.boc. Это и есть сформированное сообщение к чужому смарт-контракту которая выглядит как запрос «перевод столько-то Gram на такой-то аккаунт».
С помощью TON Light Client загружаем файл wallet-query.bo в сеть:
Код:
> sendfile wallet-query.boc
[ 1][t 1][1558747399.456575155][test-lite-client.cpp:577][!testnode] sending query from file wallet-query.boc
[ 3][t 2][1558747399.500236034][test-lite-client.cpp:587][!query] external message status is 1
Остался последний шаг — загружаем код нашего кошелька (баланс его уже пополнен, но без кода смарт-контракта им нельзя управлять). Выполняем команду sendfile new-wallet-query.boc — теперь у вас есть собственный кошелёк (аккаунт) в тестовой сети TON.
Создание исходящих транзакций
Чтобы переводить деньги с баланса созданного аккаунта, есть файл crypto/block/wallet.fif, который тоже нужно поместить в папку с собранным клиентом.
Аналогично предыдущим шагам, в нём нужно поправить сумму, которую вы переводите, адрес получателя (dest_addr), и seqno вашего кошелька (он равен 1 после инициализации кошелька и увеличивается на 1 после каждой исходящей транзакции — вы сможете увидеть его, запросив состояние своего аккаунта). Для тестов можете использовать, например, мой кошелёк — 0x4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2.
При запуске (./crypto/fift wallet.fif) скрипт возьмёт адрес вашего кошелька (откуда вы переводите) и его приватный ключ из файлов new-wallet.addr и new-wallet.pk, а полученное сообщение запишет в new-wallet-query.boc.
Как и раньше, чтобы непосредственно выполнить транзакцию, вызываем sendfile new-wallet-query.boc в клиенте. После этого не забываем обновить состояние сети командой last и проверяем, что баланс и seqno нашего кошелька изменились (getaccount <account_id>).

Выше вы увидели пример создания смарт-контракта в TON и взаимодействия с ним
За подготовку материала спасибо пользователю deNULL и порталу habr.com