Đi sâu vào Move - Ngôn ngữ lập trình chuỗi khối Libra của Facebook

Tiếp theo, chúng ta sẽ xem xét chi tiết các đặc điểm chính của ngôn ngữ Move và sự khác biệt chính của nó với một ngôn ngữ khác, đã phổ biến cho các hợp đồng thông minh - Solidity (trên nền tảng Ethereum). Tài liệu này dựa trên một nghiên cứu về sách trắng 26 trang trực tuyến có sẵn.

Giới thiệu

Move là ngôn ngữ mã byte thực thi được sử dụng để thực hiện các giao dịch của người dùng và hợp đồng thông minh. Xin lưu ý hai điểm:

  1. Trong khi Move là ngôn ngữ bytecode có thể được thực thi trực tiếp trên máy ảo Move, thì Solidity (ngôn ngữ hợp đồng thông minh của Ethereum) là ngôn ngữ cấp cao hơn được biên dịch đầu tiên thành bytecode trước khi được thực thi trên EVM (Ethereum Virtual Machine).
  2. Move có thể được sử dụng không chỉ để triển khai các hợp đồng thông minh mà còn cho các giao dịch tùy chỉnh (sẽ nói thêm về điều này sau), trong khi Solidity là một ngôn ngữ chỉ dành cho hợp đồng thông minh.


Bản dịch được thực hiện bởi nhóm dự án INDEX Protocol. Chúng tôi đã dịch rồi tài liệu lớn mô tả dự án Libra, bây giờ là lúc xem xét ngôn ngữ Move chi tiết hơn một chút. Bản dịch được thực hiện cùng với Habrauser coolsiu

Tính năng chính của Move là khả năng xác định các loại tài nguyên tùy chỉnh theo ngữ nghĩa dựa trên logic tuyến tính: một tài nguyên không bao giờ có thể được sao chép hoặc xóa hoàn toàn mà chỉ được di chuyển. Về mặt chức năng, điều này tương tự như khả năng của ngôn ngữ Rust. Các giá trị trong Rust chỉ có thể được gán cho một tên tại một thời điểm. Việc gán giá trị cho một tên khác sẽ khiến nó không còn khả dụng dưới tên trước đó.

Đi sâu vào Move - Ngôn ngữ lập trình chuỗi khối Libra của Facebook

Ví dụ: đoạn mã sau sẽ xuất hiện lỗi: Sử dụng giá trị đã di chuyển 'x'. Điều này là do không có bộ sưu tập rác trong Rust. Khi các biến vượt ra ngoài phạm vi, bộ nhớ mà chúng tham chiếu đến cũng được giải phóng. Nói một cách đơn giản, chỉ có thể có một "chủ sở hữu" của dữ liệu. Trong ví dụ này x là chủ sở hữu ban đầu và sau đó y trở thành chủ sở hữu mới. Đọc thêm về hành vi này ở đây.

Trình bày tài sản kỹ thuật số trong hệ thống mở

Có hai thuộc tính của tài sản vật chất khó thể hiện bằng kỹ thuật số:

  • Hiếm (Sự khan hiếm, ban đầu là sự khan hiếm). Số lượng tài sản (phát thải) trong hệ thống phải được kiểm soát. Việc sao chép các nội dung hiện có phải bị cấm và việc tạo ra các nội dung mới là một hoạt động đặc quyền.
  • Kiểm soát truy cập... Người tham gia hệ thống phải có khả năng bảo vệ tài sản bằng cách sử dụng các chính sách kiểm soát truy cập.

Hai đặc điểm này, vốn là tự nhiên đối với tài sản vật chất, phải được thực hiện cho các đối tượng kỹ thuật số nếu chúng ta muốn coi chúng là tài sản. Ví dụ, một kim loại hiếm có mức thâm hụt tự nhiên, và chỉ bạn mới có quyền sử dụng nó (chẳng hạn như cầm trên tay) và bạn có thể bán hoặc tiêu nó.

