From 49637a2472c1991de55495eb40206ae9d8fce3de Mon Sep 17 00:00:00 2001
From: Novus Nota <68142933+novusnota@users.noreply.github.com>
Date: Fri, 14 Jul 2023 19:20:02 +0200
Subject: [PATCH 1/2] Update TVM Overview to point to the new (empty) TVM
Initialization article
And a small polish of TVM Overview contents
---
.../tvm-instructions/tvm-initialization.md | 1 +
docs/learn/tvm-instructions/tvm-overview.md | 35 ++++++-------------
sidebars.js | 1 +
3 files changed, 13 insertions(+), 24 deletions(-)
create mode 100644 docs/learn/tvm-instructions/tvm-initialization.md
diff --git a/docs/learn/tvm-instructions/tvm-initialization.md b/docs/learn/tvm-instructions/tvm-initialization.md
new file mode 100644
index 0000000000..8b13789179
--- /dev/null
+++ b/docs/learn/tvm-instructions/tvm-initialization.md
@@ -0,0 +1 @@
+
diff --git a/docs/learn/tvm-instructions/tvm-overview.md b/docs/learn/tvm-instructions/tvm-overview.md
index db8d699f8e..44b5a0d692 100644
--- a/docs/learn/tvm-instructions/tvm-overview.md
+++ b/docs/learn/tvm-instructions/tvm-overview.md
@@ -1,10 +1,8 @@
# TVM Overview
-
-
All TON Smart Contracts are executed on their own TON Virtual Machine (TVM). TVM is built on the _stack principle_, which makes it efficient and easy to implement.
-This document provides a bird's-eye overview of how TVM executes transactions.
+This document provides a bird's-eye view of how TVM executes transactions.
:::tip
@@ -14,29 +12,29 @@ This document provides a bird's-eye overview of how TVM executes transactions.
:::
## Transactions and phases
-When some event happens on the account in one of the TON chains, it causes a **transaction**. The most common event is the "arrival of some message", but generally speaking there could be `tick-tock`, `merge`, `split` and other events.
+When some event happens on the account in one of the TON chains, it causes a **transaction**. The most common event is the "arrival of some message", but generally speaking there could be `tick-tock`, `merge`, `split` and other events.
-Each transaction consists of up to 5 phases.
+Each transaction consists of up to 5 phases:
1. **Storage phase** - in this phase, storage fees accrued by the contract due to the occupation of some space in the chain state are calculated. Read more in [Storage Fees](/develop/smart-contracts/fees#storage-fee).
2. **Credit phase** - in this phase, the balance of the contract with respect to a (possible) incoming message value and collected storage fee are calculated
3. **Compute phase** - in this phase, TVM is executed (see below), the result of the TVM execution is an aggregation of `exit_code`, `actions` (serialized list of actions), `gas_details`, `new_storage` and some others.
-4. **Action phase** - if the compute phase was successful, in this phase `actions` from the compute phase are processed. In particular, actions may include the sending of messages, updating the smart contract code, updating the libraries etc. Note that some actions may fail during processing (for instance we try to send message with more TON than the contract has), in that case the whole transaction may revert or this action may be skipped (it depends on the mode of the actions, in other words, the contract may send a `send-or-revert` or `try-send-if-no-ignore` type of message).
+4. **Action phase** - if the compute phase was successful, in this phase, `actions` from the compute phase are processed. In particular, actions may include sending messages, updating the smart contract code, updating the libraries etc. Note that some actions may fail during processing (for instance, if we try to send message with more TON than the contract has), in that case the whole transaction may revert or this action may be skipped (it depends on the mode of the actions, in other words, the contract may send a `send-or-revert` or `try-send-if-no-ignore` type of message).
5. **Bounce phase** - if the compute phase failed (it returned `exit_code >= 2`), in this phase, _bounce message_ is formed for transactions initiated by an incoming message.
## Compute phase
In this phase, the TVM execution occurs.
### TVM state
-At any one moment, the TVM state is fully determined by 6 properties:
+At any given moment, the TVM state is fully determined by 6 properties:
* Stack (see below)
* Control registers - (see below) to put it simply, this means up to 16 variables which may be directly set and read during execution
-* Current continuation - object which describes a sequence of instructions which is currently executed
+* Current continuation - object which describes a currently executed sequence of instructions
* Current codepage - to put it simply, this means the version of TVM which is currently running
* Gas limits - a set of 4 integer values; the current gas limit gl, the maximal gas limit gm, the remaining gas gr and the gas credit gc
* Library context - the hashmap of libraries which can be called by TVM
### TVM is a stack machine
-TVM is a last-input-first-output stack machine. There are 7 types of variables which may be stored in stack:
+TVM is a last-input-first-output stack machine. In total, there are 7 types of variables which may be stored in stack — three non-cell types:
* Integer - signed 257-bit integers
* Tuple - ordered collection of up to 255 elements having arbitrary value types, possibly distinct.
* Null
@@ -57,21 +55,10 @@ And four distinct flavours of cells:
* `c7` — Contains the root of temporary data. It is a Tuple.
### Initialization of TVM
-So when a transaction execution gets to the Computation phase, TVM initialises and then executes commands (opcodes) from _Current continuation_ until there are no more commands to execute (and no continuation for return jumps).
-
-A detailed description of initialization can be found in [TON Blockchain 4.4](https://ton.org/tblkch.pdf).
-For ordinary transactions caused by message the initial state is as follows:
-* stack: 5 elements are put to the stack
- * The balance of the smart contract (after crediting the value of the inbound message) is passed as an Integer amount of nanotons.
- * The balance of inbound message `m` is passed as an Integer amount of nanotons.
- * The inbound message is passed as a cell, which contains a serialized value of type Message X, where X is the type of the message body.
- * The body of the inbound message, equal to the value of field body of `m`, is passed as a cell slice
- * The function selector `s`, an Integer: `0` for tx caused by internal messages, `-1` for external, etc. Generally speaking it is the integer that identifies which event caused the transaction
- * Current continuation: continuation converted from the `code` section of the smart contract
- * Registers initialize as follows: **c0** is initialized by extraordinary continuation `ec_quit` with parameter 0. **c1** is initialized by extraordinary continuation `ec_quit` with parameter 1. **c2** is initialized by extraordinary continuation `ec_quit_exc`. **c3** is initialized by the cell with the smart-contract code. **c4** contains the cell from the `data` section of the smart contract. **c5** contains an empty list (it is serialized as a cell which contain last action in list plus reference to prev one) of output actions. **c7** is initialized as tuple with some basic blockchain context data such as time, global config, block_data, etc. See [TON Blockchain 4.4.10](https://ton.org/tblkch.pdf)
- * Current codepage is set to default value (cp=0)
- * Gas limits are initialized in accordance to Credit phase results
- * Library context is initialized as result of merging this smart contract library collection, masterchain global library collection and incoming (if any) message library collection
+
+TVM initializes when transaction execution gets to the Computation phase, and then executes commands (opcodes) from _Current continuation_ until there are no more commands to execute (and no continuation for return jumps).
+
+Detailed description of the initialization process can be found here: [TVM Initialization](/learn/tvm-instructions/tvm-initialization.md)
## TVM instructions
diff --git a/sidebars.js b/sidebars.js
index 3e4e8d36cb..703dbced2b 100644
--- a/sidebars.js
+++ b/sidebars.js
@@ -430,6 +430,7 @@ const sidebars = {
label: 'TON Virtual Machine (TVM)',
items: [
'learn/tvm-instructions/tvm-overview',
+ 'learn/tvm-instructions/tvm-initialization',
'learn/tvm-instructions/tvm-exit-codes',
'learn/tvm-instructions/instructions',
'learn/tvm-instructions/tvm-upgrade-2023-07',
From 385dcc81ac105796c150adb6f2847c330e28dbb6 Mon Sep 17 00:00:00 2001
From: Novus Nota <68142933+novusnota@users.noreply.github.com>
Date: Sat, 15 Jul 2023 00:25:44 +0200
Subject: [PATCH 2/2] Added TVM Initialization article
---
.../tvm-instructions/tvm-initialization.md | 187 ++++++++++++++++++
1 file changed, 187 insertions(+)
diff --git a/docs/learn/tvm-instructions/tvm-initialization.md b/docs/learn/tvm-instructions/tvm-initialization.md
index 8b13789179..2516ac4a27 100644
--- a/docs/learn/tvm-instructions/tvm-initialization.md
+++ b/docs/learn/tvm-instructions/tvm-initialization.md
@@ -1 +1,188 @@
+# TVM Initialization
+:::info
+To maximize your comprehension of this page, familiarizing yourself with the [TL-B language](/develop/data-formats/cell-boc) is highly recommended.
+:::
+
+TVM is invoked during the computing phase of ordinary and/or other transactions.
+
+## Initial state
+
+A new instance of TVM is initialized prior to the execution of a smart contract as follows:
+
+- The original **cc** (current continuation) is initialized using the cell slice created from the `code` section of the smart contract. In case of a frozen or uninitialized state of the account, the code must be supplied in the `init` field of the incoming message.
+
+- The **cp** (current TVM codepage) is set to the default value, which is 0. If the smart contract wants to use another TVM codepage _x_, then it must switch to it by using `SETCODEPAGE` _x_ as the first instruction of its code.
+
+- The **gas** values (_gas limits_) are initialized in accordance to Credit phase results.
+
+- The **libraries** (_library context_) computation is [described below](#library-context).
+
+- The **stack** initialization process depends on the event which caused the transaction, and its contents are [described below](#stack).
+
+- Control register **c0** (return continuation) is initialized by extraordinary continuation `ec_quit` with parameter 0. When executed, this continuation leads to a termination of TVM with exit code 0.
+
+- Control register **c1** (alternative return continuation) is initialized by extraordinary continuation `ec_quit` with parameter 1. When invoked, it leads to a termination of TVM with exit code 1. Notice, that both exit codes 0 and 1 are considered a successful termination of TVM.
+
+- Control register **c2** (exception handler) is initialized by extraordinary continuation `ec_quit_exc`. When invoked, it takes the top integer from the stack (equal to the exception number) and terminates TVM with exit code equal to that integer. This way, by default all exceptions terminate the smart contract execution with exit code equal to the exception number.
+
+- Control register **c3** (code dictionary) is initialized by the cell with the smart contract code like **cc** (current continuation) described above.
+
+- Control register **c4** (root of persistent data) is initialized by the persistent data of the smart contract, stored in its `data` section. In case of a frozen or uninitialized state of the account, the data must be supplied in the `init` field of the incoming message. Notice, that the persistent data of the smart contract does not need to be loaded in its entirery for this to occur. The root is loaded instead, and TVM may load other cells by their references from the root only when they are accessed, thus providing a form of virtual memory.
+
+- Control register **c5** (root of actions) is initialized by an empty cell. The "output action" primitives of TVM, such as `SENDMSG`, accumulate _output actions_ (e.g., outbound messages) in this register, to be performed upon successful termination of the smart contract. The TL-B scheme for its serialization is [described below](#control-register-c5)
+
+- Control register **c7** (root of temporary data) is initialized as a tuple and its structure is [described below](#control-register-c7)
+
+## Library context
+
+The _library context_ (library environment) of a smart contract is a hashmap mapping 256-bit cell (representation) hashes into the corresponding cells themselves. When an external cell reference is accessed during the execution of the smart contract, the cell referred to is looked up in the library environment and the external cell reference is transparently replaced by the cell found.
+
+The library environment for an invocation of a smart contract is computed as follows:
+1. The global library environment for the current workchain is taken from the current state of the masterchain.
+2. Then, it is augmented by the local library environment of the smart contract, stored in the `library` field of the smart contract's state. Only 256-bit keys equal to the hashes of the corresponding value cells are taken into account. If a key is present in both the global and local library environments, the local environment takes precedence in the merge.
+3. Finally, it is augmented by the `library` field of the `init` field of the incoming message (if any). Notice, that if the account is frozen or uninitialized, the `library` field of the message would be used over the local library environment from the previous step. The message library has lower precedence than both the local and the global library environments.
+
+Most common way of creating shared libraries for TVM is to publish a reference to the root cell of the library in the masterchain.
+
+## Stack
+
+Initialization of the TVM stack comes after the formation of the initial state of the TVM, and it depends on the event which caused the transaction:
+- internal message
+- external message
+- tick-tock
+- split prepare
+- merge install
+
+The last item pushed to the stack is always the _function selector_, which is an _Integer_ that identifies the event that caused the transaction.
+
+### Internal message
+
+In case of internal message, the stack is initialized by pushing the arguments to the `main()` function of the smart contract as follows:
+- The balance _b_ of the smart contract (after crediting the value of the inbound message) is passed as an _Integer_ amount of nanotons.
+- The balance _b_m of inbound message _m_ is passed as an _Integer_ amount of nanotons.
+- The inbound message _m_ is passed as a cell, which contains a serialized value of type _Message X_, where _X_ is the type of the message body.
+- The body _m_b of the inbound message, equal to the value of field body _m_ and passed as a cell slice.
+- The function selector _s_, normally equal to 0.
+
+After that, the code of the smart contract, equal to its initial value of **c3**, is executed. It selects the correct function according to _s_, which is expected to process the remaining arguments to the function and terminate afterwards.
+
+### External message
+
+An inbound external message is processed similarly to the [internal message described above](#internal-message), with the following modifications:
+- The function selector _s_ is set to -1.
+- The balance _b_m of inbound message is always 0.
+- The initial current gas limit _g_l is always 0. However, the initial gas credit _g_c > 0.
+
+The smart contract must terminate with _g_c = 0 or _g_r ≥ _g_c; otherwise, the transaction and the block containing it are invalid. Validators or collators suggesting a block candidate must never include transactions processing inbound external messages that are invalid.
+
+### Tick and tock
+
+In case of tick and tock transactions, the stack is initialized by pushing the arguments to the `main()` function of the smart contract as follows:
+- The balance _b_ of the current account is passed as an _Integer_ amount of nanotons.
+- The 256-bit address of the current account inside the masterchain as an unsigned _Integer_.
+- An integer equal to 0 for tick transactions and to -1 for tock transactions.
+- The function selector _s_, equal to -2.
+
+### Split prepare
+
+In case of split prepare transaction, the stack is initialized by pushing the arguments to the `main()` function of the smart contract as follows:
+- The balance _b_ of the current account is passed as an _Integer_ amount of nanotons.
+- A _Slice_ containing _SplitMergeInfo_.
+- The 256-bit address of the current account.
+- The 256-bit address of the sibling account.
+- An integer 0 ≤ _d_ ≤ 63, equal to the position of the only bit in which addresses of the current and sibling account differ.
+- The function selector _s_, equal to -3.
+
+### Merge install
+
+In case of merge install transaction, the stack is initialized by pushing the arguments to the `main()` function of the smart contract as follows:
+- The balance _b_ of the current account (already combined with the nanoton balance of the sibling account) is passed as an _Integer_ amount of nanotons.
+- The balance _b'_ of the sibling account, taken from the inbound message _m_ is passed as an _Integer_ amount of nanotons.
+- The message _m_ from the sibling account, automatically generated by a merge prepare transaction. Its `init` field contains the final state of the sibling account. The message is passed as a cell, which contains a serialized value of type _Message X_, where _X_ is the type of the message body.
+- The state of the sibling account, represented by a _StateInit_.
+- A _Slice_ containing _SplitMergeInfo_.
+- The 256-bit address of the current account.
+- The 256-bit address of the sibling account.
+- An integer 0 ≤ _d_ ≤ 63, equal to the position of the only bit in which addresses of the current and sibling account differ.
+- The function selector _s_, equal to -4.
+
+## Control register c5
+
+The _output actions_ of a smart contract are accumulated in cell stored in control register **c5**: the cell itself contains the last action in the list and a reference to the previous one, thus forming a linked list.
+
+The list can also be serialized as a value of type _OutList n_, where _n_ is the length of the list:
+
+```tlb
+out_list_empty$_ = OutList 0;
+
+out_list$_ {n:#}
+ prev:^(OutList n)
+ action:OutAction
+ = OutList (n + 1);
+
+out_list_node$_
+ prev:^Cell
+ action:OutAction = OutListNode;
+```
+
+The list of possible actions thereby consists of:
+- `action_send_msg` — for sending an outbound message
+- `action_set_code` — for setting an opcode
+- `action_reserve_currency` — for storing a currency collection
+- `action_change_library` — for changing the library
+
+As described in the corresponding TL-B scheme:
+
+```tlb
+action_send_msg#0ec3c86d
+ mode:(## 8)
+ out_msg:^(MessageRelaxed Any) = OutAction;
+
+action_set_code#ad4de08e
+ new_code:^Cell = OutAction;
+
+action_reserve_currency#36e6b809
+ mode:(## 8)
+ currency:CurrencyCollection = OutAction;
+
+libref_hash$0
+ lib_hash:bits256 = LibRef;
+libref_ref$1
+ library:^Cell = LibRef;
+action_change_library#26fa1dd4
+ mode:(## 7) { mode <= 2 }
+ libref:LibRef = OutAction;
+```
+
+## Control register c7
+
+Control register **c7** contains the root of temporary data as a Tuple, formed by a _SmartContractInfo_ type, containing some basic blockchain context data, such as time, global config, etc. It is described by the following TL-B scheme:
+
+```tlb
+smc_info#076ef1ea
+ actions:uint16 msgs_sent:uint16
+ unixtime:uint32 block_lt:uint64 trans_lt:uint64
+ rand_seed:bits256 balance_remaining:CurrencyCollection
+ myself:MsgAddressInt global_config:(Maybe Cell) = SmartContractInfo;
+```
+
+First component of this tuple is an _Integer_ value, which is always equal to 0x076ef1ea, after which 9 named fields follow:
+
+| Field | Type | Description |
+| ----- | ---- | ----------- |
+| `actions` | uint16 | Originally initialized by 0, but incremented by one whenever an output action is installed by a non-RAW output action primitive |
+| `msgs_sent` | uint16 | Number of messages sent |
+| `unixtime` | uint32 | Unix timestamp in seconds |
+| `block_lt` | uint64 | Represents _logical time_ of the previous block of this account. [More about logical time](https://docs.ton.org/develop/smart-contracts/guidelines/message-delivery-guarantees#what-is-a-logical-time) |
+| `trans_lt` | uint64 | Represents _logical time_ of the previous transaction of this account |
+| `rand_seed` | bits256 | Initialized deterministically starting from `rand_seed` of the block, the account address, the hash of the incoming message being processed (if any), and the transaction logical time `trans_lt` |
+| `balance_remaining` | [CurrencyCollection](/develop/data-formats/msg-tlb#currencycollection) | Remaining balance of the smart contract |
+| `myself` | [MsgAddressInt](/develop/data-formats/msg-tlb#msgaddressint-tl-b) | Address of this smart contract |
+| `global_config` | (Maybe Cell) | Contains information about the global config |
+
+Notice, that in the upcoming upgrade to the TVM, the **c7** tuple was extended from 10 to 14 elements. Read more about it [here](/learn/tvm-instructions/tvm-upgrade-2023-07).
+
+## See also
+
+- Original description of [TVM Initialization](https://docs.ton.org/tblkch.pdf#page=89&zoom=100) from the whitepaper