From 54937b2db0862bb5b67810a572a35a535d4cc54e Mon Sep 17 00:00:00 2001 From: D Ozgur Cakirkaya Date: Fri, 4 Apr 2025 14:40:48 +0100 Subject: [PATCH 01/14] minter-flow.md update --- cspell.json | 3 +- docs/v3/documentation/infra/minter-flow.md | 59 ++++++++++++---------- 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/cspell.json b/cspell.json index f07d84fa72f..541ecbe7086 100644 --- a/cspell.json +++ b/cspell.json @@ -314,7 +314,8 @@ "zerostate", "ensurepip", "Buildx", - "underperforming" + "underperforming", + "blackhole" ], "ignoreRegExpList": [ "\\(#.*\\)", diff --git a/docs/v3/documentation/infra/minter-flow.md b/docs/v3/documentation/infra/minter-flow.md index 0d7858fa3d5..d9e3491fdf3 100644 --- a/docs/v3/documentation/infra/minter-flow.md +++ b/docs/v3/documentation/infra/minter-flow.md @@ -1,64 +1,71 @@ -# Extra Currency Minting +# Extra currency minting ## Extracurrency -According to [Ton Blockchain Whitepaper 3.1.6](https://ton-blockchain.github.io/docs/tblkch.pdf#page=55), TON Blockchain allows its users to define arbitrary cryptocurrencies or tokens apart from the Toncoin, provided some conditions are met. Such additional cryptocurrencies are identified by 32-bit _currency\_ids_. The list of defined additional cryptocurrencies is a part of the blockchain configuration, -stored in the masterchain. Each internal message as well as account balance contains a special field for `ExtraCurrencyCollection` (set of extracurrencies attached to a message or kept on balance): + +According to [TON Blockchain Whitepaper 3.1.6](https://ton-blockchain.github.io/docs/tblkch.pdf#page=55), the TON Blockchain allows users to create arbitrary cryptocurrencies or tokens, in addition to the Toncoin, provided certain conditions are met. These additional cryptocurrencies are identified by 32-bit **currency\_ids**. The list of these defined cryptocurrencies is a part of the blockchain configuration stored in the MasterChain. Each internal message and account balance includes a special field for `ExtraCurrencyCollection`, which is a set of extracurrencies attached to a message or maintained in a balance: + ```tlb extra_currencies$_ dict:(HashmapE 32 (VarUInteger 32)) = ExtraCurrencyCollection; currencies$_ grams:Grams other:ExtraCurrencyCollection = CurrencyCollection; ``` ## Extracurrency config -A dictionary, or to be precise `ExtraCurrencyCollection`, of all currencies that should be minted is stored in `ConfigParam7`: + +A dictionary, specifically `ExtraCurrencyCollection`, containing all currencies to be minted is stored in `ConfigParam7`: + ```tlb _ to_mint:ExtraCurrencyCollection = ConfigParam 7; ``` -`ConfigParam 6` contains data related to minting: +`ConfigParam 6` contains data related to the minting: ```tlb _ mint_new_price:Grams mint_add_price:Grams = ConfigParam 6; ``` -`ConfigParam2` contains address of _Minter_. - - +`ConfigParam2` contains the address of **Minter**. ## Low-level minting flow -In each block, the collator compares the old global balance (global balance of all currencies at the end of prev block) with `ConfigParam7`. If any amount for any currency in `ConfigParam7` is less than it is in the global balance - the config is invalid. If any amount of any currency in `ConfigParam7` is higher than it is in the global balance a minting message will be created. -This minting message has source `-1:0000000000000000000000000000000000000000000000000000000000000000` and _Minter_ from `ConfigParam2` as destination and contains excesses of extracurrencies in `ConfigParam7` over old global balance. +In each block, the collator compares the old global balance (the global balance of all currencies at the end of the previous block) with `ConfigParam7`. If any amount for any currency in `ConfigParam7` is less than it is in the global balance, the config is invalid. If any amount of any currency in `ConfigParam7` is higher than it is in the global balance, a minting message will be created. + +This minting message has source `-1:0000000000000000000000000000000000000000000000000000000000000000` and **Minter** from `ConfigParam2` as destination and contains excesses of extracurrencies in `ConfigParam7` over the old global balance. -The issue here is that the minting message contains extra currencies only and no TON coins. That means that even if _Minter_ is set as a fundamental smart contract (presented in `ConfigParam31`), a minting message will cause the aborted transaction: `compute_ph:(tr_phase_compute_skipped reason:cskip_no_gas)`. +The problem here is that the minting message includes only additional currencies and no Toncoins. As a result, even if the **Minter** is designated as a fundamental smart contract (as indicated in `ConfigParam31`), a minting message will lead to an aborted transaction with the error: `compute_ph:(tr_phase_compute_skipped reason:cskip_no_gas)`. ## High-level minting flow -One of possible high-level minting flows implemented [here](https://github.com/ton-blockchain/governance-contract/tree/50ed2ecacc9e3cff4c77cbcc69aa07b39f5c46a2) (check `*.tolk` files) is as following: -1. There is `ExtraCurrencyAuthorizationConfig`: it is config that contains information which contracts (addresses) has authorization to request minter to mint new extracurrencies. This config has the following scheme: +One possible high-level minting flow, which is implemented [here](https://github.com/ton-blockchain/governance-contract/tree/50ed2ecacc9e3cff4c77cbcc69aa07b39f5c46a2) (check `*.tolk` files) is as follows: + +1. There is `ExtraCurrencyAuthorizationConfig`: the config contains information on which contracts (addresses) have authorization to request minter to mint new extracurrencies. This config has the following scheme: + ```tlb _ (Hashmap 32 std_addr) = ExtraCurrencyAuthorizationConfig; ``` -where key - `currency_id` and `std_addr` is _admin_ of this currency (can be in any workchain). -2. Minter accepts mint requests from _admins_, forwards request for mint to Config, Config updates `ConfigParam 7` and responses to Minter. Since extracurrencies would be minted to Minter only on next masterchain block, withdrawing extracurrencies to _admin_ should be delayed. It is done via _Echo_ smart-contract not in masterchain. When response from _Echo_ came to Minter it sends extracurrencies to _admin_. So the scheme is as follows `Admin -> Minter -> Config -> Minter -> Echo (in other workchain to wait until the next masterchain block) -> Minter -> Admin`. -Example of such flow: [minting 2'000'000'000 units of `currency_id=100`](https://testnet.tonviewer.com/transaction/20fe328c04b4896acecb6e96aaebfe6fef90dcc1441e27049302f29770904ef0) +where key - `currency_id` and `std_addr` is _admin_ of this currency (can be in any WorkChain). + +2. Minter accepts mint requests from **admins**, forwards requests for mint to **Config**, **Config** updates `ConfigParam 7`, and responds to **Minter**. Since extracurrencies would be minted to **Minter** only on the next MasterChain block, withdrawing extra currencies to **admin** should be delayed. It is done via **Echo** smart-contract, not in MasterChain. When a response from **Echo** comes to **Minter**, it sends extracurrencies to **admin**. So the scheme is as follows: + + `Admin -> Minter -> Config -> Minter -> Echo (in other workchain to wait until the next masterchain block) -> Minter -> Admin` + +An example of this flow is as follows: [minting 2'000'000'000 units of `currency_id=100`](https://testnet.tonviewer.com/transaction/20fe328c04b4896acecb6e96aaebfe6fef90dcc1441e27049302f29770904ef0) :::danger -Each mint of new extracurrency or increasing supply of existing one requires change of ConfigParam 7, thus changing config and creation keyblock. Too frequent keyblocks slows down shards (each keyblock leads to rotation of validator groups) and lite-client sync. Thus contracts like swap.tolk should not be used in production. Instead schemes with reserves, that minimize minting events, need to be used. +Each minting of new extracurrency or an increase in the supply of existing currency necessitates a change to `ConfigParam7`, which in turn alters the configuration and creation of keyblocks. Frequent keyblock generation can slow down shard performance since each key block causes a rotation of validator groups and affects the synchronization of liteclients. Therefore, contracts like `swap.tolk` should not be utilized in production environments. Instead, it is advisable to use schemes that involve reserves to minimize minting events. ::: - -:::Info -Sending of extracurrency to blackhole has the following effect: extracurrency amount is burnt, but since ConfigParam 7 is not changed, on next block Minter will receive burnt amount on it's balance. +:::info +Sending of extracurrency to blackhole has the following effect: extracurrency amount is burnt, but since `ConfigParam7` is not changed, on the next block, **Minter** will receive the burnt amount on its balance. ::: -## Bird-eye minting flow -How to mint your own extracurrency: -1. Ensure your network has Minter Contract and ConfigParam 2, ConfigParam 6 set. -2. Create Currency Admin contract that controls how extracurrency is minted. -3. Create proposal to validators to add your Currency Admin contract address to ExtraCurrencyAuthorizationConfig for some `currency_id`, and get it accepted. -4. Send `mint` request from Currency Admin contract to Minter. Wait till Minter send back extracurrency. +## How to mint your own extracurrency + +1. Ensure that your network has the **Minter Contract** and that `ConfigParam2` and `ConfigParam6` are set correctly. +2. Create a **Currency Admin Contract** that will control how the extra currency is minted. +3. Submit a proposal to the validators to add your **Currency Admin** contract address to the `ExtraCurrencyAuthorizationConfig` for a specific `currency_id` and obtain their approval. +4. Send a `mint` request from the **Currency Admin Contract** to the **Minter**. Wait for the **Minter** to return the extra currency. \ No newline at end of file From b9b5561f64796fc51f40ba49e6ada51b72f01a61 Mon Sep 17 00:00:00 2001 From: D Ozgur Cakirkaya Date: Fri, 4 Apr 2025 15:10:05 +0100 Subject: [PATCH 02/14] Cross-chain overview.md update --- .../infra/crosschain/overview.md | 35 +++++++++---------- 1 file changed, 16 insertions(+), 19 deletions(-) diff --git a/docs/v3/documentation/infra/crosschain/overview.md b/docs/v3/documentation/infra/crosschain/overview.md index 76075bc9389..7b87b50ea54 100644 --- a/docs/v3/documentation/infra/crosschain/overview.md +++ b/docs/v3/documentation/infra/crosschain/overview.md @@ -1,43 +1,40 @@ # Cross-chain bridges -Decentralized cross-chain bridges operate on TON Blockchain, allowing you to transfer assets from TON Blockchain to other blockchains and vice versa. +Decentralized cross-chain bridges function on the TON Blockchain, allowing asset transfers between this blockchain and the others. -## Toncoin Bridge +## Toncoin bridge -The Toncoin bridge allows you to transfer Toncoin between TON Blockchain and the Ethereum blockchain, as well as between TON Blockchain and the BNB Smart Chain. +The Toncoin bridge enables transfers of Toncoin between the TON and Ethereum Blockchain and between the TON and the BSC (BNB Smart Chain). -The bridge is managed by [decentralized oracles](/v3/documentation/infra/crosschain/bridge-addresses). +This bridge is managed by [decentralized oracles](/v3/documentation/infra/crosschain/bridge-addresses). -### How to use it: +### How to use it -The bridge frontend is hosted on https://ton.org/bridge. +The bridge frontend is hosted [here](https://ton.org/bridge). :::info [Bridge frontend source code](https://github.com/ton-blockchain/bridge) ::: -### TON-Ethereum smart contracts source codes +### Smart Contract source codes + +#### TON-Ethereum * [FunC (TON side)](https://github.com/ton-blockchain/bridge-func) * [Solidity (Ethereum side)](https://github.com/ton-blockchain/bridge-solidity/tree/eth_mainnet) - -### TON-BNB Smart Chain smart contracts source codes +#### TON-BSC (BNB Smart Chain) * [FunC (TON side)](https://github.com/ton-blockchain/bridge-func/tree/bsc) * [Solidity (BSC side)](https://github.com/ton-blockchain/bridge-solidity/tree/bsc_mainnet) +### Blockchain configurations -### Blockchain Configs - -You can get the actual bridge smart contract addresses and oracle addresses by inspecting the corresponding config: - -TON-Ethereum: [#71](https://github.com/ton-blockchain/ton/blob/35d17249e6b54d67a5781ebf26e4ee98e56c1e50/crypto/block/block.tlb#L738). - -TON-BSC: [#72](https://github.com/ton-blockchain/ton/blob/35d17249e6b54d67a5781ebf26e4ee98e56c1e50/crypto/block/block.tlb#L739). - -TON-Polygon: [#73](https://github.com/ton-blockchain/ton/blob/35d17249e6b54d67a5781ebf26e4ee98e56c1e50/crypto/block/block.tlb#L740). +You can find the current bridge smart contract addresses and oracle addresses by checking the corresponding configuration: +* TON-Ethereum: [#71](https://github.com/ton-blockchain/ton/blob/35d17249e6b54d67a5781ebf26e4ee98e56c1e50/crypto/block/block.tlb#L738) +* TON-BSC: [#72](https://github.com/ton-blockchain/ton/blob/35d17249e6b54d67a5781ebf26e4ee98e56c1e50/crypto/block/block.tlb#L739) +* TON-Polygon: [#73](https://github.com/ton-blockchain/ton/blob/35d17249e6b54d67a5781ebf26e4ee98e56c1e50/crypto/block/block.tlb#L740) ### Documentation @@ -45,4 +42,4 @@ TON-Polygon: [#73](https://github.com/ton-blockchain/ton/blob/35d17249e6b54d67a5 ### Cross-chain roadmap -* https://t.me/tonblockchain/146 +* [@The Open Network](https://t.me/tonblockchain/146) From 5f9b66e78dce17bd742439312bdf164e80e61d91 Mon Sep 17 00:00:00 2001 From: D Ozgur Cakirkaya Date: Mon, 7 Apr 2025 12:04:46 +0100 Subject: [PATCH 03/14] bridge-addresses.md update --- .../infra/crosschain/bridge-addresses.md | 190 +++++++++--------- 1 file changed, 99 insertions(+), 91 deletions(-) diff --git a/docs/v3/documentation/infra/crosschain/bridge-addresses.md b/docs/v3/documentation/infra/crosschain/bridge-addresses.md index 61581a6ee9a..6dffcac821b 100644 --- a/docs/v3/documentation/infra/crosschain/bridge-addresses.md +++ b/docs/v3/documentation/infra/crosschain/bridge-addresses.md @@ -1,212 +1,220 @@ -# Bridges Addresses +# Bridges addresses :::caution -To accurately get the current addresses of bridge smart contracts, see them directly in the [blockchain config](/v3/documentation/infra/crosschain/overview#blockchain-configs). It's the most secure way. +For the most accurate current addresses of bridge smart contracts, please refer to the [blockchain config](/v3/documentation/infra/crosschain/overview#blockchain-configs). This is the most secure method. ::: ## Toncoin Mainnet -### Mainnet TON-Ethereum Toncoin Bridge +### Ethereum/Toncoin bridge -Wrapped TONCOIN Address - [0x582d872a1b094fc48f5de31d3b73f2d9be47def1](https://etherscan.io/token/0x582d872a1b094fc48f5de31d3b73f2d9be47def1) +* Wrapped Toncoin address: [0x582d872a1b094fc48f5de31d3b73f2d9be47def1](https://etherscan.io/token/0x582d872a1b094fc48f5de31d3b73f2d9be47def1) -Bridge Address - [Ef_dJMSh8riPi3BTUTtcxsWjG8RLKnLctNjAM4rw8NN-xWdr](https://tonscan.org/address/Ef_dJMSh8riPi3BTUTtcxsWjG8RLKnLctNjAM4rw8NN-xWdr) +* Bridge address: [Ef_dJMSh8riPi3BTUTtcxsWjG8RLKnLctNjAM4rw8NN-xWdr](https://tonscan.org/address/Ef_dJMSh8riPi3BTUTtcxsWjG8RLKnLctNjAM4rw8NN-xWdr) -Collector Address - [EQCuzvIOXLjH2tv35gY4tzhIvXCqZWDuK9kUhFGXKLImgxT5](https://tonscan.org/address/EQCuzvIOXLjH2tv35gY4tzhIvXCqZWDuK9kUhFGXKLImgxT5) +* Collector address: [EQCuzvIOXLjH2tv35gY4tzhIvXCqZWDuK9kUhFGXKLImgxT5](https://tonscan.org/address/EQCuzvIOXLjH2tv35gY4tzhIvXCqZWDuK9kUhFGXKLImgxT5) -Governance Address - [Ef87m7_QrVM4uXAPCDM4DuF9Rj5Rwa5nHubwiQG96JmyAjQY](https://tonscan.org/address/Ef87m7_QrVM4uXAPCDM4DuF9Rj5Rwa5nHubwiQG96JmyAjQY) +* Governance address: [Ef87m7_QrVM4uXAPCDM4DuF9Rj5Rwa5nHubwiQG96JmyAjQY](https://tonscan.org/address/Ef87m7_QrVM4uXAPCDM4DuF9Rj5Rwa5nHubwiQG96JmyAjQY) -### Mainnet TON-BSC Toncoin Bridge +### BSC/Toncoin bridge -Wrapped TONCOIN Address - [0x76A797A59Ba2C17726896976B7B3747BfD1d220f](https://bscscan.com/token/0x76A797A59Ba2C17726896976B7B3747BfD1d220f) +* Wrapped Toncoin address: [0x76A797A59Ba2C17726896976B7B3747BfD1d220f](https://bscscan.com/token/0x76A797A59Ba2C17726896976B7B3747BfD1d220f) -Bridge Address - [Ef9NXAIQs12t2qIZ-sRZ26D977H65Ol6DQeXc5_gUNaUys5r](https://tonscan.org/address/Ef9NXAIQs12t2qIZ-sRZ26D977H65Ol6DQeXc5_gUNaUys5r) +* Bridge address: [Ef9NXAIQs12t2qIZ-sRZ26D977H65Ol6DQeXc5_gUNaUys5r](https://tonscan.org/address/Ef9NXAIQs12t2qIZ-sRZ26D977H65Ol6DQeXc5_gUNaUys5r) -Collector Address - [EQAHI1vGuw7d4WG-CtfDrWqEPNtmUuKjKFEFeJmZaqqfWTvW](https://tonscan.org/address/EQAHI1vGuw7d4WG-CtfDrWqEPNtmUuKjKFEFeJmZaqqfWTvW) +* Collector address: [EQAHI1vGuw7d4WG-CtfDrWqEPNtmUuKjKFEFeJmZaqqfWTvW](https://tonscan.org/address/EQAHI1vGuw7d4WG-CtfDrWqEPNtmUuKjKFEFeJmZaqqfWTvW) -Governance Address - [Ef8OvX_5ynDgbp4iqJIvWudSEanWo0qAlOjhWHtga9u2YjVp](https://tonscan.org/address/Ef8OvX_5ynDgbp4iqJIvWudSEanWo0qAlOjhWHtga9u2YjVp) +* Governance Address - [Ef8OvX_5ynDgbp4iqJIvWudSEanWo0qAlOjhWHtga9u2YjVp](https://tonscan.org/address/Ef8OvX_5ynDgbp4iqJIvWudSEanWo0qAlOjhWHtga9u2YjVp) -### Mainnet Toncoin Oracles +### Mainnet Toncoin oracles -Oracle 0 - [Ef_P2CJw784O1qVd8Qbn8RCQc4EgxAs8Ra-M3bDhZn3OfzRb](https://tonscan.org/address/Ef_P2CJw784O1qVd8Qbn8RCQc4EgxAs8Ra-M3bDhZn3OfzRb) +* Oracle 0: [Ef_P2CJw784O1qVd8Qbn8RCQc4EgxAs8Ra-M3bDhZn3OfzRb](https://tonscan.org/address/Ef_P2CJw784O1qVd8Qbn8RCQc4EgxAs8Ra-M3bDhZn3OfzRb) -Oracle 1 - [Ef8DfObDUrNqz66pr_7xMbUYckUFbIIvRh1FSNeVSLWrvo1M](https://tonscan.org/address/Ef8DfObDUrNqz66pr_7xMbUYckUFbIIvRh1FSNeVSLWrvo1M) +* Oracle 1: [Ef8DfObDUrNqz66pr_7xMbUYckUFbIIvRh1FSNeVSLWrvo1M](https://tonscan.org/address/Ef8DfObDUrNqz66pr_7xMbUYckUFbIIvRh1FSNeVSLWrvo1M) -Oracle 2 - [Ef8JKqx4I-XECLuVhTqeY1WMgbgTp8Ld3mzN-JUogBF4ZEW-](https://tonscan.org/address/Ef8JKqx4I-XECLuVhTqeY1WMgbgTp8Ld3mzN-JUogBF4ZEW-) +* Oracle 2: [Ef8JKqx4I-XECLuVhTqeY1WMgbgTp8Ld3mzN-JUogBF4ZEW-](https://tonscan.org/address/Ef8JKqx4I-XECLuVhTqeY1WMgbgTp8Ld3mzN-JUogBF4ZEW-) -Oracle 3 - [Ef8voAFh-ByCeKD3SZhjMNzioqCmDOK6S6IaeefTwYmRhgsn](https://tonscan.org/address/Ef8voAFh-ByCeKD3SZhjMNzioqCmDOK6S6IaeefTwYmRhgsn) +* Oracle 3: [Ef8voAFh-ByCeKD3SZhjMNzioqCmDOK6S6IaeefTwYmRhgsn](https://tonscan.org/address/Ef8voAFh-ByCeKD3SZhjMNzioqCmDOK6S6IaeefTwYmRhgsn) -Oracle 4 - [Ef_uJVTTToU8b3o7-Jr5pcUqenxWzDNYpyklvhl73KSIA17M](https://tonscan.org/address/Ef_uJVTTToU8b3o7-Jr5pcUqenxWzDNYpyklvhl73KSIA17M) +* Oracle 4: [Ef_uJVTTToU8b3o7-Jr5pcUqenxWzDNYpyklvhl73KSIA17M](https://tonscan.org/address/Ef_uJVTTToU8b3o7-Jr5pcUqenxWzDNYpyklvhl73KSIA17M) -Oracle 5 - [Ef93olLWqh1OuBSTOnJKWZ4NwxNq_ELK55_h_laNPVwxcEro](https://tonscan.org/address/Ef93olLWqh1OuBSTOnJKWZ4NwxNq_ELK55_h_laNPVwxcEro) +* Oracle 5: [Ef93olLWqh1OuBSTOnJKWZ4NwxNq_ELK55_h_laNPVwxcEro](https://tonscan.org/address/Ef93olLWqh1OuBSTOnJKWZ4NwxNq_ELK55_h_laNPVwxcEro) -Oracle 6 - [Ef_iUPZdKLOCrqcNpDuFGNEmiuBwMB18TBXNjDimewpDExgn](https://tonscan.org/address/Ef_iUPZdKLOCrqcNpDuFGNEmiuBwMB18TBXNjDimewpDExgn) +* Oracle 6: [Ef_iUPZdKLOCrqcNpDuFGNEmiuBwMB18TBXNjDimewpDExgn](https://tonscan.org/address/Ef_iUPZdKLOCrqcNpDuFGNEmiuBwMB18TBXNjDimewpDExgn) -Oracle 7 - [Ef_tTGGToGmONePskH_Y6ZG-QLV9Kcg5DIXeKwBvCX4YifKa](https://tonscan.org/address/Ef_tTGGToGmONePskH_Y6ZG-QLV9Kcg5DIXeKwBvCX4YifKa) +* Oracle 7: [Ef_tTGGToGmONePskH_Y6ZG-QLV9Kcg5DIXeKwBvCX4YifKa](https://tonscan.org/address/Ef_tTGGToGmONePskH_Y6ZG-QLV9Kcg5DIXeKwBvCX4YifKa) -Oracle 8 - [Ef94L53akPw-4gOk2uQOenUyDYLOaif2g2uRoiu1nv0cWYMC](https://tonscan.org/address/Ef94L53akPw-4gOk2uQOenUyDYLOaif2g2uRoiu1nv0cWYMC) +* Oracle 8: [Ef94L53akPw-4gOk2uQOenUyDYLOaif2g2uRoiu1nv0cWYMC](https://tonscan.org/address/Ef94L53akPw-4gOk2uQOenUyDYLOaif2g2uRoiu1nv0cWYMC) -EVM Addresses: 0xC4c9bd836ab8b446519736166919e3d62491E041,0xCF4A7c26186aA41390E246FA04115A0495085Ab9,0x17DcaB1B1481610F6C7a7A98cf0370dC0EC704a6,0x32162CAaEd276E77EF63194820586C942009a962,0x039f4e886432bd4f3cb5062f9861EFef3F6aDA28,0xFf441F9889Aa475d9D3b1C638C59B84c5179846D,0x0933738699dc733C46A0D4CBEbDA2f842e1Ac7d9,0x7F2bbaaC14F0f1834E6D0219F8855A5F619Fe2C4,0xfc5c6A2d01A984ba9eab7CF87A6D169aA9720c0C. +* EVM Addresses: + * 0xC4c9bd836ab8b446519736166919e3d62491E041 + * 0xCF4A7c26186aA41390E246FA04115A0495085Ab9 + * 0x17DcaB1B1481610F6C7a7A98cf0370dC0EC704a6 + * 0x32162CAaEd276E77EF63194820586C942009a962 + * 0x039f4e886432bd4f3cb5062f9861EFef3F6aDA28 + * 0xFf441F9889Aa475d9D3b1C638C59B84c5179846D + * 0x0933738699dc733C46A0D4CBEbDA2f842e1Ac7d9 + * 0x7F2bbaaC14F0f1834E6D0219F8855A5F619Fe2C4 + * 0xfc5c6A2d01A984ba9eab7CF87A6D169aA9720c0C ## Toncoin Testnet + -### Testnet TON-Ethereum Toncoin Bridge +### Ethereum/Toncoin bridge -Wrapped TONCOIN Address - [0xDB15ffaf2c88F2d89Db9365a5160D5b8c9448Ea6](https://goerli.etherscan.io/token/0xDB15ffaf2c88F2d89Db9365a5160D5b8c9448Ea6) +* Wrapped Toncoin Address - [0xDB15ffaf2c88F2d89Db9365a5160D5b8c9448Ea6](https://goerli.etherscan.io/token/0xDB15ffaf2c88F2d89Db9365a5160D5b8c9448Ea6) -Bridge Address - [Ef-56ZiqKUbtp_Ax2Qg4Vwh7yXXJCO8cNJAb229J6XXe4-aC](https://testnet.tonscan.org/address/Ef-56ZiqKUbtp_Ax2Qg4Vwh7yXXJCO8cNJAb229J6XXe4-aC) +* Bridge Address - [Ef-56ZiqKUbtp_Ax2Qg4Vwh7yXXJCO8cNJAb229J6XXe4-aC](https://testnet.tonscan.org/address/Ef-56ZiqKUbtp_Ax2Qg4Vwh7yXXJCO8cNJAb229J6XXe4-aC) -Collector Address - [EQCA1W_I267-luVo9CzV7iCcrA1OO5vVeXD0QHACvBn1jIVU](https://testnet.tonscan.org/address/EQCA1W_I267-luVo9CzV7iCcrA1OO5vVeXD0QHACvBn1jIVU) +* Collector Address - [EQCA1W_I267-luVo9CzV7iCcrA1OO5vVeXD0QHACvBn1jIVU](https://testnet.tonscan.org/address/EQCA1W_I267-luVo9CzV7iCcrA1OO5vVeXD0QHACvBn1jIVU) -Governance Address - [kf-OV1dpgFVEzEmyvAETT8gnhqZ1IqHn8RzT6dmEmvnze-9n](https://testnet.tonscan.org/address/kf-OV1dpgFVEzEmyvAETT8gnhqZ1IqHn8RzT6dmEmvnze-9n) +* Governance Address - [kf-OV1dpgFVEzEmyvAETT8gnhqZ1IqHn8RzT6dmEmvnze-9n](https://testnet.tonscan.org/address/kf-OV1dpgFVEzEmyvAETT8gnhqZ1IqHn8RzT6dmEmvnze-9n) -### Testnet TON-BSC Toncoin Bridge +### BSC/Toncoin bridge -Wrapped TONCOIN Address - [0xdb15ffaf2c88f2d89db9365a5160d5b8c9448ea6](https://testnet.bscscan.com/token/0xdb15ffaf2c88f2d89db9365a5160d5b8c9448ea6) +* Wrapped Toncoin address: [0xdb15ffaf2c88f2d89db9365a5160d5b8c9448ea6](https://testnet.bscscan.com/token/0xdb15ffaf2c88f2d89db9365a5160d5b8c9448ea6) -Bridge Address - [Ef_GmJntTDokxfhLGF1jRvMGC8Jav2V5keoNj4El2jzhHsID](https://testnet.tonscan.org/address/Ef_GmJntTDokxfhLGF1jRvMGC8Jav2V5keoNj4El2jzhHsID) +* Bridge address: [Ef_GmJntTDokxfhLGF1jRvMGC8Jav2V5keoNj4El2jzhHsID](https://testnet.tonscan.org/address/Ef_GmJntTDokxfhLGF1jRvMGC8Jav2V5keoNj4El2jzhHsID) -Collector Address - [EQDBNfV4DQzSyzNMw6BCTSZSoUi-CzWcYNsfhKxoDqfrwFtS](https://testnet.tonscan.org/address/EQDBNfV4DQzSyzNMw6BCTSZSoUi-CzWcYNsfhKxoDqfrwFtS) +* Collector address: [EQDBNfV4DQzSyzNMw6BCTSZSoUi-CzWcYNsfhKxoDqfrwFtS](https://testnet.tonscan.org/address/EQDBNfV4DQzSyzNMw6BCTSZSoUi-CzWcYNsfhKxoDqfrwFtS) -Governance Address - [kf83VnnXuaqQV1Ts2qvUr6agacM0ydOux5NNa1mcU-cEO693](https://testnet.tonscan.org/address/kf83VnnXuaqQV1Ts2qvUr6agacM0ydOux5NNa1mcU-cEO693) +* Governance address: [kf83VnnXuaqQV1Ts2qvUr6agacM0ydOux5NNa1mcU-cEO693](https://testnet.tonscan.org/address/kf83VnnXuaqQV1Ts2qvUr6agacM0ydOux5NNa1mcU-cEO693) -### Testnet Toncoin Oracles +### Testnet Toncoin oracles * Oracle 0 - TON Address - [Ef9fwskZLEuGDfYTRAtvt9k-mEdkaIskkUOsEwPw1wzXk7zR](https://testnet.tonscan.org/address/Ef9fwskZLEuGDfYTRAtvt9k-mEdkaIskkUOsEwPw1wzXk7zR) + * TON address: [Ef9fwskZLEuGDfYTRAtvt9k-mEdkaIskkUOsEwPw1wzXk7zR](https://testnet.tonscan.org/address/Ef9fwskZLEuGDfYTRAtvt9k-mEdkaIskkUOsEwPw1wzXk7zR) - EVM Address - 0xe54cd631c97be0767172ad16904688962d09d2fe + * EVM address: 0xe54cd631c97be0767172ad16904688962d09d2fe * Oracle 1 - TON Address - [Ef8jPzrhTYloKgTCsGgEFNx7OdH-sJ98etJnwrIVSsFxH9mu](https://testnet.tonscan.org/address/Ef8jPzrhTYloKgTCsGgEFNx7OdH-sJ98etJnwrIVSsFxH9mu) + * TON address: [Ef8jPzrhTYloKgTCsGgEFNx7OdH-sJ98etJnwrIVSsFxH9mu](https://testnet.tonscan.org/address/Ef8jPzrhTYloKgTCsGgEFNx7OdH-sJ98etJnwrIVSsFxH9mu) - EVM Address - 0xeb05E1B6AC0d574eF2CF29FDf01cC0bA3D8F9Bf1 + * EVM address: 0xeb05E1B6AC0d574eF2CF29FDf01cC0bA3D8F9Bf1 * Oracle 2 - TON Address - [Ef-fxGCPuPKNR6T4GcFxNQuLU5TykLKEAtkxWEfA1wBWy6JE](https://testnet.tonscan.org/address/Ef-fxGCPuPKNR6T4GcFxNQuLU5TykLKEAtkxWEfA1wBWy6JE) - - EVM Address - 0xF636f40Ebe17Fb2A1343e5EEee9D13AA90888b51 + * TON address: [Ef-fxGCPuPKNR6T4GcFxNQuLU5TykLKEAtkxWEfA1wBWy6JE](https://testnet.tonscan.org/address/Ef-fxGCPuPKNR6T4GcFxNQuLU5TykLKEAtkxWEfA1wBWy6JE) + * EVM address: 0xF636f40Ebe17Fb2A1343e5EEee9D13AA90888b51 ## Token Mainnet -### Mainnet TON-Ethereum Token Bridge +### TON/Ethereum token bridges -Ethereum Bridge Address - [0xb323692b6d4DB96af1f52E4499a2bd0Ded9af3C5](https://etherscan.io/address/0xb323692b6d4DB96af1f52E4499a2bd0Ded9af3C5) +* Ethereum bridge address: [0xb323692b6d4DB96af1f52E4499a2bd0Ded9af3C5](https://etherscan.io/address/0xb323692b6d4DB96af1f52E4499a2bd0Ded9af3C5) -Bridge Address - [Ef-1JetbPF9ubc1ga-57oHoOyDA1IShJt-BVlJnA9rrVTfrB](https://tonscan.org/address/Ef-1JetbPF9ubc1ga-57oHoOyDA1IShJt-BVlJnA9rrVTfrB) +* Bridge address: [Ef-1JetbPF9ubc1ga-57oHoOyDA1IShJt-BVlJnA9rrVTfrB](https://tonscan.org/address/Ef-1JetbPF9ubc1ga-57oHoOyDA1IShJt-BVlJnA9rrVTfrB) -Collector Address - [EQDF6fj6ydJJX_ArwxINjP-0H8zx982W4XgbkKzGvceUWvXl](https://tonscan.org/address/EQDF6fj6ydJJX_ArwxINjP-0H8zx982W4XgbkKzGvceUWvXl) +* Collector address: [EQDF6fj6ydJJX_ArwxINjP-0H8zx982W4XgbkKzGvceUWvXl](https://tonscan.org/address/EQDF6fj6ydJJX_ArwxINjP-0H8zx982W4XgbkKzGvceUWvXl) -Governance Address - [Ef8hHxV0v2I9FHh3CMX91WXjKaJav6SQlemEQm8ZvPBJdLde](https://tonscan.org/address/Ef8hHxV0v2I9FHh3CMX91WXjKaJav6SQlemEQm8ZvPBJdLde) +* Governance address: [Ef8hHxV0v2I9FHh3CMX91WXjKaJav6SQlemEQm8ZvPBJdLde](https://tonscan.org/address/Ef8hHxV0v2I9FHh3CMX91WXjKaJav6SQlemEQm8ZvPBJdLde) -### Mainnet Token Oracles +### Mainnet token oracles * Oracle 0 - - TON Public Key = a0993546fbeb4e8c90eeab0baa627659aee01726809707008e38d5742ea38aef + * TON public key: a0993546fbeb4e8c90eeab0baa627659aee01726809707008e38d5742ea38aef - TON Address - [Ef8WxwYOyAk-H0YGBc70gZFJc6oqUvcHywU-yJNBfSNh-GW9](https://tonscan.org/address/Ef8WxwYOyAk-H0YGBc70gZFJc6oqUvcHywU-yJNBfSNh-GW9) + * TON address: [Ef8WxwYOyAk-H0YGBc70gZFJc6oqUvcHywU-yJNBfSNh-GW9](https://tonscan.org/address/Ef8WxwYOyAk-H0YGBc70gZFJc6oqUvcHywU-yJNBfSNh-GW9) - ETH Address - 0x3154E640c56D023a98890426A24D1A772f5A38B2 + * ETH address: 0x3154E640c56D023a98890426A24D1A772f5A38B2 * Oracle 1 - TON Public Key = fe0a78726a82754b62517e4b7a492e1b1a8d4c9014955d2fa8f1345f1a3eafba + * TON public key: fe0a78726a82754b62517e4b7a492e1b1a8d4c9014955d2fa8f1345f1a3eafba - TON Address = [Ef8CbgwhUMYn2yHU343dcezKkvme3cyFJB7SHVY3FXhU9jqj](https://tonscan.org/address/Ef8CbgwhUMYn2yHU343dcezKkvme3cyFJB7SHVY3FXhU9jqj) + * TON address: [Ef8CbgwhUMYn2yHU343dcezKkvme3cyFJB7SHVY3FXhU9jqj](https://tonscan.org/address/Ef8CbgwhUMYn2yHU343dcezKkvme3cyFJB7SHVY3FXhU9jqj) - ETH Address = 0x8B06A5D37625F41eE9D9F543482b6562C657EA6F + * ETH Address: 0x8B06A5D37625F41eE9D9F543482b6562C657EA6F * Oracle 2 - TON Public Key = 00164233e111509b0486df85d2743defd6e2525820ee7d341c8ad92ee68d41a6 + * TON public key: 00164233e111509b0486df85d2743defd6e2525820ee7d341c8ad92ee68d41a6 - TON Address = [Ef-n3Vdme6nSe4FBDb3inTRF9B6lh3BbIwGlk0dDpUO5oFmH](https://tonscan.org/address/Ef-n3Vdme6nSe4FBDb3inTRF9B6lh3BbIwGlk0dDpUO5oFmH) +* TON address: [Ef-n3Vdme6nSe4FBDb3inTRF9B6lh3BbIwGlk0dDpUO5oFmH](https://tonscan.org/address/Ef-n3Vdme6nSe4FBDb3inTRF9B6lh3BbIwGlk0dDpUO5oFmH) - ETH Address = 0x6D5E361F7E15ebA73e41904F4fB2A7d2ca045162 + * ETH address: 0x6D5E361F7E15ebA73e41904F4fB2A7d2ca045162 * Oracle 3 - TON Public Key = 9af68ce3c030e8d21aae582a155a6f5c41ad006f9f3e4aacbb0ce579982b9ebb - - TON Address = [Ef9D1-FOb82pREFPgW7AlzNlZ7f0XnvmGakW23wpWeILAum9](https://tonscan.org/address/Ef9D1-FOb82pREFPgW7AlzNlZ7f0XnvmGakW23wpWeILAum9) + * TON public key: 9af68ce3c030e8d21aae582a155a6f5c41ad006f9f3e4aacbb0ce579982b9ebb + + * TON address: [Ef9D1-FOb82pREFPgW7AlzNlZ7f0XnvmGakW23wpWeILAum9](https://tonscan.org/address/Ef9D1-FOb82pREFPgW7AlzNlZ7f0XnvmGakW23wpWeILAum9) - ETH Address = 0x43931B8c29e34a8C16695408CD56327F511Cf086 + * ETH address: 0x43931B8c29e34a8C16695408CD56327F511Cf086 * Oracle 4 - TON Public Key = a4fef528b1e841f5fce752feeac0971f7df909e37ffeb3fab71c5ce8deb9f7d4 + * TON public key: a4fef528b1e841f5fce752feeac0971f7df909e37ffeb3fab71c5ce8deb9f7d4 - TON Address = [Ef8TBPHHIowG5pGgSVX8n4KmOaX-EEjvnOSBRlQvVsJWP_WJ](https://tonscan.org/address/Ef8TBPHHIowG5pGgSVX8n4KmOaX-EEjvnOSBRlQvVsJWP_WJ) + * TON address: [Ef8TBPHHIowG5pGgSVX8n4KmOaX-EEjvnOSBRlQvVsJWP_WJ](https://tonscan.org/address/Ef8TBPHHIowG5pGgSVX8n4KmOaX-EEjvnOSBRlQvVsJWP_WJ) - ETH Address = 0x7a0d3C42f795BA2dB707D421Add31deda9F1fEc1 + * ETH address: 0x7a0d3C42f795BA2dB707D421Add31deda9F1fEc1 * Oracle 5 - TON Public Key = 58a7ab3e3ff8281b668a86ad9fe8b72f2d14df5dcc711937915dacca1b94c07d + * TON public key: 58a7ab3e3ff8281b668a86ad9fe8b72f2d14df5dcc711937915dacca1b94c07d - TON Address = [Ef8ceN7cTemTe4ZV6AIbg5f8LsHZsYV1UaiGntvkME0KtP45](https://tonscan.org/address/Ef8ceN7cTemTe4ZV6AIbg5f8LsHZsYV1UaiGntvkME0KtP45) + * TON address: [Ef8ceN7cTemTe4ZV6AIbg5f8LsHZsYV1UaiGntvkME0KtP45](https://tonscan.org/address/Ef8ceN7cTemTe4ZV6AIbg5f8LsHZsYV1UaiGntvkME0KtP45) - ETH Address = 0x88352632350690EF22F9a580e6B413c747c01FB2 + * ETH address: 0x88352632350690EF22F9a580e6B413c747c01FB2 * Oracle 6 - TON Public Key = db60c3f50cb0302b516cd42833c7e8cad8097ad94306564b057b16ace486fb07 + * TON public key: db60c3f50cb0302b516cd42833c7e8cad8097ad94306564b057b16ace486fb07 - TON Address = [Ef8uDTu2WCcJdtuKmkDmC1yRKVxZrTp83ke5PnMECOccg3w4](https://tonscan.org/address/Ef8uDTu2WCcJdtuKmkDmC1yRKVxZrTp83ke5PnMECOccg3w4) + * TON address: [Ef8uDTu2WCcJdtuKmkDmC1yRKVxZrTp83ke5PnMECOccg3w4](https://tonscan.org/address/Ef8uDTu2WCcJdtuKmkDmC1yRKVxZrTp83ke5PnMECOccg3w4) - ETH Address = 0xeB8975966dAF0C86721C14b8Bb7DFb89FCBB99cA + * ETH address: 0xeB8975966dAF0C86721C14b8Bb7DFb89FCBB99cA * Oracle 7 - TON Public Key = 98c037c6d3a92d9467dc62c0e3da9bb0ad08c6b3d1284d4a37c1c5c0c081c7df - - TON Address = [Ef905jDDX87nPDbTSMqFB9ILVGX1zWc66PPrNhkjHrWxAnZZ](https://tonscan.org/address/Ef905jDDX87nPDbTSMqFB9ILVGX1zWc66PPrNhkjHrWxAnZZ) + * TON public key: 98c037c6d3a92d9467dc62c0e3da9bb0ad08c6b3d1284d4a37c1c5c0c081c7df - ETH Address = 0x48Bf4a783ECFb7f9AACab68d28B06fDafF37ac43 + * TON address: [Ef905jDDX87nPDbTSMqFB9ILVGX1zWc66PPrNhkjHrWxAnZZ](https://tonscan.org/address/Ef905jDDX87nPDbTSMqFB9ILVGX1zWc66PPrNhkjHrWxAnZZ) + + * ETH address: 0x48Bf4a783ECFb7f9AACab68d28B06fDafF37ac43 * Oracle 8 - TON Public Key = 5503c54a1b27525376e83d6fc326090c7d9d03079f400071b8bf05de5fbba48d + * TON public key: 5503c54a1b27525376e83d6fc326090c7d9d03079f400071b8bf05de5fbba48d - TON Address = [Ef9Ubg96xQ8jVKbl7QQJ1k8pClQLmO1Ci68nuNfbLdm9uS-x](https://tonscan.org/address/Ef9Ubg96xQ8jVKbl7QQJ1k8pClQLmO1Ci68nuNfbLdm9uS-x) + * TON address: [Ef9Ubg96xQ8jVKbl7QQJ1k8pClQLmO1Ci68nuNfbLdm9uS-x](https://tonscan.org/address/Ef9Ubg96xQ8jVKbl7QQJ1k8pClQLmO1Ci68nuNfbLdm9uS-x) - ETH Address = 0x954AE64BB0268b06ffEFbb6f454867a5F2CB3177 + * ETH address: 0x954AE64BB0268b06ffEFbb6f454867a5F2CB3177 ## Token Testnet -### Testnet TON-Ethereum Token Bridge +### TON/Ethereum token bridge -Ethereum Bridge Address - [0x4Efd8f04B6fb4CFAF0cfaAC11Fb489b97DBebB60](https://goerli.etherscan.io/address/0x4Efd8f04B6fb4CFAF0cfaAC11Fb489b97DBebB60) +* Ethereum bridge address: [0x4Efd8f04B6fb4CFAF0cfaAC11Fb489b97DBebB60](https://goerli.etherscan.io/address/0x4Efd8f04B6fb4CFAF0cfaAC11Fb489b97DBebB60) -Bridge Address - [Ef-lJBALjXSSwSKiedKzriSHixwQUxJ1BxTE05Ur5AXwZVjp](https://testnet.tonscan.org/address/Ef-lJBALjXSSwSKiedKzriSHixwQUxJ1BxTE05Ur5AXwZVjp) +* Bridge address: [Ef-lJBALjXSSwSKiedKzriSHixwQUxJ1BxTE05Ur5AXwZVjp](https://testnet.tonscan.org/address/Ef-lJBALjXSSwSKiedKzriSHixwQUxJ1BxTE05Ur5AXwZVjp) -Collector Address - [EQC1ZeKX1LNrlQ4bwi3je3KVM1AoZ3rkeyHM5hv9pYzmIh4v](https://testnet.tonscan.org/address/EQC1ZeKX1LNrlQ4bwi3je3KVM1AoZ3rkeyHM5hv9pYzmIh4v) +* Collector address: [EQC1ZeKX1LNrlQ4bwi3je3KVM1AoZ3rkeyHM5hv9pYzmIh4v](https://testnet.tonscan.org/address/EQC1ZeKX1LNrlQ4bwi3je3KVM1AoZ3rkeyHM5hv9pYzmIh4v) -Governance Address - [kf9NLH8CsGUkEKGYzCxaLd9Th6T5YkO-MXsCEU9Rw1fiRhf9](https://testnet.tonscan.org/address/kf9NLH8CsGUkEKGYzCxaLd9Th6T5YkO-MXsCEU9Rw1fiRhf9) +* Governance address: [kf9NLH8CsGUkEKGYzCxaLd9Th6T5YkO-MXsCEU9Rw1fiRhf9](https://testnet.tonscan.org/address/kf9NLH8CsGUkEKGYzCxaLd9Th6T5YkO-MXsCEU9Rw1fiRhf9) -### Testnet Token Oracles +### Testnet token oracles -> Same with Toncoin Testnet Bridge +> The same applies to the Toncoin Testnet bridge. * Oracle 0 - TON Address - [Ef9fwskZLEuGDfYTRAtvt9k-mEdkaIskkUOsEwPw1wzXk7zR](https://testnet.tonscan.org/address/Ef9fwskZLEuGDfYTRAtvt9k-mEdkaIskkUOsEwPw1wzXk7zR) - - EVM Address - 0xe54cd631c97be0767172ad16904688962d09d2fe + * TON address: [Ef9fwskZLEuGDfYTRAtvt9k-mEdkaIskkUOsEwPw1wzXk7zR](https://testnet.tonscan.org/address/Ef9fwskZLEuGDfYTRAtvt9k-mEdkaIskkUOsEwPw1wzXk7zR) + + * EVM address: 0xe54cd631c97be0767172ad16904688962d09d2fe * Oracle 1 - TON Address - [Ef8jPzrhTYloKgTCsGgEFNx7OdH-sJ98etJnwrIVSsFxH9mu](https://testnet.tonscan.org/address/Ef8jPzrhTYloKgTCsGgEFNx7OdH-sJ98etJnwrIVSsFxH9mu) + * TON address: [Ef8jPzrhTYloKgTCsGgEFNx7OdH-sJ98etJnwrIVSsFxH9mu](https://testnet.tonscan.org/address/Ef8jPzrhTYloKgTCsGgEFNx7OdH-sJ98etJnwrIVSsFxH9mu) - EVM Address - 0xeb05E1B6AC0d574eF2CF29FDf01cC0bA3D8F9Bf1 + * EVM address: 0xeb05E1B6AC0d574eF2CF29FDf01cC0bA3D8F9Bf1 * Oracle 2 - TON Address - [Ef-fxGCPuPKNR6T4GcFxNQuLU5TykLKEAtkxWEfA1wBWy6JE](https://testnet.tonscan.org/address/Ef-fxGCPuPKNR6T4GcFxNQuLU5TykLKEAtkxWEfA1wBWy6JE) + * TON address: [Ef-fxGCPuPKNR6T4GcFxNQuLU5TykLKEAtkxWEfA1wBWy6JE](https://testnet.tonscan.org/address/Ef-fxGCPuPKNR6T4GcFxNQuLU5TykLKEAtkxWEfA1wBWy6JE) - EVM Address - 0xF636f40Ebe17Fb2A1343e5EEee9D13AA90888b51 \ No newline at end of file + * EVM address: 0xF636f40Ebe17Fb2A1343e5EEee9D13AA90888b51 \ No newline at end of file From 7b19439a47fa640bdcd93a3547bb6be7df9a41ab Mon Sep 17 00:00:00 2001 From: D Ozgur Cakirkaya Date: Mon, 7 Apr 2025 12:13:30 +0100 Subject: [PATCH 04/14] network-configs.md update --- .../network/configs/network-configs.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/docs/v3/documentation/network/configs/network-configs.md b/docs/v3/documentation/network/configs/network-configs.md index d98bd9b049d..7fb0ff8009f 100644 --- a/docs/v3/documentation/network/configs/network-configs.md +++ b/docs/v3/documentation/network/configs/network-configs.md @@ -1,11 +1,13 @@ -# Network Configs +# Network configs -On this page you can find active network configs of TON Blockchain: +On this page, you can find the active network configurations for the TON Blockchain: -- Mainnet: https://ton.org/global-config.json -- Testnet: https://ton.org/testnet-global.config.json +- Mainnet: https://ton.org/global-config.json -## See Also +- Testnet: https://ton.org/testnet-global.config.json -- [Node Types](/v3/documentation/infra/nodes/node-types) -- [Blockchain Params Config](/v3/documentation/network/configs/blockchain-configs) +## See also + +- [Node types](/v3/documentation/infra/nodes/node-types) + +- [Blockchain parameters configurations](/v3/documentation/network/configs/blockchain-configs) \ No newline at end of file From 5ae498c38ef4ca9d598af6f9cf04571c84e37b6a Mon Sep 17 00:00:00 2001 From: D Ozgur Cakirkaya Date: Mon, 7 Apr 2025 16:42:41 +0100 Subject: [PATCH 05/14] blockchain-configs.md update --- .../network/configs/blockchain-configs.md | 421 ++++++++++-------- 1 file changed, 225 insertions(+), 196 deletions(-) diff --git a/docs/v3/documentation/network/configs/blockchain-configs.md b/docs/v3/documentation/network/configs/blockchain-configs.md index 23b688d260c..45b6f567325 100644 --- a/docs/v3/documentation/network/configs/blockchain-configs.md +++ b/docs/v3/documentation/network/configs/blockchain-configs.md @@ -1,45 +1,45 @@ -# Config Parameters +# Config parameters :::info -Read live values via [tonviewer](https://tonviewer.com/config) +You can view live values by using [Tonviewer](https://tonviewer.com/config). ::: -## šŸ‘‹ Introduction +## Introduction -On this page, you can find a description of the configuration parameters used in the TON Blockchain. -TON has a complex configuration with many technical parameters: some are used by the blockchain itself, some by the ecosystem. However, only a few people understand what these parameters mean. This article is necessary to provide users with a simple way to understand the parameters and their purpose. +This page provides a description of the configuration parameters used in the TON Blockchain. -## šŸ’” Prerequisites +TON features a complex configuration consisting of many technical parameters, some of which are utilized by the blockchain itself, while others serve the ecosystem. However, only a limited number of individuals fully understand the significance of these parameters. This article aims to offer users a straightforward explanation of each parameter and its purpose. -This material is intended to be read alongside the parameter list. -You can view the parameter values in the [current configuration](https://explorer.toncoin.org/config), and the way they are written into [cells](/v3/concepts/dive-into-ton/ton-blockchain/cells-as-data-storage) is described in the [block.tlb](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb) file in [TL-B](/v3/documentation/data-formats/tlb/tl-b-language) format. +## Prerequisites + +This material should be read alongside the parameter list. + +You can view the parameter values in the [current configuration](https://explorer.toncoin.org/config), and the method of writing them into [cells](/v3/concepts/dive-into-ton/ton-blockchain/cells-as-data-storage) is outlined in the [block.tlb](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb) file in [TL-B](/v3/documentation/data-formats/tlb/tl-b-language) format. :::info -The binary encoding at the end of the TON Blockchain parameter is a serialized binary representation of its configuration, enabling efficient storage or transmission of the configuration. The precise details of serialization depend on the specific encoding scheme used by the TON Blockchain. +The binary encoding found at the end of the TON Blockchain parameter represents a serialized binary format of its configuration. This allows for efficient storage and transmission of the configuration data. The specific details of the serialization process vary depending on the encoding scheme utilized by the TON Blockchain. ::: -## šŸš€ Let's get started! - -All parameters are in order, and you won't get lost. For your convenience, use the right sidebar for quick navigation. +All parameters are in place, and you won't get lost. For your convenience, please use the right sidebar for quick navigation. ## Param 0 This parameter is the address of a special smart contract that stores the blockchain's configuration. The configuration is stored in the contract to simplify its loading and modification during validator voting. :::info -In the configuration parameter, only the hash portion of the address is recorded, as the contract always resides in the [masterchain](/v3/concepts/dive-into-ton/ton-blockchain/blockchain-of-blockchains#masterchain-blockchain-of-blockchains) (workchain -1). Therefore, the full address of the contract will be written as `-1:`. +In the configuration parameter, only the hash portion of the address is recorded, as the contract always resides in the [MasterChain](/v3/concepts/dive-into-ton/ton-blockchain/blockchain-of-blockchains#masterchain-blockchain-of-blockchains) (WorkChain -1). Therefore, the full address of the contract will be written as `-1:`. ::: ## Param 1 -This parameter is the address of the [Elector](/v3/documentation/smart-contracts/contracts-specs/governance#elector) smart contract, responsible for appointing validators, distributing rewards, and voting on changes to blockchain parameters. +This parameter is the address of the [elector smart contract](/v3/documentation/smart-contracts/contracts-specs/governance#elector), responsible for appointing validators, distributing rewards, and voting on changes to blockchain parameters. ## Param 2 -This parameter represents the address of the System, on behalf of which new TONs are minted and sent as rewards for validating the blockchain. +This parameter represents the address of the system, on behalf of which new Toncoins are minted and sent as rewards for validating the blockchain. :::info -If parameter 2 is missing, parameter 0 is used instead (newly minted TONs come from the configuration smart contract). +If the parameter 2 is missing, the parameter 0 is used instead (newly minted Toncoins come from the configuration smart contract). ::: ## Param 3 @@ -47,7 +47,7 @@ If parameter 2 is missing, parameter 0 is used instead (newly minted TONs come f This parameter is the address of the transaction fee collector. :::info -If parameter 3 is missing (as is the case at the time of writing), transaction fees are sent to the Elector smart contract (parameter 1). +If the this parameter is missing (for the time being), transaction fees are directed to the elector smart contract (parameter 1). ::: ## Param 4 @@ -55,8 +55,9 @@ If parameter 3 is missing (as is the case at the time of writing), transaction f This parameter is the address of the root DNS contract of the TON network. :::info -More detailed information can be found in the [TON DNS & Domains](/v3/guidelines/web3/ton-dns/dns) article and in a more detailed original description [here](https://github.com/ton-blockchain/TEPs/blob/master/text/0081-dns-standard.md). -This contract is not responsible for selling .ton domains. +More detailed information, please see the [TON DNS & Domains](/v3/guidelines/web3/ton-dns/dns) documentation and in a more detailed original description [here](https://github.com/ton-blockchain/TEPs/blob/master/text/0081-dns-standard.md). + +This contract is not responsible for selling **.ton** domains. ::: ## Param 6 @@ -64,28 +65,28 @@ This contract is not responsible for selling .ton domains. This parameter is responsible for minting fees of new currencies. :::info -Currently, minting additional currency is not implemented and does not work. The implementation and launch of the minter are planned. +Currently, the minting of additional currency is not implemented and does not function. The implementation and launch of the minter are planned for the future. -You can learn more about the issues and prospects in the [relevant article](/v3/documentation/infra/minter-flow). +You can learn more about the issues and prospects in the [relevant documentation](/v3/documentation/infra/minter-flow). ::: ## Param 7 -This parameter stores the volume of each of the additional currencies in circulation. Data is stored in the form of a [dictionary](/v3/documentation/data-formats/tlb/tl-b-types#hashmap-parsing-example) (binary tree; probably during TON's development this structure was mistakenly named hashmap) `extracurrency_id -> amount`, the amount is presented as `VarUint 32` - an integer from `0` to `2^248`. +This parameter stores the volume of each additional currency in circulation. The data is organized as a dictionary (also referred to as a **hashmap**, although this name may be a typo during the TON Blockchain's development). The structure uses the format `extracurrency_id -> amount`, where the amount is represented as a `VarUint 32`, which is an integer ranging from `0` to `2^248`. ## Param 8 This parameter indicates the network version and additional capabilities supported by the validators. :::info -Validators are nodes in the blockchain network that are responsible for creating new blocks and verifying transactions. +Validators are nodes in the TON Blockchain network that are responsible for creating new blocks and verifying transactions. ::: -- `version`: This field specifies the version. +- `version`: This field specifies the version. -- `capabilities`: This field is a set of flags that are used to indicate the presence or absence of certain features or capabilities. +- `capabilities`: This field is a set of flags that are used to indicate the presence or absence of certain features or capabilities. -Thus, when updating the network, validators will vote to change parameter 8. This way, the TON network can be updated without downtime. +Thus, when updating the network, validators will vote to change parameter 8. This way, the TON Blockchain network can be updated without downtime. ## Param 9 @@ -93,71 +94,77 @@ This parameter contains a list (binary tree) of mandatory parameters. It ensures ## Param 10 -This parameter represents a list (binary tree) of critical TON parameters, the change of which significantly affects the network, so more voting rounds are held. +This parameter represents a list (binary tree) of critical TON parameters whose change significantly affects the network, so more voting rounds are held. ## Param 11 This parameter indicates under what conditions proposals to change the TON configuration are accepted. -- `min_tot_rounds` - the minimum number of rounds before a proposal can be applied -- `max_tot_rounds` - the maximum number of rounds, upon reaching which the proposal will automatically be rejected -- `min_wins` - the required number of wins (3/4 of validators by the sum of the pledge must vote in favor) -- `max_losses` - the maximum number of losses, upon reaching which the proposal will automatically be rejected -- `min_store_sec` and `max_store_sec` determine the possible time interval during which the proposal will be stored -- `bit_price` and `cell_price` indicate the price of storing one bit or one cell of the proposal +- `min_tot_rounds`: The minimum number of rounds before a proposal can be applied + +- `max_tot_rounds`: The maximum number of rounds, upon reaching which the proposal will automatically be rejected + +- `min_wins`: The required number of wins (3/4 of validators by the sum of the pledge must vote in favor) + +- `max_losses`: The maximum number of losses, upon reaching which the proposal will automatically be rejected + +- `min_store_sec` and `max_store_sec` determine the possible time interval during which the proposal will be stored + +- `bit_price` and `cell_price` indicate the price of storing one bit or one cell of the proposal ## Param 12 -This parameter represents the configuration of a workchain in the TON Blockchain. Workchains in the TON Blockchain are designed as independent blockchains that can operate in parallel, allowing TON to scale and process a very large number of transactions and smart contracts. +This parameter represents the configuration of a WorkChain in the TON Blockchain. WorkChains are designed as independent blockchains that can operate in parallel, allowing TON to scale and process a large number of transactions and smart contracts. -## Workchain configuration parameters +### WorkChain configuration parameters -- `enabled_since`: a UNIX timestamp of the moment this workchain was enabled; +- `enabled_since`: A UNIX timestamp of the moment this WorkChain was enabled. -- `actual_min_split`: the minimum depth of the split (sharding) of this workchain, supported by validators; +- `actual_min_split`: The minimum depth of the split (sharding) of this WorkChain, supported by validators. -- `min_split`: the minimum depth of the split of this workchain, set by the configuration; +- `min_split`: The minimum depth of the split of this WorkChain, set by the configuration. -- `max_split`: the maximum depth of the split of this workchain; +- `max_split`: The maximum depth of the split of this WorkChain. -- `basic`: a boolean flag (1 for true, 0 for false) indicating whether this workchain is basic (handles TON coins, smart contracts based on the TON Virtual Machine); +- `basic`: A boolean flag (1 for true, 0 for false) indicating whether this WorkChain is basic (handles TON coins, smart contracts based on the TON Virtual Machine). -- `active`: a boolean flag indicating whether this workchain is active at the moment; +- `active`: A boolean flag indicating whether this WorkChain is active at the moment. -- `accept_msgs`: a boolean flag indicating whether this workchain is accepting messages at the moment; +- `accept_msgs`: A boolean flag indicating whether this WorkChain is accepting messages at the moment. -- `flags`: additional flags for the workchain (reserved, currently always 0); +- `flags`: Additional flags for the WorkChain (reserved, currently always 0). -- `zerostate_root_hash` and `zerostate_file_hash`: hashes of the first block of the workchain; +- `zerostate_root_hash` and `zerostate_file_hash`: Hashes of the first block of the WorkChain. -- `version`: version of the workchain; +- `version`: Version of the WorkChain. -- `format`: the format of the workchain, which includes vm_version and vm_mode - the virtual machine used there. +- `format`: The format of the WorkChain, which includes `vm_version` and `vm_mode` - the virtual machine used there. ## Param 13 -This parameter defines the cost of filing complaints about incorrect operation of validators in the [Elector](/v3/documentation/smart-contracts/contracts-specs/governance#elector) contract. +This parameter defines the cost of filing complaints about incorrect operation of validators in the [elector smart contract](/v3/documentation/smart-contracts/contracts-specs/governance#elector). ## Param 14 -This parameter represents the reward for block creation in the TON Blockchain. Nanograms are nanoTON, thus, the reward for block creation in the masterchain equals 1.7 TON, and in the basic workchain - 1.0 TON (meanwhile, in the event of a workchain split, the block reward also splits: if there are two shardchains in the workchain, then the shard block reward will be 0.5 TON). +This parameter indicates the reward for creating a block in the TON Blockchain. Nanograms represent nanoToncoins. Therefore, the reward for block creation in the MasterChain is 1.7 Toncoins, while in the basic WorkChain, it is 1.0 Toncoins. In the event of a WorkChain split, the block reward is also divided: if there are two ShardChains within the WorkChain, then the reward for each shard block will be 0.5 Toncoins. ## Param 15 This parameter contains the duration of different stages of elections and validators' work in the TON Blockchain. For each validation period, there is an `election_id` equal to the UNIX-format time at the start of the validation. -You can get the current `election_id` (if elections are ongoing) or the past one by invoking the Elector contract's respective get-methods `active_election_id` and `past_election_ids`. -## Workchain configuration parameters +You can get the current `election_id` (if elections are ongoing) or the past one by invoking the elector smart contract's respective get-methods `active_election_id` and `past_election_ids`. -- `validators_elected_for`: the number of seconds the elected set of validators perform their role (one round). +### WorkChain configuration parameters -- `elections_start_before`: how many seconds before the end of the current round the election process for the next period will start. +- `validators_elected_for`: The number of seconds the elected set of validators perform their role (one round). -- `elections_end_before`: how many seconds before the end of the current round the validators for the next round will be chosen. +- `elections_start_before`: The seconds before the end of the current round the election process for the next period will start. -- `stake_held_for`: the period for which a validator's stake is held (for handling complaints) after the round expires. +- `elections_end_before`: The seconds before the end of the current round, the validators for the next round will be chosen. + +- `stake_held_for`: The period for which a validator's stake is held (for handling complaints) after the round expires. :::info Each value in the arguments is determined by the `uint32` data type. @@ -165,7 +172,7 @@ Each value in the arguments is determined by the `uint32` data type. ### Examples -In the TON Blockchain, it is customary to conventionally divide validation periods into even and odd ones. These rounds follow one another. Since voting for the next round takes place during the previous one, a validator needs to divide funds into two pools to have the opportunity to participate in both rounds. +In the TON Blockchain, validation periods are typically divided into **even** and **odd** rounds that alternate. Voting for the next round occurs during the previous one, so a validator must allocate their funds into two separate pools to participate in both rounds. #### Mainnet @@ -195,11 +202,11 @@ hold_start = validation_end = election_id + constants['validators_elected_for'] hold_end = hold_start + constants['stake_held_for'] = 1600098304 + 32768 = 1600131072 ``` -Thus, at the moment, the length of one round of one parity is `1600131072 - 1600000000 = 131072 seconds = 36.40888... hours` +Therefore, at this time, the length of one round of one parity is `1600131072 - 1600000000 = 131072 seconds = 36.40888... hours` #### Testnet -##### Current values: +Current values: ```python constants = { @@ -210,11 +217,11 @@ constants = { } ``` -##### Scheme +Scheme: ![image](/img/docs/blockchain-configs/config15-testnet.png) -###### How to calculate periods? +#### How to calculate periods? Let `election_id = validation_start = 160002400`. Then: @@ -225,37 +232,41 @@ hold_start = validation_end = election_id + constants['validators_elected_for'] hold_end = hold_start + constants['stake_held_for'] = 160009600 + 900 = 160010500 ``` -Thus, at the moment, the length of one round of one parity is `160010500 - 1600000000 = 10500 seconds = 175 minutes = 2.91666... hours` +Therefore, at this time, the length of one round of one parity is `160010500 - 1600000000 = 10500 seconds = 175 minutes = 2.91666... hours` ## Param 16 -This parameter represents the limits on the number of validators in the TON Blockchain. It is directly used by the Elector smart contract. +This parameter represents the limits on the number of validators in the TON Blockchain. It is directly used by the elector smart contract. -### Configuration parameters for the number of validators for elections: +### Configuration parameters for the number of validators for elections -- `max_validators`: This parameter represents the maximum number of validators that can participate in the network operation at any given time. +- `max_validators`: This parameter represents the maximum number of validators that can participate in the network operation at any given time. -- `max_main_validators`: This parameter represents the maximum number of masterchain validators. +- `max_main_validators`: This parameter represents the maximum number of masterchain validators. -- `min_validators`: This parameter represents the minimum number of validators that must support the network operation. +- `min_validators`: This parameter represents the minimum number of validators that must support the network operation. -1. The maximum number of validators is greater than or equal to the maximum number of masterchain validators. -2. The maximum number of masterchain validators must be greater than or equal to the minimum number of validators. -3. The minimum number of validators must be no less than 1. +#### Notes + +* The maximum number of validators is greater than or equal to the maximum number of MasterChain validators. + +* The maximum number of MasterChain validators must be greater than or equal to the minimum number of validators. + +* The minimum number of validators must be no less than 1. ## Param 17 This parameter represents the stake parameters configuration in the TON Blockchain. In many blockchain systems, especially those using the Proof-of-Stake or Delegated Proof-of-Stake consensus algorithm, cryptocurrency owners native to the network can "stake" their tokens to become validators and earn rewards. -## Configuration parameters: +### Configuration parameters -- `min_stake`: This parameter represents the minimum amount of TONs that an interested party needs to stake to participate in the validation process. +- `min_stake`: This parameter represents the minimum amount of Toncoins that an interested party needs to stake to participate in the validation process. -- `max_stake`: This parameter represents the maximum amount of TONs that an interested party can stake. +- `max_stake`: This parameter represents the maximum amount of Toncoins that an interested party can stake. -- `min_total_stake`: This parameter represents the minimum total amount of TONs that must be held by the chosen set of validators. +- `min_total_stake`: This parameter represents the minimum total amount of Toncoins that the chosen set of validators must hold. -- `max_stake_factor`: This parameter is a multiplier indicating how many times the maximum effective stake (pledge) can exceed the minimum stake sent by any other validator. +- `max_stake_factor`: This parameter is a multiplier indicating how many times the maximum effective stake (pledge) can exceed the minimum stake sent by any other validator. :::info Each value in the arguments is determined by the `uint32` data type. @@ -265,16 +276,15 @@ Each value in the arguments is determined by the `uint32` data type. This parameter represents the configuration for determining the prices for data storage on the TON Blockchain. This serves as a measure to prevent spam and encourages network maintenance. -### Dictionary of storage fee parameters: +### Dictionary of storage fee parameters -- `utime_since`: This parameter provides the initial Unix timestamp from which the specified prices apply. +- `utime_since`: This parameter provides the initial Unix timestamp from which the specified prices apply. -- `bit_price_ps` and `cell_price_ps`: These parameters represent the storage prices for one bit or one cell of information in the main workchains of the TON Blockchain for 65536 seconds +- `bit_price_ps` and `cell_price_ps`: These parameters represent the storage prices for one bit or one cell of information in the main WorkChains of the TON Blockchain for 65536 seconds -- `mc_bit_price_ps` and `mc_cell_price_ps`: These parameters represent the prices for computational resources specifically in the TON masterchain for 65536 seconds +- `mc_bit_price_ps` and `mc_cell_price_ps`: These parameters represent the prices for computational resources specifically in the TON MasterChain for 65536 seconds :::info - `utime_since` accepts values in the `uint32` data type. The rest accept values in the `uint64` data type. @@ -284,193 +294,201 @@ The rest accept values in the `uint64` data type. These parameters define the cost of computations in the TON network. The complexity of any computation is estimated in gas units. -- `flat_gas_limit` and `flat_gas_price`: A certain starting amount of gas is provided at a price of `flat_gas_price` (to offset the costs of launching the TON Virtual Machine). +- `flat_gas_limit` and `flat_gas_price`: A certain starting amount of gas is provided at a price of `flat_gas_price` (to offset the costs of launching the TON Virtual Machine). -- `gas_price`: This parameter reflects the price of gas in the network, in nanotons per 65536 gas units. +- `gas_price`: This parameter reflects the price of gas in the network, in nanotons per 65536 gas units. -- `gas_limit`: This parameter represents the maximum amount of gas that can be consumed per transaction. +- `gas_limit`: This parameter represents the maximum amount of gas that can be consumed per transaction. -- `special_gas_limit`: This parameter represents the limit on the amount of gas that can be consumed per transaction of a special (system) contract. +- `special_gas_limit`: This parameter represents the limit on the amount of gas that can be consumed per transaction of a special (system) contract. -- `gas_credit`: This parameter represents a credit in gas units that is provided to transactions for the purpose of checking an external message. +- `gas_credit`: This parameter represents a credit in gas units provided to transactions to check an external message. -- `block_gas_limit`: This parameter represents the maximum amount of gas that can be consumed within a single block. +- `block_gas_limit`: This parameter represents the maximum amount of gas that can be consumed within a single block. -- `freeze_due_limit` and `delete_due_limit`: Limits of accumulated storage fees (in nanoTON) at which a contract is frozen and deleted, respectively. +- `freeze_due_limit` and `delete_due_limit`: Limits of accumulated storage fees (in nanoToncoin) at which a contract is frozen and deleted, respectively. :::info -More about `gas_credit` and other parameters in the section with external messages [here](/v3/documentation/smart-contracts/transaction-fees/accept-message-effects#external-messages). +You can find more about `gas_credit` and other parameters in the section of external messages [here](/v3/documentation/smart-contracts/transaction-fees/accept-message-effects#external-messages). ::: ## Param 22 and 23 These parameters set limits on the block, upon reaching which the block is finalized and the callback of the remaining messages (if any) is carried over to the next block. -### Configuration parameters: +### Configuration parameters -- `bytes`: This section sets the limits on the block size in bytes. +- `bytes`: This section sets the limits on the block size in bytes. -- `underload`: Underload is a state when the shard realizes that there is no load and is inclined to merge if a neighboring shard is willing. +- `underload`: Underload is a state when the shard realizes that there is no load and is inclined to merge if a neighboring shard is willing. -- `soft_limit`: Soft limit - when this limit is reached, internal messages stop being processed. +- `soft_limit`: Soft limit - when this limit is reached, internal messages stop being processed. -- `hard_limit`: Hard limit - this is the absolute maximum size. +- `hard_limit`: Hard limit - this is the absolute maximum size. -- `gas`: This section sets the limits on the amount of gas that a block can consume. Gas in the context of blockchain is an indicator of computational work. The limits on underload, soft and hard limit work the same as for size in bytes. +- `gas`: This section sets the limits on the amount of gas that a block can consume. Gas, in the context of blockchain, is an indicator of computational work. The limits on underload, soft and hard limits, work the same as for size in bytes. -- `lt_delta`: This section sets the limits on the difference in logical time between the first and the last transaction. Logical time is a concept used in the TON Blockchain for ordering events. The limits on underload, soft and hard limit work the same as for size in bytes and gas. +- `lt_delta`: This section sets the limits on the difference in logical time between the first and last transaction. Logical time is a concept used in the TON Blockchain for ordering events. The limits on underload, soft and hard limits, work the same as for size in bytes and gas. :::info -In case of insufficient load on the shard and, accordingly, the desire to merge with a neighbor, `soft_limit` defines a state above which internal (internal) messages stop being processed, but external (external) ones continue. External (external) messages are processed until a limit equal to `(soft_limit + hard_limit)/2 is reached`. +If a shard has insufficient load and there is an intention to merge with a neighboring shard, the `soft_limit` indicates a threshold. When this threshold is exceeded, internal messages will stop being processed, while external messages will still be handled. External messages will continue to be processed until the total reaches a limit that is equal to half the sum of the `soft_limit` and `hard_limit`, or `(soft_limit + hard_limit) / 2`. ::: ## Param 24 and 25 -Parameter 24 represents the configuration for the cost of sending messages in the masterchain of the TON Blockchain. +Parameter 24 represents the configuration for the cost of sending messages in the MasterChain of the TON Blockchain. Parameter 25 represents the configuration for the cost of sending messages in all other cases. -### Configuration parameters defining the costs of forwarding: +### Configuration parameters defining the costs of forwarding -- `lump_price`: This parameter means the base price for forwarding a message, regardless of its size or complexity. +- `lump_price`: This parameter means the base price for forwarding a message, regardless of its size or complexity. -- `bit_price`: This parameter represents the cost per bit of message forwarding. +- `bit_price`: This parameter represents the cost per bit of message forwarding. -- `cell_price`: This parameter reflects the cost of forwarding a message per cell. A cell is the basic unit of data storage on the TON Blockchain. +- `cell_price`: This parameter reflects the cost of forwarding a message per cell. A cell is the basic unit of data storage on the TON Blockchain. -- `ihr_price_factor`: This is a factor used to calculate the cost of immediate hypercube routing (IHR). - :::info - IHR is a method of message delivery in the TON Blockchain network, where messages are sent directly to the recipient's shard chain. - ::: +- `ihr_price_factor`: This is a factor used to calculate the cost of immediate hypercube routing (IHR). -- `first_frac`: This parameter defines the fraction of the remaining remainder that will be used for the first transition along the message route. +:::info +IHR is a method of message delivery in the TON Blockchain network, where messages are sent directly to the recipient's ShardChain. +::: -- `next_frac`: This parameter defines the fraction of the remaining remainder that will be used for subsequent transitions along the message route. +- `first_frac`: This parameter defines the fraction of the remaining remainder that will be used for the first transition along the message route. + +- `next_frac`: This parameter defines the fraction of the remaining remainder that will be used for subsequent transitions along the message route. ## Param 28 -This parameter provides the configuration for the Catchain protocol in the TON Blockchain. Catchain is the lowest level consensus protocol used in TON to achieve agreement among validators. +This parameter provides the configuration for the `Catchain` protocol in the TON Blockchain. `Catchain` is the lowest-level consensus protocol used in the TON to achieve agreement among validators. -### Configuration parameters: +### Configuration parameters -- `flags`: A general field that can be used to set various binary parameters. In this case, it equals 0, which means that no specific flags are set. +- `flags`: A general field that can be used to set various binary parameters. In this case, it equals 0, which means that no specific flags are set. -- `shuffle_mc_validators`: A Boolean value indicating whether to shuffle the masterchain validators or not. If this parameter is set to 1, the validators will be shuffled; otherwise, they will not. +- `shuffle_mc_validators`: A Boolean value indicating whether to shuffle the masterchain validators or not. If this parameter is set to 1, the validators will be shuffled; otherwise, they will not. -- `mc_catchain_lifetime`: The lifetime of masterchain catchain groups in seconds. +- `mc_catchain_lifetime`: The lifetime of MasterChain's `Catchain` groups in seconds. -- `shard_catchain_lifetime`: The lifetime of shardchain catchain groups in seconds. +- `shard_catchain_lifetime`: The lifetime of ShardChain's `Catchain` groups in seconds. -- `shard_validators_lifetime`: The lifetime of a shardchain validators group in seconds. +- `shard_validators_lifetime`: The lifetime of a ShardChain's validators group in seconds. -- `shard_validators_num`: The number of validators in each shardchain validation group. +- `shard_validators_num`: The number of validators in each ShardChain validation group. ## Param 29 -This parameter provides the configuration for the consensus protocol above catchain ([Param 28](#param-28)) in the TON Blockchain. The consensus protocol is a crucial component of a blockchain network, and it ensures that all nodes agree on the state of the distributed ledger. +This parameter provides the configuration for the consensus protocol above `Catchain` ([Param 28](#param-28)) in the TON Blockchain. The consensus protocol is a crucial component of a blockchain network, and it ensures that all nodes agree on the state of the distributed ledger. -### Configuration parameters: +### Configuration parameters -- `flags`: A general field that can be used to set various binary parameters. In this case, it equals 0, which means that no specific flags are set. +- `flags`: A general field that can be used to set various binary parameters. In this case, it equals 0, which means that no specific flags are set. -- `new_catchain_ids`: A Boolean value indicating whether to generate new Catchain identifiers. If this parameter is set to 1, new identifiers will be generated. In this case, it is assigned the value of 1, which means that new identifiers will be generated. +- `new_catchain_ids`: A Boolean value indicating whether to generate new `Catchain` identifiers. If this parameter is set to 1, new identifiers will be generated. In this case, it is assigned the value of 1, which means that new identifiers will be generated. -- `round_candidates`: The number of candidates to be considered in each round of the consensus protocol. Here, it is set to 3. +- `round_candidates`: The number of candidates to be considered in each round of the consensus protocol. Here, it is set to 3. -- `next_candidate_delay_ms`: The delay in milliseconds before the right to generate a block candidate passes to the next validator. Here, it is set to 2000 ms (2 seconds). +- `next_candidate_delay_ms`: The delay in milliseconds before the right to generate a block candidate passes to the next validator. Here, it is set to 2000 ms (2 seconds). -- `consensus_timeout_ms`: The timeout for block consensus in milliseconds. Here, it is set to 16000 ms (16 seconds). +- `consensus_timeout_ms`: The timeout for block consensus in milliseconds. Here, it is set to 16000 ms (16 seconds). -- `fast_attempts`: The number of "fast" attempts to reach consensus. Here, it is set to 3. +- `fast_attempts`: The number of "fast" attempts to reach consensus. Here, it is set to 3. -- `attempt_duration`: The duration of each attempt at agreement. Here, it is set to 8. +- `attempt_duration`: The duration of each attempt at agreement. Here, it is set to 8. -- `catchain_max_deps`: The maximum number of dependencies of a Catchain block. Here, it is set to 4. +- `catchain_max_deps`: The maximum number of dependencies of a Catchain block. Here, it is set to 4. -- `max_block_bytes`: The maximum size of a block in bytes. Here, it is set to 2097152 bytes (2 MB). +- `max_block_bytes`: The maximum size of a block in bytes. Here, it is set to 2097152 bytes (2 MB). -- `max_collated_bytes`: The maximum size of serialized block correctness proofs in bytes. Here, it is set to 2097152 bytes (2 MB). +- `max_collated_bytes`: The maximum size of serialized block correctness proofs in bytes. Here, it is set to 2097152 bytes (2 MB). -- `proto_version`: The protocol version. Here, it is set to 2. +- `proto_version`: The protocol version. Here, it is set to 2. -- `catchain_max_blocks_coeff`: The coefficient limiting the rate of block generation in Catchain, [description](https://github.com/ton-blockchain/ton/blob/master/doc/catchain-dos.md). Here, it is set to 10000. +- `catchain_max_blocks_coeff`: The coefficient limiting the rate of block generation in `Catchain`, [description](https://github.com/ton-blockchain/ton/blob/master/doc/catchain-dos.md). Here, it is set to 10000. ## Param 31 -This parameter represents the configuration of smart contract addresses from which no fees are charged for either gas or storage, and where tick-tok transactions can be created. The list usually includes governance contracts. The parameter is presented as a binary tree structure — a tree (HashMap 256), where the keys are a 256-bit representation of the address. Only addresses in the masterchain can be present in this list. +This parameter represents the configuration of smart contract addresses from which no fees are charged for either gas or storage and where **tick-tok** transactions can be created. The list usually includes governance contracts. The parameter is presented as a binary tree structure — a tree (HashMap 256), where the keys are a 256-bit representation of the address. Only addresses in the MasterChain can be present in this list. ## Param 32, 34 and 36 Lists of validators from the previous (32), current (34), and next (36) rounds. Parameter 36 is set from the end of the elections until the start of the round. -### Configuration parameters: +### Configuration parameters -- `cur_validators`: This is the current list of validators. Validators are typically responsible for verifying transactions in a blockchain network. +- `cur_validators`: This is the current list of validators. Validators are typically responsible for verifying transactions in a blockchain network. -- `utime_since` and `utime_until`: These parameters provide the time period during which these validators are active. +- `utime_since` and `utime_until`: These parameters provide the time period during which these validators are active. -- `total` and `main`: These parameters provide the total number of validators and the number of validators validating the masterchain in the network. +- `total` and `main`: These parameters provide the total number of validators and the number of validators validating the MasterChain in the network. -- `total_weight`: This adds up the weights of the validators. +- `total_weight`: This adds up the weights of the validators. -- `list`: A list of validators in the tree format `id->validator-data`: `validator_addr`, `public_key`, `weight`, `adnl_addr`: These parameters provide details about each validator - their 256 addresses in the masterchain, public key, weight, ADNL address (the address used at the network level of TON). +- `list`: A list of validators in the tree format `id->validator-data`: `validator_addr`, `public_key`, `weight`, `adnl_addr`: These parameters provide details about each validator - their 256 addresses in the MasterChain, public key, weight, ADNL address (the address used at the network level of the TON). ## Param 40 -This parameter defines the structure of the configuration for punishment for improper behavior (non-validation). In the absence of the parameter, the default fine size is 101 TON. +This parameter defines the structure of the configuration for punishment for improper behavior (non-validation). In the absence of the parameter, the default fine size is 101 Toncoins. -## Configuration parameters: +### Configuration parameters -** `MisbehaviourPunishmentConfig` **: This data structure defines how improper behavior in the system is punished. +`MisbehaviourPunishmentConfig`: This data structure defines how improper behavior in the system is punished. It contains several fields: -- `default_flat_fine`: This part of the fine does not depend on the stake size. +- `default_flat_fine`: This part of the fine does not depend on the stake size. -- `default_proportional_fine`: This part of the fine is proportional to the validator's stake size. +- `default_proportional_fine`: This part of the fine is proportional to the validator's stake size. -- `severity_flat_mult`: This is the multiplier applied to the `default_flat_fine` value for significant violations by the validator. +- `severity_flat_mult`: This is the multiplier applied to the `default_flat_fine` value for significant violations by the validator. -- `severity_proportional_mult`: This is the multiplier applied to the `default_proportional_fine` value for significant violations by the validator. +- `severity_proportional_mult`: This is the multiplier applied to the `default_proportional_fine` value for significant violations by the validator. -- `unpunishable_interval`: This parameter represents the period during which offenders are not punished to eliminate temporary network problems or other anomalies. +- `unpunishable_interval`: This parameter represents the period during which offenders are not punished to eliminate temporary network problems or other anomalies. -- `long_interval`, `long_flat_mult`, `long_proportional_mult`: These parameters define a "long" period of time and multipliers for flat and proportional fines for improper behavior. +- `long_interval`, `long_flat_mult`, `long_proportional_mult`: These parameters define a "long" period of time and multipliers for flat and proportional fines for improper behavior. -- `medium_interval`, `medium_flat_mult`, `medium_proportional_mult`: Similarly, they define a "medium" period of time and multipliers for flat and proportional fines for improper behavior. +- `medium_interval`, `medium_flat_mult`, `medium_proportional_mult`: Similarly, they define a "medium" period of time and multipliers for flat and proportional fines for improper behavior. ## Param 43 -This parameter pertains to various size limits and other characteristics of accounts and messages. +This parameter relates to the size limits and other features of accounts and messages. -### Configuration parameters: +### Configuration parameters -- `max_msg_bits`: maximum message size in bits. +- `max_msg_bits`: Maximum message size in bits. -- `max_msg_cells`: maximum number of cells (a form of storage unit) a message can occupy. +- `max_msg_cells`: Maximum number of cells (a form of storage unit) a message can occupy. -- `max_library_cells`: maximum number of cells that can be used for library cells. +- `max_library_cells`: Maximum number of cells that can be used for library cells. -- `max_vm_data_depth`: maximum cell depth in messages and account state. +- `max_vm_data_depth`: Maximum cell depth in messages and account state. -- `max_ext_msg_size`: maximum external message size in bits. +- `max_ext_msg_size`: Maximum external message size in bits. -- `max_ext_msg_depth`: maximum external message depth. This could refer to the depth of the data structure within the message. +- `max_ext_msg_depth`: Maximum external message depth. This could refer to the depth of the data structure within the message. -- `max_acc_state_cells`: maximum number of cells that an account state can occupy. +- `max_acc_state_cells`: Maximum number of cells that an account state can occupy. -- `max_acc_state_bits`: maximum account state size in bits. +- `max_acc_state_bits`: Maximum account state size in bits. If absent, the default parameters are taken: -- `max_size` = 65535 -- `max_depth` = 512 -- `max_msg_bits` = 1 \<\< 21 -- `max_msg_cells` = 1 \<\< 13 -- `max_library_cells` = 1000 -- `max_vm_data_depth` = 512 -- `max_acc_state_cells` = 1 \<\< 16 -- `max_acc_state_bits` = (1 \<\< 16) \* 1023 +- `max_size` = 65535 + +- `max_depth` = 512 + +- `max_msg_bits` = 1 \<\< 21 + +- `max_msg_cells` = 1 \<\< 13 + +- `max_library_cells` = 1000 + +- `max_vm_data_depth` = 512 + +- `max_acc_state_cells` = 1 \<\< 16 + +- `max_acc_state_bits` = (1 \<\< 16) \* 1023 :::info You can view more details about the standard parameters [here](https://github.com/ton-blockchain/ton/blob/fc9542f5e223140fcca833c189f77b1a5ae2e184/crypto/block/mc-config.h#L379) in the source code. @@ -481,12 +499,12 @@ You can view more details about the standard parameters [here](https://github.co This parameter defines the list of suspended addresses, which cannot be initialized until `suspended_until`. It only applies to yet uninitiated accounts. This is a measure for stabilizing the tokenomics (limiting early miners). If not set - there are no limitations. Each address is represented as an end node in this tree, and the tree-like structure allows to effectively check the presence or absence of an address in the list. :::info -The stabilization of the tokenomics is further described in the [official report](https://t.me/tonblockchain/178) of the "The Open Network" Telegram channel. +The stabilization of the tokenomics is further described in the [official report](https://t.me/tonblockchain/178) of the **@tonblockchain** Telegram channel. ::: ## Param 45 -The list of precompiled contracts is stored in the masterchain config: +The list of precompiled contracts is stored in the MasterChain config: ``` precompiled_smc#b0 gas_usage:uint64 = PrecompiledSmc; @@ -494,64 +512,75 @@ precompiled_contracts_config#c0 list:(HashmapE 256 PrecompiledSmc) = Precompiled _ PrecompiledContractsConfig = ConfigParam 45; ``` -More details about precompiled contracts on [this page](/v3/documentation/smart-contracts/contracts-specs/precompiled-contracts). +More details about precompiled contracts are on [this page](/v3/documentation/smart-contracts/contracts-specs/precompiled-contracts). ## Param 71 - 73 -This parameter pertains to bridges for wrapping TON in other networks: +This parameter pertains to bridges for wrapping Toncoins in other networks: + +- ETH-TON **(71)** + +- BSC-TON **(72)** -- ETH-TON ** (71)** -- BSC-TON ** (72) ** -- Polygon-TON ** (73) ** +- Polygon-TON **(73)** -### Configuration parameters: + -- `bridge_address`: This is the bridge contract address that accepts TON to issue wrapped TON in other networks. +### Configuration parameters -- `oracle_multisig_address`: This is the bridge management wallet address. A multisig wallet is a type of digital wallet that requires signatures from multiple parties to authorize a transaction. It is often used to increase security. The oracles act as the parties. +- `bridge_address`: This is the bridge contract address that accepts TON to issue wrapped Toncoins in other networks. -- `oracles`: list of oracles in the form of a tree `id->address` +- `oracle_multisig_address`: This is the bridge management wallet address. A multisig wallet is a type of digital wallet that requires signatures from multiple parties to authorize a transaction. It is often used to increase security. The oracles act as the parties. -- `external_chain_address`: This is the bridge contract address in the corresponding external blockchain. +- `oracles`: List of oracles in the form of a tree `id->address` + +- `external_chain_address`: This is the bridge contract address in the corresponding external blockchain. ## Param 79, 81 and 82 -This parameter pertains to bridges for wrapping tokens from other networks into tokens on the TON network: +This parameter relates to bridges for wrapping tokens from other networks into tokens on the TON network: + +- ETH-TON **(79)** -- ETH-TON ** (79) ** -- BSC-TON ** (81) ** -- Polygon-TON ** (82) ** +- BSC-TON **(81)** -### Configuration parameters: +- Polygon-TON **(82)** -- `bridge_address` and `oracles_address`: These are the blockchain addresses of the bridge and the bridge management contract (oracles multisig), respectively. +### Configuration parameters -- `oracles`: list of oracles in the form of a tree `id->address` +- `bridge_address` and `oracles_address`: These are the blockchain addresses of the bridge and the bridge management contract (oracles multisig), respectively. -- `state_flags`: State flag. This parameter is responsible for enabling/disabling separate bridge functions. +- `oracles`: List of oracles in the form of a tree `id->address` -- `prices`: This parameter contains a list or dictionary of prices for different operations or fees associated with the bridge, such as `bridge_burn_fee`, `bridge_mint_fee`, `wallet_min_tons_for_storage`, `wallet_gas_consumption`, `minter_min_tons_for_storage`, `discover_gas_consumption`. +- `state_flags`: State flag. This parameter is responsible for enabling/disabling separate bridge functions. -- `external_chain_address`: The bridge contract address in another blockchain. +- `prices`: This parameter contains a list or dictionary of prices for different operations or fees associated with the bridge, such as `bridge_burn_fee`, `bridge_mint_fee`, `wallet_min_tons_for_storage`, `wallet_gas_consumption`, `minter_min_tons_for_storage`, `discover_gas_consumption`. -## Negative Parameters +- `external_chain_address`: The bridge contract address in another blockchain. + +## Negative parameters :::info -The difference between negative parameters and positive ones is the need for validators' verification; they usually do not have a specific assigned role. +The distinction between negative and positive parameters lies in the necessity for validators to verify them; negative parameters typically lack a specific assigned role. ::: -## Next Steps - -After a deep dive into this article, it is strongly recommended that you take the time for a more detailed study of the following documents: +## Next steps -- Original, but limited descriptions in [whitepaper.pdf](https://ton.org/whitepaper.pdf) and [tblkch.pdf](/tblkch.pdf). +After thoroughly reviewing this article, it is highly recommended that you dedicate time for a more in-depth study of the following documents: + +- The original descriptions are present, but they may be limited, in the documents: + * [The Open Network Whitepaper](https://ton.org/whitepaper.pdf) + * [Telegram Open Network Blockchain](/tblkch.pdf) -- [mc-config.h](https://github.com/ton-blockchain/ton/blob/fc9542f5e223140fcca833c189f77b1a5ae2e184/crypto/block/mc-config.h), [block.tlb](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb) and [BlockMasterConfig Type](https://docs.evercloud.dev/reference/graphql-api/field_descriptions#blockmasterconfig-type). +- Source code: + * [mc-config.h](https://github.com/ton-blockchain/ton/blob/fc9542f5e223140fcca833c189f77b1a5ae2e184/crypto/block/mc-config.h) + * [block.tlb](https://github.com/ton-blockchain/ton/blob/master/crypto/block/block.tlb) + * [BlockMasterConfig Type](https://docs.evercloud.dev/reference/graphql-api/field_descriptions#blockmasterconfig-type) -## šŸ“– See Also +## See also -On this page, you can find active network configurations of the TON Blockchain: +On these pages, you can find active network configurations of the TON Blockchain: -- Mainnet: https://ton.org/global-config.json -- Testnet: https://ton.org/testnet-global.config.json -- [Russian Version](https://github.com/delovoyhomie/description-config-for-TON-Blockchain/blob/main/Russian-version.md). +- [Mainnet configuration](https://ton.org/global-config.json) +- [Testnet configuration](https://ton.org/testnet-global.config.json) +- [Russian version](https://github.com/delovoyhomie/description-config-for-TON-Blockchain/blob/main/Russian-version.md) From 5249316b116f40e5b0456336dd8143303dd24ea5 Mon Sep 17 00:00:00 2001 From: D Ozgur Cakirkaya Date: Tue, 8 Apr 2025 14:00:25 +0100 Subject: [PATCH 06/14] config-params.md update --- .../network/configs/config-params.md | 246 +++++++++++------- 1 file changed, 150 insertions(+), 96 deletions(-) diff --git a/docs/v3/documentation/network/configs/config-params.md b/docs/v3/documentation/network/configs/config-params.md index 57b7517f3ad..9e9dd7ba53a 100644 --- a/docs/v3/documentation/network/configs/config-params.md +++ b/docs/v3/documentation/network/configs/config-params.md @@ -1,84 +1,104 @@ -# Changing the Parameters +# Changing the parameters -The aim of this document is to provide a basic explanation of configuration parameters of TON Blockchain, and to give step-by-step instructions for changing these parameters by a consensus of a majority of validators. +This document aims to provide a basic explanation of TON Blockchain's configuration parameters and give step-by-step instructions for changing these parameters based on a consensus of a majority of validators. -We assume that the reader is already familiar with [Fift](/v3/documentation/smart-contracts/fift/overview) and the [Lite Client](/v3/guidelines/nodes/running-nodes/liteserver-node), as explained in [FullNode-HOWTO (low-level)](/v3/guidelines/nodes/running-nodes/full-node), and [Validator-HOWTO (low-level)](/v3/guidelines/nodes/running-nodes/validator-node) in the sections where validators' voting for the configuration proposals is described. +We assume that the reader is already familiar with [Fift](/v3/documentation/smart-contracts/fift/overview) and the [Lite Client](/v3/guidelines/nodes/running-nodes/liteserver-node), as explained in [FullNode-HOWTO (low-level)](/v3/guidelines/nodes/running-nodes/full-node), and [Validator-HOWTO (low-level)](/v3/guidelines/nodes/running-nodes/validator-node) particularly in the sections discussing how validators vote on configuration proposals. -## 1. Configuration parameters -The **configuration parameters** are certain values that affect the behavior of validators and/or fundamental smart contracts of TON Blockchain. The current values of all configuration parameters are stored as a special part of the masterchain state and are extracted from the current masterchain state when needed. Therefore, it makes sense to speak of the values of the configuration parameters with respect to a certain masterchain block. Each shardchain block contains a reference to the latest known masterchain block; the values from the corresponding masterchain state are assumed to be active for this shardchain block and are used during its generation and validation. For masterchain blocks, the state of the previous masterchain block is used to extract the active configuration parameters. Therefore, even if one tries to change some configuration parameters inside a masterchain block, the changes will become active only for the next masterchain block. +## Configuration parameters -Each configuration parameter is identified by a signed 32-bit integer index, called **configuration parameter index** or simply **index**. The value of a configuration parameter is always a Cell. Some configuration parameters may be missing; then it is sometimes assumed that the value of this parameter is `Null`. There also is a list of **mandatory** configuration parameters that must be always present; this list is stored in configuration parameter `#10`. +The **configuration parameters** are specific values that influence the behavior of validators and fundamental smart contracts on the TON Blockchain. The current values of all configuration parameters are stored as a distinct part of the MasterChain state and are retrieved whenever necessary. Consequently, we can refer to the values of the configuration parameters concerning a particular MasterChain block. Each ShardChain block includes a reference to the most recently known MasterChain block; the values from the corresponding MasterChain state are considered active for this ShardChain block and are used during its generation and validation. -All configuration parameters are combined into a **configuration dictionary** - a Hashmap with signed 32-bit keys (configuration parameter indices) and values consisting of exactly one cell reference. In other words, a configuration dictionary is a value of TL-B type (`HashmapE 32 ^Cell`). In fact, the collection of all configuration parameters is stored in the masterchain state as a value of TL-B type `ConfigParams`: +For MasterChain blocks, the state of the previous MasterChain block is used to extract the active configuration parameters. Therefore, even if certain configuration parameters are attempted to be modified within a MasterChain block, any changes will only take effect in the subsequent MasterChain block. - _ config_addr:bits256 config:^(Hashmap 32 ^Cell) = ConfigParams; -We see that, apart from the configuration dictionary, `ConfigParams` contains `config_addr`—256-bit address of the configuration smart contract in the masterchain. More details on the configuration smart contract will be provided later. +Each configuration parameter is identified by a signed 32-bit integer known as the **configuration parameter index**, or simply the **index**. The value of a configuration parameter is always a `Cell`. In some cases, certain configuration parameters may be absent, and it is generally assumed that the value of these missing parameters is `Null`. Additionally, there is a list of **mandatory** configuration parameters that must always be present. This list is stored in the configuration parameter `#10`. -The configuration dictionary containing the active values of all configuration parameters is available via special TVM register `c7` to all smart contracts when their code is executed in a transaction. More precisely, when a smart contract is executed, `c7` is initialized by a Tuple, the only element of which is a Tuple with several "context" values useful for the execution of the smart contract, such as the current Unix time (as registered in the block header). The tenth entry of this Tuple (i.e., the one with zero-based index 9) contains a Cell representing the configuration dictionary. Therefore, it can be accessed by means of TVM instructions `PUSH c7; FIRST; INDEX 9` or by the equivalent instruction `CONFIGROOT`. In fact, special TVM instructions `CONFIGPARAM` and `CONFIGOPTPARAM` combine the previous actions with a dictionary lookup, returning any configuration parameter by its index. We refer to the TVM documentation for more details on these instructions. What is relevant here is that all configuration parameters are easily accessible from all smart contracts (masterchain or shardchain), and smart contracts may inspect them and use them to perform specific checks. For instance, a smart contract might extract workchain data storage prices from a configuration parameter to compute the price for storing a chunk of user-provided data. +All configuration parameters are combined into a **configuration dictionary**, which is a `Hashmap` with signed 32-bit keys (the configuration parameter indices) and values that consist of exactly one cell reference. In other words, a configuration dictionary is a value of the TL-B type `HashmapE 32 ^Cell`. The collection of all configuration parameters is retained in the MasterChain state as a value of the TL-B type `ConfigParams`: -The values of configuration parameters are not arbitrary. In fact, if the configuration parameter index `i` is non-negative, then the value of this parameter must be a valid value of TL-B type (`ConfigParam i`). This restriction is enforced by the validators, which will not accept changes to configuration parameters with non-negative indices unless they are valid values of the corresponding TL-B type. +`_ config_addr:bits256 config:^(Hashmap 32 ^Cell) = ConfigParams;` -Therefore, the structure of such parameters is determined in source file `crypto/block/block.tlb`, where (`ConfigParam i`) is defined for different values of `i`. For instance, +In addition to the configuration dictionary, `ConfigParams` contains `config_addr`—the 256-bit address of the configuration smart contract within the MasterChain. Further details on the configuration smart contract will be provided later. - _ config_addr:bits256 = ConfigParam 0; - _ elector_addr:bits256 = ConfigParam 1; - _ dns_root_addr:bits256 = ConfigParam 4; // root TON DNS resolver +The configuration dictionary, which contains the active values of all configuration parameters, is accessible to all smart contracts through a special TVM register called `c7` during the execution of a transaction. Specifically, when a smart contract is executed, `c7` is initialized as a tuple. This tuple consists of a single element, which is another tuple containing several "context" values that are useful for executing the smart contract, such as the current Unix time (as recorded in the block header). - capabilities#c4 version:uint32 capabilities:uint64 = GlobalVersion; - _ GlobalVersion = ConfigParam 8; // all zero if absent +The tenth entry of this inner tuple (i.e., the one indexed with zero-based index 9) contains a `Cell` representing the configuration dictionary. This configuration dictionary can be accessed by using the TVM instructions `PUSH c7; FIRST; INDEX 9` or the equivalent instruction `CONFIGROOT`. Furthermore, special TVM instructions like `CONFIGPARAM` and `CONFIGOPTPARAM` streamline this process by combining the previous actions with a dictionary lookup, allowing smart contracts to retrieve any configuration parameter by its index. -We see that the configuration parameter `#8` contains a Cell with no references and exactly 104 data bits. The first four bits must be `11000100`, then 32 bits with the currently enabled "global version" are stored, and a 64-bit integer with flags corresponding to currently enabled capabilities follows. A more detailed description of all configuration parameters will be provided in an appendix to the TON Blockchain documentation; for now, one can inspect the TL-B scheme in `crypto/block/block.tlb` and check how different parameters are used in the validator sources. +It is important to note that all configuration parameters are readily accessible to all smart contracts, whether they operate on the MasterChain or ShardChain. As a result, smart contracts can inspect these parameters and utilize them for specific checks. For instance, a smart contract might extract data storage prices for different WorkChains from a configuration parameter in order to calculate the cost of storing a piece of user-provided data. -In contrast with configuration parameters with non-negative indices, configuration parameters with negative indices can contain arbitrary values. At least, no restrictions on their values are enforced by the validators. Therefore, they can be used to store important information (such as the Unix time when certain smart contracts must start operating) that is not crucial for the block generation but is used by some of the fundamental smart contracts. -## 2. Changing configuration parameters +The values of configuration parameters are not arbitrary. Specifically, if the configuration parameter index `i` is non-negative, then its value must correspond to a valid value of the TL-B type `ConfigParam i`. Validators enforce this restriction and do not accept changes to configuration parameters with non-negative indices unless the values are valid for the corresponding TL-B type. -We have already explained that the current values of configuration parameters are stored in a special portion of the masterchain state. How do they ever get changed? +The structure of these parameters is defined in the source file `crypto/block/block.tlb`, where `ConfigParam i` is specified for different values of `i`. For example: -In fact, there is a special smart contract residing in the masterchain called the **configuration smart contract**. Its address is determined by the `config_addr` field in `ConfigParams`, which we have described before. The first cell reference in its data must contain an up-to-date copy of all configuration parameters. When a new masterchain block is generated, the configuration smart contract is looked up by its address, `config_addr`, and the new configuration dictionary is extracted from the first cell reference of its data. After some validity checks (such as verifying that any value with a non-negative 32-bit index `i` is indeed a valid value of TL-B type (`ConfigParam i`)) the validator copies this new configuration dictionary into the portion of the masterchain containing ConfigParams. This is performed after all transactions have been created, so only the final version of the new configuration dictionary stored in the configuration smart contract is inspected. If the validity checks fail, then the "true" configuration dictionary is left unchanged. In this way, the configuration smart contract cannot install invalid values of configuration parameters. If the new configuration dictionary coincides with the current configuration dictionary, then no checks are performed and no changes are made. +- `_config_addr: bits256 = ConfigParam 0;` +- `_elector_addr: bits256 = ConfigParam 1;` +- `_dns_root_addr: bits256 = ConfigParam 4; // root TON DNS resolver` +- `capabilities#c4 version:uint32 capabilities:uint64 = GlobalVersion;` +- `_GlobalVersion = ConfigParam 8; // all zero if absent` -In this way, all changes to configuration parameters are performed by the configuration smart contract, and it is its code that determines the rules for changing configuration parameters. Currently, the configuration smart contract supports two modes for changing configuration parameters: +These entries illustrate how configuration parameters are structured and defined within the specified file. -1) By means of an external message signed by a specific private key, which corresponds to a public key stored in the data of the configuration smart contract. This is the method employed in the public testnet and probably in the smaller private test networks controlled by one entity, because it enables the operator to easily change the values of any configuration parameters. Note that this public key may be changed by a special external message signed by an old key, and that if it is changed to zero, then this mechanism is disabled. Therefore, one might use it for fine-tuning immediately after the launch and then disable it for good. -2) By means of creating "configuration proposals" that are subsequently voted for or against by validators. Typically, a configuration proposal has to collect votes from more than 3/4 of all validators (by weight), and not only in one round but in several rounds (i.e., several consecutive sets of validators have to confirm the proposed parameter change). This is the distributed governance mechanism to be used by the TON Blockchain Mainnet. +The configuration parameter `#8` includes a `Cell` that has no references and contains exactly 104 data bits. The first four bits are allocated for `11000100`, followed by 32 bits that represent the currently enabled "global version." This is followed by a 64-bit integer with flags that correspond to the currently enabled capabilities. A more detailed description of all configuration parameters will be provided in an appendix to the TON Blockchain documentation. In the meantime, you can review the TL-B scheme in `crypto/block/block.tlb` to see how different parameters are utilized in the validator sources. -We would like to describe the second way of changing configuration parameters in more detail. +Unlike configuration parameters with non-negative indices, those with negative indices can hold arbitrary values. Validators do not enforce any restrictions on these values. As a result, they can be used to store essential information, such as the Unix time when specific smart contracts are set to begin operating. This information is not critical for block generation but is necessary for some fundamental smart contracts. -## 3. Creating configuration proposals +## Changing configuration parameters -A new **configuration proposal** contains the following data: -- index of the configuration parameter to be changed -- new value of the configuration parameter (or Null, if it is to be deleted) -- expiration Unix time of the proposal -- flag indicating whether the proposal is **critical** or not -- optional **old value hash** with the cell hash of the current value (the proposal can be activated only if the current value has the indicated hash) +The current values of configuration parameters are stored in a special section of the MasterChain state. But how are they changed? -Anybody with a wallet in the masterchain can create a new configuration proposal, provided he pays an adequate fee. However, only validators can vote for or against existing configuration proposals. +There is a special smart contract known as the **configuration smart contract** that resides in the MasterChain. Its address is specified by the `config_addr` field in `ConfigParams`. The first cell reference in its data must contain an up-to-date copy of all configuration parameters. When a new MasterChain block is generated, the configuration smart contract is accessed using its address (`config_addr`), and the new configuration dictionary is extracted from the first cell reference of its data. -Note that there are **critical** and **ordinary** configuration proposals. A critical configuration proposal can change any configuration parameter, including one of the so-called critical ones (the list of critical configuration parameters is stored in configuration parameter `#10`, which is itself critical). However, creating critical configuration proposals is more expensive, and they usually need to collect more validator votes in more rounds (the precise voting requirements for ordinary and critical configuration proposals are stored in critical configuration parameter `#11`). On the other hand, ordinary configuration proposals are cheaper, but they cannot change the critical configuration parameters. +Following some validity checks—like ensuring that any value with a non-negative 32-bit index `i` is indeed a valid TL-B type (`ConfigParam i`)—the validator copies this new configuration dictionary into the portion of the MasterChain that contains `ConfigParams`. This operation occurs after all transactions have been created, meaning only the final version of the new configuration dictionary stored in the smart contract is evaluated. -In order to create a new configuration proposal, one first has to generate a BoC (bag-of-cells) file containing the proposed new value. The exact way of doing this depends on the configuration parameter being changed. For instance, if we want to create a parameter `-239` containing UTF-8 string "TEST" (i.e., `0x54455354`), we could create `config-param-239.boc` as follows: invoke Fift and then type +If the validity checks fail, the existing configuration dictionary remains unchanged, ensuring that the configuration smart contract cannot install invalid parameter values. If the new configuration dictionary is identical to the current one, no checks are performed, and no changes are made. + +All changes to configuration parameters are executed by the configuration smart contract, which defines the rules for modifying these parameters. Currently, the configuration smart contract supports two methods for changing configuration parameters: + +- **External message**: This method involves an external message signed by a specific private key, which corresponds to a public key stored in the configuration smart contract's data. This approach is typically used in public testnets and possibly in smaller private test networks controlled by a single entity, as it allows the operator to easily modify any configuration parameter values. + + It is important to note that this public key can be changed through a special external message signed by the previous key, and if changed to zero, this mechanism becomes disabled. This means the method can be used for fine-tuning right after launch and then permanently disabled. + +- **Configuration proposals**: This method involves creating "configuration proposals" that validators vote on. Generally, a configuration proposal must gather votes from more than 3/4 (75%) of all validators by weight, and this requires approval in multiple rounds (i.e., several consecutive sets of validators must confirm the proposed parameter change). This serves as the distributed governance mechanism for the TON Blockchain Mainnet. + +We will provide a more detailed explanation of the second method for changing configuration parameters. + +## Creating configuration proposals + +A new **configuration proposal** includes the following information: + +- The index of the configuration parameter to be changed. + +- The new value of the configuration parameter (or `Null`, if it is to be deleted). + +- The expiration Unix time of the proposal. + +- A flag indicating whether the proposal is **critical**. + +- An optional **old value hash** that contains the cell hash of the current value (the proposal can only be activated if the current value matches the specified hash). + +Anyone with a wallet in the MasterChain can create a new configuration proposal, provided they pay the required fee. However, only validators have the authority to vote for or against existing configuration proposals. + +It is important to note that there are **critical** and **ordinary** configuration proposals. A critical configuration proposal can modify any configuration parameter, including those classified as critical. The list of critical configuration parameters is stored in configuration parameter `#10`, which is itself considered critical. Creating critical configuration proposals is more costly, and they typically require gathering more validator votes across multiple rounds. The specific voting requirements for both ordinary and critical configuration proposals are detailed in the critical configuration parameter `#11`. Conversely, ordinary configuration proposals are less expensive to create but cannot alter critical configuration parameters. + +To create a new configuration proposal, one must first generate a BoC (bag-of-cells) file that contains the proposed new value. The method for doing this varies depending on the configuration parameter being modified. For example, if we want to create a parameter `-239` containing the UTF-8 string "TEST" (i.e., `0x54455354`), we would generate `config-param-239.boc` by invoking Fift and then typing: ``` 2 boc+>B "config-param-239.boc" B>file bye ``` - -As a result, a 21-byte file `config-param-239.boc` will be created, containing the serialization of the required value. +As a result, a 21-byte file named `config-param-239.boc` will be created, which contains the serialization of the required value. -For more sophisticated cases, and especially for configuration parameters with non-negative indices this straightforward approach is not easily applicable. We recommend using `create-state` (available as `crypto/create-state` in the build directory) instead of `fift` and copying and editing suitable portions of the source files `crypto/smartcont/gen-zerostate.fif` and `crypto/smartcont/CreateState.fif`, which are usually employed to create the zero state (corresponding to the "genesis block" of other blockchain architectures) of TON Blockchain. +For more complex cases, especially for configuration parameters with non-negative indices, this straightforward approach may not be easily applicable. We recommend using `create-state`, which is available as `crypto/create-state` in the build directory, instead of using `fift`. You should also consider copying and modifying relevant portions of the source files `crypto/smartcont/gen-zerostate.fif` and `crypto/smartcont/CreateState.fif`. These files are typically used to create the zero state, corresponding to the "genesis block" found in other blockchain architectures, for the TON Blockchain. -Consider, for instance, configuration parameter `#8`, which contains the currently-enabled global blockchain version and capabilities: +For example, consider configuration parameter `#8`, which contains the currently enabled global blockchain version and its capabilities: ``` capabilities#c4 version:uint32 capabilities:uint64 = GlobalVersion; _ GlobalVersion = ConfigParam 8; ``` - -We can inspect its current value by running the lite client and typing `getconfig 8`: +We can check its current value by running the lite client and typing `getconfig 8`: ``` > getconfig 8 @@ -89,14 +109,15 @@ ConfigParam(8) = ( x{C4000000010000000000000006} ``` -Now suppose that we want to enable the capability represented by bit `#3` (`+8`), which is `capReportVersion` (when enabled, this capability forces all collators to report their supported versions and capabilities in the block headers of the blocks they generate). Therefore, we want to have `version=1` and `capabilities=14`. In this example, we can still guess the correct serialization and create the BoC file directly by typing in Fift. +Let’s consider enabling the capability represented by bit `#3` (which corresponds to `+8`), specifically the `capReportVersion` capability. When this capability is enabled, it requires all collators to include their supported versions and capabilities in the block headers of the blocks they generate. Therefore, we need to set `version=1` and `capabilities=14`. In this case, we can accurately guess the correct serialization and create the BoC file directly by entering commands in Fift. + ``` x{C400000001000000000000000E} s>c 2 boc+>B "config-param8.boc" B>file ``` -(A 30-byte file `config-param8.boc` containing the desired value is created as a result.) +A 30-byte file named `config-param8.boc` is created, containing the desired value. -However, in more complicated cases this might not be an option, so let's do this example differently. Namely, we can inspect the source files `crypto/smartcont/gen-zerostate.fif` and `crypto/smartcont/CreateState.fif` for relevant portions. +In more complicated cases, this may not be an option. Therefore, let's approach this example differently. We can inspect the source files `crypto/smartcont/gen-zerostate.fif` and `crypto/smartcont/CreateState.fif` for relevant portions. ``` // version capabilities -- @@ -115,8 +136,8 @@ and 1 capCreateStats capBounceMsgBody or capReportVersion or config.version! ``` +We observe that `config.version!`, excluding the last `8 config!`, effectively accomplishes our goal. Therefore, we can create a temporary Fift script named `create-param8.fif`: -We see that `config.version!` without the last `8 config!` essentially does what we need, so we can create a temporary Fift script, for example, `create-param8.fif`: ``` #!/usr/bin/fift -s "TonUtil.fif" include @@ -139,16 +160,16 @@ dup ."Serialized value = " getconfig 0 ConfigParam(0) = ( config_addr:x5555555555555555555555555555555555555555555555555555555555555555) x{5555555555555555555555555555555555555555555555555555555555555555} ``` -We see that the address of the configuration smart contract is `-1:5555...5555`. By running suitable get-methods of this smart contract, we can find out the required payment for creating this configuration proposal: + +We have the address of the configuration smart contract as `-1:5555...5555`. By using appropriate getter methods of this smart contract, we can determine the required payment for creating this configuration proposal: ``` > runmethod -1:5555555555555555555555555555555555555555555555555555555555555555 proposal_storage_price 0 1100000 104 0 @@ -184,9 +207,9 @@ result: [ 2340800000 ] remote result (not to be trusted): [ 2340800000 ] ``` -The parameters to get-method `proposal_storage_price` are the critical flag (0 in this case), the time interval during which this proposal will be active (1.1 Megaseconds), the total amount of bits (104) and cell references (0) in the data. The latter two quantities can be seen in the output of `create-config-proposal.fif`. - -We see that one has to pay 2.3408 Toncoin to create this proposal. It is better to add at least 1.5 Tonoin to the message to pay for the processing fees, so we are going to send 4 Toncoin along with the request (all excess Toncoin will be returned back). Now we use `wallet.fif` (or the corresponding Fift script for the wallet we are using) to create a transfer from our wallet to the configuration smart contract carrying 4 Toncoin and the body from `config-msg-body.boc`. This usually looks like: +The parameters for the `proposal_storage_price` get-method include the following: a critical flag set to 0, a time interval of 1.1 megaseconds during which the proposal will remain active, a total of 104 bits, and 0 cell references in the data. The latter two quantities can be found in the output of `create-config-proposal.fif`. + +To create this proposal, we need to pay 2.3408 Toncoins. It's advisable to add at least 1.5 Toncoins to cover the processing fees. Therefore, we will send a total of 4 Toncoins with the request (any excess Toncoins will be returned). We will then use `wallet.fif` (or the appropriate Fift script for our wallet) to execute a transfer from our wallet to the configuration smart contract, including the 4 Toncoins and the body from `config-msg-body.boc`. This process typically looks like: ``` $ fift -s wallet.fif my-wallet -1:5555555555555555555555555555555555555555555555555555555555555555 31 4. -B config-msg-body.boc @@ -210,13 +233,13 @@ B5EE9C724101040100CB0001CF89FE00000000000000000000000000000000000000000000000000 (Saved to file wallet-query.boc) ``` -Now we send the external message `wallet-query.boc` to the blockchain with the aid of the lite client. +We will now send the external message `wallet-query.boc` to the blockchain using the lite client. > sendfile wallet-query.boc .... external message status is 1 -After waiting for some time, we can inspect the incoming messages of our wallet to check for response messages from the configuration smart contract, or, if we feel lucky, simply inspect the list of all active configuration proposals by means of method `list_proposals` of the configuration smart contract. +After waiting for a brief period, we can check the incoming messages in our wallet to look for response messages from the configuration smart contract. Alternatively, if we are feeling lucky, we can directly inspect the list of all active configuration proposals by using the `list_proposals` method of the configuration smart contract. ``` > runmethod -1:5555555555555555555555555555555555555555555555555555555555555555 list_proposals @@ -227,19 +250,30 @@ remote result (not to be trusted): [ ([6465489854369209310663026020982025659862 ... caching cell FDCD887EAF7ACB51DA592348E322BBC0BD3F40F9A801CB6792EFF655A7F43BBC ``` -We see that the list of all active configuration proposals consists of exactly one entry represented by a pair. +The list of all active configuration proposals contains exactly one entry represented by a pair. + ``` [6465...6321 [1586779536 0 [8 C{FDCD...} -1] 1124...2998 () 8646...209 3 0 0]] ``` -The first number `6465..6321` is the unique identifier of the configuration proposal, equal to its 256-bit hash. The second component of this pair is a Tuple describing the status of this configuration proposal. The first component of this Tuple is the expiration Unix time of the configuration proposal (`1586779546`). The second component (`0`) is the criticality flag. Next comes the configuration proposal proper, described by the triple `[8 C{FDCD...} -1]`, where `8` is the index of the configuration parameter to be modified, `C{FDCD...}` is the cell with the new value (represented by the hash of this cell), and `-1` is the optional hash of the old value of this parameter (`-1` means that this hash has not been specified). Next we see a large number `1124...2998` representing the identifier of the current validator set, then an empty list `()` representing the set of all currently active validators that have voted for this proposal so far, then `weight_remaining` equal to `8646...209` - a number that is positive if the proposal has not yet collected enough validator votes in this round, and negative otherwise. Then we see three numbers: `3 0 0`. These numbers are `rounds_remaining` (this proposal will survive at most three rounds, i.e., changes of the current validator set), `wins` (the count of rounds where the proposal collected votes of more than 3/4 of all validators by weight), and `losses` (the count of rounds where the proposal failed to collect 3/4 of all validator votes). -We can inspect the proposed value for configuration parameter `#8` by asking the lite-client to expand cell `C{FDCD...}` using its hash `FDCD...` or a sufficiently long prefix of this hash to uniquely identify the cell in question: +The first number, `6465..6321`, serves as the unique identifier for the configuration proposal and represents its 256-bit hash. The second component of this pair is a tuple that describes the status of the configuration proposal. The first part of this tuple indicates the expiration Unix time of the proposal (`1586779546`), while the second part (`0`) acts as a criticality flag. + +Next, we find the configuration proposal itself, which is expressed by the triple `[8 C{FDCD...} -1]`. In this notation, `8` represents the index of the configuration parameter to be modified, `C{FDCD...}` denotes the cell containing the new value (its hash is represented by the value that follows), and `-1` indicates the optional hash of the old value for this parameter (where `-1` means the old hash is not specified). + +Following that, we encounter a large number, `1124...2998`, which identifies the current validator set. An empty list `()` is included to signify the set of all currently active validators who have voted for this proposal so far. Next is `weight_remaining`, equal to `8646...209`. This value is positive if the proposal has not yet garnered enough validator votes in this round, and negative otherwise. + +Lastly, we see three numbers: `3 0 0`. These represent `rounds_remaining` (the proposal can survive at most three rounds, meaning changes to the current validator set), `wins` (the count of rounds in which the proposal received votes exceeding 3/4 of all validators by weight), and `losses` (the count of rounds where the proposal failed to secure 3/4 of all validator votes). + +To inspect the proposed value for configuration parameter `#8`, you can ask the lite client to expand cell `C{FDCD...}` using its hash `FDCD...` or a sufficiently long prefix of this hash to uniquely identify the specific cell in question: + ``` > dumpcell FDC C{FDCD887EAF7ACB51DA592348E322BBC0BD3F40F9A801CB6792EFF655A7F43BBC} = x{C400000001000000000000000E} ``` -We see that the value is `x{C400000001000000000000000E}`, which is indeed the value we have embedded into our configuration proposal. We can even ask the lite client to display this Cell as a value of TL-B type (`ConfigParam 8`). + +We observe that the value is `x{C400000001000000000000000E}`, which is the value we have incorporated into our configuration proposal. Additionally, we can ask the lite client to present this Cell as a TL-B type value (`ConfigParam 8`). + ``` > dumpcellas ConfigParam8 FDC dumping cells as values of TLB type (ConfigParam 8) @@ -248,66 +282,86 @@ C{FDCD887EAF7ACB51DA592348E322BBC0BD3F40F9A801CB6792EFF655A7F43BBC} = ( (capabilities version:1 capabilities:14)) ``` -This is especially useful when we consider configuration proposals created by other people. -Note that the configuration proposal is henceforth identified by its 256-bit hash -- the huge decimal number `6465...6321`. We can inspect the current status of a specific configuration proposal by running the get-method `get_proposal` with the only argument equal to the identifier of the configuration proposal: +This is particularly useful when we evaluate configuration proposals created by others. + +Each configuration proposal is identified by its unique 256-bit hash, represented by the large decimal number `6465...6321`. To check the current status of a specific configuration proposal, you can use the `get_proposal` method, providing the identifier of the configuration proposal as the only argument: + ``` > runmethod -1:5555555555555555555555555555555555555555555555555555555555555555 get_proposal 64654898543692093106630260209820256598623953458404398631153796624848083036321 ... arguments: [ 64654898543692093106630260209820256598623953458404398631153796624848083036321 94347 ] result: [ [1586779536 0 [8 C{FDCD887EAF7ACB51DA592348E322BBC0BD3F40F9A801CB6792EFF655A7F43BBC} -1] 112474791597373109254579258586921297140142226044620228506108869216416853782998 () 864691128455135209 3 0 0] ] ``` -We obtain essentially the same result as before, but for only one configuration proposal and without the identifier of the configuration proposal at the beginning. -## 4. Voting for configuration proposals +We achieve essentially the same outcome as before, but for only one configuration proposal and without the identifier at the beginning. -Once a configuration proposal is created, it is supposed to collect votes from more than 3/4 of all current validators (by weight, i.e., by stake) in the current round and maybe in several subsequent rounds (elected validator sets). In this way, the decision to change a configuration parameter must be approved by a significant majority not only of the current set of validators but also of several subsequent sets of validators. +## Voting for configuration proposals -Voting for a configuration proposal is possible only for current validators, listed (with their permanent public keys) in configuration parameter `#34`. The process is approximately as follows: +Once a configuration proposal is created, it must collect votes from more than 75% of all current validators (based on their stake) during the current round and possibly in several subsequent rounds (with elected validator sets). This ensures that the decision to change a configuration parameter is approved by a significant majority, not only of the current set of validators but also of several future sets. -- The operator of a validator looks up `val-idx`, the (0-based) index of his validator in the current set of validators as stored in configuration parameter `#34`. -- The operator invokes a special Fift script `config-proposal-vote-req.fif` found in directory `crypto/smartcont` of the source tree, indicating `val-idx` and `config-proposal-id` as its arguments: -``` +Voting for a configuration proposal is limited to the current validators listed (with their permanent public keys) in configuration parameter `#34`. The process is outlined below: + +- The operator of a validator first looks up `val-idx`, the zero-based index of their validator in the current set of validators stored in configuration parameter `#34`. + +- The operator then invokes a special Fift script, `config-proposal-vote-req.fif`, found in the `crypto/smartcont` directory of the source tree. They must indicate both `val-idx` and `config-proposal-id` as arguments: + + ``` $ fift -s config-proposal-vote-req.fif -i 0 64654898543692093106630260209820256598623953458404398631153796624848083036321 Creating a request to vote for configuration proposal 0x8ef1603180dad5b599fa854806991a7aa9f280dbdb81d67ce1bedff9d66128a1 on behalf of validator with index 0 566F744500008EF1603180DAD5B599FA854806991A7AA9F280DBDB81D67CE1BEDFF9D66128A1 Vm90RQAAjvFgMYDa1bWZ-oVIBpkaeqnygNvbgdZ84b7f-dZhKKE= Saved to file validator-to-sign.req -``` -- After that, the vote request has to be signed by the current validator's private key, using `sign 566F744...28A1` in `validator-engine-console` connected to the validator. This process is similar to that described in [Validator-HOWTO](/v3/guidelines/nodes/running-nodes/validator-node) for participating in validator elections, but this time the currently active key has to be used. -- Next, another script `config-proposal-signed.fif` has to be invoked. It has similar arguments to `config-proposal-req.fif`, but it expects two extra arguments: the base64 representation of the public key used to sign the vote request, and the base64 representation of the signature itself. Again, this is quite similar to the process described in [Validator-HOWTO](/v3/guidelines/nodes/running-nodes/validator-node). -- In this way, the file `vote-msg-body.boc` containing the body of an internal message carrying a signed vote for this configuration proposal is created. -- After that, `vote-msg-body.boc` has to be carried in an internal message from any smart contract residing in the masterchain (typically, the controlling smart contract of the validator will be used) along with a small amount of Toncoin for processing (typically, 1.5 Toncoin should suffice). This is again completely similar to the procedure employed during validator elections. This is typically achieved by means of running: -``` -$ fift -s wallet.fif my_wallet_id -1:5555555555555555555555555555555555555555555555555555555555555555 1 1.5 -B vote-msg-body.boc -``` -(if a simple wallet is used to control the validator) and then sending the resulting file `wallet-query.boc` from the lite client: + ``` -``` -> sendfile wallet-query.boc -``` +- The vote request must then be signed using the current validator’s private key, with the command `sign 566F744...28A1` in the `validator-engine-console` connected to the validator. This process is similar to the steps described in the [Validator-HOWTO](/v3/guidelines/nodes/running-nodes/validator-node) for participating in validator elections; however, the currently active key must be used. -You can monitor answer messages from the configuration smart contract to the controlling smart contract to learn the status of your voting queries. Alternatively, you can inspect the status of the configuration proposal by means of get-method `show_proposal` of the configuration smart contract: -``` -> runmethod -1:5555555555555555555555555555555555555555555555555555555555555555 get_proposal 64654898543692093106630260209820256598623953458404398631153796624848083036321 -... -arguments: [ 64654898543692093106630260209820256598623953458404398631153796624848083036321 94347 ] -result: [ [1586779536 0 [8 C{FDCD887EAF7ACB51DA592348E322BBC0BD3F40F9A801CB6792EFF655A7F43BBC} -1] 112474791597373109254579258586921297140142226044620228506108869216416853782998 (0) 864691128455135209 3 0 0] ] -``` -This time, the list of indices of validators that voted for this configuration proposal should be non-empty, and it should contain the index of your validator. In this example, this list is (`0`), meaning that only the validator with index `0` in configuration parameter `#34` has voted. If the list becomes large enough, the last-but-one integer (the first zero in `3 0 0`) in the proposal status will increase by one, indicating a new win by this proposal. If the number of wins becomes greater than or equal to the value indicated in configuration parameter `#11`, then the configuration proposal is automatically accepted and the proposed changes become effective immediately. On the other hand, when the validator set changes, then the list of validators that have already voted becomes empty, the value of `rounds_remaining` (three in `3 0 0`) is decreased by one, and if it becomes negative, the configuration proposal is destroyed. If it is not destroyed, and if it did not win in this round, then the number of losses (the second zero in `3 0 0`) is increased. If it becomes larger than a value specified in configuration parameter `#11`, then the configuration proposal is discarded. As a result, all validators who did not vote in a round implicitly voted against. +- Next, the `config-proposal-signed.fif` script is invoked. This script has similar arguments to `config-proposal-req.fif`, but it also requires two additional arguments: the base64 representation of the public key used to sign the vote request and the base64 representation of the signature. The process is again akin to what is described in the [Validator-HOWTO](/v3/guidelines/nodes/running-nodes/validator-node). -## 5. An automated way for voting on configuration proposals +- This process generates a file named `vote-msg-body.boc`, which contains the body of an internal message carrying a signed vote for this configuration proposal. + +- After that, `vote-msg-body.boc` must be sent in an internal message from any smart contract residing in the masterchain (typically from the controlling smart contract of the validator) along with a small amount of Toncoin for processing (usually, 1.5 Toncoin is sufficient). This step follows the same procedure used during validator elections. The command is typically structured as follows: + + ``` + $ fift -s wallet.fif my_wallet_id -1:5555555555555555555555555555555555555555555555555555555555555555 1 1.5 -B vote-msg-body.boc + ``` + + (if a simple wallet controls the validator), followed by sending the resulting file `wallet-query.boc` from the lite client: + + ``` + > sendfile wallet-query.boc + ``` + +- You can monitor the response messages from the configuration smart contract to the controlling smart contract to check the status of your voting queries. Alternatively, you can inspect the status of the configuration proposal by using the `get-method` `show_proposal` of the configuration smart contract: + + ``` + > runmethod -1:5555555555555555555555555555555555555555555555555555555555555555 get_proposal 64654898543692093106630260209820256598623953458404398631153796624848083036321 + ... + arguments: [ 64654898543692093106630260209820256598623953458404398631153796624848083036321 94347 ] + result: [ [1586779536 0 [8 C{FDCD887EAF7ACB51DA592348E322BBC0BD3F40F9A801CB6792EFF655A7F43BBC} -1] 112474791597373109254579258586921297140142226044620228506108869216416853782998 (0) 864691128455135209 3 0 0] ] + ``` + In this output, the list of indices for validators that voted for this configuration proposal should not be empty and must include the index of your validator. For example, if the list contains (`0`), it indicates that only the validator with index `0` in configuration parameter `#34` has voted. If this list grows, the second-to-last integer (the first zero in `3 0 0`) in the proposal status will increase, reflecting another win for this proposal. If the number of wins reaches or exceeds the value indicated in configuration parameter `#11`, the configuration proposal is automatically accepted, and the proposed changes take effect immediately. + + Conversely, when the validator set changes, the list of validators that have already voted will become empty, the `rounds_remaining` value (currently three in `3 0 0`) will decrease by one, and if it becomes negative, the configuration proposal will be destroyed. If the proposal is not destroyed and has not won in the current round, the number of losses (the second zero in `3 0 0`) will increase. If this number exceeds the value specified in configuration parameter `#11`, the configuration proposal will be rejected. + +## An automated way of voting on configuration proposals + +The automation provided by the command `createelectionbid` in `validator-engine-console` facilitates participation in validator elections. Similarly, both `validator-engine` and `validator-engine-console` automate most of the steps mentioned in the previous section, allowing you to generate a `vote-msg-body.boc` that can be used with the controlling wallet. + +To use this method, you need to install the Fift scripts `config-proposal-vote-req.fif` and `config-proposal-vote-signed.fif` in the same directory that the validator-engine uses to locate `validator-elect-req.fif` and `validator-elect-signed.fif`, as described in Section 5 of the [Validator-HOWTO](/v3/guidelines/nodes/running-nodes/validator-node). Once you have those files set up, you can create the `vote-msg-body.boc` by executing the following command in the validator-engine-console: -Similarly to the automation provided by command `createelectionbid` of `validator-engine-console` for participating in validator elections, `validator-engine` and `validator-engine-console` offer an automated way of performing most of the steps explained in the previous section, producing a `vote-msg-body.boc` ready to be used with the controlling wallet. In order to use this method, you must install the Fift scripts `config-proposal-vote-req.fif` and `config-proposal-vote-signed.fif` into the same directory that the validator-engine uses to look up `validator-elect-req.fif` and `validator-elect-signed.fif` as explained in Section 5 of [Validator-HOWTO](/v3/guidelines/nodes/running-nodes/validator-node). After that, you simply run ``` createproposalvote 64654898543692093106630260209820256598623953458404398631153796624848083036321 vote-msg-body.boc ``` -in validator-engine-console to create `vote-msg-body.boc` with the body of the internal message to be sent to the configuration smart contract. -## 6. Upgrading the code of configuration smart contract and the elector smart contract +This command will generate the `vote-msg-body.boc`, which contains the body of the internal message to be sent to the configuration smart contract. + +## Upgrading the code of the configuration smart contract and the elector smart contract + +It may be necessary to upgrade the code of either the configuration smart contract or the elector smart contract. To do this, we will use the same mechanism described previously. The new code must be stored in a reference of a value cell, and this value cell should be proposed as the new value for the configuration parameter `-1000` (for upgrading the configuration smart contract) or `-1001` (for upgrading the elector smart contract). These parameters are considered critical, so a significant number of validator votes will be required to make changes to the configuration smart contract, similar to adopting a new constitution. We anticipate that such changes will first be tested in a test network and discussed in public forums before each validator operator makes their decision to vote for or against the proposed changes. -It may happen that the code of the configuration smart contract itself or the code of the elector smart contract has to be upgraded. To this end, the same mechanism as described above is used. The new code is to be stored in the only reference of a value cell, and this value cell has to be proposed as the new value of configuration parameter `-1000` (for upgrading the configuration smart contract) or `-1001` (for upgrading the elector smart contract). These parameters pretend to be critical, so a lot of validator votes are needed to change the configuration smart contract (this is akin to adopting a new constitution). We expect that such changes will involve first testing them in a test network, and discussing the proposed changes in public forums before each validator operator decides to vote for or against the proposed changes. +Alternatively, critical configuration parameters `0` (which indicates the address of the configuration smart contract) or `1` (which indicates the address of the elector smart contract) can be changed to other values, provided that these values match existing and correctly initialized smart contracts. Specifically, the new configuration smart contract must contain a valid configuration dictionary in the first reference of its persistent data. Since transferring changing data—such as the list of active configuration proposals or the previous and current participant lists of validator elections—between different smart contracts can be complicated, it is generally more beneficial to upgrade the code of an existing smart contract rather than change the address of the configuration smart contract. -Alternatively, critical configuration parameters `0` (the address of the configuration smart contract) or `1` (the address of the elector smart contract) can be changed to other values, that must correspond to already existing and correctly initialized smart contracts. In particular, the new configuration smart contract must contain a valid configuration dictionary in the first reference of its persistent data. Since it is not so easy to correctly transfer changing data (such as the list of active configuration proposals, or the previous and current participant lists of validator elections) between different smart contracts, in most cases it is better to upgrade the code of an existing smart contract rather than to change the configuration smart contract address. +There are two auxiliary scripts designed to create configuration proposals for upgrading the code of the configuration or elector smart contract. The script `create-config-upgrade-proposal.fif` loads a Fift assembler source file (`auto/config-code.fif` by default), which corresponds to the code automatically generated by the FunC compiler from `crypto/smartcont/config-code.fc`, and creates the corresponding configuration proposal for the configuration parameter `-1000`. Similarly, the script `create-elector-upgrade-proposal.fif` loads a Fift assembler source file (`auto/elector-code.fif` by default) and uses it to create a configuration proposal for configuration parameter `-1001`. This makes it simple to create configuration proposals to upgrade either of these two smart contracts. -There are two auxiliary scripts used to create such configuration proposals to upgrade the code of the configuration or elector smart contract. Namely, `create-config-upgrade-proposal.fif` loads a Fift assembler source file (`auto/config-code.fif` by default, corresponding to the code automatically generated by FunC compiler from `crypto/smartcont/config-code.fc`) and creates the corresponding configuration proposal (for configuration parameter `-1000`). Similarly, `create-elector-upgrade-proposal.fif` loads a Fift assembler source file (`auto/elector-code.fif` by default) and uses it to create a configuration proposal for configuration parameter `-1001`. In this way, creating configuration proposals to upgrade one of these two smart contracts should be very simple. However, one should also publish the modified FunC source of the smart contract, the exact version of the FunC compiler used to compile it, so that all validators (or rather their operators) would be able to reproduce the code in the configuration proposal (and compare the hashes) and study and discuss the source code and the changes in this code before deciding to vote for or against the proposed changes. +However, it is also essential to publish the modified FunC source code of the smart contract and specify the exact version of the FunC compiler used for compilation. This way, all validators (or their operators) will be able to reproduce the code in the configuration proposal, compare the hashes, and examine the source code and changes before deciding how to vote on the proposed changes. \ No newline at end of file From 8123759c05b202b9556f5199fc62b6ce59844d67 Mon Sep 17 00:00:00 2001 From: D Ozgur Cakirkaya Date: Tue, 8 Apr 2025 15:12:25 +0100 Subject: [PATCH 07/14] /network/protocols/adnl overview.md update --- .../network/protocols/adnl/overview.md | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/docs/v3/documentation/network/protocols/adnl/overview.md b/docs/v3/documentation/network/protocols/adnl/overview.md index 8cea9dc3414..4424c16e698 100644 --- a/docs/v3/documentation/network/protocols/adnl/overview.md +++ b/docs/v3/documentation/network/protocols/adnl/overview.md @@ -1,39 +1,38 @@ -# ADNL Protocol +# ADNL protocol -Implementation: -* https://github.com/ton-blockchain/ton/tree/master/adnl +Please see the [**implementation**](https://github.com/ton-blockchain/ton/tree/master/adnl) first. ## Overview -The cornerstone of TON is the Abstract Datagram Network Layer (ADNL). +The Abstract Datagram Network Layer (ADNL) is a fundamental component of the TON. -This is an overlay, peer-to-peer, unreliable (small-size) datagram protocol running on top of a **UDP** in **IPv4** (in the future, IPv6), with an optional **TCP fallback** if UDP is not available. +ADNL is an overlay, peer-to-peer, unreliable (small-size) datagram protocol that operates over **UDP** in **IPv4**, with plans to support **IPv6** in the future. Additionally, it has an optional **TCP fallback** for instances when UDP is unavailable. ## ADNL address -Each participant has a 256-bit ADNL Address. +Each participant in the network possesses a 256-bit ADNL Address. -The ADNL Protocol allows you to send (unreliable) and receive datagrams using only ADNL Addresses. IP Addresses and Ports are hidden by the ADNL Protocol. +The ADNL Protocol enables the sending and receiving of datagrams using only ADNL Addresses, concealing the underlying IP Addresses and Ports. -An ADNL Address is essentially equal to a 256-bit ECC public key. This public key can be arbitrarily generated, thus creating as many different network identities as the node needs. -However, one must know the corresponding private key in order to receive (and decrypt) messages intended for the recipient address. +An ADNL Address effectively functions as a 256-bit ECC public key, which can be generated arbitrarily, allowing for the creation of multiple network identities as needed by the node. -In reality, the ADNL Address is not the public key itself; instead, it is a 256-bit SHA256 hash of a serialized TL-object that can describe several types of public keys and addresses depending on its constructor. +However, the corresponding private key must be known to receive and decrypt messages intended for a specific address. -## Encryption & security +In practice, the ADNL Address is not the public key itself; rather, it is a 256-bit SHA256 hash of a serialized TL object. Depending on its constructor, this TL object can represent various types of public keys and addresses. -Normally each datagram sent is signed by the sender and encrypted so that only the recipient can decrypt the message and verify its integrity by the signature. +## Encryption and security + +Typically, each datagram sent is signed by the sender and encrypted so that only the intended recipient can decrypt the message and verify its integrity using the signature. ## Neighbor tables -Normally, a TON ADNL node will have some ā€œneighbor tableā€, which contains information about other known nodes, such as their abstract addresses, public keys, IP Addresses and UDP Ports. Over time, it will gradually -extend this table using information gathered from these known nodes. This new information can be in the form of answers to special queries or sometimes the removal of obsolete records. +A TON ADNL node will typically maintain a **neighbor table** that contains information about other known nodes, including their abstract addresses, public keys, IP addresses, and UDP ports. Over time, this table expands with information gathered from these known nodes, which may come from responses to specific queries or by removing outdated records. -ADNL allows you to set up point-to-point channels and tunnels (a chain of proxies). +ADNL facilitates the establishment of point-to-point channels and tunnels (chains of proxies). -A TCP-like stream protocol can be built over ADNL. +A TCP-like stream protocol can be constructed on top of ADNL. ## What's next? -* Read more about ADNL in the [Low-Level ADNL article](/v3/documentation/network/protocols/adnl/low-level-adnl) -* Chapter 3.1 of the [TON Whitepaper](https://docs.ton.org/ton.pdf). +* To learn more about ADNL, refer to the [Low-level ADNL documentation](/v3/documentation/network/protocols/adnl/low-level-adnl). +* See Chapter 3.1 of the [TON Whitepaper](https://docs.ton.org/ton.pdf). \ No newline at end of file From aa3c6724419f28a0c97d0a43d45fa2535947133c Mon Sep 17 00:00:00 2001 From: D Ozgur Cakirkaya Date: Tue, 8 Apr 2025 15:48:16 +0100 Subject: [PATCH 08/14] low-level-adnl.md update --- .../network/protocols/adnl/low-level-adnl.md | 97 +++++++++++-------- 1 file changed, 56 insertions(+), 41 deletions(-) diff --git a/docs/v3/documentation/network/protocols/adnl/low-level-adnl.md b/docs/v3/documentation/network/protocols/adnl/low-level-adnl.md index 892683be19b..bc084e9eb43 100644 --- a/docs/v3/documentation/network/protocols/adnl/low-level-adnl.md +++ b/docs/v3/documentation/network/protocols/adnl/low-level-adnl.md @@ -1,100 +1,115 @@ -# Low-Level ADNL +# Low-level ADNL -Abstract Datagram Network Layer (ADNL) is the core protocol of TON, which helps network peers to communicate with each other. +Abstract Datagram Network Layer (ADNL) is the core protocol of TON, which helps network peers communicate. ## Peer identity -Each peer must have at least one identity, it is possible but not necessary to use multiple. Each identity is a keypair, which is used to perform the Diffie-Hellman between peers. An abstract network address is derived from the public key in such way: `address = SHA-256(type_id || public_key)`. Note that type_id must be serialized as little-endian uint32. + +Each peer must have at least one identity; while it's possible to use multiple identities, it is not required. Each identity consists of a keypair used for performing the Diffie-Hellman exchange between peers. An abstract network address is derived from the public key in the following way: `address = SHA-256(type_id || public_key)`. Note that the `type_id` must be serialized as a little-endian uint32. ## Public-key cryptosystems list -| type_id | cryptosystem | + +| type_id | cryptosystem | |------------|---------------------| | 0x4813b4c6 | ed255191 | -_1. To perform x25519, the keypair must be generated in x25519 format. However, the public key is transmitted over the network in ed25519 format, so you have to convert the public key from x25519 to ed25519, examples of such conversions can be found [here](https://github.com/andreypfau/curve25519-kotlin/blob/f008dbc2c0ebc3ed6ca5d3251ffb7cf48edc91e2/src/commonMain/kotlin/curve25519/MontgomeryPoint.kt#L39) for Kotlin._ +* **To perform x25519, the keypair must be generated in "x25519" format. However, the public key is transmitted over the network in ed25519 format, so you have to convert the public key from x25519 to ed25519, examples of such conversions can be found [here](https://github.com/andreypfau/curve25519-kotlin/blob/f008dbc2c0ebc3ed6ca5d3251ffb7cf48edc91e2/src/commonMain/kotlin/curve25519/MontgomeryPoint.kt#L39) for Kotlin.** ## Client-server protocol (ADNL over TCP) -The client connects to the server using TCP and sends an ADNL handshake packet, which contains a server abstract address, a client public key and encrypted AES-CTR session parameters, which are determined by the client. + +The client connects to the server using TCP and sends an ADNL handshake packet. This packet contains a server abstract address, a client public key, and encrypted AES-CTR session parameters, which the client determines. ### Handshake + First, the client must perform a key agreement protocol (for example, x25519) using their private key and server public key, taking into account the server key's `type_id`. As a result, the client will gain `secret`, which is used to encrypt session keys in future steps. Then, the client has to generate AES-CTR session parameters, a 16-byte nonce and 32-byte key, both for TX (client->server) and RX (server->client) directions and serialize it into a 160-byte buffer as follows: -| Parameter | Size | +| Parameter | Size | |--------------|----------| -| rx_key | 32 bytes | -| tx_key | 32 bytes | -| rx_nonce | 16 bytes | -| tx_nonce | 16 bytes | -| padding | 64 bytes | +| rx_key | 32 bytes | +| tx_key | 32 bytes | +| rx_nonce | 16 bytes | +| tx_nonce | 16 bytes | +| padding | 64 bytes | -The purpose of padding is unknown, it is not used by server implementations. It is recommended to fill the whole 160-byte buffer with random bytes, otherwise an attacker may perform an active MitM attack using compromised AES-CTR session parameters. -The next step is to encrypt session parameters using `secret` via the key agreement protocol above. To do that, AES-256 must be initialized in CTR mode with a 128-bit big-endian counter using a (key, nonce) pair which is computed as such (`aes_params` is a 160-byte buffer which was built above): +The purpose of padding is unknown; it is not used by server implementations. It is recommended that the whole 160-byte buffer be filled with random bytes. Otherwise, an attacker may perform an active MitM attack using compromised AES-CTR session parameters. + +The next step is to encrypt the session parameters using the `secret` through the key agreement protocol outlined above. To achieve this, AES-256 needs to be initialized in CTR mode with a 128-bit big-endian counter. This will utilize a (key, nonce) pair that is computed as follows (note that `aes_params` is a 160-byte buffer that was created earlier): + ```cpp hash = SHA-256(aes_params) key = secret[0..16] || hash[16..32] nonce = hash[0..4] || secret[20..32] ``` -After the encryption of `aes_params` which is noted as `E(aes_params)`, AES should be removed because it is not needed anymore. -Now we are ready to serialize all that information to the 256-bytes handshake packet and send it to the server: +After encrypting `aes_params`, noted as `E(aes_params)`, remove AES as it is no longer needed. We are now ready to serialize all this information into the 256-byte handshake packet and send it to the server. -| Parameter | Size | Notes | +| Parameter | Size | Notes | |---------------------|-----------|------------------------------------------------------------| -| receiver_address | 32 bytes | Server peer identity as described in the corresponding section | -| sender_public | 32 bytes | Client public key | -| SHA-256(aes_params) | 32 bytes | Integrity proof of session parameters | -| E(aes_params) | 160 bytes | Encrypted session parameters | +| receiver_address | 32 bytes | Server peer identity as described in the corresponding section | +| sender_public | 32 bytes | Client public key | +| SHA-256(aes_params) | 32 bytes | Integrity proof of session parameters | +| E(aes_params) | 160 bytes | Encrypted session parameters | + +The server must decrypt session parameters using a secret derived from the key agreement protocol, just as the client does. After decryption, the server must perform the following checks to ensure the security properties of the protocol: -The server must decrypt session parameters using a secret, derived from the key agreement protocol in the same way as the client. Then the server must perform the following checks to confirm the protocol's security properties: -1. The server must have the corresponding private key for `receiver_address`, otherwise there is no way to perform the key agreement protocol. -2. `SHA-256(aes_params) == SHA-256(D(E(aes_params)))`, otherwise the key agreement protocol has failed and `secret` is not equal on both sides. +- The server must possess the corresponding private key for `receiver_address`. Without this key, it cannot execute the key agreement protocol. -If any of these checks fail, server will immediately drop the connection without responding to the client. If all checks pass, the server must issue an empty datagram (see the Datagram section) to the client in order to prove that it owns the private key for the specified `receiver_address`. +- The condition `SHA-256(aes_params) == SHA-256(D(E(aes_params)))` must hold true. If this condition is not met, it indicates that the key agreement protocol has failed and the `secret` values on both sides are not equal. +If any of these checks fail, the server will immediately drop the connection without responding to the client. If all checks pass, the server must issue an empty datagram (see the [Datagram](#datagram) section) to the client in order to prove that it owns the private key for the specified `receiver_address`. ### Datagram -Both the client and server must initialize two AES-CTR instances each, for both TX and RX directions. AES-256 must be used in CTR mode with a 128-bit big-endian counter. Each AES instance is initialized using a (key, nonce) pair belonging to it, which can be taken from `aes_params` in the handshake. +Both the client and server must initialize two AES-CTR instances each for both transmission (TX) and reception (RX) directions. The AES-256 must be used in CTR mode with a 128-bit big-endian counter. Each AES instance is initialized using a (key, nonce) pair, which can be taken from the `aes_params` during the handshake. -To send a datagram, a peer (the client or server) must build the following structure, encrypt it and send to the other peer: +To send a datagram, either the client or the server must construct the following structure, encrypt it, and send it to the other peer: -| Parameter | Size | Notes | +| Parameter | Size | Notes | |-----------|----------------------|------------------------------------------------------------| -| length | 4 bytes (LE) | Length of the whole datagram, excluding `length` field | -| nonce | 32 bytes | Random value | -| buffer | `length - 64` bytes | Actual data to be sent to the other side | -| hash | 32 bytes | `SHA-256(nonce \|\| buffer)` to ensure integrity | +| length | 4 bytes (LE) | Length of the whole datagram, excluding `length` field | +| nonce | 32 bytes | Random value | +| buffer | `length - 64` bytes | Actual data to be sent to the other side | +| hash | 32 bytes | `SHA-256(nonce \|\| buffer)` to ensure integrity | The whole structure must be encrypted using the corresponding AES instance (TX for client -> server, RX for server -> client). -The receiving peer must fetch the first 4 bytes, decrypt it into the `length` field and read exactly `length` bytes to get the full datagram. The receiving peer may start to decrypt and process `buffer` earlier, but it must take into account that it may be corrupted, intentionally or occasionally. Datagram `hash` must be checked to ensure the integrity of the `buffer`. In case of failure, no new datagrams can be issued and the connection must be dropped. +The receiving peer must fetch the first 4 bytes, decrypt it into the `length` field, and read exactly the `length` bytes to get the full datagram. The receiving peer may start to decrypt and process `buffer` earlier, but it must take into account that it may be corrupted, intentionally or occasionally. Datagram `hash` must be checked to ensure the integrity of the `buffer`. In case of failure, no new datagrams can be issued and the connection must be dropped. -The first datagram in the session always goes from the server to the client after a handshake packet was successfully accepted by the server and it's actual buffer is empty. The client should decrypt it and disconnect from the server in case of failure, because it means that the server has not followed the protocol properly and the actual session keys differs on the server and client side. +The first datagram in the session always goes from the server to the client after a handshake packet is successfully accepted by the server and its actual buffer is empty. The client should decrypt it and disconnect from the server in case of failure because it means that the server has not followed the protocol properly and the actual session keys differ on the server and client side. ### Communication details -If you want to dive into communication details, you could check article [ADNL TCP - Liteserver](/v3/documentation/network/protocols/adnl/adnl-tcp) to see some examples. +If you want to dive into communication details, you could check the article [ADNL TCP - liteserver](/v3/documentation/network/protocols/adnl/adnl-tcp) to see some examples. ### Security considerations + #### Handshake padding -It is unknown why the initial TON team decided to include this field into the handshake. `aes_params` integrity is protected by a SHA-256 hash and confidentiality is protected by the key derived from the `secret` parameter. Probably, it was intended to migrate from AES-CTR at some point. To do this, specification may be extended to include a special magic value in `aes_params`, which will signal that the peer is ready to use the updated primitives. The response to such a handshake may be decrypted twice, with new and old schemes, to clarify which scheme the other peer is actually using. + +It is unknown why the initial TON team decided to include this field in the handshake. `aes_params` integrity is protected by a SHA-256 hash, and confidentiality is protected by the key derived from the `secret` parameter. Probably, it was intended to migrate from AES-CTR at some point. To do this, the specification may be extended to include a special magic value in `aes_params`, which will signal that the peer is ready to use the updated primitives. The response to such a handshake may be decrypted twice, with new and old schemes, to clarify which scheme the other peer is actually using. #### Session parameters encryption key derivation process If an encryption key is derived only from the `secret` parameter, it will be static because the secret is static. To derive a new encryption key for each session, developers also use `SHA-256(aes_params)`, which is random if `aes_params` is random. However, the actual key derivation algorithm with the concatenation of different subarrays is considered harmful. #### Datagram nonce -It is not obvious why the `nonce` field in the datagram is present because, even without it, any two ciphertexts will differ because of the session-bounded keys for AES and encryption in CTR mode. However, the following attack can be performed in the case of an absent or predictable nonce. CTR encryption mode turns block ciphers, such as AES, into stream ciphers to make it possible to perform a bit-flipping attack. If the attacker knows the plaintext which belongs to encrypted datagram, they can obtain a pure keystream, XOR it with their own plaintext and efficiently replace the message which was sent by peer. The buffer integrity is protected by a SHA-256 hash, but an attacker can replace it too because having knowledge of a full plaintext means having knowledge of its hash. The nonce field is present to prevent such an attack, so no attacker can replace the SHA-256 without having knowledge of the nonce. + +The purpose of the `nonce` field in the datagram may not be immediately clear. Even without it, any two ciphertexts will differ due to the session-bounded keys used in AES and the encryption method in CTR mode. However, if a nonce is absent or predictable, a potential attack can occur. + +In CTR encryption mode, block ciphers like AES function as stream ciphers, allowing for bit-flipping attacks. If an attacker knows the plaintext corresponding to an encrypted datagram, they can create an exact key stream and XOR it with their own plaintext, effectively replacing the original message sent by a peer. Although buffer integrity is protected by a hash (referred to here as SHA-256), an attacker can still manipulate it because if they know the entire plaintext, they can also compute its hash. + +The nonce field is crucial for preventing such attacks, as it ensures that an attacker cannot replace the SHA-256 without also having access to the nonce. ## P2P protocol (ADNL over UDP) -Detailed description can be found in article [ADNL UDP - Internode](/v3/documentation/network/protocols/adnl/adnl-udp). +A detailed description can be found in the article [ADNL UDP - internode](/v3/documentation/network/protocols/adnl/adnl-udp). ## References -- [The Open Network, p. 80](https://ton.org/ton.pdf) + +- [The Open Network, p. 80](https://ton.org/whitepaper.pdf#80) + - [ADNL implementation in TON](https://github.com/ton-blockchain/ton/tree/master/adnl) -_Thanks to the [hacker-volodya](https://github.com/hacker-volodya) for contributing to the community!_ -_Here a [link to the original article](https://github.com/tonstack/ton-docs/tree/main/ADNL) on GitHub._ +_Thanks to the [hacker-volodya](https://github.com/hacker-volodya) for contributing to the community!_ +_Here a [link to the original article](https://github.com/tonstack/ton-docs/tree/main/ADNL) on GitHub._ \ No newline at end of file From 81b02359ba31a09699dc924c7d7da483ff391fea Mon Sep 17 00:00:00 2001 From: D Ozgur Cakirkaya Date: Tue, 8 Apr 2025 18:26:11 +0100 Subject: [PATCH 09/14] adnl-tcp.md update --- .../network/protocols/adnl/adnl-tcp.md | 234 +++++++++++------- 1 file changed, 144 insertions(+), 90 deletions(-) diff --git a/docs/v3/documentation/network/protocols/adnl/adnl-tcp.md b/docs/v3/documentation/network/protocols/adnl/adnl-tcp.md index f3aa60da3a2..aacf8d8cf88 100644 --- a/docs/v3/documentation/network/protocols/adnl/adnl-tcp.md +++ b/docs/v3/documentation/network/protocols/adnl/adnl-tcp.md @@ -1,89 +1,99 @@ -# ADNL TCP - Liteserver +# ADNL TCP - liteserver -This is the low level protocol on which all interaction in the TON network is built, it can work on top of any protocol, but is most often used on top of TCP and UDP. UDP is used for communication between nodes, and TCP is used for communication with lite servers. +This is the low-level protocol that supports all interactions within the TON network. While it can operate on top of any protocol, it is most commonly used in conjunction with TCP and UDP. Typically, UDP facilitates communication between nodes, whereas TCP is employed for communication with liteservers. -Now we will analyze ADNL running over TCP and learn how to interact with lite servers directly. +In this section, we will analyze how ADNL operates over TCP and learn how to interact directly with liteservers. -In the TCP version of ADNL, network nodes use public keys ed25519 as addresses and establish a connection using a shared key obtained using the Elliptic Curve Diffie-Hellman procedure - ECDH. +In the TCP version of ADNL, network nodes utilize public keys (ed25519) as their addresses. Connections are established using a shared key obtained through the Elliptic Curve Diffie-Hellman (ECDH) procedure. + +## Packet structure -## Packet Structure Each ADNL TCP packet, except for the handshake, has the following structure: -* 4 bytes of packet size in little endian (N) + +* 4 bytes of packet size in little-endian (N) * 32 bytes nonce (random bytes to protect against checksum attacks) * (N - 64) payload bytes * 32 bytes SHA256 checksum from nonce and payload -The entire packet, including the size, is **AES-CTR** encrypted. -After decryption, it is necessary to check whether the checksum matches the data, to check, you just need to calculate the checksum yourself and compare the result with what we have in the packet. +The entire packet, including its size, is encrypted using **AES-CTR**. -The handshake packet is an exception, it is transmitted in a partially unencrypted form and is described in the next chapter. +After decrypting the packet, you must verify that the checksum matches the data. To do this, simply calculate the checksum yourself and compare it to the checksum provided in the packet. + +The handshake packet is an exception; it is transmitted partially unencrypted and is detailed in the next chapter. ## Establishing a connection -To establish a connection, we need to know the ip, port and public key of the server, and generate our own private and public key ed25519. -Public server data such as ip, port and key can be obtained from the [global config](https://ton-blockchain.github.io/global.config.json). IP in the config in numerical form, it can be brought to normal form using, for example [this tool](https://www.browserling.com/tools/dec-to-ip). The public key in the config in base64 format. +To establish a connection, we need to know the server's IP, port, and public key and generate our own private and public key, ed25519. + +Public server data such as IP, port, and key can be obtained from the [global config](https://ton-blockchain.github.io/global.config.json). The IP in the config, which is numerical, can be converted to normal form using,(for example) [this tool](https://www.browserling.com/tools/dec-to-ip). The public key in the config is in base64 format. The client generates 160 random bytes, some of which will be used by the parties as the basis for AES encryption. -Of these, 2 permanent AES-CTR ciphers are created, which will be used by the parties to encrypt/decrypt messages after the handshake. +Two permanent AES-CTR ciphers are created, which the parties will use to encrypt/decrypt messages after the handshake. + * Cipher A - key 0 - 31 bytes, iv 64 - 79 bytes * Cipher B - key 32 - 63 bytes, iv 80 - 95 bytes -The ciphers are applied in this order: +The ciphers are utilized in the following order: + * Cipher A is used by the server to encrypt the messages it sends. -* Cipher A is used by the client to decrypt received messages. +* Cipher A is used by the client to decrypt messages it receives. * Cipher B is used by the client to encrypt the messages it sends. -* Cipher B is used by the server to decrypt received messages. - +* Cipher B is used by the server to decrypt messages it receives. + To establish a connection, the client must send a handshake packet containing: -* [32 bytes] **Server key ID** [[Details]](#getting-key-id) + +* [32 bytes] **Server key ID** [[see details here]](#getting-key-id) * [32 bytes] **Our public key is ed25519** * [32 bytes] **SHA256 hash from our 160 bytes** -* [160 bytes] **Our 160 bytes encrypted** [[Details]](#handshake-packet-data-encryption) +* [160 bytes] **Our 160 bytes encrypted** [[see details here]](#handshake-packet-data-encryption) -When receiving a handshake packet, the server will do the same actions, receive an ECDH key, decrypt 160 bytes and create 2 permanent keys. If everything works out, the server will respond with an empty ADNL packet, without payload, to decrypt which (as well as subsequent ones) we need to use one of the permanent ciphers. +When receiving a handshake packet, the server will do the same actions: receive an ECDH key, decrypt 160 bytes, and create 2 permanent keys. If everything works out, the server will respond with an empty ADNL packet, without payload, to decrypt which (as well as subsequent ones) we need to use one of the permanent ciphers. From this point on, the connection can be considered established. -After we have established a connection, we can start receiving information; the TL language is used to serialize data. +After we have established a connection, we can start receiving information; the TL language serializes data. + +[Learn more about TL here](/v3/documentation/data-formats/tl). -[More about TL](/v3/documentation/data-formats/tl) +## Ping and pong -## Ping&Pong It is optimal to send a ping packet once every 5 seconds. This is necessary to maintain the connection while no data is being transmitted, otherwise the server may terminate the connection. -The ping packet, like all the others, is built according to the standard schema described [above](#packet-structure), and carries the request ID and ping ID as payload data. +Like all the others, the ping packet is built according to the standard schema described [above](#packet-structure) and carries the request ID and ping ID as payload data. -Let's find the desired schema for the ping request [here](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/ton_api.tl#L35) and calculate the schema id as -`crc32_IEEE("tcp.ping random_id:long = tcp.Pong")`. When converted to little endian bytes, we get **9a2b084d**. +Let's find the desired schema for the ping request [here](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/ton_api.tl#L35) and calculate the schema id as `crc32_IEEE("tcp.ping random_id:long = tcp.Pong")`. When converted to little endian bytes, we get **9a2b084d**. -Thus, our ADNL ping packet will look like this: -* 4 bytes of packet size in little endian -> 64 + (4+8) = **76** +Therefore, our ADNL ping packet will look like this: + +* 4 bytes of packet size in little-endian -> 64 + (4+8) = **76** * 32 bytes nonce -> random 32 bytes * 4 bytes of ID TL schema -> **9a2b084d** -* 8 bytes of request id -> random uint64 number +* 8 bytes of request-id -> random uint64 number * 32 bytes of SHA256 checksum from nonce and payload We send our packet and wait for [tcp.pong](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/ton_api.tl#L23), `random_id` will be equal to the one we sent in ping packet. -## Receiving information from a Liteserver -All requests that are aimed at obtaining information from the blockchain are wrapped in [Liteserver Query](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/lite_api.tl#L83) schema, which in turn is wrapped in [ADNL Query](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/lite_api.tl#L22) schema. +## Receiving information from a liteserver -LiteQuery: -`liteServer.query data:bytes = Object`, id **df068c79** +All requests that are aimed at obtaining information from the blockchain are wrapped in [Liteserver query](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/lite_api.tl#L83) schema, which in turn is wrapped in [ADNL query](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/lite_api.tl#L22) schema. -ADNLQuery: -`adnl.message.query query_id:int256 query:bytes = adnl.Message`, id **7af98bb4** +* LiteQuery: + `liteServer.query data:bytes = Object`, id **df068c79** +* ADNLQuery: + `adnl.message.query query_id:int256 query:bytes = adnl.Message`, id **7af98bb4** -LiteQuery is passed inside ADNLQuery, as `query:bytes`, and the final query is passed inside LiteQuery, as `data:bytes`. +LiteQuery is passed inside ADNLQuery as `query:bytes`, and the final query is passed inside LiteQuery as `data:bytes`. -[Parsing encoding bytes in TL](/v3/documentation/data-formats/tl) +[Learn more about parsing encoding bytes in TL here](/v3/documentation/data-formats/tl). ### getMasterchainInfo -Now, since we already know how to generate TL packets for the Lite API, we can request information about the current TON masterchain block. -The masterchain block is used in many further requests as an input parameter to indicate the state (moment) in which we need information. -We are looking for the [TL schema we need](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/lite_api.tl#L60), calculate its ID and build the packet: +Since we already know how to generate TL packets for the lite API, we can request information about the current TON MasterChain block. + +The MasterChain block is used in many further requests as an input parameter to indicate the state (moment) in which we need information. + +We are looking for the [TL schema we require](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/lite_api.tl#L60), calculate its ID and build the packet: * 4 bytes of packet size in little endian -> 64 + (4+32+(1+4+(1+4+3)+3)) = **116** * 32 bytes nonce -> random 32 bytes @@ -98,6 +108,7 @@ We are looking for the [TL schema we need](https://github.com/ton-blockchain/ton * 32 bytes of checksum SHA256 from nonce and payload Packet example in hex: + ``` 74000000 -> packet size (116) 5fb13e11977cb5cff0fbf7f23f674d734cb7c4bf01322c5e6b928c5d8ea09cfd -> nonce @@ -117,6 +128,7 @@ In response, we expect to receive [liteServer.masterchainInfo](https://github.co The received packet is deserialized in the same way as the sent one - has same algorithm, but in the opposite direction, except that the response is wrapped only in [ADNLAnswer](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/lite_api.tl#L23). After decoding the response, we get a packet of the form: + ``` 20010000 -> packet size (288) 5558b3227092e39782bd4ff9ef74bee875ab2b0661cf17efdfcd4da4e53e78e6 -> nonce @@ -140,36 +152,42 @@ After decoding the response, we get a packet of the form: ``` ### runSmcMethod -We already know how to get the masterchain block, so now we can call any lite server methods. + +We already know how to get the MasterChain block, so now we can call any liteserver methods. + Let's analyze **runSmcMethod** - this is a method that calls a function from a smart contract and returns a result. Here we need to understand some new data types such as [TL-B](/v3/documentation/data-formats/tlb/tl-b-language), [Cell](/v3/documentation/data-formats/tlb/cell-boc#cell) and [BoC](/v3/documentation/data-formats/tlb/cell-boc#bag-of-cells). To execute the smart contract method, we need to build and send a request using the TL schema: + ```tlb liteServer.runSmcMethod mode:# id:tonNode.blockIdExt account:liteServer.accountId method_id:long params:bytes = liteServer.RunMethodResult ``` And wait for a response with schema: + ```tlb liteServer.runMethodResult mode:# id:tonNode.blockIdExt shardblk:tonNode.blockIdExt shard_proof:mode.0?bytes proof:mode.0?bytes state_proof:mode.1?bytes init_c7:mode.3?bytes lib_extras:mode.4?bytes exit_code:int result:mode.2?bytes = liteServer.RunMethodResult; ``` In the request, we see the following fields: -1. mode:# - uint32 bitmask of what we want to see in the response, for example, `result:mode.2?bytes` will only be present in the response if the bit with index 2 is set to one. -2. id:tonNode.blockIdExt - is our master block state that we got in the previous chapter. -3. account:[liteServer.accountId](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/lite_api.tl#L27) - workchain and smart contract address data. -4. method_id:long - 8 bytes, in which crc16 with the XMODEM table is written on behalf of the called method + bit 17 is set [[Calculation]](https://github.com/xssnick/tonutils-go/blob/88f83bc3554ca78453dd1a42e9e9ea82554e3dd2/ton/runmethod.go#L16) -5. params:bytes - [Stack](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/crypto/block/block.tlb#L783) serialized in [BoC](/v3/documentation/data-formats/tlb/cell-boc#bag-of-cells), containing arguments to call the method. [[Implementation example]](https://github.com/xssnick/tonutils-go/blob/88f83bc3554ca78453dd1a42e9e9ea82554e3dd2/tlb/stack.go) + +* mode:# - uint32 bitmask of what we want to see in the response, for example, `result:mode.2?bytes` will only be present in the response if the bit with index 2 is set to one. +* id:tonNode.blockIdExt - our master block state that we got in the previous chapter. +* account:[liteServer.accountId](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/lite_api.tl#L27) - workchain and smart contract address data. +* method_id:long - 8 bytes, in which crc16 with the XMODEM table is written on behalf of the called method + bit 17 is set [[Calculation]](https://github.com/xssnick/tonutils-go/blob/88f83bc3554ca78453dd1a42e9e9ea82554e3dd2/ton/runmethod.go#L16) +* params:bytes - [Stack](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/crypto/block/block.tlb#L783) serialized in [BoC](/v3/documentation/data-formats/tlb/cell-boc#bag-of-cells), containing arguments to call the method. [[Implementation example]](https://github.com/xssnick/tonutils-go/blob/88f83bc3554ca78453dd1a42e9e9ea82554e3dd2/tlb/stack.go) For example, we only need `result:mode.2?bytes`, then our mode will be equal to 0b100, that is 4. In response, we will get: -1. mode:# -> what was sent - 4. -2. id:tonNode.blockIdExt -> our master block against which the method was executed -3. shardblk:tonNode.blockIdExt -> shard block where the contract account is located -4. exit_code:int -> 4 bytes which is the exit code when executing the method. If everything is successful, then = 0, if not, it is equal to the exception code. -5. result:mode.2?bytes -> [Stack](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/crypto/block/block.tlb#L783) serialized in [BoC](/v3/documentation/data-formats/tlb/cell-boc#bag-of-cells), containing the values returned by the method. +* mode:# -> what was sent - 4. +* id:tonNode.blockIdExt -> our master block against which the method was executed +* shardblk:tonNode.blockIdExt -> shard block where the contract account is located +* exit_code:int -> 4 bytes which is the exit code when executing the method. If everything is successful, then = 0, if not, it is equal to the exception code. +* result:mode.2?bytes -> [Stack](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/crypto/block/block.tlb#L783) serialized in [BoC](/v3/documentation/data-formats/tlb/cell-boc#bag-of-cells), containing the values returned by the method. Let's analyze the call and getting the result from the `a2` method of the contract `EQBL2_3lMiyywU17g-or8N7v9hDmPCpttzBPE2isF2GTzpK4`: Method code in FunC: + ```func (cell, cell) a2() method_id { cell a = begin_cell().store_uint(0xAABBCC8, 32).end_cell(); @@ -179,6 +197,7 @@ Method code in FunC: ``` Fill out our request: + * `mode` = 4, we only need the result -> `04000000` * `id` = result of execution getMasterchainInfo * `account` = workchain 0 (4 bytes `00000000`), and int256 [obtained from our contract address](/v3/documentation/data-formats/tlb/tl-b-types#addresses), i.e. 32 bytes `4bdbfde5322cb2c14d7b83ea2bf0deeff610e63c2a6db7304f1368ac176193ce` @@ -186,6 +205,7 @@ Fill out our request: * `params:bytes` = Our method does not accept input parameters, so we need to pass it an empty stack (`000000`, cell 3 bytes - stack depth 0) serialized in [BoC](/v3/documentation/data-formats/tlb/cell-boc#bag-of-cells) -> `b5ee9c72010101010005000006000000` -> serialize in bytes and get `10b5ee9c72410101010005000006000000000000` 0x10 - size, 3 bytes in the end - padding. In response, we get: + * `mode:#` -> not interesting * `id:tonNode.blockIdExt` -> not interesting * `shardblk:tonNode.blockIdExt` -> not interesting @@ -193,6 +213,7 @@ In response, we get: * `result:mode.2?bytes` -> [Stack](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/crypto/block/block.tlb#L783) containing the data returned by the method in [BoC](/v3/documentation/data-formats/tlb/cell-boc#bag-of-cells) format, we will unpack it. Inside `result` we received `b5ee9c7201010501001b000208000002030102020203030400080ccffcc1000000080aabbcc8`, this is [BoC](/v3/documentation/data-formats/tlb/cell-boc#bag-of-cells) containing the data. When we deserialize it, we will get a cell: + ```json 32[00000203] -> { 8[03] -> { @@ -202,54 +223,63 @@ Inside `result` we received `b5ee9c7201010501001b0002080000020301020202030304000 32[0CCFFCC1] } ``` -If we parse it, we will get 2 values of the cell type, which our FunC method returns. -The first 3 bytes of the root cell `000002` - is the depth of the stack, that is 2. This means that the method returned 2 values. -We continue parsing, the next 8 bits (1 byte) is the value type at the current stack level. For some types, it may take 2 bytes. Possible options can be seen in [schema](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/crypto/block/block.tlb#L766). -In our case, we have `03`, which means: +If we parse it, we will get 2 values of the cell type, which our FunC method returns. The first 3 bytes of the root cell `000002` - is the depth of the stack, that is 2. This means that the method returned 2 values. + +We continue parsing, the next 8 bits (1 byte) is the value type at the current stack level. For some types, it may take 2 bytes. Possible options can be seen in [schema](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/crypto/block/block.tlb#L766). In our case, we have `03`, which means: + ```tlb vm_stk_cell#03 cell:^Cell = VmStackValue; ``` -So the type of our value is - cell, and, according to the schema, it stores the value itself as a reference. But, if we look at the stack element storage schema: + +Hence, the type of our value is - cell, and, according to the schema, it stores the value itself as a reference. However, if we look at the stack element storage schema: + ```tlb vm_stk_cons#_ {n:#} rest:^(VmStackList n) tos:VmStackValue = VmStackList (n + 1); ``` + We will see that the first link `rest:^(VmStackList n)` - is the cell of the next value on the stack, and our value `tos:VmStackValue` comes second, so to get the value we need to read the second link, that is `32[0CCFFCC1]` - this is our first cell that the contract returned. Now we can go deeper and get the second element of the stack, we go through the first link, now we have: + ```json 8[03] -> { 0[], 32[0AABBCC8] } ``` + We repeat the same process. The first 8 bits = `03` - that is, again cell. The second reference is the value `32[0AABBCC8]` and since our stack depth is 2, we complete the pass. n total, we have 2 values returned by the contract - `32[0CCFFCC1]` and `32[0AABBCC8]`. Note that they are in reverse order. In the same way, you need to pass arguments when calling a function - in reverse order from what we see in the FunC code. -[Implementation example](https://github.com/xssnick/tonutils-go/blob/46dbf5f820af066ab10c5639a508b4295e5aa0fb/ton/runmethod.go#L24) +[Please see implementation example here](https://github.com/xssnick/tonutils-go/blob/46dbf5f820af066ab10c5639a508b4295e5aa0fb/ton/runmethod.go#L24) ### getAccountState + To get account state data such as balance, code and contract data, we can use [getAccountState](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/lite_api.tl#L68). For the request, we need a [fresh master block](#getmasterchaininfo) and account address. In response, we will receive the TL structure [AccountState](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/lite_api.tl#L38). Let's analyze the AccountState TL schema: + ```tlb liteServer.accountState id:tonNode.blockIdExt shardblk:tonNode.blockIdExt shard_proof:bytes proof:bytes state:bytes = liteServer.AccountState; ``` -1. `id` - is our master block, regarding which we got the data. -2. `shardblk` - workchain shard block where our account is located, regarding which we received data. -3. `shard_proof` - merkle proof of a shard block. -4. `proof` - merkle proof of account status. -5. `state` - [BoC](/v3/documentation/data-formats/tlb/cell-boc#bag-of-cells) TL-B [account state scheme](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/crypto/block/block.tlb#L232). + +* `id` - our master block, regarding which we got the data. +* `shardblk` - WorkChain shard block where our account is located, regarding which we received data. +* `shard_proof` - Merkle proof of a shard block. +* `proof` - Merkle proof of account status. +* `state` - [BoC](/v3/documentation/data-formats/tlb/cell-boc#bag-of-cells) TL-B [account state scheme](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/crypto/block/block.tlb#L232). Of all this data, what we need is in the state, we will analyze it. For example, let's get the status of account `EQAhE3sLxHZpsyZ_HecMuwzvXHKLjYx4kEUehhOy2JmCcHCT`, `state` in the response will be (at the moment of writing this article): + ```hex b5ee9c720102350100051e000277c0021137b0bc47669b3267f1de70cbb0cef5c728b8d8c7890451e8613b2d899827026a886043179d3f6000006e233be8722201d7d239dba7d818134001020114ff00f4a413f4bcf2c80b0d021d0000000105036248628d00000000e003040201cb05060013a03128bb16000000002002012007080043d218d748bc4d4f4ff93481fd41c39945d5587b8e2aa2d8a35eaf99eee92d9ba96004020120090a0201200b0c00432c915453c736b7692b5b4c76f3a90e6aeec7a02de9876c8a5eee589c104723a18020004307776cd691fbe13e891ed6dbd15461c098b1b95c822af605be8dc331e7d45571002000433817dc8de305734b0c8a3ad05264e9765a04a39dbe03dd9973aa612a61f766d7c02000431f8c67147ceba1700d3503e54c0820f965f4f82e5210e9a3224a776c8f3fad1840200201200e0f020148101104daf220c7008e8330db3ce08308d71820f90101d307db3c22c00013a1537178f40e6fa1f29fdb3c541abaf910f2a006f40420f90101d31f5118baf2aad33f705301f00a01c20801830abcb1f26853158040f40e6fa120980ea420c20af2670edff823aa1f5340b9f2615423a3534e2a2d2b2c0202cc12130201201819020120141502016616170003d1840223f2980bc7a0737d0986d9e52ed9e013c7a21c2b2f002d00a908b5d244a824c8b5d2a5c0b5007404fc02ba1b04a0004f085ba44c78081ba44c3800740835d2b0c026b500bc02f21633c5b332781c75c8f20073c5bd0032600201201a1b02012020210115bbed96d5034705520db3c8340201481c1d0201201e1f0173b11d7420c235c6083e404074c1e08075313b50f614c81e3d039be87ca7f5c2ffd78c7e443ca82b807d01085ba4d6dc4cb83e405636cf0069006031003daeda80e800e800fa02017a0211fc8080fc80dd794ff805e47a0000e78b64c00015ae19574100d56676a1ec40020120222302014824250151b7255b678626466a4610081e81cdf431c24d845a4000331a61e62e005ae0261c0b6fee1c0b77746e102d0185b5599b6786abe06fedb1c68a2270081e8f8df4a411c4605a400031c34410021ae424bae064f613990039e2ca840090081e886052261c52261c52265c4036625ccd88302d02012026270203993828290111ac1a6d9e2f81b609402d0015adf94100cc9576a1ec1840010da936cf0557c1602d0015addc2ce0806ab33b50f6200220db3c02f265f8005043714313db3ced542d34000ad3ffd3073004a0db3c2fae5320b0f26212b102a425b3531cb9b0258100e1aa23a028bcb0f269820186a0f8010597021110023e3e308e8d11101fdb3c40d778f44310bd05e254165b5473e7561053dcdb3c54710a547abc2e2f32300020ed44d0d31fd307d307d33ff404f404d10048018e1a30d20001f2a3d307d3075003d70120f90105f90115baf2a45003e06c2170542013000c01c8cbffcb0704d6db3ced54f80f70256e5389beb198106e102d50c75f078f1b30542403504ddb3c5055a046501049103a4b0953b9db3c5054167fe2f800078325a18e2c268040f4966fa52094305303b9de208e1638393908d2000197d3073016f007059130e27f080705926c31e2b3e63006343132330060708e2903d08308d718d307f40430531678f40e6fa1f2a5d70bff544544f910f2a6ae5220b15203bd14a1236ee66c2232007e5230be8e205f03f8009322d74a9802d307d402fb0002e83270c8ca0040148040f44302f0078e1771c8cb0014cb0712cb0758cf0158cf1640138040f44301e201208e8a104510344300db3ced54925f06e234001cc8cb1fcb07cb07cb3ff400f400c9 ``` -[Parse this BoC](/v3/documentation/data-formats/tlb/cell-boc#bag-of-cells) and get +[Parse this BoC](/v3/documentation/data-formats/tlb/cell-boc#bag-of-cells) and get:
large cell @@ -358,13 +388,16 @@ b5ee9c720102350100051e000277c0021137b0bc47669b3267f1de70cbb0cef5c728b8d8c7890451
Now we need to parse the cell according to the TL-B structure: + ```tlb account_none$0 = Account; account$1 addr:MsgAddressInt storage_stat:StorageInfo storage:AccountStorage = Account; ``` + Our structure references other structures, such as: + ```tlb anycast_info$_ depth:(#<= 30) { depth >= 1 } rewrite_pfx:(bits depth) = Anycast; addr_std$10 anycast:(Maybe Anycast) workchain_id:int8 address:bits256 = MsgAddressInt; @@ -386,49 +419,62 @@ account_active$1 _:StateInit = AccountState; account_frozen$01 state_hash:bits256 = AccountState; ``` -As we can see, the cell contains a lot of data, but we will analyze the main cases and getting a balance. You can analyze the rest in a similar way. +As we can see, the cell contains a lot of data, but we will analyze the main cases and get a balance. You can analyze the rest in a similar way. Let's start parsing. In the root cell data we have: + ``` C0021137B0BC47669B3267F1DE70CBB0CEF5C728B8D8C7890451E8613B2D899827026A886043179D3F6000006E233BE8722201D7D239DBA7D818130_ ``` + Convert it to binary form and get: + ``` 11000000000000100001000100110111101100001011110001000111011001101001101100110010011001111111000111011110011100001100101110110000110011101111010111000111001010001011100011011000110001111000100100000100010100011110100001100001001110110010110110001001100110000010011100000010011010101000100001100000010000110001011110011101001111110110000000000000000000000110111000100011001110111110100001110010001000100000000111010111110100100011100111011011101001111101100000011000000100110 ``` -Let's look at our main TL-B structure, we see that we have 2 options for what can be there - `account_none$0` or `account$1`. We can understand which option we have by reading the prefix declared after the symbol $, in our case it is 1 bit. If there is 0, then we have `account_none`, or 1, then `account`. + +Let's look at our main TL-B structure, we see that we have two options for what can be there - `account_none$0` or `account$1`. We can understand which option we have by reading the prefix declared after the symbol $, in our case it is 1 bit. If there is 0, then we have `account_none`, or 1, then `account`. Our first bit from the data above = 1, so we are working with `account$1` and will use the schema: + ```tlb account$1 addr:MsgAddressInt storage_stat:StorageInfo storage:AccountStorage = Account; ``` -Next we have `addr:MsgAddressInt`, we see that for MsgAddressInt we also have several options: + +Next, we have `addr:MsgAddressInt`, we see that for MsgAddressInt we also have several options: + ```tlb addr_std$10 anycast:(Maybe Anycast) workchain_id:int8 address:bits256 = MsgAddressInt; addr_var$11 anycast:(Maybe Anycast) addr_len:(## 9) workchain_id:int32 address:(bits addr_len) = MsgAddressInt; ``` -To understand which one to work with, we, like last time, read the prefix bits, this time we read 2 bits. We cut off the already read bit, `1000000...` remains, we read the first 2 bits and get `10`, which means we are working with `addr_std$10`. -Next we need to parse `anycast:(Maybe Anycast)`, Maybe means we should read 1 bit, and if it's one, read Anycast, otherwise skip. Our remaining bits are `00000...`, read 1 bit, it's 0, so we skip Anycast. +To determine which structure to work with, we follow a similar approach as last time by reading the prefix bits. This time, we read 2 bits. After processing the first bit, we have `1000000...` remaining. Reading the first 2 bits yields `10`, indicating that we are working with `addr_std$10`. + +Next, we encounter `anycast:(Maybe Anycast)`. The "Maybe" indicates that we should read 1 bit; if it's 1, we read `Anycast`; if it's 0, we skip it. After processing, our remaining bits are `00000...`. We read 1 bit and find it to be 0, so we skip reading `Anycast`. -Next, we have `workchain_id: int8`, everything is simple here, we read 8 bits, this will be the workchain ID. We read the next 8 bits, all zeros, so the workchain is 0. +Now, we move on to `workchain_id: int8`. This is straightforward— we read 8 bits to obtain the WorkChain ID. The next 8 bits are all zeros, so the WorkChain ID is 0. -Next, we read `address:bits256`, this is 256 bits of the address, in the same way as with `workchain_id`. On reading, we get `21137B0BC47669B3267F1DE70CBB0CEF5C728B8D8C7890451E8613B2D8998270` in hex representation. +Following this, we read `address: bits256`, which consists of 256 bits for the address, similar to how we handled the `workchain_id`. Upon reading, we receive `21137B0BC47669B3267F1DE70CBB0CEF5C728B8D8C7890451E8613B2D8998270` in hexadecimal representation. +Next, we read the address `addr: MsgAddressInt` and then proceed to `storage_stat: StorageInfo` from the main structure. Its schema is: -We read the address `addr:MsgAddressInt`, then we have `storage_stat:StorageInfo` from the main structure, its schema is: ```tlb storage_info$_ used:StorageUsed last_paid:uint32 due_payment:(Maybe Grams) = StorageInfo; ``` -First comes `used:StorageUsed`, with the schema: + +First, we have `used:StorageUsed`, along with its schema: + ```tlb storage_used$_ cells:(VarUInteger 7) bits:(VarUInteger 7) public_cells:(VarUInteger 7) = StorageUsed; ``` -This is the number of cells and bits used to store account data. Each field is defined as `VarUInteger 7`, which means a uint of dynamic size, but a maximum of 7 bits. You can understand how it is arranged according to the scheme: + +This is the number of cells and bits used to store account data. Each field is defined as `VarUInteger 7`, which means a uint of dynamic size, but a maximum of 7 bits. You can understand how it is arranged according to the schema: + ```tlb var_uint$_ {n:#} len:(#< n) value:(uint (len * 8)) = VarUInteger n; ``` + In our case, n will be equal to 7. In len we will have `(#< 7)` which means the number of bits that can hold a number up to 7. You can determine it by translating 7-1=6 into binary form - `110`, we get 3 bits, so length len = 3 bits. And value is `(uint (len * 8))`. To determine it, we need to read 3 bits of the length, get a number and multiply by 8, this will be the size of `value`, that is, the number of bits that need to be read to get the value of VarUInteger. Read `cells:(VarUInteger 7)`, take our next bits from the root cell, look at the next 16 bits to understand, this is `0010011010101000`. We read the first 3 bits of len, this is `001`, i.e. 1, we get the size (uint (1 * 8)), we get uint 8, we read 8 bits, it will be `cells`, `00110101`, i.e. 53 in decimal form. We do the same for `bits` and `public_cells`. @@ -436,26 +482,32 @@ Read `cells:(VarUInteger 7)`, take our next bits from the root cell, look at the We successfully read `used:StorageUsed`, next we have `last_paid:uint32`, we read 32 bits. Everything is just as simple with `due_payment:(Maybe Grams)` here Maybe, which will be 0, so we skip Grams. But, if Maybe is 1, we can look at the Grams `amount:(VarUInteger 16) = Grams` schema and immediately understand that we already know how to work with this. Like last time, only instead of 7 we have 16. Next we have `storage:AccountStorage` with a schema: + ```tlb account_storage$_ last_trans_lt:uint64 balance:CurrencyCollection state:AccountState = AccountStorage; ``` + We read `last_trans_lt:uint64`, this is 64 bits, storing lt of the last account transaction. And finally, the balance represented by the schema: + ```tlb currencies$_ grams:Grams other:ExtraCurrencyCollection = CurrencyCollection; ``` -From here we will read `grams:Grams` which will be the account balance in nano-tones. -`grams:Grams` is `VarUInteger 16`, to store 16 (in binary form `10000`, subtracting 1 we get `1111`), then we read the first 4 bits, and multiply the resulting value by 8, then we read the received number of bits, it is our balance. + +From here we will read `grams:Grams` which will be the account balance in nano-tones. `grams:Grams` is `VarUInteger 16`, to store 16 (in binary form `10000`, subtracting 1 we get `1111`), then we read the first 4 bits, and multiply the resulting value by 8, then we read the received number of bits, it is our balance. Let's analyze our remaining bits according to our data: + ``` 100000000111010111110100100011100111011011101001111101100000011000000100110 ``` + Read first 4 bits - `1000`, this is 8. 8*8=64, read next 64 bits = `0000011101011111010010001110011101101110100111110110000001100000`, removing extra zero bits, we get `11101011111010010001110011101101110100111110110000001100000`, that is equal to `531223439883591776`, and, translating from nano to TON, we get `531223439.883591776`. We will stop here, since we have already analyzed all the main cases, the rest can be obtained in a similar way with what we have analyzed. Also, additional information on parsing TL-B can be found in [official documentation](/v3/documentation/data-formats/tlb/tl-b-language) ### Other methods -Now, having studied all the information, you can call and process responses for other lite-server methods as well. Same principle :) + +After studying all the information, you can call and process responses for other liteserver methods using the same principle. ## Additional technical details of the handshake @@ -463,6 +515,7 @@ Now, having studied all the information, you can call and process responses for The key id is the SHA256 hash of the serialized TL schema. The most commonly used TL schemas for the keys are: + ```tlb pub.ed25519 key:int256 = PublicKey -- ID c6b41348 pub.aes key:int256 = PublicKey -- ID d4adbc2d @@ -471,12 +524,12 @@ pub.unenc data:bytes = PublicKey -- ID 0a451fb6 pk.aes key:int256 = PrivateKey -- ID 3751e8a5 ``` -As an example, for keys of type ED25519 that are used for handshake, the key ID will be the SHA256 hash from -**[0xC6, 0xB4, 0x13, 0x48]** and **public key**, (36 byte array, prefix + key) +As an example, for keys of type ed25519 that are used for handshake, the key ID will be the SHA256 hash from **[0xC6, 0xB4, 0x13, 0x48]** and **public key**, (36 byte array, prefix + key). -[Code example](https://github.com/xssnick/tonutils-go/blob/2b5e5a0e6ceaf3f28309b0833cb45de81c580acc/liteclient/crypto.go#L16) +[Please see code example](https://github.com/xssnick/tonutils-go/blob/2b5e5a0e6ceaf3f28309b0833cb45de81c580acc/liteclient/crypto.go#L16). ### Handshake packet data encryption + The handshake packet is sent in a semi-open form, only 160 bytes are encrypted, containing information about permanent ciphers. To encrypt them, we need an AES-CTR cipher, to get it we need a SHA256 hash of 160 bytes and [ECDH shared key](#getting-a-shared-key-using-ecdh) @@ -487,26 +540,27 @@ The cipher is built like this: After the cipher is assembled, we encrypt our 160 bytes with it. -[Code example](https://github.com/xssnick/tonutils-go/blob/2b5e5a0e6ceaf3f28309b0833cb45de81c580acc/liteclient/connection.go#L361) +[Please see code example](https://github.com/xssnick/tonutils-go/blob/2b5e5a0e6ceaf3f28309b0833cb45de81c580acc/liteclient/connection.go#L361). ### Getting a shared key using ECDH + To calculate the shared key, we need our private key and the server's public key. The essence of DH is to obtain a shared secret key, without disclosing private information. I will give an example of how this happens, in the most simplified form. Suppose we need to generate a shared key between us and the server, the process will look like this: -1. We generate secret and public numbers like **6** and **7** -2. The server generates secret and public numbers like **5** and **15** -3. We exchange public numbers with the server, send **7** to the server, it sends us **15**. -4. We calculate: **7^6 mod 15 = 4** -5. The server calculates: **7^5 mod 15 = 7** -6. We exchange the received numbers, we give the server **4**, it gives us **7** -7. We calculate **7^6 mod 15 = 4** -8. The server calculates: **4^5 mod 15 = 4** -9. Shared key = **4** +* We generate secret and public numbers like **6** and **7** +* The server generates secret and public numbers like **5** and **15** +* We exchange public numbers with the server, send **7** to the server, it sends us **15**. +* We calculate: **7^6 mod 15 = 4** +* The server calculates: **7^5 mod 15 = 7** +* We exchange the received numbers, we give the server **4**, it gives us **7** +* We calculate **7^6 mod 15 = 4** +* The server calculates: **4^5 mod 15 = 4** +* Shared key = **4** The details of the ECDH itself will be omitted for the sake of simplicity. It is calculated using 2 keys, private and public, by finding a common point on the curve. If interested, it is better to read about it separately. -[Code example](https://github.com/xssnick/tonutils-go/blob/2b5e5a0e6ceaf3f28309b0833cb45de81c580acc/liteclient/crypto.go#L32) +[Please see code example](https://github.com/xssnick/tonutils-go/blob/2b5e5a0e6ceaf3f28309b0833cb45de81c580acc/liteclient/crypto.go#L32). ## References -_Here a [link to the original article](https://github.com/xssnick/ton-deep-doc/blob/master/ADNL-TCP-Liteserver.md) by [Oleg Baranov](https://github.com/xssnick)._ +_Here is a [link to the original article](https://github.com/xssnick/ton-deep-doc/blob/master/ADNL-TCP-Liteserver.md) by [Oleg Baranov](https://github.com/xssnick)._ From 91d152cc3c52d508a5dde95bb6c7f5b97765b971 Mon Sep 17 00:00:00 2001 From: D Ozgur Cakirkaya Date: Tue, 8 Apr 2025 23:25:42 +0100 Subject: [PATCH 10/14] adnl-udp.md update --- .../network/protocols/adnl/adnl-udp.md | 181 +++++++++++------- 1 file changed, 116 insertions(+), 65 deletions(-) diff --git a/docs/v3/documentation/network/protocols/adnl/adnl-udp.md b/docs/v3/documentation/network/protocols/adnl/adnl-udp.md index 767f7178847..330ddee7075 100644 --- a/docs/v3/documentation/network/protocols/adnl/adnl-udp.md +++ b/docs/v3/documentation/network/protocols/adnl/adnl-udp.md @@ -1,20 +1,23 @@ -# ADNL UDP - Internode +# ADNL UDP - internode -ADNL over UDP is used by nodes and TON components to communicate with each other. It is a low-level protocol on top of which other, higher-level TON protocols such as DHT and RLDP operate. -In this article, we will learn how ADNL over UDP works for basic communication between nodes. +ADNL over UDP is a low-level protocol used by nodes and TON components to communicate with one another. It serves as the foundation for other higher-level TON protocols, such as DHT (Distributed Hash Table) and RLDP (Reliable Large Datagram Protocol). -Unlike ADNL over TCP, in the UDP implementation, the handshake takes place in a different form, and an additional layer is used in the form of channels, but other principles are similar: -encryption keys are also generated based on our private key and the peer's public key, which is known in advance from the config or received from other network nodes. +This article will explain how ADNL over UDP facilitates basic communication between nodes. -In the UDP version of ADNL, the connection is established in the same time with the receiving of initial data from the peer if the initiator sent 'create channel' message, the channel's key will be calculated and the channel creation will be confirmed. -When the channel is established, further communication will continue inside it. +Unlike ADNL over TCP, the UDP implementation involves a different form of handshake and includes an additional layer in the form of channels. However, the underlying principles remain similar: encryption keys are generated based on our private key and the peer's public key, which is either known in advance from the configuration or received from other network nodes. + +In the UDP version of ADNL, the connection is established simultaneously with the reception of initial data from the peer. If the initiator sends a **create channel** message, the channel’s key will be calculated, and the channel's creation will be confirmed. + +Once the channel is established, further communication continues within it. ## Packet structure and communication ### First packets -Let's analyze the initialization of the connection with the DHT node and obtaining a signed list of its addresses in order to understand how the protocol works. -Find the node you like in [global config](https://ton-blockchain.github.io/global.config.json), in the `dht.nodes` section. For example: +Let's analyze the connection initialization with the DHT node and obtain a signed list of its addresses to understand how the protocol functions. + +Find a node you prefer in the [global config](https://ton-blockchain.github.io/global.config.json), specifically in the `dht.nodes` section. For example: + ```json { "@type": "dht.node", @@ -41,36 +44,46 @@ Find the node you like in [global config](https://ton-blockchain.github.io/globa } ``` -1. Let's take its ED25519 key, `fZnkoIAxrTd4xeBgVpZFRm5SvVvSx7eN3Vbe8c83YMk`, and decode it from base64 -2. Take its IP address `1091897261` and translate it into an understandable format using [service](https://www.browserling.com/tools/dec-to-ip) or using conversion to little endian bytes, we will get `65.21.7.173` -3. Combine with the port, get `65.21.7.173:15813` and establish a UDP connection. +Let's take the ed25519 key, `fZnkoIAxrTd4xeBgVpZFRm5SvVvSx7eN3Vbe8c83YMk`, and decode it from base64. + +Next, we will take its IP address, 1091897261, and convert it into a readable format using [this service](https://www.browserling.com/tools/dec-to-ip) or by converting it to little-endian bytes. This will give us the IP address `65.21.7.173`. + +Finally, we will combine this IP address with the port to obtain `65.21.7.173:15813` and establish a UDP connection. + +We aim to establish a communication channel with the node to obtain specific information, particularly a list of signed addresses. To achieve this, we will generate two messages. The first message will be to create the channel [(see the code)](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/ton_api.tl#L129): -We want to open a channel to communicate with node and get some information, and as the main task - to receive a list of signed addresses from it. To do this, we will generate 2 messages, the first - [create a channel](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/ton_api.tl#L129): ```tlb adnl.message.createChannel key:int256 date:int = adnl.Message ``` -Here we have 2 parameters - key and date. As a date, we will specify the current unix timestamp. And for the key - we need to generate a new ED25519 private+public key pair specially for the channel, they will be used for initialization of [public encryption key](/v3/documentation/network/protocols/adnl/adnl-tcp#getting-a-shared-key-using-ecdh). We will use our generated public key in the `key` parameter of the message, and just save the private one for now. -Serialize the filled TL structure and get: +We have two parameters to consider: a key and a date. The date will be represented by the current Unix timestamp. For the key, we need to generate a new ed25519 private and public key pair specifically for the channel. This key pair will be used to initialize the public encryption key, as outlined in the [link here](/v3/documentation/network/protocols/adnl/adnl-tcp#getting-a-shared-key-using-ecdh). We will use the generated public key as the value for the `key` parameter in the message, while we will store the private key for future use. + +Next, we will serialize the populated TL structure to get the final result: + ``` bbc373e6 -- TL ID adnl.message.createChannel d59d8e3991be20b54dde8b78b3af18b379a62fa30e64af361c75452f6af019d7 -- key 555c8763 -- date ``` -Next, let's move to our main query - [get a list of addresses](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/ton_api.tl#L198). +Next, let's proceed to our main query - [retrieve a list of addresses](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/ton_api.tl#L198). + To execute it, we first need to serialize its TL structure: + ```tlb dht.getSignedAddressList = dht.Node ``` -It has no parameters, so we just serialize it. It will be just its id - `ed4879a9`. -Next, since this is a higher level request of the DHT protocol, we need to first wrap it in an `adnl.message.query` TL structure: +There are no parameters to consider, so we will simply serialize it. The result will be just its ID: `ed4879a9`. + +Next, since this is a higher-level request within the DHT protocol, we must first wrap it in an `adnl.message.query` TL structure: + ```tlb adnl.message.query query_id:int256 query:bytes = adnl.Message ``` -As `query_id` we generate random 32 bytes, as `query` we use our main request, [wrapped as an array of bytes](/v3/documentation/data-formats/tl#encoding-bytes-array). -We will get: + +We generate a random 32 bytes for `query_id`, and the `query` represents our main request, [wrapped as an array of bytes](/v3/documentation/data-formats/tl#encoding-bytes-array): + ``` 7af98bb4 -- TL ID adnl.message.query d7be82afbc80516ebca39784b8e2209886a69601251571444514b7f17fcd8875 -- query_id @@ -79,7 +92,8 @@ d7be82afbc80516ebca39784b8e2209886a69601251571444514b7f17fcd8875 -- query_id ### Building the packet -All communication is carried out using packets, the content of which is [TL structure](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/ton_api.tl#L81): +All communication is conducted using packets, which contain the following structure: [TL structure](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/ton_api.tl#L81): + ```tlb adnl.packetContents rand1:bytes -- random 7 or 15 bytes @@ -102,15 +116,20 @@ adnl.packetContents ``` -Once we have serialized all the messages we want to send, we can start building the packet. -Packets to be sent to a channel differ in content from packets that are sent before the channel is initialized. -First, let's analyze the main packet, which is used for initialization. +Once we have serialized all the messages we wish to send, we can begin building the packet. + +Packets sent to a channel have a different content structure compared to packets sent before the channel is initialized. + +First, let’s examine the main packet used for initialization. + +During the initial data exchange, before the channel is established, the packet's serialized content structure is prefixed with the peer's public key, which is 32 bytes. + +Our public key is also 32 bytes, and the SHA-256 hash of the serialized TL of the packet's content structure is another 32 bytes. + +The content of the packet is encrypted using the [shared key](/v3/documentation/network/protocols/adnl/adnl-tcp#getting-a-shared-key-using-ecdh), which is derived from our private key and the public key of the server. -During the initial data exchange, outside the channel, the serialized content structure of the packet is prefixed with the public key of the peer - 32 bytes. -Our public key is 32 bytes, the sha256 hash of the serialized TL of the content structure of the packet - 32 bytes. -The content of the packet is encrypted using the [shared key](/v3/documentation/network/protocols/adnl/adnl-tcp#getting-a-shared-key-using-ecdh), obtained from our private key and the public key of the server. +Let's serialize the structure of our packet content and parse it byte by byte: -Serialize our packet content structure, and parse it byte by byte: ``` 89cd42d1 -- TL ID adnl.packetContents 0f 4e0e7dd6d0c5646c204573bc47e567 -- rand1, 15 (0f) random bytes @@ -141,8 +160,11 @@ c6b41348 -- TL 00000000 -- dst_reinit_date (present because flag's tenth bit = 1) 0f 2b6a8c0509f85da9f3c7e11c86ba22 -- rand2, 15 (0f) random bytes ``` -After serialization - we need to sign the resulting byte array with our private client's (not channel's) ED25519 key, which we generated and saved before. -After we have generated the signature (64 bytes in size), we need to add it to the packet, serialize it again, but now add the 11th bit to the flag, which means the presence of the signature: + +After serialization, we need to sign the resulting byte array using our private client's key, specifically ed25519, which we generated and saved earlier. + +Once we have created the signature (which is 64 bytes in size), we must add it to the packet and serialize it again. This time, we will also set the 11th bit in the flag to indicate the presence of the signature: + ``` 89cd42d1 -- TL ID adnl.packetContents 0f 4e0e7dd6d0c5646c204573bc47e567 -- rand1, 15 (0f) random bytes @@ -176,21 +198,27 @@ c6b41348 -- TL 000000 -- 0f 2b6a8c0509f85da9f3c7e11c86ba22 -- rand2, 15 (0f) random bytes ``` -Now we have an assembled, signed and serialized packet, which is an array of bytes. -For subsequent verification of its integrity by the recipient, we need to calculate packet's sha256 hash. For example, let this be `408a2a4ed623b25a2e2ba8bbe92d01a3b5dbd22c97525092ac3203ce4044dcd2`. -Now let's encrypt the content of our packet with the AES-CTR cipher, using [shared key](/v3/documentation/network/protocols/adnl/adnl-tcp#getting-a-shared-key-using-ecdh), obtained from our private key and the public key of the peer (not the channel's key). +We now have an assembled, signed, and serialized packet, which consists of an array of bytes. + +Next, we need to calculate the packet's SHA-256 hash, allowing the recipient to verify its integrity later. For instance, let’s say the hash is `408a2a4ed623b25a2e2ba8bbe92d01a3b5dbd22c97525092ac3203ce4044dcd2`. + +Now, we will encrypt the contents of our packet using the AES-CTR cipher, utilizing the [shared key](/v3/documentation/network/protocols/adnl/adnl-tcp#getting-a-shared-key-using-ecdh) that is derived from our private key and the peer’s public key (not the channel's key). + +We are almost ready to send the packet; we just need to [calculate the ID](/v3/documentation/network/protocols/adnl/adnl-tcp#getting-key-id) of the ed25519 peer key and concatenate everything together: + -We are almost ready for sending, just remains to [calculate ID](/v3/documentation/network/protocols/adnl/adnl-tcp#getting-key-id) of ED25519 peer key and concat everything together: ``` daa76538d99c79ea097a67086ec05acca12d1fefdbc9c96a76ab5a12e66c7ebb -- server Key ID afc46336dd352049b366c7fd3fc1b143a518f0d02d9faef896cb0155488915d6 -- our public key 408a2a4ed623b25a2e2ba8bbe92d01a3b5dbd22c97525092ac3203ce4044dcd2 -- sha256 content hash (before encryption) ... -- encrypted content of the packet ``` -Now we can send our built packet to peer via UDP, and wait for a response. -In response, we will receive a packet with similar structure, but with different messages. It will consist of: +We can now send our constructed packet to the peer via UDP and await a response. + +In response, we will receive a packet with a similar structure, but containing different messages. It will consist of: + ``` 68426d4906bafbd5fe25baf9e0608cf24fffa7eca0aece70765d64f61f82f005 -- ID of our key 2d11e4a08031ad3778c5e060569645466e52bd1bd2c7b78ddd56def1cf3760c9 -- server public key, for shared key @@ -198,13 +226,15 @@ f32fa6286d8ae61c0588b5a03873a220a3163cad2293a5dace5f03f06681e88a -- sha256 cont ... -- the encrypted content of the packet ``` -The deserialization of the packet from the server is as follows: -1. We check the ID of the key from the packet to understand that the packet is for us. -2. Using the public key of the server from the packet and our private key, we calculate a shared key and decrypt the content of the packet -3. Compare the sha256 hash sent to us with the hash received from the decrypted data, they must match -4. Start deserializing the packet content using the `adnl.packetContents` TL schema +The process of deserializing the packet from the server is as follows: + +* We first check the ID of the key within the packet to confirm that the packet is intended for us. +* Using the server's public key found in the packet along with our private key, we calculate a shared key to decrypt the packet's content. +* We then compare the SHA-256 hash provided to us with the hash obtained from the decrypted data; they must match. +* Finally, we begin deserializing the packet content using the `adnl.packetContents` TL schema. The content of the packet will look like this: + ``` 89cd42d1 -- TL ID adnl.packetContents 0f 985558683d58c9847b4013ec93ea28 -- rand1, 15 (0f) random bytes @@ -234,22 +264,30 @@ ee354563 -- reinit 000000 -- 0f c3354d35749ffd088411599101deb2 -- rand2, 15 (0f) random bytes ``` -The server responded to us with two messages: `adnl.message.confirmChannel` and `adnl.message.answer`. -With `adnl.message.answer` everything is simple, this is the answer to our request `dht.getSignedAddressList`, we will analyze it in the article about DHT. -Let's focus on `adnl.message.confirmChannel`, which means that the peer has confirmed the creation of the channel and sent us its public channel key. Now, having our private channel key and the peer's public channel key, we can calculate the [shared key](/v3/documentation/network/protocols/adnl/adnl-tcp#getting-a-shared-key-using-ecdh). +The server responded with two messages: `adnl.message.confirmChannel` and `adnl.message.answer`. + +The `adnl.message.answer` is straightforward; it is the response to our request for `dht.getSignedAddressList`, which we will explore further in the article about DHT. + +Now, let’s focus on `adnl.message.confirmChannel`. This indicates that the peer has confirmed the creation of the channel and has sent us its public channel key. With our private channel key and the peer's public channel key, we can compute the [shared key](/v3/documentation/network/protocols/adnl/adnl-tcp#getting-a-shared-key-using-ecdh). + +Once we have calculated the shared channel key, we need to derive two keys from it: one for encrypting outgoing messages and another for decrypting incoming messages. + +Deriving these two keys is quite simple. The second key is simply the shared key written in reverse order. For example: -Now when we have calculated the shared channel key, we need to make 2 keys out of it - one for encrypting outgoing messages, the other for decrypting incoming messages. -Making 2 keys out of it is quite simple, the second key is equal to the shared key written in reverse order. Example: ``` Shared key : AABB2233 First key: AABB2233 Second key: 3322BBAA ``` -It remains to determine which key to use for what, we can do this by comparing the id of our public channel key with the id of the public key of the server channel, converting them to a numerical form - uint256. This approach is used to ensure that both the server and the client determine which key to use for what. If the server uses the first key for encryption, then with this approach the client will always use it for decryption. + +We need to determine which key to use for specific purposes. To do this, we can compare the ID of our public channel key with the ID of the server channel's public key, converting both to a numerical format (uint256). + +This method ensures that both the server and the client agree on which key is used for what function. If the server uses the first key for encryption, this approach guarantees that the client will always use it for decryption. The terms of use are: + ``` The server id is smaller than our id: Encryption: First Key @@ -263,14 +301,17 @@ If the ids are equal (nearly impossible): Encryption: First Key Decryption: First Key ``` -[[Implementation example]](https://github.com/xssnick/tonutils-go/blob/46dbf5f820af066ab10c5639a508b4295e5aa0fb/adnl/adnl.go#L502) + +[[Please see implementation example]](https://github.com/xssnick/tonutils-go/blob/46dbf5f820af066ab10c5639a508b4295e5aa0fb/adnl/adnl.go#L502). ### Communication in a channel -All subsequent packet exchange will occur within the channel, and channel keys will be used for encryption. -Let's send the same `dht.getSignedAddressList` request inside a newly created channel to see the difference. +All future packet exchanges will take place within the channel, and the channel keys will be utilized for encryption. + +Let's send the same `dht.getSignedAddressList` request within a newly created channel to observe the differences. + +We will construct the packet for the channel using the same `adnl.packetContents` structure: -Let's build the packet for the channel using the same `adnl.packetContents` structure: ``` 89cd42d1 -- TL ID adnl.packetContents 0f c1fbe8c4ab8f8e733de83abac17915 -- rand1, 15 (0f) random bytes @@ -283,22 +324,29 @@ fe3c0f39a89917b7f393533d1d06b605b673ffae8bbfab210150fe9d29083c35 -- que 0100000000000000 -- confirm_seqno (flag's seventh bit = 1), 1 because it is the last seqno received from the server 07 e4092842a8ae18 -- rand2, 7 (07) random bytes ``` -The packets in a channel are quite simple and essentially consist of sequences (seqno) and the messages themselves. -After serialization, like last time, we calculate the sha256 hash of the packet. Then we encrypt the packet using the key intended for the outgoing packets of the channel. -[Calculate](/v3/documentation/network/protocols/adnl/adnl-tcp#getting-key-id) `pub.aes` ID of encryption key of our outgoing messages, and we build our packet: +The packets in a channel are quite straightforward and essentially consist of a sequence number (seqno) and the messages themselves. + +After serialization, as we did last time, we calculate the SHA256 hash of the packet. Next, we encrypt the packet using the designated key for outgoing packets in the channel. + +To do this we [calculate](/v3/documentation/network/protocols/adnl/adnl-tcp#getting-key-id) `pub.aes` - ID of the encryption key for our outgoing messages and then build our packet: + ``` bcd1cf47b9e657200ba21d94b822052cf553a548f51f539423c8139a83162180 -- ID of encryption key of our outgoing messages 6185385aeee5faae7992eb350f26ba253e8c7c5fa1e3e1879d9a0666b9bd6080 -- sha256 content hash (before encryption) ... -- the encrypted content of the packet ``` -We send a packet via UDP and wait for a response. In response, we will receive a packet of the same type as we sent (the same fields), but with the answer to our request `dht.getSignedAddressList`. + +We send a packet via UDP and wait for a response. In response, we receive a packet of the same type as the one we sent, containing the answer to our request for `dht.getSignedAddressList`. ## Other message types -For basic communication, messages like `adnl.message.query` and `adnl.message.answer` are used, which we discussed above, but other types of messages are also used for some situations, which we will discuss in this section. + +For basic communication, messages such as `adnl.message.query` and `adnl.message.answer` are utilized, which we discussed earlier. However, there are also other types of messages used for specific situations, which we will cover in this section. ### adnl.message.part -This message type is a piece of one of the other possible message types, such as `adnl.message.answer`. This method of data transferring is used when the message is too large to be transmitted in a single UDP datagram. + +This message type is part of another possible message type, such as `adnl.message.answer`. This method of data transfer is used when a message is too large to be sent in a single UDP datagram. + ```tlb adnl.message.part hash:int256 -- sha256 hash of the original message @@ -307,21 +355,24 @@ offset:int -- offset according to the beginning of the original mess data:bytes -- piece of data of the original message = adnl.Message; ``` -Thus, in order to assemble the original message, we need to get several parts and, according to the offsets, concat them into a single bytes array. -And then process it as a message (according to the ID prefix in this bytes array). + +To reconstruct the original message, we need to gather several parts and concatenate them into a single-byte array based on the specified offsets. + + We will then process this array as a message using the ID prefix contained within it. + ### adnl.message.custom + ```tlb adnl.message.custom data:bytes = adnl.Message; ``` -Such messages are used when the logic at the higher level does not correspond to the request-response format, messages of this type allow you to completely move the processing to the higher level, since the message carries only an array of bytes, without query_id and other fields. -Messages of this type are used, for example, in RLDP, since there can be only one response to many requests, this logic is controlled by RLDP itself. -### Conclusion +Messages of this type are utilized when the logic at a higher level does not align with the typical request-response format. These messages allow for the complete relocation of processing to a higher level, as they consist solely of an array of bytes without including query IDs or other fields. + +For instance, in RLDP, such messages are used since there can be only one response to multiple requests. RLDP itself manages this logic. -Further communication takes place on the basis of the logic described in this article, -but the content of the packets depends on higher level protocols such as DHT and RLDP. +Further communication occurs based on the logic outlined in this article, though the content of the packets relies on higher-level protocols like DHT and RLDP. ## References -_Here a [link to the original article](https://github.com/xssnick/ton-deep-doc/blob/master/ADNL-UDP-Internal.md) by [Oleg Baranov](https://github.com/xssnick)._ \ No newline at end of file +_Here is the [link to the original article](https://github.com/xssnick/ton-deep-doc/blob/master/ADNL-UDP-Internal.md) by [Oleg Baranov](https://github.com/xssnick)._ \ No newline at end of file From d92c5febb4812f2b1d5296952d278e0fc4a9b52d Mon Sep 17 00:00:00 2001 From: D Ozgur Cakirkaya Date: Wed, 9 Apr 2025 08:45:52 +0100 Subject: [PATCH 11/14] ton-dht.md update --- .../network/protocols/dht/ton-dht.md | 64 +++++++------------ 1 file changed, 23 insertions(+), 41 deletions(-) diff --git a/docs/v3/documentation/network/protocols/dht/ton-dht.md b/docs/v3/documentation/network/protocols/dht/ton-dht.md index 5b10092bfcf..e4f5d33f7dc 100644 --- a/docs/v3/documentation/network/protocols/dht/ton-dht.md +++ b/docs/v3/documentation/network/protocols/dht/ton-dht.md @@ -1,68 +1,50 @@ -# TON DHT Service +# TON DHT service -Implementation: -* https://github.com/ton-blockchain/ton/tree/master/dht -* https://github.com/ton-blockchain/ton/tree/master/dht-server +Please see the implementations: + +* [DHT](https://github.com/ton-blockchain/ton/tree/master/dht) +* [DHT Server](https://github.com/ton-blockchain/ton/tree/master/dht-server) ## Overview -The Kademlia-like Distributed Hash Table (DHT) plays a crucial role in the networking part of the TON project and is used to locate other nodes in the network. +The Kademlia-like Distributed Hash Table (DHT) plays a crucial role in the networking aspect of the TON project, enabling the discovery of other nodes within the network. -The keys of the TON DHT are simply 256-bit integers. In most cases, they are computed as a SHA256 of a TL-serialized object. +The keys used in the TON DHT are 256-bit integers, often derived from a SHA256 of a TL-serialized object. -The values assigned to these 256-bit keys are essentially arbitrary byte strings of limited length. The interpretation of -such byte strings is determined by the preimage of the corresponding key; it -is usually known both by the node that looks up the key and by the node -that stores the key. +The values associated with these 256-bit keys are essentially arbitrary byte strings of limited length. The meaning of these byte strings is determined by the pre-image of the corresponding key; this is typically known by both the node performing the key lookup and the node storing the key. -In the simplest case, the key represents an ADNL Address of some node and the value can be its IP address and port. +In its simplest form, the key represents an ADNL address of a node, while the value could be its IP address and port. -The key-value mapping of the TON DHT is kept on the DHT nodes. +The key-value mappings of the TON DHT are maintained on the DHT nodes. ## DHT nodes -Each DHT Node has a 256-bit DHT address. Unlike an ADNL Address, a DHT Address should not change too often, otherwise other nodes would be unable to locate the keys they are looking for. - -It is expected that the value of key `K` will be stored on `S` Kademlia-nearest nodes to `K`. +Each DHT node has a 256-bit DHT address. Unlike an ADNL address, a DHT address should not change too frequently; otherwise, other nodes will be unable to locate the keys they are searching for. -Kademlia distance = 256-bit key `XOR` 256-bit DHT node address (it has nothing to do with geographic location). +The value of key `K` is expected to be stored on the `S` Kademlia-nearest nodes to `K`. -`S` is a small parameter, for example `S = 7`, which is needed to improve reliability of -the DHT (if we would keep the key only on one node, the nearest one to `K`, -the value of that key would be lost if that single node goes offline). +Kademlia distance is calculated by performing a 256-bit `XOR` operation between the key `X` and the 256-bit DHT node address. This distance does not relate to geographic location. +`S` is a small parameter, for instance, `S = 7`, which helps improve the reliability of the DHT. If the key were stored only on a single node (the nearest one to `K`) the value of that key would be lost if that node were to go offline. + ## Kademlia routing table -Any node participating in a DHT usually maintains a Kademlia routing table. +A node participating in a DHT typically maintains a Kademlia routing table. -It consists of 256 buckets, numbered from 0 to 255. The `i`-th -bucket will contain information about some known nodes (a fixed number -of the ā€œbestā€ nodes and maybe some extra candidates) that lie at a Kademlia -distance from `2^i` to `2^(i+1) āˆ’ 1` from the node’s address `a`. +This table consists of 256 buckets, numbered from 0 to 255. The `i`-th bucket contains information about known nodes that lie within a Kademlia distance from `2^i` to `2^(i+1) āˆ’ 1` from the node’s address `a`. Each bucket holds a fixed number of the ā€œbestā€ nodes, along with some additional candidate nodes. -This information includes their DHT Addresses, IP Addresses and UDP Ports and -some availability information such as the time and the delay of the last ping. +The information stored in these buckets includes the DHT addresses, IP addresses, UDP ports, and availability details, such as the time and delay of the last ping. -When a Kademlia node learns about any other Kademlia node as a result -of some query, it places it into a suitable bucket of its routing table, first -as a candidate. Then, if some of the ā€œbestā€ nodes in that bucket fail (e.g., do -not respond to ping queries for a long time), they can be replaced by some -of these candidates. In this way the Kademlia routing table stays populated. +When a Kademlia node discovers another Kademlia node through a query, it places that node into the appropriate bucket as a candidate. If some of the ā€œbestā€ nodes in that bucket become unresponsive (for example, if they do not reply to ping queries for an extended period), they can be replaced by some of these candidates. This process ensures that the Kademlia routing table remains populated. ## Key-value pairs -Key-value pairs can be added and updated in the TON DHT. +Key-value pairs can be added and updated in the TON DHT. The rules for these updates can vary. In some cases, they allow for the old value to be replaced with a new one as long as the new value is signed by the owner or creator. This signature must be retained as part of the value so that it can be verified later by any other nodes that receive this key's value. -The ā€œupdate rulesā€ can differ. In some cases, they simply -permit replacing the old value with the new value, provided that the new value -is signed by the owner/creator (the signature must be kept as part of the value, to -be checked later by any other nodes after they obtain the value of this key). -In other cases, the old value somehow affects the new value. For example, it -can contain a sequence number and the old value is overwritten only if the -new sequence number is larger (to prevent replay attacks). +In other cases, the old value impacts the new value in some way. For example, the old value may contain a sequence number, and it can only be overwritten if the new sequence number is larger. This helps prevent replay attacks. -TON DHT is not only used to store the IP Addresses of ADNL Nodes, but is also used for other purposes - it can store a list of addresses of the nodes which are storing a specific torrent of TON Storage, a list of addresses of nodes included in an overlay subnetwork, ADNL Addresses of TON services or ADNL Addresses of accounts of TON Blockchain and so on. +The TON DHT is not only used to store the IP addresses of ADNL nodes; it also serves other purposes. It can store a list of addresses of nodes that are holding a specific torrent in TON Storage, a list of addresses of nodes included in an overlay subnetwork, ADNL addresses of TON services, and ADNL addresses of accounts on the TON Blockchain, among others. :::info -Read more about TON DHT in [DHT](/v3/documentation/network/protocols/dht/dht-deep-dive) article, or in Chapter 3.2. of the [TON Whitepaper](https://docs.ton.org/ton.pdf). +Learn more about TON DHT in [DHT](/v3/documentation/network/protocols/dht/dht-deep-dive) documentation, or in Chapter 3.2. of the [TON Whitepaper](https://docs.ton.org/ton.pdf). ::: \ No newline at end of file From 73746f63e5c7d714bf33ad90addd64d1746a631b Mon Sep 17 00:00:00 2001 From: D Ozgur Cakirkaya Date: Wed, 9 Apr 2025 12:33:12 +0100 Subject: [PATCH 12/14] dht-deep-dive.md update --- .../network/protocols/dht/dht-deep-dive.md | 157 +++++++++++------- 1 file changed, 94 insertions(+), 63 deletions(-) diff --git a/docs/v3/documentation/network/protocols/dht/dht-deep-dive.md b/docs/v3/documentation/network/protocols/dht/dht-deep-dive.md index 9b629c5ddb2..3eb34085591 100644 --- a/docs/v3/documentation/network/protocols/dht/dht-deep-dive.md +++ b/docs/v3/documentation/network/protocols/dht/dht-deep-dive.md @@ -1,57 +1,67 @@ # DHT -DHT stands for Distributed Hash Table and is essentially a distributed key-value database, -where each member of the network can store something, for example, information about themselves. +DHT stands for Distributed Hash Table, which is a type of distributed key-value database. In this system, each member of the network can store information, such as details about themselves. -The implementation of DHT in TON is inherently similar to the implementation of [Kademlia](https://codethechange.stanford.edu/guides/guide_kademlia.html), which is used in IPFS. -Any network member can run a DHT node, generate keys and store data. -To do this, he needs to generate a random ID and inform other nodes about himself. +The implementation of DHT in TON is similar to the [Kademlia](https://codethechange.stanford.edu/guides/guide_kademlia.html) protocol, which is also used in IPFS. -To determine which node to store the data on, an algorithm is used to determine the "distance" between the node and the key. -The algorithm is simple: we take the ID of the node and the ID of the key, we perform the XOR operation. The smaller the value, the closer the node. -The task is to store the key on the nodes as close as possible to the key, so that other network participants can, using -the same algorithm, find a node that can give data on this key. +Any network participant can operate a DHT node, generate keys, and store data. To do this, they need to create a random ID and inform other nodes about their presence. + +An algorithm determines the "distance" between the node and the key, which helps identify which node should store the data. The algorithm is straightforward: it takes the node's ID and the key's ID and performs the `XOR` operation. A smaller resulting value indicates a closer proximity between the node and the key. + +The goal is to store the key on nodes that are as close as possible to the key so that other network participants can, using the same algorithm, easily locate a node that can provide data associated with that key. ## Finding a value by key -Let's look at an example with a search for a key, [connect to any DHT node and establish a connection via ADNL UDP](/v3/documentation/network/protocols/adnl/adnl-udp#packet-structure-and-communication). -For example, we want to find the address and public key for connecting to the node that hosts foundation.ton site. -Let's say we have already obtained the ADNL address of this site by executing the Get method of the DNS contract. -The ADNL address in hex representation is `516618cf6cbe9004f6883e742c9a2e3ca53ed02e3e36f4cef62a98ee1e449174`. -Now our goal is to find the ip, port and public key of the node that has this address. +Let's examine an example involving a search for a key: [connect to any DHT node and establish a connection via ADNL UDP](/v3/documentation/network/protocols/adnl/adnl-udp#packet-structure-and-communication). + +Suppose we want to find the address and public key needed to connect to the node hosting the `foundation.ton` site. + +Assuming we have already obtained this site's ADNL address by executing the "get method" of the DNS contract, the ADNL address in hexadecimal format is `516618cf6cbe9004f6883e742c9a2e3ca53ed02e3e36f4cef62a98ee1e449174`. + +Our objective is to determine the IP address, port number, and public key of the node associated with this address. + +To achieve this, we first need to get the ID of the DHT key. We will begin by populating the DHT key schema: -To do this, we need to get the ID of the DHT key, first we will fill the DHT key schema: ```tlb dht.key id:int256 name:bytes idx:int = dht.Key ``` -`name` is the type of key, for ADNL addresses the word `address` is used, and, for example, to search for shardchain nodes - `nodes`. But the key type can be any array of bytes, depending on the value you are looking for. -Filling in this schema, we get: +The term `name` refers to the type of key. For ADNL addresses, the term `address` is used. For instance, when searching for ShardChain nodes, the term `nodes` is used. However, the key type can vary and may consist of any array of bytes, depending on the specific value you are seeking. + +By applying this schema, we get: + ``` 8fde67f6 -- TL ID dht.key 516618cf6cbe9004f6883e742c9a2e3ca53ed02e3e36f4cef62a98ee1e449174 -- our searched ADNL address 07 61646472657373 -- key type, the word "address" as an TL array of bytes 00000000 -- index 0 because there is only 1 key ``` -Next - get the key ID, sha256 hash from the bytes serialized above. It will be `b30af0538916421b46df4ce580bf3a29316831e0c3323a7f156df0236c5b2f75` -Now we can start searching. To do this, we need to execute a query that has [schema](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/ton_api.tl#L197): +Next, retrieve the key ID and the SHA256 hash from the bytes serialized above. It will be `b30af0538916421b46df4ce580bf3a29316831e0c3323a7f156df0236c5b2f75`. + +Now we can begin our search. To do this, we need to execute a query that has [schema](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/ton_api.tl#L197): + ```tlb dht.findValue key:int256 k:int = dht.ValueResult ``` -`key` is the id of our DHT key, and `k` is the "width" of the search, the smaller it is, the more accurate, but fewer potential nodes to query. The maximum k for nodes in a TON is 10, usually 6 is used. -Let's populate this structure, serialize and send the request using the `adnl.message.query` schema. [You can read more about this in another article](/v3/documentation/network/protocols/adnl/adnl-udp#packet-structure-and-communication). +The `key` represents the ID of our DHT key, while `k` indicates the "width" of the search. A smaller value for `k` results in a more accurate search but limits the number of potential nodes to query. In a TON, the maximum value for `k` is 10, although 6 is typically used. + +Now, let's populate this structure, serialize it, and send the request using the `adnl.message.query` schema. For more details, please refer to the documentation [here](/v3/documentation/network/protocols/adnl/adnl-udp#packet-structure-and-communication). In response, we can get: + * `dht.valueNotFound` - if the value is not found. * `dht.valueFound` - if the value is found on this node. -##### dht.valueNotFound -If we get `dht.valueNotFound`, the response will contain a list of nodes that are known to the node we requested and are as close as possible to the key we requested from the list of nodes known to it. In this case, we need to connect and add the received nodes to the list known to us. -After that, from the list of all nodes known to us, select the closest, accessible and not yet requested, and make the same request to it. And so on until we try all the nodes in the range we have chosen or until we stop receiving new nodes. +### dht.valueNotFound + +If we receive `dht.valueNotFound`, the response will include a list of nodes that are known to the node we queried and as close as possible to the key we requested. In this situation, we need to connect to these received nodes and add them to our list of known nodes. + +Afterwards, we will select the closest, accessible nodes that have not yet been queried from our entire list of known nodes and send the same request to one of them. We will continue this process until we have tried all the nodes within our chosen range or until we stop receiving new nodes. + +Now, let's take a closer look at the fields in the response and the schemas that are used: -Let's analyze the response fields in more detail, the schemas used: ```tlb adnl.address.udp ip:int port:int = adnl.Address; adnl.addressList addrs:(vector adnl.Address) version:int reinit_date:int priority:int expire_at:int = adnl.AddressList; @@ -61,22 +71,26 @@ dht.nodes nodes:(vector dht.node) = dht.Nodes; dht.valueNotFound nodes:dht.nodes = dht.ValueResult; ``` + `dht.nodes -> nodes` - list of DHT nodes (array). -Each node has an `id` which is its public key, usually [pub.ed25519](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/ton_api.tl#L47), used as a server key to connect to the node via ADNL. Also, each node has a list of addresses `addr_list:adnl.addressList`, version and signature. +Each node has an `id`, which serves as its public key, typically represented as [pub.ed25519](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/ton_api.tl#L47). This key is used to connect to the node via ADNL. Additionally, each node contains a list of addresses, `addr_list:adnl.addressList`, along with its version and signature. + +We need to verify the signature of each node. To do this, we first read the value of the `signature` field and then set it to zero, effectively making it an empty byte array. Next, we serialize the TL structure `dht.node` using this empty signature and check the `signature` field that we emptied earlier. + +We validate the serialized bytes using the public key from the `id` field. [[Please see implementation example]](https://github.com/xssnick/tonutils-go/blob/46dbf5f820af066ab10c5639a508b4295e5aa0fb/adnl/dht/client.go#L91). -We need to check the signature of each node, for this we read the value of `signature` and set the field to zero (we make it an empty bytes array). After - we serialize the TL structure `dht.node` with the empty signature and check the `signature` field that was before emptying. -We check on the received serialized bytes, using the public key from `id` field. [[Implementation example]](https://github.com/xssnick/tonutils-go/blob/46dbf5f820af066ab10c5639a508b4295e5aa0fb/adnl/dht/client.go#L91) +From the list `addrs:(vector adnl.Address)`, we select an address and attempt to establish an ADNL UDP connection, using `id` (the public key) as the server key. -From the list `addrs:(vector adnl.Address)` we take the address and try to establish an ADNL UDP connection, as the server key we use `id`, which is the public key. +To determine the "distance" to this node, we retrieve the [key ID](/v3/documentation/network/protocols/adnl/adnl-tcp#getting-key-id) from the `id` field and calculate the distance using the `XOR` operation between the node's key ID and the desired key. If the distance is small enough, we can make the same request to this node. This process continues until we find a value or run out of new nodes. -To find out the "distance" to this node - we need to take [key id](/v3/documentation/network/protocols/adnl/adnl-tcp#getting-key-id) from the key from the `id` field and check the distance by the XOR operation from the node's key id and the desired key. -If the distance is small enough, we can make the same request to this node. And so on, until we find a value or there are no more new nodes. +### dht.valueFound + +The response will include the value itself, complete key information, and optionally a signature, depending on the value type. -##### dht.valueFound -The response will contain the value itself, the full key information, and optionally a signature (depends on value type). Let's analyze the response fields in more detail, the schemas used: + ```tlb adnl.address.udp ip:int port:int = adnl.Address; adnl.addressList addrs:(vector adnl.Address) version:int reinit_date:int priority:int expire_at:int = adnl.AddressList; @@ -93,56 +107,71 @@ dht.value key:dht.keyDescription value:bytes ttl:int signature:bytes = dht.Value dht.valueFound value:dht.Value = dht.ValueResult; ``` -First, let's analyze `key:dht.keyDescription`, it is a complete description of the key, the key itself and information about who and how can update the value. + +Let's determine `key:dht.keyDescription`. This provides a complete description of the key, including the key itself and information about who can update its value and how. * `key:dht.key` - the key must match the one from which we took the key ID for the search. * `id:PublicKey` - the public key of the record owner. * `update_rule:dht.UpdateRule` - record update rule. -* * `dht.updateRule.signature` - only the owner of the private key can update the record, the `signature` of both the key and the value must be valid -* * `dht.updateRule.anybody` - everyone can update the record, `signature` is empty and not checked -* * `dht.updateRule.overlayNodes` - nodes from the same overlay can update the key, used to find nodes of the same overlay and add yourself + * `dht.updateRule.signature` - only the owner of the private key can update the record, the `signature` of both the key and the value must be valid + * `dht.updateRule.anybody` - everyone can update the record, `signature` is empty and not checked + * `dht.updateRule.overlayNodes` - nodes from the same overlay can update the key, used to find nodes of the same overlay and add yourself + +### dht.updateRule.signature + +After reviewing the key's description, we proceed based on the `updateRule`. In the ADNL address lookup, the type is always `dht.updateRule.signature`. -###### dht.updateRule.signature -After reading the description of the key, we act depending on the `updateRule`, for the ADNL address lookup case the type is always `dht.updateRule.signature`. -We check the key signature in the same way as last time, make the signature an empty byte array, serialize and check. After - we repeat the same for the value, i.e. for the entire `dht.value` object (while returning the key signature to its place). +We verify the key signature in the same manner as before. First, we set the signature to an empty byte array, serialize it, and perform the necessary checks. Next, we repeat this process for the entire `dht.value` object while ensuring that the key signature is restored to its original state. -[[Implementation example]](https://github.com/xssnick/tonutils-go/blob/46dbf5f820af066ab10c5639a508b4295e5aa0fb/adnl/dht/client.go#L331) +[[Please see implementation example]](https://github.com/xssnick/tonutils-go/blob/46dbf5f820af066ab10c5639a508b4295e5aa0fb/adnl/dht/client.go#L331). + +### dht.updateRule.overlayNodes + +Used for keys that contain information about other nodes, shards of the WorkChain in the network, the value always follows the TL structure `overlay.nodes`. -###### dht.updateRule.overlayNodes -Used for keys containing information about other nodes-shards of the workchain in the network, the value always has the TL structure `overlay.nodes`. The value field must be empty. ```tlb overlay.node id:PublicKey overlay:int256 version:int signature:bytes = overlay.Node; overlay.nodes nodes:(vector overlay.node) = overlay.Nodes; ``` + To check for validity, we must check all `nodes` and for each check `signature` against its `id` by serializing the TL structure: + ```tlb overlay.node.toSign id:adnl.id.short overlay:int256 version:int = overlay.node.ToSign; ``` -As we can see, id should be replaced with adnl.id.short, which is the key id (hash) of the `id` field from the original structure. After serialization - we check the signature with the data. -As a result, we get a valid list of nodes that are able to give us information about the workchain shard we need. -###### dht.updateRule.anybody -There are no signatures, anyone can update. +We should replace the `id` with `adnl.id.short`, which is the key identifier (hash) from the original structure's `id` field. After serialization, we will verify the signature against the data. + +As a result, we obtain a valid list of nodes that can provide information about the required WorkChain shard. -#### Using a value +### dht.updateRule.anybody -When everything is verified and the `ttl:int` value has not expired, we can start working with the value itself, i.e. `value:bytes`. For an ADNL address, there must be an `adnl.addressList` structure inside. -It will contain ip addresses and ports of servers corresponding to the requested ADNL address. In our case, there will most likely be 1 RLDP-HTTP address of the `foundation.ton` service. -We will use the public key `id:PublicKey` from the DHT key information as the server key. +There are no signatures required; anyone can make updates. -After the connection is established, we can request the pages of the site using the RLDP protocol. The task from the DHT side at this stage is completed. +### Using a value + +Once everything has been verified and the `ttl:int` value has not expired, we can begin working with the value itself, specifically `value:bytes`. For an ADNL address, this will include an `adnl.addressList` structure. + +This structure will contain the IP addresses and ports of the servers corresponding to the requested ADNL address. In our case, we will most likely have one RLDP-HTTP address associated with the `foundation.ton` service. + +We will use the public key, `id:PublicKey`, from the DHT key information as the server key. + +After establishing the connection, we can request the site's pages using the RLDP protocol. At this stage, the task from the DHT perspective is complete. ### Search for nodes that store the state of the blockchain -DHT is also used to find information about the nodes that store the data of workchains and their shards. The process is the same as when searching for any key, the only difference is in the serialization of the key itself and the validation of the response, we will analyze these points in this section. +DHT is also used to locate information about the nodes storing the data of WorkChains and their shards. The process for retrieving this information is similar to searching for any key; however, the key serialization and response validation differ. We will examine these aspects in this section. + +To retrieve data, such as that of the MasterChain and its shards, we need to complete the TL structure: -In order to get data, for example, of the masterchain and its shards, we need to fill in the TL structure: ``` tonNode.shardPublicOverlayId workchain:int shard:long zero_state_file_hash:int256 = tonNode.ShardPublicOverlayId; ``` -Where `workchain` in the case of a masterchain will be equal to -1, its shard will be equal to -922337203685477580 (0xFFFFFFFFFFFFFFFF), and `zero_state_file_hash` is the hash of the zero state of the chain (file_hash), like other data, it can be taken from the global network config, in the `"validator"` field + +In the context of a MasterChain, the `workchain` value will be set to `-1`. The corresponding shard will be represented as `-922337203685477580 (0xFFFFFFFFFFFFFFFF)`. Additionally, the `zero_state_file_hash` refers to the hash of the chain’s zero state (file_hash). Like other data, this can be obtained from the global network configuration in the `validator` field. + ```json "zero_state": { "workchain": -1, @@ -152,23 +181,25 @@ Where `workchain` in the case of a masterchain will be equal to -1, its shard wi "file_hash": "XplPz01CXAps5qeSWUtxcyBfdAo5zVb1N979KLSKD24=" } ``` -After we have filled in `tonNode.shardPublicOverlayId`, we serialize it and get the key id from it by hashing (as always). -We need to use the resulting key ID as `name` to fill in the `pub.overlay name:bytes = PublicKey` structure, wrapping it in TL bytes array. Next, we serialize it, and we get the key ID now from it. +Once we fill in `tonNode.shardPublicOverlayId`, we will serialize it and obtain the key ID by hashing, as we normally do. -The resulting id will be the key to use in +Next, we use this key ID as the `name` to populate the `pub.overlay name:bytes = PublicKey` structure, wrapping it in a TL bytes array. After serialization, we will retrieve the key ID again from this structure. + +This resulting ID will serve as the key for the command: ```bash dht.findValue ``` -, and the `name` field's value will be the word `nodes`. We repeat the process from the previous section, everything is the same as last time, but `updateRule` will be [dht.updateRule.overlayNodes](#dhtupdateruleoverlaynodes). +In this command, the `name` field will have the value `nodes`. We will repeat the process from the previous section; everything remains the same as before, but this time the `updateRule` will be set to [dht.updateRule.overlayNodes](#dhtupdateruleoverlaynodes). + +After the validation process, we will obtain the public keys (IDs) of the nodes that have information about our workchain and shard. To access the ADNL addresses of these nodes, we will hash the keys to create IDs and repeat the same procedure for each ADNL address, similar to how we did for the `foundation.ton` domain. -After validation - we will get the public keys (`id`) of the nodes that have information about our workchain and shard. To get the ADNL addresses of the nodes, we need to make IDs from the keys (using the hashing method) and repeat the procedure described above for each of the ADNL addresses, as with the ADNL address of the `foundation.ton` domain. +As a result, we will have the addresses of the nodes. If desired, we can use these addresses to discover additional nodes within the same chain using [overlay.getRandomPeers](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/ton_api.tl#L237). -As a result, we will get the addresses of the nodes from which, if we want, we can find out the addresses of other nodes of this chain using [overlay.getRandomPeers](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/ton_api.tl#L237). -We will also be able to receive all the information about the blocks from these nodes. +These nodes will also provide us with all the information regarding the blocks. ## References -_Here a [link to the original article](https://github.com/xssnick/ton-deep-doc/blob/master/DHT.md) by [Oleg Baranov](https://github.com/xssnick)._ \ No newline at end of file +_Here is the [link to the original article](https://github.com/xssnick/ton-deep-doc/blob/master/DHT.md) by [Oleg Baranov](https://github.com/xssnick)._ \ No newline at end of file From 5890ee109f4edbf01b6c3b379fe0cee321753036 Mon Sep 17 00:00:00 2001 From: D Ozgur Cakirkaya Date: Wed, 9 Apr 2025 15:07:32 +0100 Subject: [PATCH 13/14] rldp.md update --- .../documentation/network/protocols/rldp.md | 161 +++++++++++------- 1 file changed, 96 insertions(+), 65 deletions(-) diff --git a/docs/v3/documentation/network/protocols/rldp.md b/docs/v3/documentation/network/protocols/rldp.md index fd2eda3dfe6..bf4b8191a63 100644 --- a/docs/v3/documentation/network/protocols/rldp.md +++ b/docs/v3/documentation/network/protocols/rldp.md @@ -1,22 +1,23 @@ # RLDP -Implementation: -* https://github.com/ton-blockchain/ton/tree/master/rldp -* https://github.com/ton-blockchain/ton/tree/master/rldp2 -* https://github.com/ton-blockchain/ton/tree/master/rldp-http-proxy +Please see the implementations: + +* [RLDP Part 1](https://github.com/ton-blockchain/ton/tree/master/rldp) +* [RLDP Part 2](https://github.com/ton-blockchain/ton/tree/master/rldp2) +* [RLDP HTTP Proxy](https://github.com/ton-blockchain/ton/tree/master/rldp-http-proxy) ## Overview -RLDP - Reliable Large Datagram Protocol - is a protocol that runs on top of ADNL UDP, which is used to transfer large data blocks and -includes Forward Error Correction (FEC) algorithms as a replacement of acknowledgment packets on the other side. -This makes it possible to transfer data between network components more efficiently, but with more traffic consumption. +The Reliable Large Datagram Protocol (RLDP) operates on top of the ADNL UDP protocol and is designed for transferring large data blocks. It incorporates Forward Error Correction (FEC) algorithms, which allow it to replace acknowledgment packets typically sent from the receiver back to the sender. + +This capability enables more efficient data transfer between network components, although it results in increased traffic consumption. -RLDP is used everywhere in TON infrastructure, for example, to download blocks from other nodes and transfer data to them, -to access TON websites and TON Storage. +RLDP plays a crucial role throughout the TON infrastructure. It is used for various purposes, such as downloading blocks from other nodes, transferring data to those nodes, and accessing TON websites and TON Storage. ## Protocol -RLDP uses the following TL structures for communication: +RLDP utilizes the following TL structures for communication: + ```tlb fec.raptorQ data_size:int symbol_size:int symbols_count:int = fec.Type; fec.roundRobin data_size:int symbol_size:int symbols_count:int = fec.Type; @@ -30,36 +31,43 @@ rldp.message id:int256 data:bytes = rldp.Message; rldp.query query_id:int256 max_answer_size:long timeout:int data:bytes = rldp.Message; rldp.answer query_id:int256 data:bytes = rldp.Message; ``` -The serialized structure is wrapped in the `adnl.message.custom` TL schema and sent over ADNL UDP. -RLDP Transfers are used to transfer big data, a random `transfer_id` is generated, and the data itself is processed by the FEC algorithm. -The resulting pieces are wrapped in a `rldp.messagePart` structure and sent to the peer until the peer sends us `rldp.complete` or until timeout. -When the receiver has collected the pieces of `rldp.messagePart` necessary to assemble a complete message, it concat them all together, decodes using FEC and -deserializes the resulting byte array into one of the `rldp.query` or `rldp.answer` structures, depending on the type (tl prefix id). +The serialized structure is encapsulated in the `adnl.message.custom` TL schema and transmitted over ADNL UDP. + +RLDP transfers are utilized for sending large amounts of data. A random `transfer_id` is generated, and the data is then processed using the FEC algorithm. + +The resulting segments are wrapped in a `rldp.messagePart` structure and sent to the peer until the peer responds with `rldp.complete` or a timeout occurs. + +Once the receiver has gathered the necessary `rldp.messagePart` pieces to reconstruct the complete message, it concatenates them, decodes them using FEC, and then deserializes the resulting byte array into either an `rldp.query` or `rldp.answer` structure, depending on the type indicated by the `tl prefix id`. ### FEC -Valid Forward Error Correction algorithms for use with RLDP are RoundRobin, Online, and RaptorQ. -Currently for data encoding [RaptorQ](https://www.qualcomm.com/media/documents/files/raptorq-technical-overview.pdf) is used. +Valid Forward Error Correction (FEC) algorithms suitable for RLDP include RoundRobin, Online, and RaptorQ. + +Currently, [RaptorQ](https://www.qualcomm.com/media/documents/files/raptorq-technical-overview.pdf) is used for data encoding. #### RaptorQ -The essence of RaptorQ is that the data is divided into so-called symbols - blocks of the same, predetermined size. -Matrices are created from blocks, and discrete mathematical operations are applied to them. This allows us to create an almost infinite number of symbols. -from the same data. All symbols are mixed, and it is possible to recover lost packets without requesting additional data from the server, while using fewer packets than it would be if we sent the same pieces in a loop. +The core concept of RaptorQ is the division of data into symbols, which are blocks of a fixed, predetermined size. + +These blocks are organized into matrices, where discrete mathematical operations are performed. This process enables the creation of an almost limitless number of symbols from the same original data. + +All the generated symbols are combined and sent to the recipient, allowing for the recovery of lost packets without the need for additional requests to the server. This method uses fewer packets than would be required if the same pieces of data were sent repeatedly. -The generated symbols are sent to the peer until he reports that all data has been received and restored (decoded) by applying the same discrete operations. +The symbols are transmitted to the peer until they confirm that all data has been received and successfully restored (decoded) by applying the same discrete operations. -[[Implementation example of RaptorQ in Golang]](https://github.com/xssnick/tonutils-go/tree/46dbf5f820af066ab10c5639a508b4295e5aa0fb/adnl/rldp/raptorq) +[[Please see implementation example of RaptorQ in Golang]](https://github.com/xssnick/tonutils-go/tree/46dbf5f820af066ab10c5639a508b4295e5aa0fb/adnl/rldp/raptorq). ## RLDP-HTTP -To interact with TON Sites, HTTP wrapped in RLDP is used. The hoster runs his site on any HTTP webserver and starts rldp-http-proxy next to it. -All requests from the TON network come via the RLDP protocol to the proxy, and the proxy reassembles the request into simple HTTP and calls the original web server locally. +To interact with TON Sites, the RLDP (Reverse Lightweight Data Protocol) is used to wrap HTTP requests. The host sets up their site on any standard HTTP web server and runs `rldp-http-proxy` alongside it. -The user on his side launches the proxy, for example, [Tonutils Proxy](https://github.com/xssnick/TonUtils-Proxy), and uses the `.ton` sites, all traffic is wrapped in the reverse order, requests go to the local HTTP proxy, and it sends them via RLDP to the remote TON site. +All incoming requests from the TON network are directed to the proxy via the RLDP protocol. The proxy then converts these requests into standard HTTP format and calls the original web server locally. + +On the user's side, they launch a proxy, such as [Tonutils Proxy](https://github.com/xssnick/TonUtils-Proxy), to access the .ton sites. All traffic is wrapped in the reverse order: requests are sent to the local HTTP proxy, which then forwards them via RLDP to the remote TON site. + +HTTP communication within RLDP is structured using TL formats: -HTTP inside RLDP is implemented using TL structures: ```tlb http.header name:string value:string = http.Header; http.payloadPart data:bytes trailer:(vector http.header) last:Bool = http.PayloadPart; @@ -68,29 +76,34 @@ http.response http_version:string status_code:int reason:string headers:(vector http.request id:int256 method:string url:string http_version:string headers:(vector http.header) = http.Response; http.getNextPayloadPart id:int256 seqno:int max_chunk_size:int = http.PayloadPart; ``` -This is not pure HTTP in text form, everything is wrapped in binary TL and unwrapped back to be sent to the web server or browser by the proxy itself. + +This is not pure HTTP in text form; everything is wrapped in a binary TL and unwrapped before being sent to the web server or browser by the proxy itself. The scheme of work is as follows: * Client sends `http.request` * The server checks the `Content-Length` header when receiving a request -* * If not 0, sends a `http.getNextPayloadPart` request to the client -* * When receiving a request, the client sends `http.payloadPart` - the requested body piece depending on `seqno` and `max_chunk_size`. -* * The server repeats requests, incrementing `seqno`, until it receives all the chunks from the client, i.e. until the `last:Bool` field of the last chunk received is true. + * If not 0, sends a `http.getNextPayloadPart` request to the client + * When receiving a request, the client sends `http.payloadPart` - the requested body piece depending on `seqno` and `max_chunk_size`. + * The server repeats requests, incrementing `seqno`, until it receives all the chunks from the client, i.e. until the `last:Bool` field of the last chunk received is true. * After processing the request, the server sends `http.response`, the client checks the `Content-Length` header -* * If it is not 0, then sends a `http.getNextPayloadPart` request to the server, and the operations are repeated, as in the case of the client but vice-versa. + * If it is not 0, then sends a `http.getNextPayloadPart` request to the server, and the operations are repeated, as in the case of the client but vice-versa. -## Request the TON Site +## Request the TON site To understand how RLDP works, let's look at an example of getting data from the TON site `foundation.ton`. -Let's say we have already got its ADNL address by calling the Get method of the NFT-DNS contract, [determined the address and port of the RLDP service using DHT](https://github.com/xssnick/ton-deep-doc/blob/master/DHT.md), and [connected to it over ADNL UDP](https://github.com/xssnick/ton-deep-doc/blob/master/ADNL-UDP-Internal.md). + +Assuming say we have already got its ADNL address by calling the Get method of the NFT-DNS contract, [determined the address and port of the RLDP service using DHT](https://github.com/xssnick/ton-deep-doc/blob/master/DHT.md), and [connected to it over ADNL UDP](https://github.com/xssnick/ton-deep-doc/blob/master/ADNL-UDP-Internal.md). ### Send a GET request to `foundation.ton` -To do this, fill in the structure: + +To accomplish this, please complete the following structure: + ```tlb http.request id:int256 method:string url:string http_version:string headers:(vector http.header) = http.Response; ``` Serialize `http.request` by filling in the fields: + ``` e191b161 -- TL ID http.request 116505dac8a9a3cdb464f9b5dd9af78594f23f1c295099a9b50c8245de471194 -- id = {random} @@ -103,6 +116,7 @@ e191b161 -- TL ID http ``` Now let's wrap our serialized `http.request` into `rldp.query` and serialize it too: + ``` 694d798a -- TL ID rldp.query 184c01cb1a1e4dc9322e5cabe8aa2d2a0a4dd82011edaf59eb66f3d4d15b1c5c -- query_id = {random} @@ -116,30 +130,38 @@ Now let's wrap our serialized `http.request` into `rldp.query` and serialize it ### Encoding and sending packets -Now we need to apply the FEC RaptorQ algorithm to this data. +We now need to apply the FEC RaptorQ algorithm to our data. -Let's create an encoder, for this we need to turn the resulting byte array into symbols of a fixed size. In TON, the symbol size is 768 bytes. -To do this, let's split the array into pieces of 768 bytes. In the last piece, if it comes out smaller than 768, it will need to be padded with zero bytes to the required size. +First, we will create an encoder, which requires us to convert the resulting byte array into symbols of a fixed size. In this case, the symbol size is 768 bytes. -Our array is 156 bytes in size, which means there will be only 1 piece, and we need to pad it with 612 zero bytes to a size of 768. +To achieve this, we'll divide the array into segments of 768 bytes each. If the last segment is smaller than 768 bytes, we will pad it with zero bytes to reach the required size. -Also, constants are selected for the encoder, depending on the size of the data and the symbol, you can learn more about this in the documentation of RaptorQ itself, but in order not to get into mathematical jungle, I recommend using a ready-made library that implements such encoding. -[[Example of creating an encoder]](https://github.com/xssnick/tonutils-go/blob/46dbf5f820af066ab10c5639a508b4295e5aa0fb/adnl/rldp/raptorq/encoder.go#L15) and [[Symbol encoding example]](https://github.com/xssnick/tonutils-go/blob/be3411cf412f23e6889bf0b648904306a15936e7/adnl/rldp/raptorq/solver.go#L26). +Our current array is 156 bytes long, which means it will consist of only one segment. To make it 768 bytes, we need to add 612 zero bytes for padding. -Symbols are encoded and sent in a round-robin style: we initially define `seqno` which is 0, and increment it by 1 for each successive encoded packet. For example, if we have 2 symbols, then we encode and send the first one, increase seqno by 1, then the second and increase seqno by 1, then again the first one and increase seqno, which at this moment is already equal to 2, by another 1. -And so until we receive a message that the peer has accepted the data. +Additionally, the constants chosen for the encoder depend on the data size and the symbol size. For more detailed information, you can refer to the RaptorQ documentation. However, to simplify the process and avoid complex mathematical calculations, we recommend using a pre-existing library that implements this encoding. + +Please see the examples: + +* [[Example of creating an encoder]](https://github.com/xssnick/tonutils-go/blob/46dbf5f820af066ab10c5639a508b4295e5aa0fb/adnl/rldp/raptorq/encoder.go#L15) +* [[Symbol encoding example]](https://github.com/xssnick/tonutils-go/blob/be3411cf412f23e6889bf0b648904306a15936e7/adnl/rldp/raptorq/solver.go#L26) + +Symbols are encoded and transmitted in a round-robin manner. We start with an initial sequence number, `seqno`, set to 0, and increment it by 1 for each subsequent encoded packet. For instance, if we have two symbols, we first encode and send the first symbol, then increase `seqno` by 1. Next, we encode and send the second symbol and again increase `seqno` by 1. After that, we return to the first symbol and increment `seqno` (which is now 2) by another 1. + +This process continues until we receive a message indicating that the peer has accepted the data. + +Having created the encoder, we are now ready to send data. To do this, we will fill in the TL schema: -Now, when we have created the encoder, we are ready to send data, for this we will fill in the TL schema: ```tlb fec.raptorQ data_size:int symbol_size:int symbols_count:int = fec.Type; rldp.messagePart transfer_id:int256 fec_type:fec.Type part:int total_size:long seqno:int data:bytes = rldp.MessagePart; ``` + * `transfer_id` - random int256, the same for all messageParts within the same data transfer. * `fec_type` is `fec.raptorQ`. -* * `data_size` = 156 -* * `symbol_size` = 768 -* * `symbols_count` = 1 + * `data_size` = 156 + * `symbol_size` = 768 + * `symbols_count` = 1 * `part` in our case always 0, can be used for transfers that hit the size limit. * `total_size` = 156. The size of our transfer data. * `seqno` - for the first packet will be equal to 0, and for each subsequent packet it will increase by 1, will be used as parameter to decode and encode symbol. @@ -147,43 +169,52 @@ rldp.messagePart transfer_id:int256 fec_type:fec.Type part:int total_size:long s After serializing `rldp.messagePart`, wrap it in `adnl.message.custom` and send it over ADNL UDP. -We send packets in a loop, increasing seqno all the time, until we wait for the `rldp.complete` message from the peer, or we stop on a timeout. After we have sent a number of packets equal to the number of our symbols, we can slow down and send an additional packet, for example, once every 10 milliseconds or fewer. -The extra packets are used for recovery in case of data loss, since UDP is a fast but unreliable protocol. +We will send packets in a continuous loop, incrementing the `seqno` each time, until we either receive the `rldp.complete` message from the peer or reach a timeout. Once we have sent a number of packets equal to the number of our symbols, we can slow down the transmission and send additional packets, for example, once every 10 milliseconds or even less frequently. + +These extra packets are intended for recovery in case of data loss, as UDP is a fast but unreliable protocol. -[[Implementation example]](https://github.com/xssnick/tonutils-go/blob/be3411cf412f23e6889bf0b648904306a15936e7/adnl/rldp/rldp.go#L249) +[[Please see implementation example]](https://github.com/xssnick/tonutils-go/blob/be3411cf412f23e6889bf0b648904306a15936e7/adnl/rldp/rldp.go#L249). ### Processing the response from `foundation.ton` -During the sending, we can already expect a response from the server, in our case we are waiting for `rldp.answer` with `http.response` inside. -It will come to us in the same way, in the form of an RLDP transfer, as it was sent at the time of the request, but `transfer_id` will be inverted (each byte XOR 0xFF). -We will get `adnl.message.custom` messages containing `rldp.messagePart`. +During the sending process, we can expect a response from the server. In our case, we are waiting for `rldp.answer` containing `http.response`. + +The response will arrive in the same format as it was sent during the request, but the `transfer_id` will be inverted (each byte will undergo an `XOR` operation with `0xFF`). + +We will receive `adnl.message.custom` messages that include `rldp.messagePart`. -First we need to get the FEC information from the first received message of the transfer, specifically the `data_size`, `symbol_size` and `symbols_count` parameters from the `fec.raptorQ` messagePart structure. -We need them to initialize the RaptorQ decoder. [[Example]](https://github.com/xssnick/tonutils-go/blob/be3411cf412f23e6889bf0b648904306a15936e7/adnl/rldp/rldp.go#L137) +First, we need to extract FEC information from the initial message received during the transfer. Specifically, we are looking for the `data_size`, `symbol_size`, and `symbols_count` parameters from the `fec.raptorQ` messagePart structure. -After initialization, we add the received symbols with their `seqno` to our decoder, and once we have accumulated the minimum required number equal to `symbols_count`, we can try to decode the full message. On success, we will send `rldp.complete`. [[Example]](https://github.com/xssnick/tonutils-go/blob/be3411cf412f23e6889bf0b648904306a15936e7/adnl/rldp/rldp.go#L168) +These parameters are essential for initializing the RaptorQ decoder. [[Please see the example]](https://github.com/xssnick/tonutils-go/blob/be3411cf412f23e6889bf0b648904306a15936e7/adnl/rldp/rldp.go#L137). + +After initialization, we add the received symbols along with their `seqno` to our decoder. Once we have gathered the minimum required number of symbols, equal to `symbols_count`, we can attempt to decode the full message. If successful, we will send `rldp.complete`. [[Please see the example]](https://github.com/xssnick/tonutils-go/blob/be3411cf412f23e6889bf0b648904306a15936e7/adnl/rldp/rldp.go#L168). + +The result will be a `rldp.answer` message containing the same `query_id` as in the sent `rldp.query`. The data must include `http.response`. -The result will be a `rldp.answer` message with the same query_id as in the `rldp.query` we sent. The data must contain `http.response`. ```tlb http.response http_version:string status_code:int reason:string headers:(vector http.header) no_payload:Bool = http.Response; ``` -With the main fields, I think everything is clear, the essence is the same as in HTTP. -An interesting flag here is `no_payload`, if it is true, then there is no body in the response, (`Content-Length` = 0). -The response from the server can be considered received. -If `no_payload` = false, then there is content in the response, and we need to get it. -To do this, we need to send a request with a TL schema `http.getNextPayloadPart` wrapped in `rldp.query`. +The main fields are generally straightforward, as they function similarly to those in HTTP. + +One notable flag is `no_payload`. If this flag is set to true, it indicates that there is no body in the response, meaning `Content-Length` is 0. In this case, the response from the server can be considered received. + +If `no_payload` is false, this means there is content in the response, and we need to retrieve it. To do this, we should send a request using the TL schema `http.getNextPayloadPart`, which should be wrapped in `rldp.query`. + ```tlb http.getNextPayloadPart id:int256 seqno:int max_chunk_size:int = http.PayloadPart; ``` -`id` should be the same as we sent in `http.request`, `seqno` - 0, and +1 for each next part. `max_chunk_size` is the maximum chunk size we are ready to accept, typically 128 KB (131072 bytes) is used. -In response, we will receive: +`id` must match the value sent in `http.request`, `seqno` should be 0, and increment by 1 for each subsequent part. The `max_chunk_size` indicates the largest chunk size we can accept, with a typical value of 128 KB (131072 bytes). + +In response, we will receive the following information: + ```tlb http.payloadPart data:bytes trailer:(vector http.header) last:Bool = http.PayloadPart; ``` -If `last` = true, then we have reached the end, we can put all the pieces together and get a complete response body, for example, html. + +If `last` is true, then we have reached the end. We can combine all the pieces to create a complete response body, such as HTML. ## References -_Here a [link to the original article](https://github.com/xssnick/ton-deep-doc/blob/master/RLDP.md) by [Oleg Baranov](https://github.com/xssnick)._ +_Here is the [link to the original article](https://github.com/xssnick/ton-deep-doc/blob/master/RLDP.md) by [Oleg Baranov](https://github.com/xssnick)._ From 440c39d86d8f2ee7d23eca36238e5407b0a13a8a Mon Sep 17 00:00:00 2001 From: D Ozgur Cakirkaya Date: Wed, 9 Apr 2025 15:38:55 +0100 Subject: [PATCH 14/14] overlay.md update --- .../network/protocols/overlay.md | 88 ++++++++++--------- 1 file changed, 46 insertions(+), 42 deletions(-) diff --git a/docs/v3/documentation/network/protocols/overlay.md b/docs/v3/documentation/network/protocols/overlay.md index 335b100db4f..775c436744c 100644 --- a/docs/v3/documentation/network/protocols/overlay.md +++ b/docs/v3/documentation/network/protocols/overlay.md @@ -1,93 +1,97 @@ # Overlay subnetworks -Implementation: -* https://github.com/ton-blockchain/ton/tree/master/overlay +Please see the implementation: + +* [Overlay](https://github.com/ton-blockchain/ton/tree/master/overlay) ## Overview -The architecture of TON is built in such a way that a lot of chains can exist simultaneously and independently in it - they can be both private or public. -Nodes have the ability to choose which shards and chains they store and process. -At the same time, the communication protocol remains unchanged due to its universality. Protocols such as DHT, RLDP and Overlays allow this to be achieved. -We are already familiar with the first two, in this section we will learn what Overlay is. -Overlays are responsible for dividing a single network into additional subnetworks. Overlays can be both public, to which anyone can connect, and private, where additional credentials is needed for entry, known only to a certain amount of people. +The architecture of the TON is designed to support multiple chains that can operate simultaneously and independently, whether they are private or public. Nodes have the flexibility to choose which shards and chains they store and process. + +Despite this variability, the communication protocol remains consistent due to its universal nature. Protocols such as DHT (Distributed Hash Table), RLDP (Reliable Layered Datagram Protocol), and overlays facilitate this functionality. + +We are already familiar with the first two protocols; in this section, we will focus on overlays. + +Overlays are responsible for partitioning a single network into additional subnetworks. These overlays can be public, allowing anyone to connect, or private, requiring specific credentials for access, which are known only to a limited group of individuals. All chains in the TON ecosystem, including the MasterChain, communicate using their respective overlays. To join an overlay, a node must locate other nodes that are already part of it and begin exchanging data with them. -All chains in TON, including the masterchain, communicate using their own overlay. -To join it, you need to find the nodes that are already in it, and start exchanging data with them. -For the public overlays you can find nodes using DHT. +For public overlays, you can discover nodes using the DHT protocol. -## ADNL vs Overlay networks +## ADNL vs overlay networks -In contrast to ADNL, the TON overlay networks usually do not support -sending datagrams to other arbitrary nodes. Instead, some ā€œsemi-permanent -linksā€ are established between certain nodes (called ā€œneighborsā€ with respect to -the overlay network under consideration) and messages are usually forwarded -along these links (i.e. from a node to one of its neighbors). +In contrast to ADNL, TON overlay networks typically do not allow the sending of datagrams to arbitrary nodes. Instead, they establish "semi-permanent links" between specific nodes, known as "neighbors," within the overlay network. Messages are usually forwarded along these links, meaning communication happens from one node to one of its neighbors. -Each overlay subnetwork has a 256-bit network identifier usually equal -to a SHA256 of the description of the overlay network—a TL-serialized object. +Each overlay subnetwork is assigned a 256-bit network identifier, which is usually equivalent to a SHA256 that describes the overlay network as a TL-serialized object. -Overlay subnetworks can be public or private. +Overlay subnetworks can either be public or private. -Overlay subnetworks work according to a special [gossip](https://en.wikipedia.org/wiki/Gossip_protocol) protocol. +These subnetworks operate using a special [gossip](https://en.wikipedia.org/wiki/Gossip_protocol) protocol. ## Interaction with overlay nodes -We have already analyzed an example with finding overlay nodes in an article about DHT, -in the section [Search for nodes that store the state of the blockchain](/v3/documentation/network/protocols/dht/dht-deep-dive#search-for-nodes-that-store-the-state-of-the-blockchain). -In this section, we will focus on interacting with them. +We have already analyzed an example of finding overlay nodes in an article about Distributed Hash Tables (DHT). This was discussed in the section titled [Search for nodes that store the state of the blockchain](/v3/documentation/network/protocols/dht/dht-deep-dive#search-for-nodes-that-store-the-state-of-the-blockchain). -When querying the DHT, we will get the addresses of the overlay nodes, from which we can find out the addresses of other nodes of this overlay using [overlay.getRandomPeers](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/ton_api.tl#L237) query. -Once we connect to a sufficient number of nodes, we can receive all blocks information and other chain events from them, as well as send our transactions to them for processing. +In this section, we will focus on how to interact with these nodes. + +When querying the DHT, we will retrieve the addresses of the overlay nodes. From these addresses, we can discover the addresses of additional nodes within the overlay by using the [overlay.getRandomPeers](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/ton_api.tl#L237) query. + +After connecting to a sufficient number of nodes, we will be able to receive information about all blocks and other chain events from them. Additionally, we can send our transactions to these nodes for processing. ### Find more neighbors -Let's look at an example of getting nodes in an overlay. +To retrieve nodes in an overlay, send a request `overlay.getRandomPeers` to any known node. + +Make sure to serialize the TL schema: -To do this, send a request `overlay.getRandomPeers` to any known node of the overlay, serialize the TL schema: ```tlb overlay.node id:PublicKey overlay:int256 version:int signature:bytes = overlay.Node; overlay.nodes nodes:(vector overlay.node) = overlay.Nodes; overlay.getRandomPeers peers:overlay.nodes = overlay.Nodes; ``` -`peers` - should contain the peers we know, so we don't get them back, but since we don't know any yet, `peers.nodes` will be an empty array. -In case if we want to not just get some information, but participate in overlay and get broadcasts, we should also add in `peers` information about our node, from which we're doing request. -When peers will get info about us - they will start to send us broadcasts using ADNL or RLDP. +The `peers` array should include the peers we are aware of so that we do not receive messages from them again. Since we currently do not know any peers, `peers.nodes` will initially be an empty array. + +If we want to retrieve information, participate in the overlay, and receive broadcasts, we need to include information about our own node in the `peers` array during the request. Once the peers are aware of our presence, they will begin to send us broadcasts using ADNL or RLDP. + +Additionally, each request made within the overlay must be prefixed with the TL schema: -Each request inside the overlay must be prefixed with the TL schema: ```tlb overlay.query overlay:int256 = True; ``` -The `overlay` should be the id of the overlay - the id of the `tonNode.ShardPublicOverlayId` schema key - the same one we used to search the DHT. -We need to concat 2 serialized schemas by simply concatenating 2 serialized byte arrays, `overlay.query` will come first, `overlay.getRandomPeers` second. +The `overlay` should be the overlay's ID, specifically the ID of the `tonNode.ShardPublicOverlayId` schema key, which we also used to search the DHT. -We wrap the resulting array in the `adnl.message.query` schema and send it via ADNL. In response, we are waiting for `overlay.nodes` - this will be a list of overlay nodes to which we can connect and, if necessary, repeat the same request to new of them until we get enough connections. +To combine two serialized schemas, we should concatenate two serialized byte arrays: `overlay.query` will come first, followed by `overlay.getRandomPeers`. + +We then wrap the resulting array in the `adnl.message.query` schema and send it via ADNL. In response, we expect `overlay.nodes`, which will be a list of overlay nodes that we can connect to. If necessary, we can repeat the request to any new nodes until we acquire enough connections. ### Functional requests -Once the connection is established, we can access the overlay nodes using [requests](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/ton_api.tl#L413) `tonNode.*`. +Once the connection is established, we can access the overlay nodes using `tonNode.*` via the [requests](https://github.com/ton-blockchain/ton/blob/ad736c6bc3c06ad54dc6e40d62acbaf5dae41584/tl/generate/scheme/ton_api.tl#L413). + +We utilize the RLDP protocol for these types of requests. It's crucial to remember that every query in the overlay must begin with the `overlay.query` prefix. -For requests of this kind, the RLDP protocol is used. And it's important not to forget the `overlay.query` prefix - it must be used for every query in the overlay. +The requests themselves are quite standard and resemble those we discussed in the article about ADNL TCP found [here](/v3/documentation/network/protocols/adnl/adnl-tcp#getmasterchaininfo). -There is nothing unusual about the requests themselves, they are very similar to what we [did in the article about ADNL TCP](/v3/documentation/network/protocols/adnl/adnl-tcp#getmasterchaininfo). +For example, the `downloadBlockFull` request follows the familiar block ID schema: -For example, the `downloadBlockFull` request uses the already familiar schema of block id: ```tlb tonNode.downloadBlockFull block:tonNode.blockIdExt = tonNode.DataFull; ``` -By passing it, we will be able to download the full information about the block, in response we will receive: + +By passing this step, we can download complete information about the block, and in response, we will receive: + ```tlb tonNode.dataFull id:tonNode.blockIdExt proof:bytes block:bytes is_link:Bool = tonNode.DataFull; or tonNode.dataFullEmpty = tonNode.DataFull; ``` -If present, the `block` field will contain data in TL-B format. -Thus, we can receive information directly from the nodes. +If the `block` field is present, it will contain data in TL-B format. + +This allows us to receive information directly from the nodes. ## References -_Here a [link to the original article](https://github.com/xssnick/ton-deep-doc/blob/master/Overlay-Network.md) by [Oleg Baranov](https://github.com/xssnick)._ +_Here is the [link to the original article](https://github.com/xssnick/ton-deep-doc/blob/master/Overlay-Network.md) by [Oleg Baranov](https://github.com/xssnick)._