Để minh họa cách chúng tôi đến hai chỗ nghỉ này, hãy bắt đầu bằng những câu sau:

Đề xuất số 1: Quy tắc đơn giản nhất không có sự khan hiếm và kiểm soát truy cập

Đi sâu vào Move - Ngôn ngữ lập trình chuỗi khối Libra của Facebook

  • G [K]: = n biểu thị bản cập nhật của một số có thể truy cập bằng khóa К trong trạng thái toàn cầu của blockchain, với một ý nghĩa mới n.
  • giao dịch ⟨Alice, 100⟩ có nghĩa là đặt số dư tài khoản của Alice thành 100.

Giải pháp trên có một số vấn đề chính:

  • Alice có thể nhận được số lượng xu không giới hạn bằng cách gửi giao dịch ⟨Alice, 100⟩.
  • Số tiền Alice gửi cho Bob là vô dụng, vì Bob có thể gửi cho mình số lượng không giới hạn số tiền bằng cách sử dụng cùng một kỹ thuật.

Đề xuất số 2: Tính đến khoản thâm hụt

Đi sâu vào Move - Ngôn ngữ lập trình chuỗi khối Libra của Facebook

Bây giờ chúng tôi đang theo dõi tình hình để số lượng xu Ka ít nhất là bằng n trước khi thực hiện giao dịch chuyển nhượng. Tuy nhiên, trong khi điều này giải quyết được vấn đề khan hiếm, không có thông tin về ai có thể gửi tiền của Alice (hiện tại, bất kỳ ai cũng có thể làm điều này, điều chính là không vi phạm quy tắc giới hạn số lượng).

Đề xuất # 3: Kết hợp giữa khan hiếm và kiểm soát truy cập

Đi sâu vào Move - Ngôn ngữ lập trình chuỗi khối Libra của Facebook

Chúng tôi giải quyết vấn đề này bằng cơ chế chữ ký điện tử xác minh_sig trước khi kiểm tra số dư, có nghĩa là Alice sử dụng khóa cá nhân của mình để ký giao dịch và xác nhận rằng cô ấy là chủ sở hữu số tiền của mình.

Ngôn ngữ lập trình chuỗi khối

Các ngôn ngữ blockchain hiện tại phải đối mặt với các vấn đề sau (tất cả chúng đã được giải quyết trong Move (lưu ý: Thật không may, tác giả của bài viết chỉ hấp dẫn Ethereum trong các so sánh của mình, vì vậy chỉ nên xem xét chúng trong bối cảnh này. Ví dụ: hầu hết những điều sau đây cũng được giải quyết trong EOS.)):

Đại diện gián tiếp của tài sản. Nội dung được mã hóa bằng số nguyên nhưng số nguyên không giống với nội dung. Trên thực tế, không có loại hoặc giá trị nào đại diện cho Bitcoin/Ether/<Any Coin>! Điều này làm cho việc viết chương trình sử dụng tài sản trở nên khó khăn và dễ xảy ra lỗi. Các mẫu như chuyển nội dung đến/từ các thủ tục hoặc lưu trữ nội dung trong cấu trúc yêu cầu sự hỗ trợ đặc biệt từ ngôn ngữ.

Thâm hụt không thể mở rộng... Ngôn ngữ chỉ đại diện cho một tài sản khan hiếm. Ngoài ra, các biện pháp khắc phục sự khan hiếm được trình bày trực tiếp vào ngữ nghĩa của chính ngôn ngữ đó. Nhà phát triển, nếu anh ta muốn tạo một nội dung tùy chỉnh, phải tự mình kiểm soát cẩn thận tất cả các khía cạnh của tài nguyên đó. Đây chính xác là những vấn đề của hợp đồng thông minh Ethereum.

