一年多前,人們得知 Telegram Messenger 計畫發布自己的去中心化網絡 電報開放網絡。 隨後出現了一份大量的技術文件,據稱是尼古拉·杜羅夫撰寫的,描述了未來網路的結構。 對於那些錯過的人,我建議您閱讀我對這份文件的重述(
從那時起,就沒有關於 TON 開發狀況的重大新聞,直到幾天前(在其中一篇文章中)
◦
◦
◦
◦
◦
◦
◦
◦
我再說一遍,該頁面和來自 Telegram 的所有這些文件都沒有得到官方確認,但這些材料的數量使它們非常可信。 啟動已發布的客戶端 風險自擔.
建立測試客戶端
首先,讓我們嘗試建置並運行一個測試客戶端 - 幸運的是,
-
下載並解壓縮
來源檔案 。 下載最新版本非常重要,因為現階段無法保證向後相容性。 -
確保系統上安裝了最新版本的 make、cmake(版本 3.0.2 或更高版本)、OpenSSL(包括 C 頭檔)、g++ 或 clang。 我不需要安裝任何東西,一切都立即組合在一起。
-
我們假設原始碼被解壓縮到一個資料夾中
~/lite-client
。 除此之外,為組裝的專案建立一個空資料夾(例如,~/liteclient-build
),並從中得出(cd ~/liteclient-build
)調用命令:cmake ~/lite-client cmake --build . --target test-lite-client
為了建立智能合約的 Fiveft 語言解釋器(更多相關資訊請見下文),我們也調用cmake --build . --target fift
-
下載目前版本
設定檔 連接到測試網路並將其與組裝好的客戶端放在資料夾中。 -
完成,您可以啟動客戶端:
./test-lite-client -C ton-lite-client-test1.config.json
如果一切都正確完成,您應該看到如下內容:
正如我們所看到的,可用的命令很少:
◦ help
— 顯示指令清單;
◦ quit
- 出去;
◦ time
— 顯示伺服器上的目前時間;
◦ status
— 顯示連線和本機資料庫狀態;
◦ last
— 更新區塊鏈的狀態(下載最後一個區塊)。 在發出任何請求之前執行此命令非常重要,以確保您看到網路的當前狀態。
◦ sendfile
<filename>
— 將本機檔案上傳至 TON 網路。 這就是與網路互動的發生方式 - 例如,包括創建新的智慧合約和請求在帳戶之間轉移資金;
◦ getaccount
<address>
— 顯示目前(執行指令時) last
) 指定地址的帳戶狀態;
◦ privkey
<filename>
— 從本機檔案載入私鑰。
如果在啟動用戶端時,您使用選項將資料夾傳輸到用戶端 -D
,然後他會將主鏈的最後一個區塊添加到其中:
./test-lite-client -C ton-lite-client-test1.config.json -D ~/ton-db-dir
現在我們可以繼續做更有趣的事情 - 學習 Fift 語言,嘗試編譯智能合約(例如,創建測試錢包),將其上傳到網路並嘗試在帳戶之間轉移資金。
語言五
來自文件
該文件相當龐大,有87頁,我不會在本文的框架內詳細複述其內容(至少因為我自己還沒讀完:)。 我將重點關注要點並給出一些這種語言的程式碼範例。
從根本上來說,Fift 的語法非常簡單:它的程式碼包括 話,通常用空格或換行符號分隔(特殊情況:某些單字後面不需要分隔符號)。 任何 слово 是一個區分大小寫的字元序列,對應於某個特定的 決心 (粗略地說,解釋器遇到這個詞時應該做什麼)。 如果沒有單字的定義,解釋器會嘗試將其解析為數字並將其放入堆疊中。 順便說一句,這裡的數字突然變成了 257 位元整數,而且根本沒有分數,更準確地說,它們立即變成一對整數,形成有理分數的分子和分母。
單字往往與堆疊頂部的值互動。 一個單獨的詞類型 - 字首 — 不使用堆疊,而是使用來源檔案中的後續字元。 例如,這就是字串文字的實現方式 - 引號字元 ("
) 是一個前綴詞,用於尋找下一個(結束)引號,並將它們之間的字串壓入堆疊。 單行程式碼的行為方式相同(//
) 和多行 (/*
) 評論。
這幾乎是該語言的整個內部結構的終點。 其他一切(包括控制結構)都被定義為單字(或者是內部的,例如算術運算和新單字的定義;或者是在「標準庫」中定義的) Fift.fif
,位於資料夾中 crypto/fift
在來源中)。
Five 中的一個簡單範例程式:
{ dup =: x dup * =: y } : setxy
3 setxy x . y . x y + .
7 setxy x . y . x y + .
第一行定義一個新詞 setxy
(注意前綴 {
,它在結束區塊之前創建一個區塊 }
和前綴 :
,它實際上定義了這個詞)。 setxy
從堆疊頂部取得一個數字,將其定義(或重新定義)為全域的 持續的 x
,並將該數字的平方作為常數 y
(鑑於常數的值可以重新定義,我寧願將它們稱為變量,但我遵循語言中的命名約定)。
接下來的兩行將一個數字放入堆疊並調用 setxy
,然後顯示常數的值 x
, y
(該字用於輸出 .
),兩個常數都放入堆疊中,求和,並列印結果。 結果我們會看到:
3 9 12 ok
7 49 56 ok
(解釋器在交互輸入模式下處理完當前行後會列印“ok”行)
好吧,完整的程式碼範例:
"Asm.fif" include
-1 constant wc // create a wallet in workchain -1 (masterchain)
// Create new simple wallet
<{ SETCP0 DUP IFNOTRET INC 32 THROWIF // return if recv_internal, fail unless recv_external
512 INT LDSLICEX DUP 32 PLDU // sign cs cnt
c4 PUSHCTR CTOS 32 LDU 256 LDU ENDS // sign cs cnt cnt' pubk
s1 s2 XCPU // sign cs cnt pubk cnt' cnt
EQUAL 33 THROWIFNOT // ( seqno mismatch? )
s2 PUSH HASHSU // sign cs cnt pubk hash
s0 s4 s4 XC2PU // pubk cs cnt hash sign pubk
CHKSIGNU // pubk cs cnt ?
34 THROWIFNOT // signature mismatch
ACCEPT
SWAP 32 LDU NIP
DUP SREFS IF:<{
8 LDU LDREF // pubk cnt mode msg cs
s0 s2 XCHG SENDRAWMSG // pubk cnt cs ; ( message sent )
}>
ENDS
INC NEWC 32 STU 256 STU ENDC c4 POPCTR
}>c
// code
<b 0 32 u,
newkeypair swap dup constant wallet_pk
"new-wallet.pk" B>file
B,
b> // data
// no libraries
<b b{00110} s, rot ref, swap ref, b> // create StateInit
dup ."StateInit: " <s csr. cr
dup hash dup constant wallet_addr
."new wallet address = " wc . .": " dup x. cr
wc over 7 smca>$ type cr
256 u>B "new-wallet.addr" B>file
<b 0 32 u, b>
dup ."signing message: " <s csr. cr
dup hash wallet_pk ed25519_sign_uint rot
<b b{1000100} s, wc 8 i, wallet_addr 256 u, b{000010} s, swap <s s, b{0} s, swap B, swap <s s, b>
dup ."External message for initialization is " <s csr. cr
2 boc+>B dup Bx. cr
"new-wallet-query.boc" tuck B>file
."(Saved to file " type .")" cr
這個看起來嚇人的檔案用於創建智能合約 - 它將被放置在一個檔案中 new-wallet-query.boc
執行後。 請注意,TON 虛擬機器這裡使用的是另一種彙編語言(我不會詳細介紹它),其指令將放在區塊鏈上。
因此,TVM 的彙編程式是用 Fift 編寫的 - 該彙編程式的原始程式碼位於檔案中 crypto/fift/Asm.fif
和 連接在上述程式碼的開頭。
我能說什麼,顯然 Nikolai Durov 只是喜歡創建新的程式語言:)
創建智能合約並與 TON 交互
因此,假設我們已經如上所述組裝了 TON 客戶端和 Fift 解釋器,並熟悉了該語言。 現在如何創建智能合約? 文件中對此進行了描述
TON 帳戶
正如我在
在一個工作鏈中,儲存了許多具有自己的 account_id 識別碼的帳戶。 對於主鍊和零工作鏈,它們的長度是256位元。 因此,帳戶標識符的寫法例如如下:
-1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0d
這是「原始」格式:首先是工作鏈 ID,然後是冒號,以及十六進位表示法的帳戶 ID。
此外,還有一種縮短的格式——工作鏈號和帳戶地址以二進位形式編碼,並添加校驗和,所有這些都以 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:(raw@^Cell
x{}
x{FF0020DDA4F260D31F01ED44D0D31FD166BAF2A1F80001D307D4D1821804A817C80073FB0201FB00A4C8CB1FC9ED54}
))
data:(just
value:(raw@^Cell
x{}
x{0000000D}
))
library:hme_empty))))
x{CFF8156775B79325E5D62E742D9B96C30B6515A5CD2F1F64C5DA4B193C03F070E0D2068086C000000000000000451C90E00DC0E35B7DB5FB8C134_}
x{FF0020DDA4F260D31F01ED44D0D31FD166BAF2A1F80001D307D4D1821804A817C80073FB0201FB00A4C8CB1FC9ED54}
x{0000000D}
我們看到儲存在指定工作鏈的 DHT 中的結構。 例如,在該領域 storage.balance
是經常帳餘額,單位為 storage.state.code
- 智能合約程式碼,以及 storage.state.data
- 其當前數據。 請注意,TON 資料儲存 - Cell、cells - 是樹狀的,每個儲存格都可以有自己的資料和子儲存格。 這在最後幾行顯示為縮排。
建構智能合約
現在讓我們自己創建一個這樣的結構(它被稱為 BOC - 細胞袋)使用第五語言。 幸運的是,您不必自己編寫智能合約 - 在資料夾中 crypto/block
來源存檔中有一個文件 new-wallet.fif
,這將幫助我們創建一個新的錢包。 讓我們將其複製到包含已組裝客戶端的資料夾中(~/liteclient-build
,如果您按照上面的說明進行操作)。 我在上面引用了它的內容作為 Fift 上的程式碼範例。
如下執行該文件:
./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)
這意味著帶有ID的錢包 -1:4fcd520b8fcca096b567d734be3528edc6bed005f6930a9ec9ac1aa714f211f2
(或者,什麼是相同的, 0f9PzVILj8yglrVn1zS-NSjtxr7QBfaTCp7JrBqnFPIR8nhZ
)創建成功。 對應的程式碼將在文件中 new-wallet-query.boc
,他的地址是在 new-wallet.addr
,私鑰位於 new-wallet.pk
(小心 - 再次運行腳本將覆蓋這些文件)。
當然,TON 網路還不知道這個錢包;它僅以這些文件的形式儲存。 現在需要將其上傳到網路。 然而問題是,創建智能合約需要支付佣金,而你的帳戶餘額仍然為零。
在工作模式下,這個問題將透過在交易所購買克(或從另一個錢包轉移)來解決。 嗯,在目前的測試模式下,已經創建了一個特殊的智能合約,您可以像這樣索取最多 20 克的智能合約。
產生對其他人智能合約的請求
我們向智能合約發出請求,該合約像這樣左右分配克。 在同一個資料夾中 crypto/block
查找文件 testgiver.fif
:
// "testgiver.addr" file>B 256 B>u@
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
我們還將其保存在已組裝客戶端的資料夾中,但我們將更正第五行 - 在「行」之前constant dest_addr
」。 讓我們將其替換為您之前創建的錢包地址(完整,非縮寫)。 開頭不需要寫“-1:”,而是在開頭寫“0x”。
您也可以更改線路 6.666 Gram*/ constant amount
— 這是您要求的克數(不超過 20)。 即使指定整數,也要保留小數點。
最後,您需要更正該行 0x00000011 constant seqno
。 這裡的第一個數字是目前的序號,儲存在發行克的帳戶中。 我可以從哪裡得到它? 如上所述,啟動客戶端並運行:
last
getaccount -1:8156775b79325e5d62e742d9b96c30b6515a5cd2f1f64c5da4b193c03f070e0d
最後,智能合約資料將包含
...
x{FF0020DDA4F260D31F01ED44D0D31FD166BAF2A1F80001D307D4D1821804A817C80073FB0201FB00A4C8CB1FC9ED54}
x{0000000D}
數字 0000000D(你的會更大)是必須替換的序號 testgiver.fif
.
就這樣,儲存檔案並運行(./crypto/fift testgiver.fif
)。 輸出將是一個文件 wallet-query.boc
。 這就是形成的樣子 сообщение 到其他人的智能合約 - 請求“將這麼多克轉移到某個帳戶”。
使用客戶端,我們將其上傳到網路:
> 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
如果你現在打電話 last
,然後再次請求我們請求克的帳戶的狀態,然後我們應該看到它的序號增加了 XNUMX - 這意味著它向我們的帳戶發送了錢。
最後一步仍然是 - 下載我們錢包的代碼(其餘額已被補充,但如果沒有智能合約代碼,我們將無法管理它)。 我們開展 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
)並檢查我們錢包的餘額和序號是否已更改(getaccount <account_id>
).
就這樣,現在我們可以在 TON 中建立智慧合約並向它們發送請求。 正如您所看到的,當前的功能已經足夠,例如,製作一個帶有圖形介面的更友好的錢包(但是,預計它將已經作為信使的一部分提供)。
只有註冊用戶才能參與調查。
您有興趣繼續分析 TON、TVM、Fift 的文章嗎?
-
是的,我正在等待 TON 概述系列文章的完成
-
是的,閱讀有關第五語言的更多內容很有趣
-
是的,我想了解有關 TON 虛擬機及其彙編器的更多信息
-
不,這些都不有趣
39 位用戶投票。 12 名用戶棄權。
您對 Telegram 推出 TON 的計劃有何看法?
-
我對這個計畫寄予厚望
-
我只是饒有興趣地關注著它的發展。
-
我對此表示懷疑並懷疑它的成功。
-
我傾向於認為這項舉措是失敗的,對於廣大群眾來說是不必要的
47 位用戶投票。 12 名用戶棄權。
來源: www.habr.com