diff --git a/modules/__init__.py b/modules/__init__.py index 298302b0..8b92c260 100644 --- a/modules/__init__.py +++ b/modules/__init__.py @@ -34,6 +34,7 @@ class Setting: 'stake': Setting('validator', None, 'Stake amount'), 'stakePercent': Setting('validator', 99, 'Stake percent if `stake` is null'), 'isSlashing': Setting('validator', None, 'Create complaints to validators'), + 'validatorWalletName': Setting('validator', 'wallet_001', 'Validator\'s wallet name'), 'maxFactor': Setting('validator', None, 'Param send to Elector. if null will be taken from 17 config param'), 'participateBeforeEnd': Setting('validator', None, 'Amount of seconds before start of round to participate'), 'liquid_pool_addr': Setting('liquid-staking', None, 'Liquid staking pool address'), diff --git a/modules/collator_config.py b/modules/collator_config.py new file mode 100644 index 00000000..9234b08f --- /dev/null +++ b/modules/collator_config.py @@ -0,0 +1,91 @@ +import json +import requests + +from mypylib.mypylib import color_print +from modules.module import MtcModule + + +class CollatorConfigModule(MtcModule): + + @staticmethod + def check_config_url(url): + try: + r = requests.get(url, timeout=3) + if r.status_code != 200: + print(f'Failed to get config from {url}: {r.status_code} code; {r.text}') + return + return r.json() + except Exception as e: + print(f'Failed to get config from {url}: {e}') + return + + @staticmethod + def check_config_file(path): + try: + with open(path, 'r') as f: + return json.load(f) + except Exception as e: + print(f'Failed to read config from {path}: {e}') + return + + @staticmethod + def get_config(path): + if 'http' in path: + config = CollatorConfigModule.check_config_url(path) + else: + config = CollatorConfigModule.check_config_file(path) + if config is None: + raise Exception(f'Failed to get config') + return config + + def add_collator_config_to_vc(self, config: dict): + self.local.add_log(f"Adding collator options config to validator console", "debug") + path = self.ton.tempDir + f'/collator_config.json' + with open(path, 'w') as f: + json.dump(config, f) + result = self.ton.validatorConsole.Run(f"setcollatoroptionsjson {path}") + return 'success' in result, result + + def set_collator_config(self, args): + if len(args) != 1: + color_print("{red}Bad args. Usage:{endc} set_collator_config ") + return + location = args[0] + config = self.get_config(location) + self.ton.set_collator_config(location) + added, msg = self.add_collator_config_to_vc(config) + if not added: + print(f'Failed to add collator config to validator console: {msg}') + color_print("set_collator_config - {red}ERROR{endc}") + return + color_print("set_collator_config - {green}OK{endc}") + + def get_collator_config(self, args): + location = self.ton.get_collator_config_location() + print(f'Collator config location: {location}') + path = self.ton.tempDir + f'/current_collator_config.json' + output = self.ton.validatorConsole.Run(f'getcollatoroptionsjson {path}') + if 'saved config to' not in output: + print(f'Failed to get collator config: {output}') + color_print("get_collator_config - {red}ERROR{endc}") + return + with open(path, 'r') as f: + config = json.load(f) + print(f'Collator config:') + print(json.dumps(config, indent=4)) + color_print("get_collator_config - {green}OK{endc}") + + def update_collator_config(self, args): + location = self.ton.get_collator_config_location() + config = self.get_config(location) + added, msg = self.add_collator_config_to_vc(config) + if not added: + print(f'Failed to add collator config to validator console: {msg}') + color_print("update_collator_config - {red}ERROR{endc}") + return + color_print("update_collator_config - {green}OK{endc}") + + def add_console_commands(self, console): + console.AddItem("set_collator_config", self.set_collator_config, self.local.translate("set_collator_config_cmd")) + console.AddItem("update_collator_config", self.update_collator_config, self.local.translate("update_collator_config_cmd")) + console.AddItem("get_collator_config", self.get_collator_config, self.local.translate("get_collator_config_cmd")) diff --git a/modules/nominator_pool.py b/modules/nominator_pool.py index a5adcc4b..14f4fbdd 100644 --- a/modules/nominator_pool.py +++ b/modules/nominator_pool.py @@ -62,6 +62,8 @@ def do_activate_pool(self, pool, ex=True): elif account.status == "active": self.local.add_log("do_activate_pool warning: account status is active", "warning") else: + validator_wallet = self.ton.GetValidatorWallet() + self.ton.check_account_active(validator_wallet.addrB64) self.ton.SendFile(pool.bocFilePath, pool, timeout=False, remove=False) #end define diff --git a/modules/single_pool.py b/modules/single_pool.py index d2721c5a..5b5c6e2b 100644 --- a/modules/single_pool.py +++ b/modules/single_pool.py @@ -51,6 +51,7 @@ def do_activate_single_pool(self, pool): self.local.add_log("start activate_single_pool function", "debug") boc_mode = "--with-init" validator_wallet = self.ton.GetValidatorWallet() + self.ton.check_account_active(validator_wallet.addrB64) result_file_path = self.ton.SignBocWithWallet(validator_wallet, pool.bocFilePath, pool.addrB64_init, 1, boc_mode=boc_mode) self.ton.SendFile(result_file_path, validator_wallet) diff --git a/mytoncore/mytoncore.py b/mytoncore/mytoncore.py index 726b0d2f..ed643083 100644 --- a/mytoncore/mytoncore.py +++ b/mytoncore/mytoncore.py @@ -1180,9 +1180,7 @@ def SignBocWithWallet(self, wallet, boc_path, dest, coins, **kwargs): # Balance checking account = self.GetAccount(wallet.addrB64) - if account.balance < coins + 0.1: - raise Exception("Wallet balance is less than requested coins") - #end if + self.check_account_balance(account, coins + 0.1) # Bounceable checking destAccount = self.GetAccount(dest) @@ -1864,6 +1862,25 @@ def GetWalletId(self, wallet): return subwallet #end define + def check_account_balance(self, account, coins): + if not isinstance(account, Account): + account = self.GetAccount(account) + if account.balance < coins: + raise Exception(f"Account {account.addrB64} balance is less than requested coins. Balance: {account.balance}, requested amount: {coins} (need {coins - account.balance} more)") + # end if + # end define + + def check_account_active(self, account): + if not isinstance(account, Account): + address = account + account = self.GetAccount(account) + else: + address = account.addrB64 + if account.status != "active": + raise Exception(f"Account {address} account is uninitialized") + # end if + # end define + def MoveCoins(self, wallet, dest, coins, **kwargs): self.local.add_log("start MoveCoins function", "debug") flags = kwargs.get("flags", list()) @@ -1884,11 +1901,8 @@ def MoveCoins(self, wallet, dest, coins, **kwargs): # Balance checking account = self.GetAccount(wallet.addrB64) - if account.balance < coins + 0.1: - raise Exception("Wallet balance is less than requested coins") - if account.status != "active": - raise Exception("Wallet account is uninitialized") - #end if + self.check_account_balance(account, coins + 0.1) + self.check_account_active(account) # Bounceable checking destAccount = self.GetAccount(dest) @@ -3986,6 +4000,16 @@ def delete_custom_overlay(self, name: str): del self.local.db['custom_overlays'][name] self.local.save() + def set_collator_config(self, location: str): + self.local.db['collator_config'] = location + self.local.save() + + def get_collator_config_location(self): + default = 'https://raw.githubusercontent.com/ton-blockchain/ton-blockchain.github.io/main/default_collator_options.json' + location = self.local.db.get('collator_config', default) + if location is None: + location = default + return location def GetNetworkName(self): data = self.local.read_db(self.liteClient.configPath) diff --git a/mytonctrl/mytonctrl.py b/mytonctrl/mytonctrl.py index 9598716f..ba60f84b 100755 --- a/mytonctrl/mytonctrl.py +++ b/mytonctrl/mytonctrl.py @@ -128,6 +128,10 @@ def inject_globals(func): module = CustomOverlayModule(ton, local) module.add_console_commands(console) + from modules.collator_config import CollatorConfigModule + module = CollatorConfigModule(ton, local) + module.add_console_commands(console) + if ton.using_validator(): from modules.validator import ValidatorModule module = ValidatorModule(ton, local) @@ -384,7 +388,7 @@ def Upgrade(ton, args): try: from mytoninstaller.mytoninstaller import set_node_argument, get_node_args node_args = get_node_args() - if node_args['--state-ttl'] == '604800': + if node_args.get('--state-ttl') == '604800': set_node_argument(ton.local, ["--state-ttl", "-d"]) except Exception as e: color_print(f"{{red}}Failed to set node argument: {e} {{endc}}") diff --git a/mytonctrl/resources/translate.json b/mytonctrl/resources/translate.json index 22c2b283..7bbfcf1d 100644 --- a/mytonctrl/resources/translate.json +++ b/mytonctrl/resources/translate.json @@ -419,6 +419,16 @@ "ru": "{green}Доступно обновление MyTonCtrl. {red}Пожалуйста, обновите его с помощью команды `update`.{endc}", "zh_TW": "{green}MyTonCtrl 有可用更新. {red}請使用 `update` 命令進行更新.{endc}" }, + "update_mtc2_warning": { + "en": "{red}This version is outdated. Please update to the second version: `update mytonctrl2`{endc}", + "ru": "{red}Данная версия устарела. Пожалуйста обновитесь на вторую версию: `update mytonctrl2`{endc}", + "zh_TW": "{red}這個版本已經過時了。請更新至第二版本: `update mytonctrl2`{endc}" + }, + "disk_usage_warning": { + "en": "{red} Disk is almost full, clean the TON database immediately: https://docs.ton.org/participate/nodes/node-maintenance-and-security#database-grooming {endc}", + "ru": "{red} Диск почти заполнен, немедленно очистите базу данных TON: https://docs.ton.org/participate/nodes/node-maintenance-and-security#database-grooming {endc}", + "zh_TW": "{red} 磁盤幾乎滿了,立即清理 TON 數據庫: https://docs.ton.org/participate/nodes/node-maintenance-and-security#database-grooming {endc}" + }, "ton_update_available": { "en": "{green}TON update available. {red}Please update it with `upgrade` command.{endc}", "ru": "{green}Доступно обновление TON. {red}Пожалуйста, обновите его с помощью команды `upgrade`.{endc}",