Người dùng phát hành tài sản của họ, mã thông báo ERC-20, sử dụng số nguyên để xác định cả giá trị và tổng nguồn cung. Bất cứ khi nào mã thông báo mới được tạo, mã hợp đồng thông minh phải xác minh độc lập việc tuân thủ các quy tắc phát thải. Ngoài ra, việc trình bày gián tiếp tài sản, trong một số trường hợp, dẫn đến sai sót nghiêm trọng - trùng lặp, chi tiêu gấp đôi hoặc thậm chí mất hoàn toàn tài sản.

Thiếu kiểm soát truy cập linh hoạt... Chính sách kiểm soát truy cập duy nhất được sử dụng hiện nay là một lược đồ chữ ký sử dụng mật mã không đối xứng. Giống như bảo vệ sự khan hiếm, các chính sách kiểm soát truy cập được gắn sâu vào ngữ nghĩa của ngôn ngữ. Nhưng làm thế nào để mở rộng ngôn ngữ để cho phép các lập trình viên xác định các chính sách kiểm soát truy cập của riêng họ thường là một công việc rất khó khăn.

Điều này cũng đúng trên Ethereum, nơi các hợp đồng thông minh không có hỗ trợ mật mã riêng để kiểm soát truy cập. Nhà phát triển phải đặt kiểm soát quyền truy cập theo cách thủ công, chẳng hạn như sử dụng công cụ sửa đổi onlyOwner.

Mặc dù tôi là một fan hâm mộ lớn của Ethereum, nhưng tôi tin rằng các thuộc tính tài sản phải được ngôn ngữ này hỗ trợ nguyên bản vì mục đích bảo mật. Đặc biệt, việc chuyển Ether sang một hợp đồng thông minh liên quan đến việc gửi động, điều này đã tạo ra một loại lỗi mới được gọi là lỗ hổng đăng nhập lại. Công văn động ở đây có nghĩa là logic thực thi của mã sẽ được xác định trong thời gian chạy (động) thay vì lúc biên dịch (tĩnh).

Do đó, trong Solidity, khi hợp đồng A gọi một hàm trong hợp đồng B, hợp đồng B có thể chạy mã không đúng ý định của nhà phát triển hợp đồng A, điều này có thể dẫn đến lỗ hổng tái nhập (hợp đồng A vô tình đóng vai hợp đồng B để rút tiền trước khi số dư tài khoản thực tế bị trừ).

Nguyên tắc cơ bản về thiết kế ngôn ngữ di chuyển

Tài nguyên đơn hàng đầu tiên

Ở mức độ cao, tương tác giữa các mô-đun / tài nguyên / thủ tục trong ngôn ngữ Move rất giống với mối quan hệ giữa các lớp / đối tượng và phương thức trong ngôn ngữ OOP.
Mô-đun di chuyển tương tự như các hợp đồng thông minh trong các blockchain khác. Mô-đun khai báo các loại tài nguyên và các thủ tục xác định các quy tắc để tạo, hủy và cập nhật các tài nguyên đã khai báo. Nhưng tất cả những điều này chỉ là quy ước (“biệt ngữ”) Trong Move. Chúng tôi sẽ minh họa điểm này một chút sau.

Tính linh hoạt

Move tăng thêm tính linh hoạt cho Libra thông qua tập lệnh. Mọi giao dịch trong Libra đều bao gồm một tập lệnh, về cơ bản là quy trình cốt lõi của giao dịch. Tập lệnh có thể thực hiện một hành động được chỉ định, ví dụ: thanh toán cho một danh sách người nhận được chỉ định hoặc sử dụng lại các tài nguyên khác - ví dụ: bằng cách gọi một thủ tục trong đó logic chung được chỉ định. Đây là lý do tại sao tập lệnh giao dịch Move mang lại sự linh hoạt cao hơn. Một tập lệnh có thể sử dụng cả hành vi một lần và lặp lại, trong khi Ethereum chỉ có thể thực thi các tập lệnh lặp lại (gọi một phương thức trên phương thức hợp đồng thông minh). Sở dĩ nó được gọi là “có thể tái sử dụng” là vì các chức năng của hợp đồng thông minh có thể được thực hiện nhiều lần. (ghi chú: Vấn đề ở đây rất tinh tế. Một mặt, các tập lệnh giao dịch ở dạng mã byte giả cũng tồn tại trong Bitcoin. Mặt khác, theo tôi hiểu, Move mở rộng ngôn ngữ này, trên thực tế, đến cấp độ ngôn ngữ hợp đồng thông minh chính thức).

