Skip to content

Commit 4ac35ae

Browse files
committed
add downloading blocks and states from ton storage
1 parent c6ff0b7 commit 4ac35ae

File tree

3 files changed

+108
-5
lines changed

3 files changed

+108
-5
lines changed

mytoninstaller/settings.py

Lines changed: 92 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
import os
22
import os.path
3+
import time
4+
35
import psutil
46
import base64
57
import subprocess
@@ -16,7 +18,8 @@
1618
ip2int,
1719
Dict, int2ip
1820
)
19-
from mytoninstaller.utils import StartValidator, StartMytoncore, start_service, stop_service, get_ed25519_pubkey
21+
from mytoninstaller.utils import StartValidator, StartMytoncore, start_service, stop_service, get_ed25519_pubkey, \
22+
disable_service
2023
from mytoninstaller.config import SetConfig, GetConfig, get_own_ip, backup_config
2124
from mytoncore.utils import hex2b64
2225

@@ -86,8 +89,9 @@ def FirstNodeSettings(local):
8689
args = [validatorAppPath, "--global-config", globalConfigPath, "--db", ton_db_dir, "--ip", addr, "--logname", tonLogPath]
8790
subprocess.run(args)
8891

89-
# Скачать дамп
90-
DownloadDump(local)
92+
# Download dumps from TON Storage
93+
download_archive_from_ts(local)
94+
# DownloadDump(local)
9195

9296
# chown 1
9397
local.add_log("Chown ton-work dir", "debug")
@@ -106,6 +110,89 @@ def is_testnet(local):
106110
return True
107111
return False
108112

113+
def download_bag(local, bag_id: str):
114+
local_ts_url = f"http://127.0.0.1:{local.buffer.ton_storage.api_port}"
115+
downloads_path = '/tmp/ts-downloads/'
116+
117+
resp = requests.post(local_ts_url + '/api/v1/add', json={'bag_id': bag_id, 'download_all': True, 'path': downloads_path})
118+
if not resp.json()['ok']:
119+
local.add_log("Error adding bag: " + resp.json(), "error")
120+
return False
121+
resp = requests.get(local_ts_url + f'/api/v1/details?bag_id={bag_id}').json()
122+
while not resp['completed']:
123+
if resp['size'] == 0:
124+
local.add_log(f"STARTING DOWNLOADING {bag_id}", "debug")
125+
time.sleep(20)
126+
resp = requests.get(local_ts_url + f'/api/v1/details?bag_id={bag_id}').json()
127+
continue
128+
text = f'DOWNLOADING {bag_id} {round((resp["downloaded"] / resp["size"]) * 100)}% ({resp["downloaded"] / 10**6} / {resp["size"] / 10**6} MB), speed: {resp["download_speed"] / 10**6} MB/s'
129+
local.add_log(text, "debug")
130+
time.sleep(20)
131+
resp = requests.get(local_ts_url + f'/api/v1/details?bag_id={bag_id}').json()
132+
local.add_log(f"DOWNLOADED {bag_id}", "debug")
133+
return True
134+
135+
136+
def download_archive_from_ts(local):
137+
archive_block = os.getenv('ARCHIVE_BLOCKS')
138+
dump = local.buffer.dump
139+
if not archive_block and not dump:
140+
return
141+
142+
enable_ton_storage(local)
143+
url = 'https://archival-dump.ton.org/index/mainnet.json'
144+
if is_testnet(local):
145+
url = 'https://archival-dump.ton.org/index/testnet.json'
146+
147+
state_bag = {}
148+
block_bags = []
149+
150+
blocks_config = requests.get(url).json()
151+
if dump:
152+
state_bag = blocks_config['states'][-1]
153+
else:
154+
for block in blocks_config['blocks']:
155+
if block['to'] >= archive_block:
156+
block_bags.append(block)
157+
for state in blocks_config['states']:
158+
state_bag = state
159+
if state['at_block'] > archive_block:
160+
break
161+
if not state_bag or not block_bags:
162+
local.add_log("Skip downloading archive blocks: No bags found for the specified block", "error")
163+
return
164+
165+
local.add_log(f"Downloading blockchain state for block {state_bag['at_block']}", "info")
166+
if not download_bag(local, state_bag['bag']):
167+
local.add_log("Error downloading state bag", "error")
168+
return
169+
local.add_log("Downloading archive blocks", "info")
170+
for bag in block_bags:
171+
local.add_log(f"Downloading blocks from {bag['from']} to {bag['to']}", "info")
172+
if not download_bag(local, bag['bag']):
173+
local.add_log("Error downloading archive bag", "error")
174+
return
175+
local.add_log(f"Downloading blocks is completed", "info")
176+
177+
states_dir = local.buffer.ton_db_dir + 'archive/states'
178+
blocks_dir = local.buffer.ton_db_dir + 'archive/packages'
179+
downloads_path = '/tmp/ts-downloads/'
180+
181+
os.makedirs(states_dir, exist_ok=True)
182+
os.makedirs(blocks_dir, exist_ok=True)
183+
184+
subprocess.run(f'mv {downloads_path}/{state_bag["bag"]}/state-*/* {states_dir}', shell=True)
185+
# subprocess.run(['rm', '-rf', f"{downloads_path}/{state_bag['bag']}"])
186+
187+
for bag in block_bags:
188+
subprocess.run(f'mv {downloads_path}/{bag["bag"]}/packages/* {blocks_dir}', shell=True)
189+
# subprocess.run(['rm', '-rf', f"{downloads_path}/{bag['bag']}"])
190+
subprocess.run(['rm', '-rf', downloads_path])
191+
192+
stop_service(local, "ton_storage") # stop TS
193+
disable_service(local, "ton_storage")
194+
195+
109196
def DownloadDump(local):
110197
dump = local.buffer.dump
111198
if dump is False:
@@ -636,6 +723,8 @@ def enable_ton_storage(local):
636723
local.add_log("write mconfig", "debug")
637724
SetConfig(path=mconfig_path, data=mconfig)
638725

