README

relay

ETH-TON bridge connecting link
​​
​
​

Runtime requirements

  • CPU: 8 cores, 2 GHz
  • RAM: 16 GB
  • Storage: 200 GB fast SSD
  • Network: 100 MBit/s

How to run

To simplify the build and create some semblance of standardization in this repository there is a set of scripts for configuring the relay.
NOTE: scripts are prepared and tested on Ubuntu 20.04. You may need to modify them a little for other distros.
  1. 1.
    Setup relay service
    • Native version (a little more complex way, but gives some performance gain and reduces the load):
      1
      ./scripts/setup.sh -t native
      Copied!
    • OR docker version (the simplest way, but adds some overhead):
      1
      ./scripts/setup.sh -t docker
      Copied!
      Not recommended for machines with lower specs than required
    At this stage, a systemd service relay is created. Configs and keys will be in /etc/relay and TON node DB will be in /var/db/relay.
    Do not start this service yet!
  2. 2.
    Prepare config
    Either add the environment variables to the [Service] section of unit file. It is located at /etc/systemd/system/relay.service.
    This method is recommended because you can just make a backup of /etc/relay and not be afraid for it's safety, all keys in it are encrypted
    1
    [Service]
    2
    ...
    3
    Environment=RELAY_MASTER_KEY=stub-master-key
    4
    Environment=RELAY_STAKER_ADDRESS=your-staker-address
    5
    Environment=ETH_MAINNET_URL=eth-http-rpc-endpoint
    6
    Environment=POLYGON_URL=polygon-http-rpc-endpoint
    7
    ...
    Copied!
    Or simply replace the ${..} parameters in the config. It is located at /etc/relay/config.yaml.
  3. 3.
    Generate keys
    1
    ./scripts/generate.sh -t docker # or `native`, depends on your installation type
    Copied!
    if you already have seed phrases that you want to import, then add the -i flag
    This script will print unencrypted data. Be sure to write it down somewhere! And also make a backup of the /etc/relay folder!
  4. 4.
    Link relay keys
    Use ETH address and TON public key from the previous step to link this relay setup with your staker address at https://v2.tonbridge.io/relayers/create. When you start the linking process go to step 5 and start the relay. It will begin to confirm the public key and address on the air. It may take some time to sync at first (~40 minutes).
    During linking you will need to send at least 0.05 ETH to your relay ETH address so that the relay can confirm his ownership.
    If you think that this is a lot or if the gas price is more than 300 GWEI now, then you can change the values in the config.
  5. 5.
    Enable and start relay service
    1
    systemctl enable relay
    2
    systemctl start relay
    3
    ​
    4
    # Optionally check if it is running normally. It will take some time to start.
    5
    # Relay is fully operational when it prints `Initialized relay`
    6
    journalctl -fu relay
    Copied!
    Relay will be running on UDP port 30000 by default, so make sure that this port is not blocked by firewall.
    NOTE: docker installation uses port 30000 in unit file, so you may need to update the service if you decide to change it. All environment variables must also be passed to container (e.g. -e RELAY_MASTER_KEY).
    Relay has a built-in Prometheus metrics exporter which is configured in the metrics_settings section of the config. By default, metrics are available at http://127.0.0.1:10000/
    Response example:
    1
    eth_subscriber_last_processed_block{staker="0:7a9701bede7f86bf039aba200c1bb421a388bbb4b0580bfaeafa66f908d2b246",chain_id="250"} 19757952
    2
    eth_subscriber_pending_confirmation_count{staker="0:7a9701bede7f86bf039aba200c1bb421a388bbb4b0580bfaeafa66f908d2b246",chain_id="250"} 0
    3
    eth_subscriber_last_processed_block{staker="0:7a9701bede7f86bf039aba200c1bb421a388bbb4b0580bfaeafa66f908d2b246",chain_id="1"} 13467334
    4
    eth_subscriber_pending_confirmation_count{staker="0:7a9701bede7f86bf039aba200c1bb421a388bbb4b0580bfaeafa66f908d2b246",chain_id="1"} 0
    5
    eth_subscriber_last_processed_block{staker="0:7a9701bede7f86bf039aba200c1bb421a388bbb4b0580bfaeafa66f908d2b246",chain_id="137"} 20486774
    6
    eth_subscriber_pending_confirmation_count{staker="0:7a9701bede7f86bf039aba200c1bb421a388bbb4b0580bfaeafa66f908d2b246",chain_id="137"} 0
    7
    eth_subscriber_last_processed_block{staker="0:7a9701bede7f86bf039aba200c1bb421a388bbb4b0580bfaeafa66f908d2b246",chain_id="56"} 12140031
    8
    eth_subscriber_pending_confirmation_count{staker="0:7a9701bede7f86bf039aba200c1bb421a388bbb4b0580bfaeafa66f908d2b246",chain_id="56"} 0
    9
    ton_subscriber_ready{staker="0:7a9701bede7f86bf039aba200c1bb421a388bbb4b0580bfaeafa66f908d2b246"} true
    10
    ton_subscriber_current_utime{staker="0:7a9701bede7f86bf039aba200c1bb421a388bbb4b0580bfaeafa66f908d2b246"} 1635368353
    11
    ton_subscriber_time_diff{staker="0:7a9701bede7f86bf039aba200c1bb421a388bbb4b0580bfaeafa66f908d2b246"} 5
    12
    ton_subscriber_pending_message_count{staker="0:7a9701bede7f86bf039aba200c1bb421a388bbb4b0580bfaeafa66f908d2b246"} 0
    13
    bridge_pending_eth_event_count{staker="0:7a9701bede7f86bf039aba200c1bb421a388bbb4b0580bfaeafa66f908d2b246"} 0
    14
    bridge_pending_ton_event_count{staker="0:7a9701bede7f86bf039aba200c1bb421a388bbb4b0580bfaeafa66f908d2b246"} 0
    15
    staking_user_data_tokens_balance{staker="0:7a9701bede7f86bf039aba200c1bb421a388bbb4b0580bfaeafa66f908d2b246"} 100000000000000
    16
    staking_current_relay_round{staker="0:7a9701bede7f86bf039aba200c1bb421a388bbb4b0580bfaeafa66f908d2b246"} 5
    17
    staking_elections_start_time{staker="0:7a9701bede7f86bf039aba200c1bb421a388bbb4b0580bfaeafa66f908d2b246",round_num="5"} 1635541843
    18
    staking_elections_status{staker="0:7a9701bede7f86bf039aba200c1bb421a388bbb4b0580bfaeafa66f908d2b246",round_num="5"} 0
    Copied!

