diff --git a/mytoninstaller/config.py b/mytoninstaller/config.py index c1a78dd2..871e691c 100644 --- a/mytoninstaller/config.py +++ b/mytoninstaller/config.py @@ -5,7 +5,7 @@ import base64 from mytoncore.utils import hex2b64, dict2b64 -from mytoninstaller.utils import StartMytoncore, GetInitBlock +from mytoninstaller.utils import StartMytoncore, GetInitBlock, get_ed25519_pubkey_text from mypylib.mypylib import ip2int, Dict @@ -134,3 +134,19 @@ def GetLiteServerConfig(local): result.id.key= key.decode() return result #end define + +def get_ls_proxy_config(local): + ls_proxy_config_path = "/var/ls_proxy/ls-proxy-config.json" + ls_proxy_config = GetConfig(path=ls_proxy_config_path) + ip = get_own_ip() + port = ls_proxy_config.ListenAddr.split(':')[1] + privkey_text = ls_proxy_config.Clients[0].PrivateKey + + result = Dict() + result.ip = ip2int(ip) + result.port = port + result.id = Dict() + result.id["@type"]= "pub.ed25519" + result.id.key= get_ed25519_pubkey_text(privkey_text) + return result +#end define diff --git a/mytoninstaller/mytoninstaller.py b/mytoninstaller/mytoninstaller.py index 3400df55..ee542a6f 100644 --- a/mytoninstaller/mytoninstaller.py +++ b/mytoninstaller/mytoninstaller.py @@ -7,29 +7,29 @@ import json import subprocess -from mypylib.mypylib import MyPyClass, run_as_root +from mypylib.mypylib import MyPyClass, run_as_root, color_print from mypyconsole.mypyconsole import MyPyConsole -from mytoninstaller.config import GetLiteServerConfig +from mytoninstaller.config import GetLiteServerConfig, get_ls_proxy_config from mytoninstaller.utils import GetInitBlock from mytoncore.utils import dict2b64, str2bool, b642dict from mytoninstaller.settings import ( - FirstNodeSettings, - FirstMytoncoreSettings, - EnableValidatorConsole, - EnableLiteServer, - EnableDhtServer, - EnableJsonRpc, - EnablePytonv3, + FirstNodeSettings, + FirstMytoncoreSettings, + EnableValidatorConsole, + EnableLiteServer, + EnableDhtServer, + EnableJsonRpc, EnableTonHttpApi, - DangerousRecoveryValidatorConfigFile, - CreateSymlinks, + DangerousRecoveryValidatorConfigFile, + CreateSymlinks, + enable_ls_proxy ) from mytoninstaller.config import ( - CreateLocalConfig, - BackupVconfig, - BackupMconfig, + CreateLocalConfig, + BackupVconfig, + BackupMconfig, ) from functools import partial @@ -62,10 +62,12 @@ def inject_globals(func): console.name = "MyTonInstaller" console.color = console.RED console.AddItem("status", inject_globals(Status), "Print TON component status") - console.AddItem("enable", inject_globals(Enable), "Enable some function: 'FN' - Full node, 'VC' - Validator console, 'LS' - Liteserver, 'DS' - DHT-Server, 'JR' - jsonrpc, 'PT' - ton-http-api. Example: 'enable FN'") + console.AddItem("enable", inject_globals(Enable), "Enable some function") console.AddItem("update", inject_globals(Enable), "Update some function: 'JR' - jsonrpc. Example: 'update JR'") - console.AddItem("plsc", inject_globals(PrintLiteServerConfig), "Print LiteServer config") - console.AddItem("clcf", inject_globals(CreateLocalConfigFile), "CreateLocalConfigFile") + console.AddItem("plsc", inject_globals(PrintLiteServerConfig), "Print lite-server config") + console.AddItem("clcf", inject_globals(CreateLocalConfigFile), "Create lite-server config file") + console.AddItem("print_ls_proxy_config", inject_globals(print_ls_proxy_config), "Print ls-proxy config") + console.AddItem("create_ls_proxy_config_file", inject_globals(create_ls_proxy_config_file), "Create ls-proxy config file") console.AddItem("drvcf", inject_globals(DRVCF), "Dangerous recovery validator config file") console.AddItem("setwebpass", inject_globals(SetWebPassword), "Set a password for the web admin interface") @@ -123,10 +125,22 @@ def Status(local, args): def Enable(local, args): - name = args[0] - if name == "PT": + try: + name = args[0] + except: + color_print("{red}Bad args. Usage:{endc} enable ") + print("'FN' - Full node") + print("'VC' - Validator console") + print("'LS' - Lite-Server") + print("'DS' - DHT-Server") + print("'JR' - jsonrpc") + print("'THA' - ton-http-api") + print("'LSP' - ls-proxy") + print("Example: 'enable FN'") + return + if name == "THA": CreateLocalConfigFile(local, args) - args = ["python3", "-m", "mytoninstaller", "-u", local.buffer.user, "-e", "enable{name}".format(name=name)] + args = ["python3", "-m", "mytoninstaller", "-u", local.buffer.user, "-e", f"enable{name}"] run_as_root(args) #end define @@ -159,6 +173,15 @@ def CreateLocalConfigFile(local, args): run_as_root(args) #end define +def print_ls_proxy_config(local, args): + ls_proxy_config = get_ls_proxy_config(local) + text = json.dumps(ls_proxy_config, indent=4) + print(text) +#end define + +def create_ls_proxy_config_file(local, args): + print("TODO") +#end define def Event(local, name): if name == "enableFN": @@ -173,9 +196,10 @@ def Event(local, name): DangerousRecoveryValidatorConfigFile(local) if name == "enableJR": EnableJsonRpc(local) - if name == "enablePT": - # EnablePytonv3(local) + if name == "enableTHA": EnableTonHttpApi(local) + if name == "enableLSP": + enable_ls_proxy(local) if name == "clc": ix = sys.argv.index("-i") initBlock_b64 = sys.argv[ix+1] @@ -219,12 +243,12 @@ def General(local): ### Start of the program ### def mytoninstaller(): - local = MyPyClass(__file__) - console = MyPyConsole() - - Init(local, console) - if len(sys.argv) > 1: - General(local) - else: - console.Run() - local.exit() + local = MyPyClass(__file__) + console = MyPyConsole() + + Init(local, console) + if len(sys.argv) > 1: + General(local) + else: + console.Run() + local.exit() diff --git a/mytoninstaller/scripts/ls_proxy_installer.sh b/mytoninstaller/scripts/ls_proxy_installer.sh new file mode 100644 index 00000000..16630251 --- /dev/null +++ b/mytoninstaller/scripts/ls_proxy_installer.sh @@ -0,0 +1,103 @@ +#!/bin/bash +set -e + +# Проверить sudo +if [ "$(id -u)" != "0" ]; then + echo "Please run script as root" + exit 1 +fi + +# install parameters +src_path=/usr/src +bin_path=/usr/bin +openssl_path=${bin_path}/openssl_3 + +# Get arguments +while getopts u:s:b:o: flag +do + case "${flag}" in + u) user=${OPTARG};; + s) src_path=${OPTARG};; + b) bin_path=${OPTARG};; + o) openssl_path=${OPTARG};; + *) + echo "Flag -${flag} is not recognized. Aborting" + exit 1;; + esac +done + +# install parameters +author=xssnick +repo=tonutils-liteserver-proxy +branch=master +bin_name=ls_proxy + +# Цвета +COLOR='\033[95m' +ENDC='\033[0m' + +# Клонирование репозиториев с github.com +echo -e "${COLOR}[1/4]${ENDC} Cloning github repository" +echo "https://github.com/${author}/${repo}.git -> ${branch}" + +cd ${src_path} +rm -rf ${repo} +git clone --branch=${branch} --recursive https://github.com/${author}/${repo}.git + +# Установка компонентов +echo -e "${COLOR}[2/4]${ENDC} Installing required packages" + +arc=$(dpkg --print-architecture) +go_version_url=https://go.dev/VERSION?m=text +go_version=$(curl -s ${go_version_url} | head -n 1) +go_url=https://go.dev/dl/${go_version}.linux-${arc}.tar.gz +go_path=/usr/local/go/bin/go +rm -rf /usr/local/go +wget -c ${go_url} -O - | tar -C /usr/local -xz + +# Расчитываем количество процессоров для сборки +if [[ "$OSTYPE" =~ darwin.* ]]; then + cpu_number=$(sysctl -n hw.logicalcpu) +else + memory=$(cat /proc/meminfo | grep MemAvailable | awk '{print $2}') + cpu_number=$(($memory/2100000)) + max_cpu_number=$(nproc) + if [ ${cpu_number} -gt ${max_cpu_number} ]; then + cpu_number=$((${max_cpu_number}-1)) + fi + if [ ${cpu_number} == 0 ]; then + echo "Warning! insufficient RAM" + cpu_number=1 + fi +fi + +# Компилируем из исходников +echo -e "${COLOR}[3/4]${ENDC} Source compilation, use ${cpu_number} cpus" + +proxy_src_path=${src_path}/${repo} +ton_src_path=${proxy_src_path}/ton +proxy_internal_path=${proxy_src_path}/internal/emulate/lib + +proxy_build_path=${bin_path}/${bin_name} +ton_build_path=${proxy_build_path}/ton +proxy_db_path=/var/${bin_name} +proxy_lib_path=${proxy_db_path}/lib + +mkdir -p ${proxy_lib_path} +mkdir -p ${ton_build_path} && cd ${ton_build_path} +cmake -DCMAKE_BUILD_TYPE=Release -DOPENSSL_FOUND=1 -DOPENSSL_INCLUDE_DIR=${openssl_path}/include -DOPENSSL_CRYPTO_LIBRARY=${openssl_path}/libcrypto.a ${ton_src_path} +make emulator -j ${cpu_number} +cp ${ton_build_path}/emulator/libemulator.so ${proxy_lib_path} +cp ${ton_build_path}/emulator/libemulator.so ${proxy_internal_path} +cp ${ton_build_path}/emulator/emulator_export.h ${proxy_internal_path} + +# Компилируем +cd ${proxy_src_path} +CGO_ENABLED=1 ${go_path} build -o ${proxy_db_path}/${bin_name} ${proxy_src_path}/cmd/main.go + +# Настроить директорию работы +chown -R ${user}:${user} ${proxy_db_path} + +# Выход из программы +echo -e "${COLOR}[4/4]${ENDC} ${bin_name} installation complete" +exit 0 diff --git a/mytoninstaller/settings.py b/mytoninstaller/settings.py index 60e3e211..f1c73a4f 100644 --- a/mytoninstaller/settings.py +++ b/mytoninstaller/settings.py @@ -1,6 +1,7 @@ import os import os.path import psutil +import base64 import subprocess import requests import random @@ -15,7 +16,7 @@ ip2int, Dict ) -from mytoninstaller.utils import StartValidator, StartMytoncore +from mytoninstaller.utils import StartValidator, StartMytoncore, start_service, stop_service, get_ed25519_pubkey from mytoninstaller.config import SetConfig, GetConfig, get_own_ip from mytoncore.utils import hex2b64 @@ -428,8 +429,7 @@ def EnableDhtServer(local): subprocess.run(args) # start DHT-Server - args = ["systemctl", "restart", "dht-server"] - subprocess.run(args) + start_service(local, "dht-server") #end define @@ -447,22 +447,6 @@ def EnableJsonRpc(local): color_print(text) #end define - -def EnablePytonv3(local): - local.add_log("start EnablePytonv3 function", "debug") - user = local.buffer.user - - pythonv3installer_path = pkg_resources.resource_filename('mytoninstaller.scripts', 'pytonv3installer.sh') - local.add_log(f"Running script: {pythonv3installer_path}", "debug") - exitCode = run_as_root(["bash", pythonv3installer_path, "-u", user]) - if exitCode == 0: - text = "EnablePytonv3 - {green}OK{endc}" - else: - text = "EnablePytonv3 - {red}Error{endc}" - color_print(text) -#end define - - def EnableTonHttpApi(local): local.add_log("start EnablePytonv3 function", "debug") user = local.buffer.user @@ -474,17 +458,70 @@ def EnableTonHttpApi(local): else: text = "EnableTonHttpApi - {red}Error{endc}" color_print(text) +#end define + +def enable_ls_proxy(local): + local.add_log("start enable_ls_proxy function", "debug") + user = local.buffer.user + ls_proxy_port = random.randint(2000, 65000) + metrics_port = random.randint(2000, 65000) + bin_name = "ls_proxy" + ls_proxy_db_path = f"/var/{bin_name}" + ls_proxy_path = f"{ls_proxy_db_path}/{bin_name}" + ls_proxy_config_path = f"{ls_proxy_db_path}/ls-proxy-config.json" + + installer_path = pkg_resources.resource_filename('mytoninstaller.scripts', 'ls_proxy_installer.sh') + local.add_log(f"Running script: {installer_path}", "debug") + exitCode = run_as_root(["bash", installer_path, "-u", user]) + if exitCode != 0: + color_print("enable_ls_proxy - {red}Error{endc}") + #end if + + # Прописать автозагрузку + add2systemd(name=bin_name, user=user, start=ls_proxy_path, workdir=ls_proxy_db_path) + # Первый запуск - создание конфига + start_service(local, bin_name) + stop_service(local, bin_name) + + # read ls_proxy config + local.add_log("read ls_proxy config", "debug") + ls_proxy_config = GetConfig(path=ls_proxy_config_path) + + # read mytoncore config + local.add_log("read mytoncore config", "debug") + mconfig = GetConfig(path=local.buffer.mconfig_path) + ls_pubkey_path = mconfig.liteClient.liteServer.pubkeyPath + ls_port = mconfig.liteClient.liteServer.port + + # read ls_pubkey + with open(ls_pubkey_path, 'rb') as file: + data = file.read() + pubkey = data[4:] + ls_pubkey = base64.b64encode(pubkey).decode("utf-8") + #end with + + # prepare config + ls_proxy_config.ListenAddr = f"0.0.0.0:{ls_proxy_port}" + ls_proxy_config.MetricsAddr = f"127.0.0.1:{metrics_port}" + ls_proxy_config.Backends = [{ + "Name": "local_ls", + "Addr": f"127.0.0.1:{ls_port}", + "Key": ls_pubkey + }] + + # write ls_proxy config + local.add_log("write ls_proxy config", "debug") + SetConfig(path=ls_proxy_config_path, data=ls_proxy_config) + + # start ls_proxy + start_service(local, bin_name) + color_print("enable_ls_proxy - {green}OK{endc}") +#end define def DangerousRecoveryValidatorConfigFile(local): local.add_log("start DangerousRecoveryValidatorConfigFile function", "info") - # install and import cryptography library - args = ["pip3", "install", "cryptography"] - subprocess.run(args) - from cryptography.hazmat.primitives import serialization - from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey - # Get keys from keyring keys = list() keyringDir = "/var/ton-work/db/keyring/" @@ -528,10 +565,8 @@ def DangerousRecoveryValidatorConfigFile(local): file = open(path, 'rb') data = file.read() file.close() - peivkey = data[4:] - privkeyObject = Ed25519PrivateKey.from_private_bytes(peivkey) - pubkeyObject = privkeyObject.public_key() - pubkey = pubkeyObject.public_bytes(encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw) + privkey = data[4:] + pubkey = get_ed25519_pubkey(privkey) if pubkey == ls_pubkey: ls_id = hex2b64(item) keys.remove(ls_id) @@ -562,10 +597,8 @@ def DangerousRecoveryValidatorConfigFile(local): file = open(path, 'rb') data = file.read() file.close() - peivkey = data[4:] - privkeyObject = Ed25519PrivateKey.from_private_bytes(peivkey) - pubkeyObject = privkeyObject.public_key() - pubkey = pubkeyObject.public_bytes(encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw) + privkey = data[4:] + pubkey = get_ed25519_pubkey(privkey) if pubkey == vPubkey: vcId = hex2b64(item) keys.remove(vcId) diff --git a/mytoninstaller/utils.py b/mytoninstaller/utils.py index c811f158..a2cd817f 100644 --- a/mytoninstaller/utils.py +++ b/mytoninstaller/utils.py @@ -2,34 +2,51 @@ import json import time import subprocess +from nacl.signing import SigningKey def GetInitBlock(): - from mypylib.mypylib import MyPyClass - from mytoncore import MyTonCore - - mytoncore_local = MyPyClass('mytoncore.py') - ton = MyTonCore(mytoncore_local) - initBlock = ton.GetInitBlock() - return initBlock -# end define - + from mypylib.mypylib import MyPyClass + from mytoncore import MyTonCore + + mytoncore_local = MyPyClass('mytoncore.py') + ton = MyTonCore(mytoncore_local) + initBlock = ton.GetInitBlock() + return initBlock +#end define + +def start_service(local, service_name:str, sleep:int=1): + local.add_log(f"Start/restart {service_name} service", "debug") + args = ["systemctl", "restart", service_name] + subprocess.run(args) + + local.add_log(f"sleep {sleep} sec", "debug") + time.sleep(sleep) +#end define + +def stop_service(local, service_name:str): + local.add_log(f"Stop {service_name} service", "debug") + args = ["systemctl", "stop", service_name] + subprocess.run(args) +#end define def StartValidator(local): - # restart validator - local.add_log("Start/restart validator service", "debug") - args = ["systemctl", "restart", "validator"] - subprocess.run(args) - - # sleep 10 sec - local.add_log("sleep 10 sec", "debug") - time.sleep(10) -# end define - + start_service(local, "validator", sleep=10) +#end define def StartMytoncore(local): - # restart mytoncore - local.add_log("Start/restart mytoncore service", "debug") - args = ["systemctl", "restart", "mytoncore"] - subprocess.run(args) -# end define + start_service(local, "mytoncore") +#end define + +def get_ed25519_pubkey_text(privkey_text): + privkey = base64.b64decode(privkey_text) + pubkey = get_ed25519_pubkey(privkey) + pubkey_text = base64.b64encode(pubkey).decode("utf-8") + return pubkey_text +#end define + +def get_ed25519_pubkey(privkey): + privkey_obj = SigningKey(privkey) + pubkey = privkey_obj.verify_key.encode() + return pubkey +#end define diff --git a/requirements.txt b/requirements.txt index 22953b42..f7705c47 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,6 +1,6 @@ crc16 requests psutil -cryptography fastcrc jsonpickle +pynacl diff --git a/scripts/install.sh b/scripts/install.sh index 79e1f316..b57b9453 100644 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -106,7 +106,7 @@ cd $SOURCES_DIR/${repo} pip3 install -U . # TODO: make installation from git directly -echo -e "${COLOR}[3/5]${ENDC} Running mytoninstaller" +echo -e "${COLOR}[4/5]${ENDC} Running mytoninstaller" # DEBUG parent_name=$(ps -p $PPID -o comm=) @@ -125,5 +125,5 @@ mkdir -p ${version_dir} echo ${migrate_version} > ${version_path} chown ${user}:${user} ${version_dir} ${version_path} -echo -e "${COLOR}[4/4]${ENDC} Mytonctrl installation completed" +echo -e "${COLOR}[5/5]${ENDC} Mytonctrl installation completed" exit 0 diff --git a/scripts/ton_installer.sh b/scripts/ton_installer.sh index 9f053379..95a0c334 100644 --- a/scripts/ton_installer.sh +++ b/scripts/ton_installer.sh @@ -134,21 +134,24 @@ else cmake -DCMAKE_BUILD_TYPE=Release $SOURCES_DIR/ton -GNinja -DOPENSSL_FOUND=1 -DOPENSSL_INCLUDE_DIR=$opensslPath/include -DOPENSSL_CRYPTO_LIBRARY=$opensslPath/libcrypto.a fi -# Компилируем из исходников -echo -e "${COLOR}[4/6]${ENDC} Source Compilation" +# Расчитываем количество процессоров для сборки if [[ "$OSTYPE" =~ darwin.* ]]; then - cpuNumber=$(sysctl -n hw.logicalcpu) + cpu_number=$(sysctl -n hw.logicalcpu) else memory=$(cat /proc/meminfo | grep MemAvailable | awk '{print $2}') - cpuNumber=$(cat /proc/cpuinfo | grep "processor" | wc -l) - if [ ${cpuNumber} == 0 ]; then + cpu_number=$(($memory/2100000)) + max_cpu_number=$(nproc) + if [ ${cpu_number} -gt ${max_cpu_number} ]; then + cpu_number=$((${max_cpu_number}-1)) + fi + if [ ${cpu_number} == 0 ]; then echo "Warning! insufficient RAM" - cpuNumber=1 + cpu_number=1 fi fi -echo "use ${cpuNumber} cpus" -ninja -j ${cpuNumber} fift validator-engine lite-client pow-miner validator-engine-console generate-random-id dht-server func tonlibjson rldp-http-proxy +echo -e "${COLOR}[4/6]${ENDC} Source compilation, use ${cpu_number} cpus" +ninja -j ${cpu_number} fift validator-engine lite-client validator-engine-console generate-random-id dht-server func tonlibjson rldp-http-proxy # Скачиваем конфигурационные файлы lite-client echo -e "${COLOR}[5/6]${ENDC} Downloading config files" diff --git a/setup.py b/setup.py index 1d991cca..c4302d88 100644 --- a/setup.py +++ b/setup.py @@ -2,53 +2,48 @@ from os.path import dirname, join with open(join(dirname(__file__), "README.md"), "r") as f: - long_description = f.read() + long_description = f.read() +with open(join(dirname(__file__), "requirements.txt")) as file: + install_requires = file.read().split('\n') version = 'v0.1' setup( - author='igroman787', - author_email='igroman787', - name='mytonctrl', - version=version, - packages=find_packages('.', exclude=['tests']), - install_requires=[ - 'crc16', - 'requests', - 'psutil', - 'cryptography', - 'fastcrc', - 'jsonpickle', - ], - package_data={ - 'mytoninstaller.scripts': ['*.sh'], - 'mytoncore': [ - 'contracts/**/*', - 'complaints/*' - ], - 'mytonctrl': [ - 'resources/*', - 'scripts/*', - 'migrations/*.sh' - ], - '': ['requirements.txt'], - }, - zip_safe=True, - python_requires='>=3.7', - classifiers=[ - "Development Status :: 3 - Alpha", - "Intended Audience :: Developers", - "Programming Language :: Python :: 3.7", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "License :: Other/Proprietary License", - "Topic :: Software Development :: Libraries" - ], - url="https://github.com/ton-blockchain/mytonctrl", - description="MyTonCtrl", - long_description_content_type="text/markdown", - long_description=long_description, + author='igroman787', + author_email='igroman787', + name='mytonctrl', + version=version, + packages=find_packages('.', exclude=['tests']), + install_requires=install_requires, + package_data={ + 'mytoninstaller.scripts': ['*.sh'], + 'mytoncore': [ + 'contracts/**/*', + 'complaints/*' + ], + 'mytonctrl': [ + 'resources/*', + 'scripts/*', + 'migrations/*.sh' + ], + '': ['requirements.txt'], + }, + zip_safe=True, + python_requires='>=3.7', + classifiers=[ + "Development Status :: 3 - Alpha", + "Intended Audience :: Developers", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "License :: Other/Proprietary License", + "Topic :: Software Development :: Libraries" + ], + url="https://github.com/ton-blockchain/mytonctrl", + description="MyTonCtrl", + long_description_content_type="text/markdown", + long_description=long_description, )