Skip to content
61 changes: 61 additions & 0 deletions modules/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import typing
from dataclasses import dataclass

from modules.module import MtcModule
from modules.pool import PoolModule
from modules.nominator_pool import NominatorPoolModule
from modules.single_pool import SingleNominatorModule
from modules.validator import ValidatorModule
from modules.controller import ControllerModule


MODES = {
'validator': ValidatorModule,
'nominator-pool': NominatorPoolModule,
'single-nominator': SingleNominatorModule,
'liquid-staking': ControllerModule,
}


def get_mode(mode_name: str) -> typing.Optional[MtcModule]:
return MODES.get(mode_name)


@dataclass
class Setting:
mode: typing.Optional[str]
default_value: typing.Any
description: str


SETTINGS = {
'stake': Setting('validator', None, 'Stake amount'),
'stakePercent': Setting('validator', 99, 'Stake percent if `stake` is null'),
'isSlashing': Setting('validator', None, 'Create complaints to validators'),
'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'),
'min_loan': Setting('liquid-staking', 41000, 'Min loan amount'),
'max_loan': Setting('liquid-staking', 43000, 'Max loan amount'),
'max_interest_percent': Setting('liquid-staking', 10, 'Max interest percent'),
'duplicateSendfile': Setting(None, True, 'Duplicate external to public Liteservers'),
'sendTelemetry': Setting(None, True, 'Send node telemetry'),
'telemetryLiteUrl': Setting(None, 'https://telemetry.toncenter.com/report_status', 'Telemetry url'),
'overlayTelemetryUrl': Setting(None, 'https://telemetry.toncenter.com/report_overlays', 'Overlay telemetry url'),
'duplicateApi': Setting(None, 'sendTelemetry', 'Duplicate external to Toncenter'),
'duplicateApiUrl': Setting(None, 'https://[testnet.]toncenter.com/api/v2/sendBoc', 'Toncenter api url for duplicate'),
'liteclient_timeout': Setting(None, 3, 'Liteclient default timeout'),
'console_timeout': Setting(None, 3, 'Validator console default timeout'),
'fift_timeout': Setting(None, 3, 'Fift default timeout'),
'useDefaultCustomOverlays': Setting(None, True, 'Participate in default custom overlays node eligible to'),
'defaultCustomOverlaysUrl': Setting(None, 'https://ton-blockchain.github.io/fallback_custom_overlays.json', 'Default custom overlays config url'),
}


def get_setting(name: str) -> typing.Optional[Setting]:
return SETTINGS.get(name)


def get_mode_settings(name: str):
return {k: v for k, v in SETTINGS.items() if v.mode == name}

3 changes: 3 additions & 0 deletions modules/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@

class ControllerModule(MtcModule):

description = 'Liquid staking controllers.'
default_value = False

def do_create_controllers(self):
new_controllers = self.ton.GetControllers()
old_controllers = self.ton.local.db.get("using_controllers", list())
Expand Down
5 changes: 4 additions & 1 deletion modules/module.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
from abc import ABC, abstractmethod
from mytoncore.mytoncore import MyTonCore


class MtcModule(ABC):

description = '' # module text description
default_value = True # is module enabled by default

def __init__(self, ton, local, *args, **kwargs):
from mytoncore.mytoncore import MyTonCore
self.ton: MyTonCore = ton
self.local = local

Expand Down
3 changes: 3 additions & 0 deletions modules/nominator_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

class NominatorPoolModule(PoolModule):

description = 'Standard nominator pools.'
default_value = False

def do_create_pool(self, pool_name, validator_reward_share_percent, max_nominators_count, min_validator_stake,
min_nominator_stake):
self.ton.local.add_log("start CreatePool function", "debug")
Expand Down
3 changes: 3 additions & 0 deletions modules/pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

class PoolModule(MtcModule):

description = 'Basic pools functions.'
default_value = False

def print_pools_list(self, args):
table = list()
table += [["Name", "Status", "Balance", "Version", "Address"]]
Expand Down
3 changes: 3 additions & 0 deletions modules/single_pool.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

class SingleNominatorModule(PoolModule):

description = 'Orbs\'s single nominator pools.'
default_value = False

def do_create_single_pool(self, pool_name, owner_address):
self.ton.local.add_log("start create_single_pool function", "debug")

Expand Down
8 changes: 6 additions & 2 deletions modules/validator.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
from mypylib.mypylib import color_print
from modules.module import MtcModule

from mytoncore.functions import Elections


class ValidatorModule(MtcModule):

description = ('Validator functions. Activates participating in elections and staking. '
'If pools and l/s modes are disabled stakes from validator wallet.')

default_value = True

def vote_offer(self, args):
if len(args) == 0:
color_print("{red}Bad args. Usage:{endc} vo <offer-hash>")
Expand All @@ -15,6 +18,7 @@ def vote_offer(self, args):
color_print("VoteOffer - {green}OK{endc}")

def vote_election_entry(self, args):
from mytoncore.functions import Elections
Elections(self.ton.local, self.ton)
color_print("VoteElectionEntry - {green}OK{endc}")

Expand Down
6 changes: 0 additions & 6 deletions mytoncore/modes.py

This file was deleted.

8 changes: 4 additions & 4 deletions mytoncore/mytoncore.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import requests
from fastcrc import crc16

from mytoncore.modes import MODES
from modules import MODES
from mytoncore.utils import xhex2hex, ng2g
from mytoncore.liteclient import LiteClient
from mytoncore.validator_console import ValidatorConsole
Expand Down Expand Up @@ -3209,9 +3209,9 @@ def get_modes(self):
if 'modes' not in self.local.db:
self.local.db['modes'] = current_modes
self.migrate_to_modes()
for mode in MODES:
if mode not in current_modes:
current_modes[mode] = MODES[mode] # assign default mode value
for name, mode in MODES.items():
if name not in current_modes:
current_modes[name] = mode.default_value # assign default mode value
return current_modes