Example config

NOTE: The syntax ${VAR} can also be used everywhere in config. It will be replaced by the value of the environment variable VAR.
1
---
2
# Keystore password
3
master_password: "${RELAY_MASTER_KEY}"
4
# Your address from which you specified keys
5
staker_address: "${RELAY_STAKER_ADDRESS}"
6
bridge_settings:
7
# Keystore data path
8
keys_path: "/etc/relay/keys.json"
9
# Bridge contract address
10
bridge_address: "0:65d2002fae133c1064ae0f0ff44e416e52f112cf8faece53cd39e93d0f4d23d7"
11
# If set, relay will not participate in elections. Default: false
12
ignore_elections: false
13
# EVM network configs
14
networks:
15
# Ethereum
16
- chain_id: 1
17
# RPC node HTTP endpoint
18
endpoint: "${ETH_MAINNET_URL}"
19
# Timeout, used for simple getter requests. Default: 10
20
get_timeout_sec: 10
21
# Timeout, used for processing eth_getLogs response. Default: 120
22
blocks_processing_timeout_sec: 120
23
# Max simultaneous connection count. Default: 10
24
pool_size: 10
25
# Idle polling interval. Default: 60
26
poll_interval_sec: 60
27
# Maximum blocks range for getLogs request
28
max_block_range: 5000
29
# Smart Chain
30
- chain_id: 56
31
# Public endpoint
32
endpoint: https://bsc-dataseed.binance.org
33
get_timeout_sec: 10
34
pool_size: 10
35
poll_interval_sec: 60
36
max_block_range: 5000
37
# Fantom Opera
38
- chain_id: 250
39
# Public endpoint
40
endpoint: https://rpc.ftm.tools
41
get_timeout_sec: 10
42
pool_size: 10
43
poll_interval_sec: 60
44
max_block_range: 5000
45
# Polygon
46
- chain_id: 137
47
endpoint: "${POLYGON_URL}"
48
get_timeout_sec: 10
49
pool_size: 10
50
poll_interval_sec: 60
51
max_block_range: 5000
52
node_settings:
53
# Root directory for relay DB. Default: "./db"
54
db_path: "/var/db/relay"
55
# UDP port, used for ADNL node. Default: 30303
56
adnl_port: 30000
57
# Path to temporary ADNL keys.
58
# NOTE: Will be generated if it was not there.
59
# Default: "./adnl-keys.json"
60
temp_keys_path: "/etc/relay/adnl-keys.json"
61
metrics_settings:
62
# Listen address of metrics. Used by the client to gather prometheus metrics.
63
# Default: "127.0.0.1:10000"
64
listen_address: "127.0.0.1:10000"
65
# URL path to the metrics. Default: "/"
66
# Example: `curl http://127.0.0.1:10000/`
67
metrics_path: "/"
68
# Metrics update interval in seconds. Default: 10
69
collection_interval_sec: 10
70
# log4rs settings.
71
# See https://docs.rs/log4rs/1.0.0/log4rs/ for more details
72
logger_settings:
73
appenders:
74
stdout:
75
kind: console
76
encoder:
77
pattern: "{h({l})} {M} = {m} {n}"
78
root:
79
level: error
80
appenders:
81
- stdout
82
loggers:
83
relay:
84
level: info
85
appenders:
86
- stdout
87
additive: false
Copied!

