Skip to content

Commit a464438

Browse files
committed
Merge branch 'mytoncrl1_merge' into mytonctrl2_merge
# Conflicts: # mytoncore/mytoncore.py # mytonctrl.py # mytonctrl/scripts/upgrade.sh # scripts/ton_installer.sh
2 parents f50f6af + 47275a9 commit a464438

File tree

4 files changed

+269
-0
lines changed

4 files changed

+269
-0
lines changed

custom_overlays.py

Lines changed: 191 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,191 @@
1+
import base64
2+
import json
3+
import requests
4+
5+
from mypylib.mypylib import color_print
6+
7+
8+
def hex2base64(h):
9+
b = bytes.fromhex(h)
10+
b64 = base64.b64encode(b)
11+
s = b64.decode("utf-8")
12+
return s
13+
14+
15+
def parse_config(name: str, config: dict, vset: list = None):
16+
"""
17+
Converts config to validator-console friendly format
18+
:param name: custom overlay name
19+
:param config: config
20+
:param vset: list of validators adnl addresses, can be None if `@validators` not in config
21+
:return:
22+
"""
23+
result = {
24+
"name": name,
25+
"nodes": []
26+
}
27+
for k, v in config.items():
28+
if k == '@validators' and v:
29+
if vset is None:
30+
raise Exception("Validators set is not defined but @validators is in config")
31+
for v_adnl in vset:
32+
result["nodes"].append({
33+
"adnl_id": hex2base64(v_adnl),
34+
"msg_sender": False,
35+
})
36+
else:
37+
result["nodes"].append({
38+
"adnl_id": hex2base64(k),
39+
"msg_sender": v["msg_sender"],
40+
})
41+
if v["msg_sender"]:
42+
result["nodes"][-1]["msg_sender_priority"] = v["msg_sender_priority"]
43+
return result
44+
45+
46+
def add_custom_overlay(args):
47+
from mytonctrl import ton, local
48+
if len(args) != 2:
49+
color_print("{red}Bad args. Usage:{endc} add_custom_overlay <name> <path_to_config>")
50+
return
51+
path = args[1]
52+
with open(path, 'r') as f:
53+
config = json.load(f)
54+
ton.set_custom_overlay(args[0], config)
55+
if '@validators' in config:
56+
print('Dynamic overlay will be added within 1 minute')
57+
else:
58+
result = add_custom_overlay_to_vc(local, ton, parse_config(args[0], config))
59+
if not result:
60+
print('Failed to add overlay to validator console')
61+
color_print("add_custom_overlay - {red}ERROR{endc}")
62+
return
63+
color_print("add_custom_overlay - {green}OK{endc}")
64+
65+
66+
def list_custom_overlays(args):
67+
from mytonctrl import ton
68+
if not ton.get_custom_overlays():
69+
color_print("{red}No custom overlays{endc}")
70+
return
71+
for k, v in ton.get_custom_overlays().items():
72+
color_print(f"Custom overlay {{bold}}{k}{{endc}}:")
73+
print(json.dumps(v, indent=4))
74+
75+
76+
def delete_custom_overlay(args):
77+
from mytonctrl import ton
78+
if len(args) != 1:
79+
color_print("{red}Bad args. Usage:{endc} delete_custom_overlay <name>")
80+
return
81+
if '@validators' in ton.get_custom_overlays().get(args[0], {}):
82+
ton.delete_custom_overlay(args[0])
83+
print('Dynamic overlay will be deleted within 1 minute')
84+
else:
85+
ton.delete_custom_overlay(args[0])
86+
result = delete_custom_overlay_from_vc(ton, args[0])
87+
if not result:
88+
print('Failed to delete overlay from validator console')
89+
color_print("delete_custom_overlay - {red}ERROR{endc}")
90+
return
91+
color_print("delete_custom_overlay - {green}OK{endc}")
92+
93+
94+
def check_node_eligible_for_custom_overlay(ton, config: dict):
95+
vconfig = ton.GetValidatorConfig()
96+
my_adnls = vconfig.adnl
97+
node_adnls = [i["adnl_id"] for i in config["nodes"]]
98+
for adnl in my_adnls:
99+
if adnl.id in node_adnls:
100+
return True
101+
return False
102+
103+
104+
def delete_custom_overlay_from_vc(ton, name: str):
105+
result = ton.validatorConsole.Run(f"delcustomoverlay {name}")
106+
return 'success' in result
107+
108+
109+
def add_custom_overlay_to_vc(local, ton, config: dict):
110+
if not check_node_eligible_for_custom_overlay(ton, config):
111+
local.add_log(f"Node has no adnl address required for custom overlay {config.get('name')}", "debug")
112+
return False
113+
local.add_log(f"Adding custom overlay {config.get('name')}", "debug")
114+
path = ton.tempDir + f'/custom_overlay_{config["name"]}.json'
115+
with open(path, 'w') as f:
116+
json.dump(config, f)
117+
result = ton.validatorConsole.Run(f"addcustomoverlay {path}")
118+
return 'success' in result
119+
120+
121+
def custom_overlays(local, ton):
122+
config = get_default_custom_overlay(local, ton)
123+
if config is not None:
124+
ton.set_custom_overlay('default', config)
125+
deploy_custom_overlays(local, ton)
126+
127+
128+
def deploy_custom_overlays(local, ton):
129+
result = ton.validatorConsole.Run("showcustomoverlays")
130+
if 'unknown command' in result:
131+
return # node old version
132+
names = []
133+
for line in result.split('\n'):
134+
if line.startswith('Overlay'):
135+
names.append(line.split(' ')[1].replace('"', '').replace(':', ''))
136+
137+
config34 = ton.GetConfig34()
138+
current_el_id = config34['startWorkTime']
139+
current_vset = [i["adnlAddr"] for i in config34['validators']]
140+
141+
config36 = ton.GetConfig36()
142+
next_el_id = config36['startWorkTime'] if config36['validators'] else 0
143+
next_vset = [i["adnlAddr"] for i in config36['validators']]
144+
145+
for name in names:
146+
# check that overlay still exists in mtc db
147+
pure_name = name
148+
suffix = name.split('_')[-1]
149+
if suffix.startswith('elid') and suffix.split('elid')[-1].isdigit(): # probably election id
150+
pure_name = '_'.join(name.split('_')[:-1])
151+
el_id = int(suffix.split('elid')[-1])
152+
if el_id not in (current_el_id, next_el_id):
153+
local.add_log(f"Overlay {name} is not in current or next election, deleting", "debug")
154+
delete_custom_overlay_from_vc(ton, name) # delete overlay if election id is not in current or next election
155+
continue
156+
157+
if pure_name not in ton.get_custom_overlays():
158+
local.add_log(f"Overlay {name} ({pure_name}) is not in mtc db, deleting", "debug")
159+
delete_custom_overlay_from_vc(ton, name) # delete overlay if it's not in mtc db
160+
161+
for name, config in ton.get_custom_overlays().items():
162+
if name in names:
163+
continue
164+
if '@validators' in config:
165+
new_name = name + '_elid' + str(current_el_id)
166+
if new_name not in names:
167+
node_config = parse_config(new_name, config, current_vset)
168+
add_custom_overlay_to_vc(local, ton, node_config)
169+
170+
if next_el_id != 0:
171+
new_name = name + '_elid' + str(next_el_id)
172+
if new_name not in names:
173+
node_config = parse_config(new_name, config, next_vset)
174+
add_custom_overlay_to_vc(local, ton, node_config)
175+
else:
176+
node_config = parse_config(name, config)
177+
add_custom_overlay_to_vc(local, ton, node_config)
178+
179+
180+
def get_default_custom_overlay(local, ton):
181+
if not local.db.get('useDefaultCustomOverlays', True):
182+
return None
183+
network = ton.GetNetworkName()
184+
default_url = 'https://ton-blockchain.github.io/fallback_custom_overlays.json'
185+
url = local.db.get('defaultCustomOverlaysUrl', default_url)
186+
resp = requests.get(url)
187+
if resp.status_code != 200:
188+
local.add_log(f"Failed to get default custom overlays from {url}", "error")
189+
return None
190+
config = resp.json()
191+
return config.get(network)