Безопасность

Định dạng thực thi Move là mã byte, một mặt là ngôn ngữ cấp cao hơn ngôn ngữ hợp ngữ nhưng cấp độ thấp hơn mã nguồn. Mã byte được kiểm tra trong thời gian chạy (trên chuỗi) về tài nguyên, loại và mức độ an toàn của bộ nhớ bằng cách sử dụng trình xác minh mã byte, sau đó được trình thông dịch thực thi. Cách tiếp cận này cho phép Move cung cấp tính bảo mật của mã nguồn nhưng không có quá trình biên dịch và nhu cầu thêm trình biên dịch vào hệ thống. Biến Move thành ngôn ngữ mã byte thực sự là một giải pháp tốt. Nó không cần phải được biên dịch từ nguồn, như trường hợp của Solidity và không cần phải lo lắng về các lỗi hoặc các cuộc tấn công có thể xảy ra đối với cơ sở hạ tầng của trình biên dịch.

Khả năng xác minh

Mục tiêu của chúng tôi là thực hiện kiểm tra dễ dàng nhất có thể vì tất cả việc này được thực hiện trên chuỗi (lưu ý: trực tuyến, trong quá trình thực hiện mỗi giao dịch, vì vậy bất kỳ sự chậm trễ nào cũng dẫn đến sự chậm lại của toàn bộ mạng), tuy nhiên, ban đầu thiết kế ngôn ngữ đã sẵn sàng để sử dụng các công cụ xác minh tĩnh ngoài chuỗi. Mặc dù điều này được ưu tiên hơn nhưng hiện tại việc phát triển các công cụ xác minh (dưới dạng một bộ công cụ riêng biệt) đã bị hoãn lại trong tương lai và hiện chỉ hỗ trợ xác minh động trong thời gian chạy (trên chuỗi).

Môđun

Mô-đun Move cung cấp tính trừu tượng hóa dữ liệu và bản địa hóa các hoạt động quan trọng trên tài nguyên. Việc đóng gói được cung cấp bởi mô-đun, kết hợp với sự bảo vệ được cung cấp bởi hệ thống loại Move, đảm bảo rằng các thuộc tính được đặt trên các loại của mô-đun không thể bị vi phạm bởi mã bên ngoài mô-đun. Đây là một thiết kế trừu tượng được suy nghĩ kỹ lưỡng, có nghĩa là dữ liệu trong hợp đồng chỉ có thể được thay đổi trong phạm vi của hợp đồng, chứ không thể thay đổi bên ngoài.

Đi sâu vào Move - Ngôn ngữ lập trình chuỗi khối Libra của Facebook

Di chuyển tổng quan

Ví dụ về kịch bản giao dịch chứng minh rằng các hành động độc hại hoặc bất cẩn của một lập trình viên bên ngoài một mô-đun không thể làm tổn hại đến tính bảo mật của tài nguyên của mô-đun. Tiếp theo, chúng ta sẽ xem xét các ví dụ về cách các mô-đun, tài nguyên và thủ tục được sử dụng để lập trình chuỗi khối Libra.

Thanh toán ngang hàng

Đi sâu vào Move - Ngôn ngữ lập trình chuỗi khối Libra của Facebook

Số lượng xu được chỉ định trong số tiền sẽ được chuyển từ số dư của người gửi đến người nhận.
Có một số điều mới ở đây (được đánh dấu màu đỏ):

  • 0x0: địa chỉ của tài khoản nơi lưu trữ mô-đun
  • Tiền tệ: tên mô-đun
  • Coin: loại tài nguyên
  • Giá trị đồng xu được trả về bởi thủ tục là giá trị tài nguyên thuộc loại 0x0.
  • di chuyển (): giá trị không thể được sử dụng lại
  • copy (): giá trị có thể được sử dụng sau này