726+
local.buffer.ton_storage = ton_storage
727+
639728
# start ton_storage
640729
start_service(local, bin_name)
641730
color_print("enable_ton_storage - {green}OK{endc}")

mytoninstaller/utils.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ def stop_service(local, service_name:str):
3030
subprocess.run(args)
3131
#end define
3232

33+
def disable_service(local, service_name: str):
34+
local.add_log(f"Disable {service_name} service", "debug")
35+
args = ["systemctl", "disable", service_name]
36+
subprocess.run(args)
37+
3338
def StartValidator(local):
3439
start_service(local, "validator", sleep=10)
3540
#end define

scripts/install.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,16 @@ def run_cli():
3434
ignore=lambda x: x["mode"] != "validator", # do not ask this question if mode is not validator
3535
choices=["Validator wallet", "Nominator pool", "Single pool", "Liquid Staking", "Skip"],
3636
),
37+
inquirer.Text(
38+
"archive-blocks",
39+
message="Do you want to download archive blocks via TON Storage? If yes, provide block seqno to start from or press Enter to skip.",
40+
ignore=lambda x: x["mode"] == "validator",
41+
validate=lambda _, x: not x or (x.isdigit() and int(x) >= 0),
42+
),
3743
inquirer.Confirm(
3844
"dump",
39-
message="Do you want to download blockchain's dump? "
40-
"This reduces synchronization time but requires to download a large file",
45+
message="Do you want to download latest blockchain's state via TON Storage?",
46+
ignore= lambda x: x["archive-blocks"],
4147
),
4248
inquirer.Text(
4349
"add-shard",
@@ -60,6 +66,7 @@ def parse_args(answers: dict):
6066
archive_ttl = answers["archive-ttl"]
6167
add_shard = answers["add-shard"]
6268
validator_mode = answers["validator-mode"]
69+
archive_blocks = answers["archive-blocks"]
6370
dump = answers["dump"]
6471

6572
res = f' -n {network}'
@@ -71,6 +78,8 @@ def parse_args(answers: dict):
7178
os.putenv('ARCHIVE_TTL', archive_ttl) # set env variable
7279
if add_shard:
7380
os.putenv('ADD_SHARD', add_shard)
81+
if archive_blocks:
82+
os.putenv('ARCHIVE_BLOCKS', archive_blocks)
7483

7584
if validator_mode and validator_mode not in ('Skip', 'Validator wallet'):
7685
if validator_mode == 'Nominator pool':

0 commit comments

Comments
 (0)