mytonctrl/resources/translate.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,6 +419,16 @@
419419
"ru": "{green}Доступно обновление MyTonCtrl. {red}Пожалуйста, обновите его с помощью команды `update`.{endc}",
420420
"zh_TW": "{green}MyTonCtrl 有可用更新. {red}請使用 `update` 命令進行更新.{endc}"
421421
},
422+
"update_mtc2_warning": {
423+
"en": "{red}This version is outdated. Please update to the second version: `update mytonctrl2`{endc}",
424+
"ru": "{red}Данная версия устарела. Пожалуйста обновитесь на вторую версию: `update mytonctrl2`{endc}",
425+
"zh_TW": "{red}這個版本已經過時了。請更新至第二版本: `update mytonctrl2`{endc}"
426+
},
427+
"disk_usage_warning": {
428+
"en": "{red} Disk is almost full, clean the TON database immediately: https://docs.ton.org/participate/nodes/node-maintenance-and-security#database-grooming {endc}",
429+
"ru": "{red} Диск почти заполнен, немедленно очистите базу данных TON: https://docs.ton.org/participate/nodes/node-maintenance-and-security#database-grooming {endc}",
430+
"zh_TW": "{red} 磁盤幾乎滿了,立即清理 TON 數據庫: https://docs.ton.org/participate/nodes/node-maintenance-and-security#database-grooming {endc}"
431+
},
422432
"ton_update_available": {
423433
"en": "{green}TON update available. {red}Please update it with `upgrade` command.{endc}",
424434
"ru": "{green}Доступно обновление TON. {red}Пожалуйста, обновите его с помощью команды `upgrade`.{endc}",

scripts/set_archive_ttl.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
import subprocess
2+
import sys
3+
4+
with open('/etc/systemd/system/validator.service', 'r') as file:
5+
service = file.read()
6+
7+
8+
for line in service.split('\n'):
9+
if line.startswith('ExecStart'):
10+
exec_start = line
11+
break
12+
13+
14+
if '--archive-ttl' in exec_start:
15+
print('Archive TTL is already set')
16+
sys.exit(100)
17+
18+
default_command = 'ExecStart = /usr/bin/ton/validator-engine/validator-engine --threads --daemonize --global-config /usr/bin/ton/global.config.json --db /var/ton-work/db/ --logname /var/ton-work/log --state-ttl 604800 --verbosity'
19+
20+
# ExecStart = /usr/bin/ton/validator-engine/validator-engine --threads 31 --daemonize --global-config /usr/bin/ton/global.config.json --db /var/ton-work/db/ --logname /var/ton-work/log --state-ttl 604800 --verbosity 1
21+
22+
t = exec_start.split(' ')
23+
t.pop(t.index('--threads') + 1) # pop threads value since it's different for each node
24+
t.pop(t.index('--verbosity') + 1) # pop verbosity value
25+
26+
if ' '.join(t) != default_command:
27+
print('ExecStart is not default. Please set archive-ttl manually in `/etc/systemd/system/validator.service`.')
28+
sys.exit(101)
29+
30+
archive_ttl = sys.argv[1]
31+
32+
new_exec_start = exec_start + f' --archive-ttl {archive_ttl}'
33+
34+
with open('/etc/systemd/system/validator.service', 'w') as file:
35+
file.write(service.replace(exec_start, new_exec_start))
36+
37+
subprocess.run(['systemctl', 'daemon-reload'])
38+
subprocess.run(['systemctl', 'restart', 'validator'])

scripts/set_state_ttl.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import subprocess
2+
import sys
3+
4+
with open('/etc/systemd/system/validator.service', 'r') as file:
5+
service = file.read()
6+
7+
8+
for line in service.split('\n'):
9+
if line.startswith('ExecStart'):
10+
exec_start = line
11+
break
12+
13+
14+
if exec_start.split(' ')[2] != '/usr/bin/ton/validator-engine/validator-engine':
15+
raise Exception('Invalid node start command in service file')
16+
17+
18+
if '--state-ttl 604800' not in exec_start:
19+
print('No state-ttl or custom one found in ExecStart')
20+
sys.exit(0)
21+
22+
new_exec_start = exec_start.replace('--state-ttl 604800', '')
23+
24+
with open('/etc/systemd/system/validator.service', 'w') as file:
25+
file.write(service.replace(exec_start, new_exec_start))
26+
27+
subprocess.run(['systemctl', 'daemon-reload'])
28+
subprocess.run(['systemctl', 'restart', 'validator'])
29+
30+
print('Removed state-ttl from service file.')

0 commit comments

Comments
 (0)