Phân tích cú pháp mã: trong bước đầu tiên, người gửi gọi một thủ tục có tên rút_lời_gửi từ một mô-đun được lưu trữ trong 0x0. Tiền tệ. Ở bước thứ hai, người gửi chuyển tiền cho người nhận bằng cách chuyển giá trị tài nguyên tiền xu vào quy trình gửi tiền của mô-đun 0x0. Tiền tệ.

Dưới đây là ba ví dụ về lỗi trong mã sẽ bị từ chối khi kiểm tra:
Nhân đôi tiền bằng cách thay đổi cuộc gọi di chuyển (đồng xu) trên sao chép (đồng xu). Tài nguyên chỉ có thể được di chuyển. Cố gắng sao chép số lượng tài nguyên (ví dụ: bằng cách gọi sao chép (đồng xu) trong ví dụ trên) sẽ dẫn đến lỗi khi kiểm tra mã bytecode.

Tái sử dụng tiền bằng cách chỉ định di chuyển (đồng xu) hai lần . Thêm một dòng 0x0.Currency.deposit (sao chép (some_other_payee), di chuyển (coin)) ví dụ: cách trên sẽ cho phép người gửi “tiêu” xu hai lần - lần đầu tiên với người nhận thanh toán và lần thứ hai với some_other_người nhận tiền. Đây là một hành vi không mong muốn không thể xảy ra với một tài sản vật chất. May mắn thay, Move sẽ từ chối chương trình này.

Mất tiền do bị từ chối di chuyển (đồng xu). Nếu bạn không di chuyển tài nguyên (ví dụ: bằng cách xóa dòng chứa di chuyển (đồng xu)), lỗi xác minh mã byte sẽ được đưa ra. Điều này bảo vệ các lập trình viên Move khỏi việc mất tiền do vô tình hoặc cố ý.

Mô-đun tiền tệ

Đi sâu vào Move - Ngôn ngữ lập trình chuỗi khối Libra của Facebook

Mỗi tài khoản có thể chứa 0 hoặc nhiều mô-đun (hiển thị dưới dạng hình chữ nhật) và một hoặc nhiều giá trị tài nguyên (hiển thị dưới dạng hình trụ). Ví dụ: một tài khoản tại 0x0 chứa mô-đun 0x0. Tiền tệ và giá trị của loại tài nguyên 0x0.Currency.Coin. Tài khoản tại địa chỉ 0x1 có hai tài nguyên và một mô-đun; Tài khoản tại địa chỉ 0x2 có hai mô-đun và một giá trị tài nguyên.

Khoảnh khắc Nekotory:

  • Tập lệnh giao dịch là nguyên tử - nó được thực thi hoàn toàn hoặc hoàn toàn không.
  • Mô-đun là một đoạn mã tồn tại lâu dài và có thể truy cập được trên toàn cầu.
  • Trạng thái toàn cục được cấu trúc dưới dạng bảng băm, trong đó khóa là địa chỉ tài khoản
  • Tài khoản không thể chứa nhiều hơn một giá trị tài nguyên của một loại nhất định và không nhiều hơn một mô-đun có tên nhất định (tài khoản tại 0x0 không thể chứa tài nguyên bổ sung 0x0.Currency.Coin hoặc mô-đun khác có tên Tiền tệ)
  • Địa chỉ của mô-đun được khai báo là một phần của loại (0x0.Currency.Coin и 0x1.Currency.Coin là những loại riêng biệt không thể sử dụng thay thế cho nhau)
  • Lập trình viên có thể lưu trữ nhiều phiên bản của loại tài nguyên này trong một tài khoản bằng cách xác định tài nguyên tùy chỉnh của họ - (tài nguyên TwoCoins {c1: 0x0.Currency.Coin, c2: 0x0.Currency.Coin})
  • Bạn có thể tham chiếu đến một tài nguyên theo tên của nó mà không có xung đột, ví dụ bạn có thể tham chiếu đến hai tài nguyên bằng cách sử dụng TwoCoins.c1 и TwoCoins.c2.

