คุณคงเคยได้ยินว่าโทรเลข
ทีม Serokell ซึ่งมีประสบการณ์มากมายในการพัฒนาโครงการบล็อกเชนขนาดใหญ่ไม่สามารถยืนหยัดได้ เราได้มอบหมายพนักงานห้าคนเข้าร่วมการแข่งขัน และสองสัปดาห์ต่อมาพวกเขาก็ได้ที่หนึ่งภายใต้ชื่อเล่นแบบสุ่ม (ใน) สุดเก๋อย่าง Sexy Chameleon ในบทความนี้ ฉันจะพูดถึงว่าพวกเขาทำได้อย่างไร เราหวังว่าในอีกสิบนาทีข้างหน้าคุณจะได้อ่านเรื่องราวที่น่าสนใจเป็นอย่างน้อยและอย่างน้อยที่สุดคุณจะพบสิ่งที่มีประโยชน์ซึ่งคุณสามารถนำไปใช้ในงานของคุณได้
แต่ขอเริ่มต้นด้วยบริบทเล็กน้อย
การแข่งขันและเงื่อนไข
ดังนั้นงานหลักของผู้เข้าร่วมคือการดำเนินการตามสัญญาอัจฉริยะที่เสนอตั้งแต่หนึ่งรายการขึ้นไป ตลอดจนจัดทำข้อเสนอเพื่อปรับปรุงระบบนิเวศ TON การแข่งขันเริ่มตั้งแต่วันที่ 24 กันยายนถึง 15 ตุลาคม และประกาศผลในวันที่ 15 พฤศจิกายนเท่านั้น ค่อนข้างนานเมื่อพิจารณาว่าในช่วงเวลานี้ Telegram สามารถจัดการและประกาศผลการแข่งขันเกี่ยวกับการออกแบบและพัฒนาแอปพลิเคชันใน C ++ เพื่อทดสอบและประเมินคุณภาพการโทร VoIP ใน Telegram
เราเลือกสัญญาอัจฉริยะสองฉบับจากรายการที่เสนอโดยผู้จัดงาน สำหรับหนึ่งในนั้น เราใช้เครื่องมือที่เผยแพร่กับ TON และเครื่องมือที่สองถูกนำมาใช้ในภาษาใหม่ที่พัฒนาโดยวิศวกรของเราสำหรับ TON โดยเฉพาะและสร้างไว้ใน Haskell
การเลือกภาษาการเขียนโปรแกรมเชิงฟังก์ชันไม่ใช่เรื่องบังเอิญ ในตัวเรา
ทำไมเราถึงตัดสินใจเข้าร่วม?
กล่าวโดยสรุป เนื่องจากความเชี่ยวชาญของเราเป็นโครงการที่ไม่ได้มาตรฐานและซับซ้อนซึ่งต้องใช้ทักษะพิเศษและมักจะมีคุณค่าทางวิทยาศาสตร์ต่อชุมชนไอที เราสนับสนุนการพัฒนาโอเพ่นซอร์สอย่างยิ่งและมีส่วนร่วมในการเผยแพร่ให้แพร่หลาย และยังร่วมมือกับมหาวิทยาลัยชั้นนำของรัสเซียในสาขาวิทยาการคอมพิวเตอร์และคณิตศาสตร์
งานที่น่าสนใจของการแข่งขันและการมีส่วนร่วมในโครงการ Telegram อันเป็นที่รักของเรานั้นเป็นแรงจูงใจที่ดีเยี่ยมในตัวมันเอง แต่เงินรางวัลก็กลายเป็นแรงจูงใจเพิ่มเติม 🙂
การวิจัยบล็อกเชน TON
เราติดตามการพัฒนาใหม่ๆ ในบล็อกเชน ปัญญาประดิษฐ์ และการเรียนรู้ของเครื่องจักรอย่างใกล้ชิด และพยายามที่จะไม่พลาดการเผยแพร่ที่สำคัญเพียงครั้งเดียวในแต่ละด้านที่เราทำงาน ดังนั้นเมื่อเริ่มการแข่งขันทีมของเราก็คุ้นเคยกับไอเดียจาก
เมื่อการแข่งขันเริ่มต้น รหัสก็ถูกเผยแพร่ไปแล้ว ดังนั้น เพื่อเป็นการประหยัดเวลา เราจึงตัดสินใจหาคำแนะนำหรือบทสรุปที่เขียนโดย โดยผู้ใช้. น่าเสียดายที่สิ่งนี้ไม่ได้ให้ผลลัพธ์ใด ๆ นอกเหนือจากคำแนะนำในการประกอบแพลตฟอร์มบน Ubuntu แล้ว เราไม่พบวัสดุอื่นใด
เอกสารประกอบได้รับการค้นคว้ามาอย่างดี แต่อ่านยากในบางพื้นที่ บ่อยครั้งเราต้องกลับไปยังจุดหนึ่งและเปลี่ยนจากคำอธิบายระดับสูงของแนวคิดเชิงนามธรรมไปเป็นรายละเอียดการนำไปปฏิบัติระดับต่ำ
มันจะง่ายกว่านี้ถ้าข้อกำหนดไม่มีคำอธิบายโดยละเอียดของการนำไปปฏิบัติเลย ข้อมูลเกี่ยวกับวิธีที่เครื่องเสมือนเป็นตัวแทนสแต็กมีแนวโน้มที่จะเบี่ยงเบนความสนใจของนักพัฒนาในการสร้างสัญญาอัจฉริยะสำหรับแพลตฟอร์ม TON มากกว่าที่จะช่วยเหลือพวกเขา
ห้าม: รวบรวมโครงการเข้าด้วยกัน
ที่ Serokell เราเป็นแฟนตัวยง
ดังนั้นเราจึงเริ่มต้นด้วยการสร้าง
$ cd ~/.config/nixpkgs/overlays && git clone https://github.com/serokell/ton.nix
$ cd /path/to/ton/repo && nix-shell
[nix-shell]$ cmakeConfigurePhase && make
โปรดทราบว่าคุณไม่จำเป็นต้องติดตั้งการขึ้นต่อกันใดๆ Nix จะทำทุกอย่างให้คุณอย่างน่าอัศจรรย์ ไม่ว่าคุณจะใช้ NixOS, Ubuntu หรือ macOS
การเขียนโปรแกรมสำหรับ TON
รหัสสัญญาอัจฉริยะในเครือข่าย TON ทำงานบน TON Virtual Machine (TVM) TVM มีความซับซ้อนมากกว่าเครื่องเสมือนอื่นๆ ส่วนใหญ่ และมีฟังก์ชันที่น่าสนใจมาก เช่น สามารถทำงานได้ ความต่อเนื่อง и เชื่อมโยงไปยังข้อมูล.
นอกจากนี้ ทีมจาก TON ยังได้สร้างภาษาการเขียนโปรแกรมใหม่สามภาษา:
ห้า เป็นภาษาโปรแกรมสแต็กสากลที่มีลักษณะคล้าย
ฟันซี เป็นภาษาโปรแกรมสัญญาอัจฉริยะที่มีลักษณะคล้ายกับ
ผู้ประกอบคนที่ห้า — ห้าไลบรารีสำหรับสร้างโค้ดปฏิบัติการแบบไบนารีสำหรับ TVM Fifth Assembler ไม่มีคอมไพเลอร์ นี้
การแข่งขันของเราทำงาน
ในที่สุดก็ถึงเวลาดูผลลัพธ์ของความพยายามของเรา
ช่องทางการชำระเงินแบบอะซิงโครนัส
ช่องทางการชำระเงินเป็นสัญญาอัจฉริยะที่อนุญาตให้ผู้ใช้สองคนส่งการชำระเงินนอกบล็อคเชน เป็นผลให้คุณไม่เพียงประหยัดเงิน (ไม่มีค่าคอมมิชชัน) แต่ยังประหยัดเวลาด้วย (คุณไม่ต้องรอบล็อกถัดไปที่จะดำเนินการ) การชำระเงินอาจมีเพียงเล็กน้อยตามต้องการและบ่อยเท่าที่ต้องการ ในกรณีนี้ คู่สัญญาไม่จำเป็นต้องเชื่อใจซึ่งกันและกัน เนื่องจากความเป็นธรรมของการชำระหนี้ขั้นสุดท้ายรับประกันโดยสัญญาอัจฉริยะ
เราพบวิธีแก้ไขปัญหาที่ค่อนข้างง่าย ทั้งสองฝ่ายสามารถแลกเปลี่ยนข้อความที่ลงนาม โดยแต่ละฝ่ายจะมีตัวเลขสองตัว ซึ่งเป็นจำนวนเงินที่แต่ละฝ่ายชำระเต็มจำนวน ตัวเลขสองตัวนี้ทำงานเหมือนกัน
อันที่จริง ตัวเลขตัวเดียวก็เพียงพอที่จะนำแนวคิดนี้ไปใช้ แต่เราทิ้งทั้งสองไว้เพราะวิธีนี้เราสามารถสร้างอินเทอร์เฟซผู้ใช้ที่สะดวกยิ่งขึ้นได้ นอกจากนี้เรายังตัดสินใจรวมจำนวนเงินที่ชำระไว้ในแต่ละข้อความด้วย หากไม่มีข้อความดังกล่าว หากข้อความสูญหายด้วยเหตุผลบางประการ แม้ว่าจำนวนเงินทั้งหมดและการคำนวณขั้นสุดท้ายจะถูกต้อง แต่ผู้ใช้อาจไม่สังเกตเห็นการสูญเสีย
เพื่อทดสอบแนวคิดของเรา เรามองหาตัวอย่างของการใช้โปรโตคอลช่องทางการชำระเงินที่เรียบง่ายและรัดกุม น่าแปลกที่เราพบเพียงสองรายการเท่านั้น:
ลักษณะ วิธีการที่คล้ายกัน เฉพาะในกรณีของช่องทางเดียวเท่านั้นบทช่วยสอน ซึ่งอธิบายแนวคิดเดียวกันกับของเรา แต่ไม่ได้อธิบายรายละเอียดที่สำคัญมากมาย เช่น ความถูกต้องทั่วไป และขั้นตอนการแก้ไขข้อขัดแย้ง
เห็นได้ชัดว่าเป็นการเหมาะสมที่จะอธิบายโปรโตคอลของเราโดยละเอียด โดยให้ความสำคัญกับความถูกต้องเป็นพิเศษ หลังจากทำซ้ำหลายครั้ง ข้อมูลจำเพาะก็พร้อม และตอนนี้คุณก็ทำได้เช่นกัน
เราใช้สัญญาใน FunC และเราเขียนยูทิลิตี้บรรทัดคำสั่งสำหรับการโต้ตอบกับสัญญาของเราทั้งหมดใน Fift ตามที่ผู้จัดงานแนะนำ เราสามารถเลือกภาษาอื่นสำหรับ CLI ของเราได้ แต่เราสนใจที่จะลองใช้ Fit เพื่อดูว่ามันทำงานอย่างไรในทางปฏิบัติ
พูดตามตรงหลังจากทำงานกับ Fift เราไม่เห็นเหตุผลที่น่าสนใจใด ๆ ที่จะเลือกใช้ภาษานี้มากกว่าภาษายอดนิยมและใช้งานอย่างแข็งขันด้วยเครื่องมือและห้องสมุดที่พัฒนาขึ้น การเขียนโปรแกรมในภาษาแบบสแต็กนั้นค่อนข้างไม่เป็นที่พอใจเนื่องจากคุณต้องนึกถึงสิ่งที่อยู่ในสแต็กอย่างต่อเนื่องและคอมไพเลอร์ไม่ได้ช่วยในเรื่องนี้
ดังนั้นตามความเห็นของเรา เหตุผลเดียวสำหรับการมีอยู่ของ Fift คือบทบาทของมันในฐานะภาษาโฮสต์สำหรับ Fift Assembler แต่จะดีกว่าไหมถ้าฝัง TVM แอสเซมเบลอร์เป็นภาษาที่มีอยู่ แทนที่จะสร้างภาษาใหม่ขึ้นมาเพื่อจุดประสงค์หลักเพียงอย่างเดียวนี้
TVM Haskell eDSL
ตอนนี้ถึงเวลาพูดคุยเกี่ยวกับสัญญาอันชาญฉลาดฉบับที่สองของเราแล้ว เราตัดสินใจที่จะพัฒนากระเป๋าเงินแบบหลายลายเซ็น แต่การเขียนสัญญาอัจฉริยะอีกฉบับใน FunC คงจะน่าเบื่อเกินไป เราต้องการเพิ่มรสชาติ และนั่นคือภาษาแอสเซมบลีของเราเองสำหรับ TVM
เช่นเดียวกับ Fift Assembler ภาษาใหม่ของเราถูกฝังไว้ แต่เราเลือก Haskell เป็นโฮสต์แทนที่จะเป็น Fift ทำให้เราใช้ประโยชน์จากระบบประเภทขั้นสูงได้อย่างเต็มที่ เมื่อทำงานกับสัญญาอัจฉริยะ ซึ่งต้นทุนของข้อผิดพลาดเล็กๆ น้อยๆ อาจสูงมาก ในความคิดของเรา การพิมพ์แบบคงที่ถือเป็นข้อได้เปรียบที่ยิ่งใหญ่
เพื่อแสดงให้เห็นว่าแอสเซมเบลอร์ TVM มีลักษณะอย่างไรที่ฝังอยู่ใน Haskell เราได้ติดตั้งกระเป๋าเงินมาตรฐานไว้ ต่อไปนี้เป็นบางสิ่งที่ควรคำนึงถึง:
- สัญญานี้ประกอบด้วยหนึ่งฟังก์ชัน แต่คุณสามารถใช้ได้มากเท่าที่คุณต้องการ เมื่อคุณกำหนดฟังก์ชันใหม่ในภาษาโฮสต์ (เช่น Haskell) eDSL ของเราจะช่วยให้คุณสามารถเลือกได้ว่าต้องการให้กลายเป็นกิจวัตรแยกต่างหากใน TVM หรือเพียงแทรกในบรรทัด ณ จุดที่มีการโทร
- เช่นเดียวกับ Haskell ฟังก์ชันมีประเภทที่ได้รับการตรวจสอบ ณ เวลาคอมไพล์ ใน eDSL ของเรา ประเภทอินพุตของฟังก์ชันคือประเภทของสแต็กที่ฟังก์ชันคาดหวัง และประเภทผลลัพธ์คือประเภทของสแต็กที่จะสร้างขึ้นหลังจากการเรียก
- รหัสมีคำอธิบายประกอบ
stacktype
อธิบายประเภทสแต็กที่คาดหวังที่จุดเรียก ในสัญญากระเป๋าเงินต้นฉบับ สิ่งเหล่านี้เป็นเพียงความคิดเห็น แต่ใน eDSL ของเรา จริงๆ แล้วสิ่งเหล่านี้เป็นส่วนหนึ่งของโค้ดและได้รับการตรวจสอบ ณ เวลาคอมไพล์ สามารถใช้เป็นเอกสารหรือคำสั่งที่ช่วยให้นักพัฒนาค้นหาปัญหาได้หากโค้ดเปลี่ยนแปลงและประเภทสแต็กเปลี่ยนไป แน่นอนว่าคำอธิบายประกอบดังกล่าวจะไม่ส่งผลกระทบต่อประสิทธิภาพรันไทม์ เนื่องจากไม่มีการสร้างโค้ด TVM สำหรับหมายเหตุเหล่านั้น - นี่ยังคงเป็นต้นแบบที่เขียนขึ้นภายในสองสัปดาห์ ดังนั้นจึงยังมีงานอีกมากที่ต้องทำในโครงการนี้ ตัวอย่างเช่น อินสแตนซ์ทั้งหมดของคลาสที่คุณเห็นในโค้ดด้านล่างควรถูกสร้างขึ้นโดยอัตโนมัติ
นี่คือลักษณะการใช้งาน Multisig Wallet บน eDSL ของเรา:
main :: IO ()
main = putText $ pretty $ declProgram procedures methods
where
procedures =
[ ("recv_external", decl recvExternal)
, ("recv_internal", decl recvInternal)
]
methods =
[ ("seqno", declMethod getSeqno)
]
data Storage = Storage
{ sCnt :: Word32
, sPubKey :: PublicKey
}
instance DecodeSlice Storage where
type DecodeSliceFields Storage = [PublicKey, Word32]
decodeFromSliceImpl = do
decodeFromSliceImpl @Word32
decodeFromSliceImpl @PublicKey
instance EncodeBuilder Storage where
encodeToBuilder = do
encodeToBuilder @Word32
encodeToBuilder @PublicKey
data WalletError
= SeqNoMismatch
| SignatureMismatch
deriving (Eq, Ord, Show, Generic)
instance Exception WalletError
instance Enum WalletError where
toEnum 33 = SeqNoMismatch
toEnum 34 = SignatureMismatch
toEnum _ = error "Uknown MultiSigError id"
fromEnum SeqNoMismatch = 33
fromEnum SignatureMismatch = 34
recvInternal :: '[Slice] :-> '[]
recvInternal = drop
recvExternal :: '[Slice] :-> '[]
recvExternal = do
decodeFromSlice @Signature
dup
preloadFromSlice @Word32
stacktype @[Word32, Slice, Signature]
-- cnt cs sign
pushRoot
decodeFromCell @Storage
stacktype @[PublicKey, Word32, Word32, Slice, Signature]
-- pk cnt' cnt cs sign
xcpu @1 @2
stacktype @[Word32, Word32, PublicKey, Word32, Slice, Signature]
-- cnt cnt' pk cnt cs sign
equalInt >> throwIfNot SeqNoMismatch
push @2
sliceHash
stacktype @[Hash Slice, PublicKey, Word32, Slice, Signature]
-- hash pk cnt cs sign
xc2pu @0 @4 @4
stacktype @[PublicKey, Signature, Hash Slice, Word32, Slice, PublicKey]
-- pubk sign hash cnt cs pubk
chkSignU
stacktype @[Bool, Word32, Slice, PublicKey]
-- ? cnt cs pubk
throwIfNot SignatureMismatch
accept
swap
decodeFromSlice @Word32
nip
dup
srefs @Word8
pushInt 0
if IsEq
then ignore
else do
decodeFromSlice @Word8
decodeFromSlice @(Cell MessageObject)
stacktype @[Slice, Cell MessageObject, Word8, Word32, PublicKey]
xchg @2
sendRawMsg
stacktype @[Slice, Word32, PublicKey]
endS
inc
encodeToCell @Storage
popRoot
getSeqno :: '[] :-> '[Word32]
getSeqno = do
pushRoot
cToS
preloadFromSlice @Word32
สามารถดูซอร์สโค้ดฉบับสมบูรณ์ของ eDSL และสัญญากระเป๋าเงินหลายลายเซ็นได้ที่
สรุปผลการแข่งขันและ TON
งานของเราใช้เวลาทั้งหมด 380 ชั่วโมง (รวมถึงการทำความคุ้นเคยกับเอกสาร การประชุม และการพัฒนาจริง) นักพัฒนาห้ารายเข้าร่วมในโครงการแข่งขัน ได้แก่ CTO หัวหน้าทีม ผู้เชี่ยวชาญด้านแพลตฟอร์มบล็อกเชน และนักพัฒนาซอฟต์แวร์ Haskell
เราพบทรัพยากรที่จะเข้าร่วมในการแข่งขันได้โดยไม่ยาก เนื่องจากจิตวิญญาณของแฮ็กกาธอน การทำงานเป็นทีมอย่างใกล้ชิด และความต้องการที่จะดื่มด่ำไปกับเทคโนโลยีใหม่ ๆ อย่างรวดเร็วนั้นน่าตื่นเต้นอยู่เสมอ การนอนไม่หลับหลายคืนเพื่อให้ได้ผลลัพธ์สูงสุดในสภาวะที่มีทรัพยากรจำกัดจะได้รับการชดเชยด้วยประสบการณ์อันล้ำค่าและความทรงจำที่ยอดเยี่ยม นอกจากนี้ การทำงานดังกล่าวถือเป็นการทดสอบกระบวนการของบริษัทที่ดีเสมอ เนื่องจากเป็นเรื่องยากมากที่จะบรรลุผลลัพธ์ที่ดีอย่างแท้จริงโดยปราศจากปฏิสัมพันธ์ภายในที่ดี
นอกเหนือจากเนื้อเพลง: เราประทับใจกับปริมาณงานของทีม TON พวกเขาสามารถสร้างระบบการทำงานที่ซับซ้อน สวยงาม และที่สำคัญที่สุดได้ TON ได้พิสูจน์ตัวเองแล้วว่าเป็นแพลตฟอร์มที่มีศักยภาพสูง อย่างไรก็ตาม เพื่อให้ระบบนิเวศนี้พัฒนาขึ้น จำเป็นต้องดำเนินการอีกมาก ทั้งในแง่ของการใช้งานในโครงการบล็อคเชน และในแง่ของการปรับปรุงเครื่องมือการพัฒนา ตอนนี้เราภูมิใจที่ได้เป็นส่วนหนึ่งของกระบวนการนี้
หากหลังจากอ่านบทความนี้แล้ว หากคุณยังคงมีคำถามหรือมีแนวคิดเกี่ยวกับวิธีใช้ TON เพื่อแก้ไขปัญหาของคุณ
ที่มา: will.com