def enable_mode(self, name):
Expand Down
60 changes: 55 additions & 5 deletions mytonctrl/mytonctrl.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,8 +70,10 @@ def inject_globals(func):
console.AddItem("installer", inject_globals(Installer), local.translate("installer_cmd"))
console.AddItem("status", inject_globals(PrintStatus), local.translate("status_cmd"))
console.AddItem("status_modes", inject_globals(mode_status), local.translate("status_modes_cmd"))
console.AddItem("status_settings", inject_globals(settings_status), local.translate("settings_status_cmd"))
console.AddItem("enable_mode", inject_globals(enable_mode), local.translate("enable_mode_cmd"))
console.AddItem("disable_mode", inject_globals(disable_mode), local.translate("disable_mode_cmd"))
console.AddItem("about", inject_globals(about), local.translate("about_cmd"))
console.AddItem("get", inject_globals(GetSettings), local.translate("get_cmd"))
console.AddItem("set", inject_globals(SetSettings), local.translate("set_cmd"))
console.AddItem("rollback", inject_globals(rollback_to_mtc1), local.translate("rollback_cmd"))
Expand Down Expand Up @@ -184,6 +186,7 @@ def inject_globals(func):
#end define



def activate_ton_storage_provider(local, ton, args):
wallet_name = "provider_wallet_001"
wallet = ton.GetLocalWallet(wallet_name)
Expand All @@ -201,6 +204,25 @@ def activate_ton_storage_provider(local, ton, args):
#end define


def about(local, ton, args):
from modules import get_mode, get_mode_settings
if len(args) != 1:
color_print("{red}Bad args. Usage:{endc} about <mode_name>")
mode_name = args[0]
mode = get_mode(mode_name)
if mode is None:
color_print(f"{{red}}Mode {mode_name} not found{{endc}}")
return
mode_settings = get_mode_settings(mode_name)
color_print(f'''{{cyan}}===[ {mode_name} MODE ]==={{endc}}''')
color_print(f'''Description: {mode.description}''')
color_print('Enabled: ' + color_text('{green}yes{endc}' if ton.get_mode_value(mode_name) else '{red}no{endc}'))
print('Settings:', 'no' if len(mode_settings) == 0 else '')
for setting_name, setting in mode_settings.items():
color_print(f' {{bold}}{setting_name}{{endc}}: {setting.description}.\n Default value: {setting.default_value}')
#end define


def check_installer_user():
args = ["whoami"]
process = subprocess.run(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=3)
Expand Down Expand Up @@ -447,13 +469,28 @@ def sl(ton, args):
Slashing(ton.local, ton)
#end define


def mode_status(ton, args):
from modules import get_mode
modes = ton.get_modes()
text = "########## {bold}Modes{endc} ########## \n"
for mode in modes:
status = '{green}enabled{endc}' if modes[mode] else '{red}disabled{endc}'
text += f"{mode}: {status}\n"
color_print(text)
table = [["Name", "Status", "Description"]]
for mode_name in modes:
mode = get_mode(mode_name)
status = color_text('{green}enabled{endc}' if modes[mode_name] else '{red}disabled{endc}')
table.append([mode_name, status, mode.description])
print_table(table)
#end define


def settings_status(ton, args):
from modules import SETTINGS
table = [["Name", "Description", "Mode", "Default value", "Current value"]]
for name, setting in SETTINGS.items():
current_value = ton.local.db.get(name)
table.append([name, setting.description, setting.mode, setting.default_value, current_value])
print_table(table)
#end define


def PrintStatus(local, ton, args):
opt = None
Expand Down Expand Up @@ -1289,6 +1326,19 @@ def SetSettings(ton, args):
color_print(f"{{red}} Error: set {name} ... is deprecated and does not work {{endc}}."
f"\nInstead, use {{bold}}enable_mode {mode_name}{{endc}}")
return
force = False
if len(args) > 2:
if args[2] == "--force":
force = True
from modules import get_setting
setting = get_setting(name)
if setting is None and not force:
color_print(f"{{red}} Error: setting {name} not found.{{endc}} Use flag --force to set it anyway")
return
if setting is not None and setting.mode is not None:
if not ton.get_mode_value(setting.mode) and not force:
color_print(f"{{red}} Error: mode {setting.mode} is disabled.{{endc}} Use flag --force to set it anyway")
return
ton.SetSettings(name, value)
color_print("SetSettings - {green}OK{endc}")
#end define
Expand Down
10 changes: 10 additions & 0 deletions mytonctrl/resources/translate.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,16 @@
"ru": "Показать режимы MTC",
"zh_TW": "顯示 MTC 模式"
},
"settings_status_cmd": {
"en": "Show all available settings with their description and values",
"ru": "Показать все доступные настройки с их описанием и значениями",
"zh_TW": "顯示所有可用設定及其描述和值"
},
"about_cmd": {
"en": "Mode description",
"ru": "Описание режима",
"zh_TW": "模式描述"
},
"enable_mode_cmd": {
"en": "Enable mode",
"ru": "Включить режим",
Expand Down
2 changes: 2 additions & 0 deletions mytoninstaller/scripts/set_node_argument.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ def set_node_arg(arg_name: str, arg_value: str = ''):
assert arg_name.startswith('-'), 'arg_name must start with "-" or "--"'
service = get_validator_service()
command = get_node_start_command()
if command.split(' ')[0] != '/usr/bin/ton/validator-engine/validator-engine':
raise Exception('Invalid node start command in service file')
if command is None:
raise Exception('Cannot find node start command in service file')
args = get_node_args(command)
Expand Down