Thông báo tài nguyên tiền xu

Đi sâu vào Move - Ngôn ngữ lập trình chuỗi khối Libra của Facebook
Mô-đun được đặt tên Tiền tệ và một loại tài nguyên có tên Coin

Khoảnh khắc Nekotory:

  • Coin là một cấu trúc với một trường kiểu u64 (số nguyên không dấu 64-bit)
  • Chỉ thủ tục mô-đun Tiền tệ có thể tạo hoặc hủy các giá trị thuộc loại Coin.
  • Các mô-đun và tập lệnh khác chỉ có thể ghi hoặc tham chiếu trường giá trị thông qua các thủ tục công khai do mô-đun cung cấp.

Bán tiền đặt cọc

Đi sâu vào Move - Ngôn ngữ lập trình chuỗi khối Libra của Facebook

Thủ tục này chấp nhận một tài nguyên Coin làm đầu vào và kết hợp nó với tài nguyên Coinđược lưu trữ trong tài khoản của người nhận:

  1. Phá hủy tài nguyên đầu vào Coin và ghi lại giá trị của nó.
  2. Nhận liên kết đến tài nguyên Coin duy nhất được lưu trữ trong tài khoản của người nhận.
  3. Thay đổi giá trị của số Xu theo giá trị được truyền trong tham số khi gọi thủ tục.

Khoảnh khắc Nekotory:

  • Giải nén, BorrowGlobal - thủ tục tích hợp
  • Giải nén Đây là cách duy nhất để xóa tài nguyên loại T. Quy trình lấy tài nguyên làm đầu vào, hủy tài nguyên đó và trả về giá trị được liên kết với các trường của tài nguyên.
  • Vay toàn cầu lấy một địa chỉ làm đầu vào và trả về một tham chiếu đến một phiên bản duy nhất của T được xuất bản (sở hữu) bởi địa chỉ đó
  • &mut Đồng xu đây là một liên kết đến tài nguyên Coin

Thực hiện rút_from_sender

Đi sâu vào Move - Ngôn ngữ lập trình chuỗi khối Libra của Facebook

Thủ tục này:

  1. Nhận liên kết đến một tài nguyên duy nhất Coin, được liên kết với tài khoản của người gửi
  2. Giảm giá trị của tài nguyên Coin thông qua liên kết với số tiền được chỉ định
  3. Tạo và trả về một tài nguyên mới Coin với số dư được cập nhật.

Khoảnh khắc Nekotory:

  • Tiền gửi có thể do bất cứ ai gây ra, nhưng rút_lời_gửi chỉ có quyền truy cập vào số tiền của tài khoản gọi điện
  • GetTxnĐịa chỉ người gửi tương tự như tin nhắn.người gửi trong sự vững chắc
  • Từ chốiTrừ khi tương tự như yêu cầu trong sự vững chắc. Nếu việc kiểm tra này không thành công, giao dịch sẽ bị dừng và tất cả các thay đổi sẽ được khôi phục.
  • Đóng gói nó cũng là một thủ tục tích hợp để tạo ra một tài nguyên mới thuộc loại T.
  • Cũng như Giải nén, Đóng gói chỉ có thể được gọi bên trong mô-đun nơi tài nguyên được mô tả T

Kết luận

Chúng tôi đã xem xét các đặc điểm chính của ngôn ngữ Move, so sánh nó với Ethereum và cũng đã làm quen với cú pháp cơ bản của tập lệnh. Cuối cùng, tôi thực sự khuyên bạn nên kiểm tra giấy trắng gốc. Nó bao gồm rất nhiều chi tiết liên quan đến nguyên tắc thiết kế ngôn ngữ lập trình, cũng như nhiều liên kết hữu ích.

Nguồn: www.habr.com

Thêm một lời nhận xét