Dive into Move, Facebook's Libra Blockchain Programming Language

Next, we will consider in detail the main characteristics of the Move language and what are its key differences with another, already popular language for smart contracts - Solidity (on the Ethereum platform). The material is based on a study of the available online 26-page whitepaper.

Introduction

Move is an executable bytecode language that is used to execute user transactions and smart contracts. Pay attention to two points:

  1. While Move is a bytecode language that can be directly executed on the Move virtual machine, Solidity (Ethereum's smart contract language) is a higher-level language that is first compiled to bytecode before being executed on an EVM (Ethereum Virtual Machine ).
  2. Move can be used not only to implement smart contracts, but also for custom transactions (more on this later), while Solidity is a smart contract-only language.


The translation was made by the INDEX Protocol project team. We have previously translated great material describing the Libra project, now it's time to take a closer look at the Move language. The translation was made together with the habrauser coolsiu

A key feature of Move is the ability to define custom resource types with semantics based on linear logic: a resource can never be copied or implicitly deleted, only moved. Functionally, this is similar to the features of the Rust language. Values ​​in Rust can only be assigned to one name at a time. Assigning a value to another name makes it inaccessible under the previous name.

Dive into Move, Facebook's Libra Blockchain Programming Language

For example, the following code snippet will throw an error: Use of moved value 'x'. This is because there is no garbage collection in Rust. When variables go out of scope, the memory they refer to is freed as well. Simply put, there can only be one "owner" of the data. In this example x is the original owner and then y becomes the new owner. Read more about this behavior here..

Representation of digital assets in open systems

There are two properties of physical assets that are difficult to digitally represent:

  • Rarity (Scarcity, originally scarcity). The number of assets (emission) in the system must be controlled. Duplication of existing assets must be prohibited, and creating new ones is a privileged operation.
  • Access control... The system participant must be able to protect assets using access control policies.

These two characteristics, which are natural for physical assets, must be implemented for digital objects if we want to consider them as assets. For example, a rare metal has a natural scarcity, and only you have access to it (holding it in your hands, for example) and you can sell or spend it.

To illustrate how we arrived at these two properties, let's start with the following sentences:

Suggestion # 1: The Simplest Rule Without Scarcity and Access Control

Dive into Move, Facebook's Libra Blockchain Programming Language

  • G [K]: = n denotes an update to a number accessible by a key К in the global state of the blockchain, with a new meaning n.
  • transaction ⟨Alice, 100⟩ means setting Alice's account balance to 100.

The above solution has several major problems:

  • Alice can receive an unlimited number of coins by simply sending transaction ⟨Alice, 100⟩.
  • The coins Alice sends to Bob are useless, as Bob could send himself an unlimited number of coins using the same technique.

Suggestion # 2: Taking into account the deficit

Dive into Move, Facebook's Libra Blockchain Programming Language

Now we are monitoring the situation so that the number of coins Ka was at least equal n before the transfer transaction. However, while this solves the problem of scarcity, there is no information about who can send Alice's coins (for now, anyone can do this, the main thing is not to violate the rule of limiting the amount).

Proposal # 3: Combining scarcity and access control

Dive into Move, Facebook's Libra Blockchain Programming Language

We solve this problem with a digital signature mechanism verify_sig before checking the balance, which means that Alice uses her private key to sign the transaction and confirm that she is the owner of her coins.

Blockchain programming languages

Existing blockchain languages ​​face the following problems (all of them were solved in Move (note: unfortunately, the author of the article only appeals to Ethereum in his comparisons, so it is worth taking them only in this context. For example, most of the following is also resolved in EOS.)):

Indirect representation of assets. An asset is encoded using an integer, but an integer value is not the same as an asset. In fact, there is no type or value representing bitcoin / ether / <Any Coin>! This makes it difficult and error-prone to write programs that use assets. Patterns such as passing assets to/from procedures or storing assets in structures require special support from the language.

The deficit is not expandable... Language represents only one scarce asset. In addition, the remedies against scarcity are hardwired directly into the semantics of the language itself. The developer, if he wants to create a custom asset, must carefully control all aspects of the resource himself. These are exactly the problems of Ethereum smart contracts.

Users issue their assets, ERC-20 tokens, using integers to determine both the value and the total supply. Whenever new tokens are created, the smart contract code must independently verify compliance with the emission rules. In addition, the indirect presentation of assets leads, in some cases, to serious errors - duplication, double spending or even complete loss of assets.

Lack of flexible access control... The only access control policy in use today is a signature scheme using asymmetric cryptography. Like scarcity protection, access control policies are deeply embedded in the semantics of the language. But how to extend the language to allow programmers to define their own access control policies is often a very tricky task.

This is also true for Ethereum, where smart contracts do not have native support for cryptography for access control. Developers must manually write access control, for example, using the onlyOwner modifier.

Even though I am a big fan of Ethereum, I believe that asset properties should be natively supported by the language for security purposes. In particular, passing Ether into a smart contract enables dynamic dispatch, which has introduced a new class of bugs known as re-entrancy vulnerabilities. Dynamic dispatch here means that the code execution logic will be determined at run time (dynamic) and not at compile time (static).

Thus, in Solidity, when contract A calls a function of contract B, contract B may run code that was not intended by the developer of contract A, which can lead to re-entry vulnerabilities (contract A accidentally acts as contract B to withdraw money before the balances are actually deducted from the account).

Move Language Design Fundamentals

First-order resources

At a high level, the interaction between modules / resources / procedures in the Move language is very similar to the relationship between classes / objects and methods in OOP languages.
Move modules are similar to smart contracts in other blockchains. The module declares resource types and procedures that define the rules for creating, destroying, and updating declared resources. But all these are just conventions (β€œjargon”) In Move. We will illustrate this point a little later.

Flexibility

Move adds flexibility to Libra through scripting. Every transaction in Libra includes a script, which is actually the main procedure of the transaction. The script can either perform one specified action, for example, making payments to a specified list of recipients, or reuse other resources, for example, by calling a procedure that defines common logic. This is why Move transaction scripts offer a lot of flexibility. A script can use both one-time and recurring behaviors, while Ethereum can only execute recurring scripts (calling a single smart contract method). The reason it is called "repeated" is because smart contract functions can be executed multiple times. (note: here the moment is very subtle. On the one hand, there are transaction scripts in the form of pseudo-bytecode in Bitcoin. On the other hand, as I understand it, Move expands this language, in fact, to the level of a full-fledged smart contract language).

Security

The Move executable format is bytecode, which, on the one hand, is a higher-level language than assembler, but lower-level than source code. The bytecode is checked in run-time (on-chain) for resources, types, and memory safety using a bytecode verifier and then executed by the interpreter. This approach allows Move to provide the security of source code, but without the compilation process and the need to add a compiler to the system. Making Move a bytecode language is a really good idea. It does not need to be compiled from source, as in the case of Solidity, there is no need to worry about possible failures or attacks on the compiler infrastructure.

Verifiability

We aim to make the checks as easy as possible, as it all goes on-chain (note: online, during the execution of each transaction, so any delay leads to a slowdown of the entire network), but initially the language design is ready to use off-chain static verification tools. Although this is more preferable, the development of verification tools (as a separate toolkit) has been postponed for the future, and only dynamic verification in run-time (on-chain) is currently supported.

Modularity

Move modules provide data abstraction and localize critical operations on resources. The encapsulation provided by the module, combined with the protection provided by the Move type system, ensures that properties set on the module's types cannot be violated by code outside the module. This is a fairly well thought-out abstraction design, meaning that the data inside the contract can only change within the framework of the contract, but not outside.

Dive into Move, Facebook's Libra Blockchain Programming Language

Move overview

The transaction script example demonstrates that malicious or careless actions by a programmer outside a module cannot compromise the security of a module's resources. Next, we'll look at examples of how modules, resources, and procedures are used to program the Libra blockchain.

Peer-to-Peer payments

Dive into Move, Facebook's Libra Blockchain Programming Language

The number of coins specified in amount will be transferred from the sender's balance to the recipient.
There are several new points here (highlighted in red inscriptions):

  • 0x0: address of the account where the module is stored
  • Currency: module name
  • Coin: resource type
  • The coin value returned by the procedure is a resource value of type 0x0.Currency.Coin
  • move (): value cannot be used again
  • copy (): value can be used later

Parse the code: in the first step, the sender calls a procedure named withdraw_from_sender from a module stored in 0x0.Currency. In the second step, the sender transfers funds to the recipient by moving the value of the coin resource into the module's deposit procedure 0x0.Currency.

Here are three examples of errors in code that will be rejected by checks:
Duplicate funds by changing the call move (coin) on copy (coin). Resources can only be moved. Attempting to duplicate the amount of a resource (for example, by calling copy (coin) in the example above) will result in an error while checking the bytecode.

Reuse of funds by specifying move (coin) twice . Adding a line 0x0.Currency.deposit(copy(some_other_payee), move(coin)) example above will allow the sender to "spend" the coins twice - the first time with the payee, and the second time with some_other_payee. This is an undesirable behavior that is not possible with a physical asset. Fortunately, Move will reject this program.

Loss of funds due to denial move (coin). If you do not move the resource (for example, by removing the line containing move (coin)), a bytecode verification error will be raised. This protects Move programmers from accidental or malicious loss of funds.

Currency module

Dive into Move, Facebook's Libra Blockchain Programming Language

Each account can contain 0 or more modules (depicted as boxes) and one or more resource values ​​(depicted as cylinders). For example, an account at 0x0 contains module 0x0.Currency and a resource value of type 0x0.Currency.Coin. Account at address 0x1 has two resources and one module; Account at address 0x2 has two modules and one resource value.

Some moments:

  • The transaction script is atomic - either completely executed, or not at all.
  • A module is a long-lived piece of code that is globally available.
  • The global state is structured as a hash table, where the account address is the key
  • Accounts can contain no more than one resource value of a given type and no more than one module with a given name (an account at 0x0 cannot contain an additional resource 0x0.Currency.Coin or another module named Currency)
  • The address of the declared module is part of the type (0x0.Currency.Coin ΠΈ 0x1.Currency.Coin are separate types that cannot be used interchangeably)
  • Programmers can store multiple instances of a given resource type in an account by defining their custom resource - (resource TwoCoins {c1: 0x0.Currency.Coin, c2: 0x0.Currency.Coin})
  • You can refer to a resource by its name without conflict, for example you can refer to two resources using TwoCoins.c1 ΠΈ TwoCoins.c2.

Coin resource declaration

Dive into Move, Facebook's Libra Blockchain Programming Language
Named module Currency and a resource type named Coin

Some moments:

  • Coin is a structure with one field of type u64 (64-bit unsigned integer)
  • Only module procedures Currency can create or destroy values ​​of type Coin.
  • Other modules and scripts can only write or refer to the value field through public procedures provided by the module.

Implementation of the deposit

Dive into Move, Facebook's Libra Blockchain Programming Language

This procedure accepts a resource Coin as input and concatenates it with a resource Coinstored on the beneficiary's account:

  1. Destroying the input resource Coin and writing its value.
  2. Obtaining a link to a unique Coin resource stored on the recipient's account.
  3. Changing the value of the number of Coins by the value passed in the parameter when calling the procedure.

Some moments:

  • Unpack, BorrowGlobal - built-in procedures
  • Unpack this is the only way to delete a resource of type T. The procedure takes a resource as input, destroys it, and returns the value associated with the fields of the resource.
  • BorrowGlobal takes an address as input and returns a reference to the unique instance of T published (owned) by that address
  • &mut Coin this is a link to a resource Coin

Implementing withdraw_from_sender

Dive into Move, Facebook's Libra Blockchain Programming Language

This procedure:

  1. Gets a link to a unique resource Coin, linked to the sender's account
  2. Decreases the value of a resource Coin by reference for the specified amount
  3. Creates and returns a new resource Coin with updated balance.

Some moments:

  • Deposit can be called by anyone, but withdraw_from_sender has access only to the coins of the calling account
  • GetTxnSenderAddress similar to msg.sender in Solidity
  • RejectUnless similar to require in Solidity. If this check fails, the execution of the transaction stops and all changes are rolled back.
  • pack it is also a built-in procedure that creates a new resource of type T.
  • As well as Unpack, pack can only be called inside the module where the resource is declared T

Conclusion

We analyzed the main characteristics of the Move language, compared it with Ethereum, and also got acquainted with the basic syntax of scripts. Finally, I highly recommend browsing original white paper. It includes many details about programming language design principles, as well as many useful links.

Source: habr.com

Add a comment