Architecture overview

The relay is simultaneously the TON node and can communicate with all EVM networks specified in the config. Its purpose is to check and sign transaction events.
At startup, it synchronizes the TON node and downloads blockchain state. It searches Bridge contract state in it, all connectors, active configurations and pending events. Then it subscribes to the Bridge contract in TON and listens for connector deployment events. Each new connector can produce activation event which signals that relay should subscribe to the event configuration contract. Each configuration contract produces event deployment events, relay sees and checks them.
  • For TON-to-EVM events, only the correctness of data packing is checked (all other stuff is verified on the contracts side). If the event is correct, the relay converts this data into ETH ABI encoded bytes and signs it with its ETH key. This signature is sent along with a confirmation message. If the data in the event was invalid then the relay sends a rejection message.
    TON-to-EVM ABI mapping rules:
    1
    bytes => same
    2
    string => same
    3
    uintX => same
    4
    intX => same
    5
    bool => same
    6
    fixedbytes => same
    7
    fixedarray => same but mapped
    8
    array => same but mapped
    9
    tuple => same but mapped
    10
    _ => unsupported
    Copied!
  • For EVM-to-TON events, all event parameters are checked on the relay side. It waits for or looking for a transaction on the specified EVM network, converts event data to the TVM cell and sends a confirmation message if everything was correct. Otherwise, it sends a rejection message.
    ETH-to-TON ABI mapping rules:
    1
    address => bytes (of length 20)
    2
    bytes => bytes or cell (*)
    3
    string => same
    4
    intX => same
    5
    uintX => same
    6
    bool => same
    7
    array => same but mapped
    8
    fixedbytes1 => depends on context (**)
    9
    fixedbytesX => same
    10
    fixedarray => same but mapped
    11
    tuple => same but mapped or cell (***)
    12
    _ => unsupported
    Copied!
    When converting ABI from EVM format to TON, there is a mechanism for controlling this process. You can add a bytes1 (**) element which sets context flags to its value.
    Currently, there are only three flags:
    • 0x01 - place tuples to new cell (***)
    • 0x02 - interpret bytes as encoded TVM cell (*)
    • 0x04 - insert default cell in case of error with flag 0x02 (*)
    NOTE: Flags can't be changed inside an array element! This would lead to inconsistent array items ABI.
The decision to make the relay a TON node was not made by chance. In the first version, several relays were connected to the one "light" node which was constantly restarted or to the graphql which also was quite unreliable. As a result, relays instantly see all events and vote for them almost simultaneously in one block. The implementation is more optimized than C++ node, so they don't harm the network.

Changelog

2.0.5 (2021-11-27)

Features
  • Improved ETH events verification
  • Updated events ABI
  • Added ton_subscriber_shard_client_time_diff, ton_subscriber_mc_block_seqno and ton_subscriber_shard_client_mc_block_seqno values into metrics

2.0.4 (2021-11-11)

Features
  • Use jemalloc by default
Bugfixes
  • Fixed blocks GC memory issues

2.0.3 (2021-11-09)

Features
  • Hot reload for metrics exporter and logger settings (SIGHUP signal)
  • Blocks and states garbage collection
  • Additional EVM RPC timing controls
  • Improved database layout and increased data locality
Bugfixes
  • Fixed exported metrics format
  • Fixed event confirmation counters
  • Fixed time diff metrics
  • Reduced blocks range for eth_getLogs
  • Ignore descending blocks for ETH rpc

2.0.2

Features
  • Added setup scripts for fast deployment
Bugfixes
  • Fixed bridge contracts interaction logic according to new changes

2.0.1

Initial release
Last modified 3d ago
Copy link