From 55c94410d14824f099ddc00f02957f2165ac2712 Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Mon, 29 May 2023 22:11:07 +0300 Subject: [PATCH 01/43] add controller --- mytoncore.py | 228 +++++++++++++++++++++++++++++++++++++++++++++++---- mytonctrl.py | 45 +++++++++- 2 files changed, 253 insertions(+), 20 deletions(-) diff --git a/mytoncore.py b/mytoncore.py index 01cf614e..42645b74 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -662,7 +662,7 @@ def GetDomainAdnlAddr(self, domainName): #end define def GetLocalWallet(self, walletName, version=None, subwallet=None): - local.AddLog("start GetLocalWallet function", "debug") + #local.AddLog("start GetLocalWallet function", "debug") if walletName is None: return None walletPath = self.walletsDir + walletName @@ -674,7 +674,7 @@ def GetLocalWallet(self, walletName, version=None, subwallet=None): #end define def GetWalletFromFile(self, filePath, version): - local.AddLog("start GetWalletFromFile function", "debug") + #local.AddLog("start GetWalletFromFile function", "debug") # Check input args if (".addr" in filePath): filePath = filePath.replace(".addr", '') @@ -725,7 +725,7 @@ def AddrFile2Object(self, object): #end define def WalletVersion2Wallet(self, wallet): - local.AddLog("start WalletVersion2Wallet function", "debug") + #local.AddLog("start WalletVersion2Wallet function", "debug") if wallet.version is not None: return walletsVersionList = self.GetWalletsVersionList() @@ -749,7 +749,7 @@ def SetWalletVersion(self, addrB64, version): #end define def GetWalletVersionFromHash(self, inputHash): - local.AddLog("start GetWalletVersionFromHash function", "debug") + #local.AddLog("start GetWalletVersionFromHash function", "debug") arr = dict() arr["v1r1"] = "d670136510daff4fee1889b8872c4c1e89872ffa1fe58a23a5f5d99cef8edf32" arr["v1r2"] = "2705a31a7ac162295c8aed0761cc6e031ab65521dd7b4a14631099e02de99e18" @@ -1339,10 +1339,10 @@ def PrepareComplaint(self, electionId, inputFileName): return fileName #end define - def CreateElectionRequest(self, wallet, startWorkTime, adnlAddr, maxFactor): + def CreateElectionRequest(self, addrB64, startWorkTime, adnlAddr, maxFactor): local.AddLog("start CreateElectionRequest function", "debug") fileName = self.tempDir + self.nodeName + str(startWorkTime) + "_validator-to-sign.bin" - args = ["validator-elect-req.fif", wallet.addrB64, startWorkTime, maxFactor, adnlAddr, fileName] + args = ["validator-elect-req.fif", addrB64, startWorkTime, maxFactor, adnlAddr, fileName] result = self.fift.Run(args) fileName = Pars(result, "Saved to file ", '\n') resultList = result.split('\n') @@ -1471,6 +1471,7 @@ def ProcessRecoverStake(self): def GetStake(self, account, args=None): stake = local.db.get("stake") usePool = local.db.get("usePool") + useController = local.db.get("useController") stakePercent = local.db.get("stakePercent", 99) vconfig = self.GetValidatorConfig() validators = vconfig.get("validators") @@ -1497,6 +1498,8 @@ def GetStake(self, account, args=None): if stake is None and usePool: stake = account.balance - 20 + if stake is None and useController: + stake = account.balance - 20 if stake is None: sp = stakePercent / 100 if sp > 1 or sp < 0: @@ -1536,7 +1539,7 @@ def GetMaxFactor(self): #end define def GetValidatorWallet(self, mode="stake"): - local.AddLog("start GetValidatorWallet function", "debug") + #local.AddLog("start GetValidatorWallet function", "debug") walletName = local.db.get("validatorWalletName") wallet = self.GetLocalWallet(walletName) return wallet @@ -1544,17 +1547,13 @@ def GetValidatorWallet(self, mode="stake"): def ElectionEntry(self, args=None): usePool = local.db.get("usePool") + useController = local.db.get("useController") wallet = self.GetValidatorWallet() addrB64 = wallet.addrB64 if wallet is None: raise Exception("Validator wallet not found") #end if - if usePool: - pool = self.GetPool(mode="stake") - addrB64 = pool.addrB64 - #end if - local.AddLog("start ElectionEntry function", "debug") # Check if validator is not synchronized validatorStatus = self.GetValidatorStatus() @@ -1589,6 +1588,16 @@ def ElectionEntry(self, args=None): local.AddLog("Elections entry already completed", "info") return #end if + + if usePool: + pool = self.GetPool(mode="stake") + addrB64 = pool.addrB64 + elif useController: + controllerAddr = self.GetControllerAddress() + self.CheckController(controllerAddr) + self.CreateLoanRequest(controllerAddr) + addrB64 = self.GetControllerAddress() + #end if # Calculate stake account = self.GetAccount(addrB64) @@ -1610,15 +1619,23 @@ def ElectionEntry(self, args=None): # Create fift's. Continue with pool or walet if usePool: - var1 = self.CreateElectionRequest(pool, startWorkTime, adnlAddr, maxFactor) + var1 = self.CreateElectionRequest(pool.addrB64, startWorkTime, adnlAddr, maxFactor) validatorSignature = self.GetValidatorSignature(validatorKey, var1) - validatorPubkey, resultFilePath = self.SignElectionRequestWithPoolWithValidator(pool, startWorkTime, adnlAddr, validatorPubkey_b64, validatorSignature, maxFactor, stake) + validatorPubkey, resultFilePath = self.SignElectionRequestWithPool(pool, startWorkTime, adnlAddr, validatorPubkey_b64, validatorSignature, maxFactor, stake) # Send boc file to TON resultFilePath = self.SignBocWithWallet(wallet, resultFilePath, pool.addrB64, 1.3) self.SendFile(resultFilePath, wallet) + elif useController: + var1 = self.CreateElectionRequest(controllerAddr, startWorkTime, adnlAddr, maxFactor) + validatorSignature = self.GetValidatorSignature(validatorKey, var1) + validatorPubkey, resultFilePath = self.SignElectionRequestWithController(controllerAddr, startWorkTime, adnlAddr, validatorPubkey_b64, validatorSignature, maxFactor, stake) + + # Send boc file to TON + resultFilePath = self.SignBocWithWallet(wallet, resultFilePath, controllerAddr, 1.03) + self.SendFile(resultFilePath, wallet) else: - var1 = self.CreateElectionRequest(wallet, startWorkTime, adnlAddr, maxFactor) + var1 = self.CreateElectionRequest(wallet.addrB64, startWorkTime, adnlAddr, maxFactor) validatorSignature = self.GetValidatorSignature(validatorKey, var1) validatorPubkey, resultFilePath = self.SignElectionRequestWithValidator(wallet, startWorkTime, adnlAddr, validatorPubkey_b64, validatorSignature, maxFactor) @@ -3495,8 +3512,8 @@ def GetPendingWithdraws(self): return pendingWithdraws #end define - def SignElectionRequestWithPoolWithValidator(self, pool, startWorkTime, adnlAddr, validatorPubkey_b64, validatorSignature, maxFactor, stake): - local.AddLog("start SignElectionRequestWithPoolWithValidator function", "debug") + def SignElectionRequestWithPool(self, pool, startWorkTime, adnlAddr, validatorPubkey_b64, validatorSignature, maxFactor, stake): + local.AddLog("start SignElectionRequestWithPool function", "debug") fileName = self.tempDir + str(startWorkTime) + "_validator-query.boc" fiftScript = self.contractsDir + "nominator-pool/func/validator-elect-signed.fif" args = [fiftScript, pool.addrB64, startWorkTime, maxFactor, adnlAddr, validatorPubkey_b64, validatorSignature, fileName, stake] @@ -3613,6 +3630,173 @@ def GetPoolData(self, addrB64): poolData["stakeHeldFor"] = data[15] return poolData #end define + + def CreateController(self, amount=1): + local.AddLog("start CreateController function", "debug") + wallet = self.GetValidatorWallet() + liquidPoolAddr = local.db.get("liquidPoolAddr") + contractPath = self.contractsDir + "jetton_pool/" + if not os.path.isdir(contractPath): + self.DownloadContract("https://github.com/ton-blockchain/jetton_pool") + #end if + + fileName = contractPath + "fift-scripts/deploy_controller.boc" + resultFilePath = self.SignBocWithWallet(wallet, fileName, liquidPoolAddr, amount) + self.SendFile(resultFilePath, wallet) + #end define + + def GetControllerAddress(self): + wallet = self.GetValidatorWallet() + addr_hash = HexAddr2Dec(wallet.addr) + liquidPoolAddr = local.db.get("liquidPoolAddr") + cmd = f"runmethodfull {liquidPoolAddr} get_controller_address_legacy {wallet.workchain} {addr_hash}" + result = self.liteClient.Run(cmd) + buff = self.Result2List(result) + wc = buff[0] + addr_hash = Dec2HexAddr(buff[1]) + addrFull = f"{wc}:{addr_hash}" + controllerAddr = self.AddrFull2AddrB64(addrFull) + return controllerAddr + #end define + + def CheckController(self, controllerAddr): + local.AddLog("start CheckController function", "debug") + controllerData = self.GetControllerData(controllerAddr) + saveControllerAddr = local.db.get("controllerAddr") + if controllerData["approved"] != -1: + raise Exception(f"GetControllerAddress error: controller not approved: {controllerAddr}") + if saveControllerAddr != controllerAddr: + local.AddLog("GetControllerAddress warning: controller is not up to date. Recreating the controller", "warning") + self.CreateController() + local.db["controllerAddr"] = controllerAddr + #end define + + def GetControllerData(self, controllerAddr): + cmd = f"runmethodfull {controllerAddr} get_validator_controller_data" + result = self.liteClient.Run(cmd) + data = self.Result2List(result) + if data is None: + return + result_vars = ["state", "approved", "stake_amount_sent", "stake_at", "saved_validator_set_hash", "validator_set_changes_count", "validator_set_change_time", "stake_held_for", "borrowed_amount", "borrowing_time"] + controllerData = dict() + for name in result_vars: + controllerData[name] = data.pop(0) + return controllerData + #end define + + def CreateLoanRequest(self, controllerAddr): + local.AddLog("start CreateLoanRequest function", "debug") + min_loan = local.db.get("min_loan", 41000) + max_loan = local.db.get("max_loan", 43000) + max_interest_percent = local.db.get("max_interest_percent", 0.015) + # TODO + # Проверить наличие старого кредита + controllerData = self.GetControllerData(controllerAddr) + if controllerData["borrowed_amount"] != 0: + local.AddLog("CreateLoanRequest info: loan already taken") + return + #end if + + wallet = self.GetValidatorWallet() + max_interest = int(max_interest_percent*65536) + fiftScript = self.contractsDir + "jetton_pool/fift-scripts/generate-loan-request.fif" + resultFilePath = self.tempDir + self.nodeName + wallet.name + "_loan_request.boc" + args = [fiftScript, min_loan, max_loan, max_interest, resultFilePath] + result = self.fift.Run(args) + resultFilePath = self.SignBocWithWallet(wallet, resultFilePath, controllerAddr, 1.01) + self.SendFile(resultFilePath, wallet) + self.WaitLoan(controllerAddr) + #end define + + def WaitLoan(self, controllerAddr): + local.AddLog("start WaitLoan function", "debug") + for i in range(10): + time.sleep(3) + controllerData = self.GetControllerData(controllerAddr) + if controllerData["borrowed_amount"] != 0: + return + raise Exception("WaitLoan error: time out") + #end define + + def ReturnUnusedLoan(self, controllerAddr): + local.AddLog("start ReturnUnusedLoan function", "debug") + wallet = self.GetValidatorWallet() + fileName = self.contractsDir + "jetton_pool/fift-scripts/return_unused_loan.boc" + resultFilePath = self.SignBocWithWallet(wallet, fileName, controllerAddr, 1.05) + self.SendFile(resultFilePath, wallet) + #end define + + def WithdrawFromController(self, controllerAddr, amount): + local.AddLog("start WithdrawFromController function", "debug") + wallet = self.GetValidatorWallet() + fiftScript = self.contractsDir + "jetton_pool/fift-scripts/withdraw-controller.fif" + resultFilePath = self.tempDir + self.nodeName + wallet.name + "_withdraw_request.boc" + args = [fiftScript, amount, resultFilePath] + result = self.fift.Run(args) + resultFilePath = self.SignBocWithWallet(wallet, resultFilePath, controllerAddr, 1.06) + self.SendFile(resultFilePath, wallet) + #end define + + def SignElectionRequestWithController(self, controllerAddr, startWorkTime, adnlAddr, validatorPubkey_b64, validatorSignature, maxFactor, stake): + local.AddLog("start SignElectionRequestWithController function", "debug") + fileName = self.tempDir + str(startWorkTime) + "_validator-query.boc" + fiftScript = self.contractsDir + "jetton_pool/fift-scripts/controller-elect-signed.fif" + args = [fiftScript, controllerAddr, startWorkTime, maxFactor, adnlAddr, validatorPubkey_b64, validatorSignature, fileName, stake] + print(f"args: {args}") + result = self.fift.Run(args) + print(f"result: {result}") + pubkey = Pars(result, "validator public key ", '\n') + fileName = Pars(result, "Saved to file ", '\n') + return pubkey, fileName + #end define + + def ControllerUpdateValidatorSet(self): + local.AddLog("start ControllerUpdateValidatorSet function", "debug") + wallet = self.GetValidatorWallet() + controllerAddr = self.GetControllerAddress() + controllerData = self.GetControllerData(controllerAddr) + if controllerData is None: + return + #en if + + timeNow = int(time.time()) + config34 = self.GetConfig34() + fullElectorAddr = self.GetFullElectorAddr() + returnedStake = self.GetReturnedStake(fullElectorAddr, controllerAddr) + print(f"Controller returnedStake: {returnedStake}") + pendingWithdraws = self.GetPendingWithdraws() + if (controllerData["state"] == 3 and + controllerData["validator_set_changes_count"] < 2 and + controllerData["validator_set_change_time"] < config34["startWorkTime"]): + self.ControllerProcessUpdateValidatorSet(controllerAddr, wallet) + controllerData = self.GetControllerData(controllerAddr) + if (returnedStake > 0 and + controllerData["state"] == 3 and + controllerData["validator_set_changes_count"] >= 2 and + timeNow - controllerData["validator_set_change_time"] > controllerData["stake_held_for"] + 60): + self.ControllerRecoverStake(controllerAddr) + #end define + + def ControllerProcessUpdateValidatorSet(self, controllerAddr, wallet): + local.AddLog("start ControllerProcessUpdateValidatorSet function", "debug") + fileName = self.contractsDir + "jetton_pool/fift-scripts/update_validator_hash.boc" + resultFilePath = self.SignBocWithWallet(wallet, fileName, controllerAddr, 1.07) + self.SendFile(resultFilePath, wallet) + local.AddLog("ControllerProcessUpdateValidatorSet completed") + #end define + + def ControllerRecoverStake(self, controllerAddr): + wallet = self.GetValidatorWallet() + if wallet is None: + raise Exception("Validator wallet not found") + #end if + + local.AddLog("start ControllerRecoverStake function", "debug") + fileName = self.contractsDir + "jetton_pool/fift-scripts/recover_stake.boc" + resultFilePath = self.SignBocWithWallet(wallet, fileName, controllerAddr, 1.04) + self.SendFile(resultFilePath, wallet) + local.AddLog("ControllerRecoverStake completed") + #end define def GetNetworkName(self): mainnetValidatorsElectedFor = 65536 @@ -3950,10 +4134,15 @@ def ValidatorDownEvent(): def Elections(ton): usePool = local.db.get("usePool") + useController = local.db.get("useController") if usePool == True: ton.PoolsUpdateValidatorSet() ton.RecoverStake() ton.ElectionEntry() + elif useController == True: + ton.ControllerUpdateValidatorSet() + ton.RecoverStake() + ton.ElectionEntry() else: ton.RecoverStake() ton.ElectionEntry() @@ -4410,6 +4599,11 @@ def Dec2HexAddr(dec): return h64 #end define +def HexAddr2Dec(h): + d = int(h, 16) + return d +#end define + def xhex2hex(x): try: b = x[1:] diff --git a/mytonctrl.py b/mytonctrl.py index 665755a7..7ccc7f3a 100755 --- a/mytonctrl.py +++ b/mytonctrl.py @@ -69,6 +69,12 @@ def Init(argv): console.AddItem("deposit_to_pool", DepositToPool, local.Translate("deposit_to_pool_cmd")) console.AddItem("withdraw_from_pool", WithdrawFromPool, local.Translate("withdraw_from_pool_cmd")) console.AddItem("delete_pool", DeletePool, local.Translate("delete_pool_cmd")) + + console.AddItem("new_controller", NewController, local.Translate("_")) + console.AddItem("get_controller_data", GetControllerData, local.Translate("_")) + console.AddItem("create_loan_request", CreateLoanRequest, local.Translate("_")) + console.AddItem("return_unused_loan", ReturnUnusedLoan, local.Translate("_")) + console.AddItem("withdraw_from_controller", WithdrawFromController, local.Translate("_")) # Process input parameters opts, args = getopt.getopt(argv,"hc:w:",["config=","wallets="]) @@ -1151,9 +1157,42 @@ def UpdateValidatorSet(args): except: ColorPrint("{red}Bad args. Usage:{endc} update_validator_set ") return - wallet = self.GetValidatorWallet() - self.PoolUpdateValidatorSet(poolAddr, wallet) - ColorPrint("DeletePool - {green}OK{endc}") + wallet = ton.GetValidatorWallet() + ton.PoolUpdateValidatorSet(poolAddr, wallet) + ColorPrint("UpdateValidatorSet - {green}OK{endc}") +#end define + +def NewController(args): + if len(args) == 1: + amount = int(args[0]) + else: + amount = 1 + ton.CreateController(amount) + ColorPrint("NewController - {green}OK{endc}") +#end define + +def GetControllerData(args): + controllerAddr = ton.GetControllerAddress() + data = ton.GetControllerData(controllerAddr) + print(f"GetControllerAddress: {controllerAddr}") + print(f"GetControllerData: {data}") +#end define + +def CreateLoanRequest(args): + controllerAddr = ton.GetControllerAddress() + ton.CreateLoanRequest(controllerAddr) +#end define + +def ReturnUnusedLoan(args): + controllerAddr = ton.GetControllerAddress() + ton.ReturnUnusedLoan(controllerAddr) +#end define + +def WithdrawFromController(args): + controllerAddr = ton.GetControllerAddress() + account = ton.GetAccount(controllerAddr) + amount = account.balance-10.1 + ton.WithdrawFromController(controllerAddr, amount) #end define From 3b01f119acd4b32ced95d9160cf914a5f6476f29 Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Wed, 14 Jun 2023 16:53:53 +0300 Subject: [PATCH 02/43] Update mytoncore.py --- mytoncore.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mytoncore.py b/mytoncore.py index 42645b74..0304c342 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -3637,7 +3637,7 @@ def CreateController(self, amount=1): liquidPoolAddr = local.db.get("liquidPoolAddr") contractPath = self.contractsDir + "jetton_pool/" if not os.path.isdir(contractPath): - self.DownloadContract("https://github.com/ton-blockchain/jetton_pool") + self.DownloadContract("https://github.com/igroman787/jetton_pool") #end if fileName = contractPath + "fift-scripts/deploy_controller.boc" From 998f509fef8ecdcb94c7f5e0376abb72f4988dcf Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Tue, 20 Jun 2023 23:19:29 +0300 Subject: [PATCH 03/43] add controller checks --- docs/ru/controllers.md | 83 ++++++++++++++++++++++ mytoncore.py | 153 ++++++++++++++++++++++++++++++----------- mytonctrl.py | 61 ++++++++++------ 3 files changed, 236 insertions(+), 61 deletions(-) create mode 100644 docs/ru/controllers.md diff --git a/docs/ru/controllers.md b/docs/ru/controllers.md new file mode 100644 index 00000000..87a7d21e --- /dev/null +++ b/docs/ru/controllers.md @@ -0,0 +1,83 @@ +# Контроллеры + +## Запуск валидатора в режиме работы контроллеров + +1. Подготовьте аппаратное обеспечение для валидатора - 32 виртуальных ядер, 64GB памяти, 1TB SSD, фиксированный IP-адрес, скорость интернета 1Gb/s. + + Для поддержания стабильности сети рекомендуется разместить валидаторы в различных местах по всему миру, а не концентрировать их в одном дата-центре. Вы можете использовать [этот сайт](https://status.toncenter.com/) для определения нагрузки на различные места. Согласно карте, высокая нагрузка на дата-центры в Европе, особенно в Финляндии, Германии и Париже. Поэтому использование провайдеров, таких как Hetzner и OVH, не рекомендуется. + + > Ваше оборудование должно соответствовать указанной конфигурации или быть выше. Запуск валидатора на слабом оборудовании негативно влияет на сеть и может привести к штрафам. + + > С мая 2021 года Hetzner запретил майнинг на своих серверах, в настоящее время под это правило попадают алгоритмы PoW и PoS. Установка даже обычного узла будет считаться нарушением условий договора. + + > **Рекомендуемые провайдеры:** [Amazon](https://aws.amazon.com/), [DigitalOcean](https://www.digitalocean.com/), [Linode](https://www.linode.com/), [Alibaba Cloud](https://alibabacloud.com/), [Latitude](https://www.latitude.sh/). + +2. Установите и синхронизируйте **mytonctrl** в соответствии с описанием в [этой инструкции](https://github.com/ton-blockchain/mytonctrl/blob/master/docs/ru/manual-ubuntu.md) — следуйте **только** пунктам 1, 2 и 3. + + Вы также можете обратиться к этой [Видеоинструкции](https://ton.org/docs/#/nodes/run-node) для дополнительной помощи. + +3. Переведите 1 TON на адрес кошелька валидатора, который отображается в списке `wl`. + +4. Используйте команду `aw` для активации кошелька валидатора. + +5. Переведите достаточно TON на адрес кошелька валидатора. + +6. Задайте адрес ликвидного пула, котрый будет одалживать TON для валидации: + ``` + set liquid_pool_addr EQCaHqeMgvlZRS6mDA0lzp78CF3QRNWfBQ86rE1SDcK4dijQ + ``` + +7. Задайте параметры кредитования, котрые вам подходят: + ``` + set min_loan 41000 + set max_loan 43000 + set max_interest_percent 1.5 + ``` + + где `min_loan` - это минимальная сумма кредита который мы готовы получить у ликвидного пула, + `max_loan` - это максимальная сумма кредита который мы готовы получить у ликвидного пула, + `max_interest_percent` - это максимальная процентная ставка ликвидного пула за один цикл валидации на которую мы согласны. + +8. Создайте два контроллера одной командой: + + ``` + new_controllers + ``` + + > (!) Используйте https://tonmon.xyz/, чтобы определить текущую минимальную ставку валидатора. + +9. Введите `controllers_list` чтобы отобразить адреса контроллеров: + + ``` + controllers_list + Address Status Balance + kf89KYOeRPRRDyjt_3bPsz92cKSghRqw64efNr8mT1eeHDaS active 0.704345 + kf_lT8QNykLh5PN5ictNX22maiyIf9iK787fXg6nJ_zB-jbN active 0.720866 + ``` + +10. Совершите депозит валидатора в каждый кнтроллер: + + ``` + deposit_to_controller kf89KYOeRPRRDyjt_3bPsz92cKSghRqw64efNr8mT1eeHDaS 10000 + deposit_to_controller kf_lT8QNykLh5PN5ictNX22maiyIf9iK787fXg6nJ_zB-jbN 10000 + ``` + + где `10000` TON - это сумма депозита. + +11. Активируйте режим работы контроллеров: + + ```bash + set useController true + set stake null + ``` + + > (!) Если до этого вы использовали номинатор-пулы, не забудьте отключить их использование командой `set usePool false`. + + +## Переключение обычного валидатора в режим работы контроллеров + +1. Введите `set stake 0`, чтобы отключить участие в выборах. + +2. Дождитесь, когда оба ваших депозита вернутся от электора. + +3. Следуйте инструкциям "Запуск валидатора в режиме работы контроллеров", начиная с **6-го шага**. \ No newline at end of file diff --git a/mytoncore.py b/mytoncore.py index 0304c342..c20f47f6 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -1399,7 +1399,9 @@ def SignBocWithWallet(self, wallet, bocPath, dest, coins, **kwargs): #end if seqno = self.GetSeqno(wallet) - resultFilePath = self.tempDir + self.nodeName + wallet.name + "_wallet-query" + #resultFilePath = self.tempDir + self.nodeName + wallet.name + "_wallet-query" + boc_name = os.path.splitext(os.path.basename(bocPath))[0] + resultFilePath = self.tempDir + self.nodeName + boc_name + "_sign_with_" + wallet.name if "v1" in wallet.version: fiftScript = "wallet.fif" args = [fiftScript, wallet.path, dest, seqno, coins, "-B", bocPath, resultFilePath] @@ -1499,7 +1501,7 @@ def GetStake(self, account, args=None): if stake is None and usePool: stake = account.balance - 20 if stake is None and useController: - stake = account.balance - 20 + stake = account.balance - 30 if stake is None: sp = stakePercent / 100 if sp > 1 or sp < 0: @@ -1542,6 +1544,8 @@ def GetValidatorWallet(self, mode="stake"): #local.AddLog("start GetValidatorWallet function", "debug") walletName = local.db.get("validatorWalletName") wallet = self.GetLocalWallet(walletName) + if wallet is None: + raise Exception("GetValidatorWallet error: Validator wallet not found") return wallet #end define @@ -1550,9 +1554,6 @@ def ElectionEntry(self, args=None): useController = local.db.get("useController") wallet = self.GetValidatorWallet() addrB64 = wallet.addrB64 - if wallet is None: - raise Exception("Validator wallet not found") - #end if local.AddLog("start ElectionEntry function", "debug") # Check if validator is not synchronized @@ -1593,10 +1594,10 @@ def ElectionEntry(self, args=None): pool = self.GetPool(mode="stake") addrB64 = pool.addrB64 elif useController: - controllerAddr = self.GetControllerAddress() + controllerAddr = self.GetController(mode="stake") self.CheckController(controllerAddr) self.CreateLoanRequest(controllerAddr) - addrB64 = self.GetControllerAddress() + addrB64 = controllerAddr #end if # Calculate stake @@ -1672,10 +1673,6 @@ def GetValidatorKeyByTime(self, startWorkTime, endWorkTime): def RecoverStake(self): wallet = self.GetValidatorWallet() - if wallet is None: - raise Exception("Validator wallet not found") - #end if - local.AddLog("start RecoverStake function", "debug") fullElectorAddr = self.GetFullElectorAddr() returnedStake = self.GetReturnedStake(fullElectorAddr, wallet.addrB64) @@ -1692,10 +1689,6 @@ def RecoverStake(self): def PoolRecoverStake(self, poolAddr): wallet = self.GetValidatorWallet() - if wallet is None: - raise Exception("Validator wallet not found") - #end if - local.AddLog("start PoolRecoverStake function", "debug") resultFilePath = self.PoolProcessRecoverStake() resultFilePath = self.SignBocWithWallet(wallet, resultFilePath, poolAddr, 1.2) @@ -3630,26 +3623,38 @@ def GetPoolData(self, addrB64): poolData["stakeHeldFor"] = data[15] return poolData #end define + + def GetLiquidPoolAddr(self): + liquid_pool_addr = local.db.get("liquid_pool_addr") + if liquid_pool_addr is None: + raise Exception("GetLiquidPoolAddr error: liquid_pool_addr not set") + return liquid_pool_addr + #end define - def CreateController(self, amount=1): - local.AddLog("start CreateController function", "debug") + def CreateControllers(self): + local.AddLog("start CreateControllers function", "debug") wallet = self.GetValidatorWallet() - liquidPoolAddr = local.db.get("liquidPoolAddr") + liquid_pool_addr = self.GetLiquidPoolAddr() contractPath = self.contractsDir + "jetton_pool/" if not os.path.isdir(contractPath): self.DownloadContract("https://github.com/igroman787/jetton_pool") #end if - fileName = contractPath + "fift-scripts/deploy_controller.boc" - resultFilePath = self.SignBocWithWallet(wallet, fileName, liquidPoolAddr, amount) - self.SendFile(resultFilePath, wallet) + fileName0 = contractPath + "fift-scripts/deploy_controller0.boc" + fileName1 = contractPath + "fift-scripts/deploy_controller1.boc" + resultFilePath0 = self.SignBocWithWallet(wallet, fileName0, liquid_pool_addr, 1) + self.SendFile(resultFilePath0, wallet) + time.sleep(10) + resultFilePath1 = self.SignBocWithWallet(wallet, fileName1, liquid_pool_addr, 1) + self.SendFile(resultFilePath1, wallet) + local.db["controllersAddr"] = self.GetControllers() #end define - def GetControllerAddress(self): + def GetControllerAddress(self, controller_id): wallet = self.GetValidatorWallet() addr_hash = HexAddr2Dec(wallet.addr) - liquidPoolAddr = local.db.get("liquidPoolAddr") - cmd = f"runmethodfull {liquidPoolAddr} get_controller_address_legacy {wallet.workchain} {addr_hash}" + liquid_pool_addr = self.GetLiquidPoolAddr() + cmd = f"runmethodfull {liquid_pool_addr} get_controller_address_legacy {controller_id} {wallet.workchain} {addr_hash}" result = self.liteClient.Run(cmd) buff = self.Result2List(result) wc = buff[0] @@ -3661,14 +3666,68 @@ def GetControllerAddress(self): def CheckController(self, controllerAddr): local.AddLog("start CheckController function", "debug") + now = GetTimestamp() controllerData = self.GetControllerData(controllerAddr) - saveControllerAddr = local.db.get("controllerAddr") + saveControllersAddr = local.db.get("controllersAddr", list()) if controllerData["approved"] != -1: - raise Exception(f"GetControllerAddress error: controller not approved: {controllerAddr}") - if saveControllerAddr != controllerAddr: - local.AddLog("GetControllerAddress warning: controller is not up to date. Recreating the controller", "warning") - self.CreateController() - local.db["controllerAddr"] = controllerAddr + raise Exception(f"CheckController error: controller not approved: {controllerAddr}") + if controllerData["borrowed_amount"] > 0 and controllerData["borrowing_time"] > now: + local.AddLog("CheckController warning: controller has loan. Return unused loan", "warning") + self.ReturnUnusedLoan(controllerAddr) + if controllerAddr not in saveControllersAddr: + raise Exception("CheckController error: controller is not up to date. Use new_controllers") + #end define + + def GetControllers(self): + local.AddLog("start GetControllers function", "debug") + controller0 = self.GetControllerAddress(controller_id=0) + controller1 = self.GetControllerAddress(controller_id=1) + controllers = [controller0, controller1] + return controllers + #end define + + def GetController(self, mode): + controllers = self.GetControllers() + for controllerAddr in controllers: + if mode == "stake" and self.IsControllerReadyToStake(controllerAddr): + return controllerAddr + if mode == "vote" and self.IsControllerReadyToVote(controllerAddr): + return controllerAddr + raise Exception("Validator controller not found or not ready") + #end define + + def GetControllerRequiredBalanceForLoan(self, controllerAddr, credit, interest): + cmd = f"runmethodfull {controllerAddr} required_balance_for_loan {credit} {interest}" + result = self.liteClient.Run(cmd) + data = self.Result2List(result) + if data is None: + return + result_vars = ["min_amount", "validator_amount"] + result = dict() + for name in result_vars: + result[name] = data.pop(0) + return result + #end define + + def GetControllerLastSentStakeTime(self, addrB64): + controllerData = self.GetControllerData(addrB64) + return controllerData["stake_at"] + #end define + + def IsControllerReadyToStake(self, addrB64): + now = GetTimestamp() + config15 = self.GetConfig15() + lastSentStakeTime = self.GetControllerLastSentStakeTime(addrB64) + stakeFreezeDelay = config15["validatorsElectedFor"] + config15["stakeHeldFor"] + result = lastSentStakeTime + stakeFreezeDelay < now + print(f"{addrB64}: {result}. {lastSentStakeTime}, {stakeFreezeDelay}, {now}") + return result + #end define + + def IsControllerReadyToVote(self, addrB64): + vwl = self.GetValidatorsWalletsList() + result = addrB64 in vwl + return result #end define def GetControllerData(self, controllerAddr): @@ -3677,7 +3736,7 @@ def GetControllerData(self, controllerAddr): data = self.Result2List(result) if data is None: return - result_vars = ["state", "approved", "stake_amount_sent", "stake_at", "saved_validator_set_hash", "validator_set_changes_count", "validator_set_change_time", "stake_held_for", "borrowed_amount", "borrowing_time"] + result_vars = ["state", "halted", "approved", "stake_amount_sent", "stake_at", "saved_validator_set_hash", "validator_set_changes_count", "validator_set_change_time", "stake_held_for", "borrowed_amount", "borrowing_time"] controllerData = dict() for name in result_vars: controllerData[name] = data.pop(0) @@ -3688,7 +3747,8 @@ def CreateLoanRequest(self, controllerAddr): local.AddLog("start CreateLoanRequest function", "debug") min_loan = local.db.get("min_loan", 41000) max_loan = local.db.get("max_loan", 43000) - max_interest_percent = local.db.get("max_interest_percent", 0.015) + max_interest_percent = local.db.get("max_interest_percent", 1.5) + max_interest = int(max_interest_percent/100*65536) # TODO # Проверить наличие старого кредита controllerData = self.GetControllerData(controllerAddr) @@ -3697,8 +3757,13 @@ def CreateLoanRequest(self, controllerAddr): return #end if + # Проверить хватает ли ставки валидатора + min_amount, validator_amount = self.GetControllerRequiredBalanceForLoan(controllerAddr, max_loan, max_interest) + if validator_amount < min_amount: + raise Exception("CreateLoanRequest error: too_high_loan_request_amount") + #end if + wallet = self.GetValidatorWallet() - max_interest = int(max_interest_percent*65536) fiftScript = self.contractsDir + "jetton_pool/fift-scripts/generate-loan-request.fif" resultFilePath = self.tempDir + self.nodeName + wallet.name + "_loan_request.boc" args = [fiftScript, min_loan, max_loan, max_interest, resultFilePath] @@ -3725,6 +3790,14 @@ def ReturnUnusedLoan(self, controllerAddr): resultFilePath = self.SignBocWithWallet(wallet, fileName, controllerAddr, 1.05) self.SendFile(resultFilePath, wallet) #end define + + def DepositToController(self, controllerAddr, amount): + local.AddLog("start DepositToController function", "debug") + wallet = self.GetValidatorWallet() + fileName = self.contractsDir + "jetton_pool/fift-scripts/top-up.boc" + resultFilePath = self.SignBocWithWallet(wallet, fileName, controllerAddr, amount) + self.SendFile(resultFilePath, wallet) + #end define def WithdrawFromController(self, controllerAddr, amount): local.AddLog("start WithdrawFromController function", "debug") @@ -3749,11 +3822,17 @@ def SignElectionRequestWithController(self, controllerAddr, startWorkTime, adnlA fileName = Pars(result, "Saved to file ", '\n') return pubkey, fileName #end define - + def ControllerUpdateValidatorSet(self): local.AddLog("start ControllerUpdateValidatorSet function", "debug") + controllers = self.GetControllers() + for controller in controllers: + self.ControllerUpdateValidatorSetProcess(controller) + #end define + + def ControllerUpdateValidatorSetProcess(self, controllerAddr): + local.AddLog("start ControllerUpdateValidatorSetProcess function", "debug") wallet = self.GetValidatorWallet() - controllerAddr = self.GetControllerAddress() controllerData = self.GetControllerData(controllerAddr) if controllerData is None: return @@ -3787,10 +3866,6 @@ def ControllerProcessUpdateValidatorSet(self, controllerAddr, wallet): def ControllerRecoverStake(self, controllerAddr): wallet = self.GetValidatorWallet() - if wallet is None: - raise Exception("Validator wallet not found") - #end if - local.AddLog("start ControllerRecoverStake function", "debug") fileName = self.contractsDir + "jetton_pool/fift-scripts/recover_stake.boc" resultFilePath = self.SignBocWithWallet(wallet, fileName, controllerAddr, 1.04) diff --git a/mytonctrl.py b/mytonctrl.py index 7ccc7f3a..8ae23805 100755 --- a/mytonctrl.py +++ b/mytonctrl.py @@ -70,10 +70,10 @@ def Init(argv): console.AddItem("withdraw_from_pool", WithdrawFromPool, local.Translate("withdraw_from_pool_cmd")) console.AddItem("delete_pool", DeletePool, local.Translate("delete_pool_cmd")) - console.AddItem("new_controller", NewController, local.Translate("_")) + console.AddItem("new_controllers", NewControllers, local.Translate("_")) + console.AddItem("controllers_list", PrintControllersList, local.Translate("_")) console.AddItem("get_controller_data", GetControllerData, local.Translate("_")) - console.AddItem("create_loan_request", CreateLoanRequest, local.Translate("_")) - console.AddItem("return_unused_loan", ReturnUnusedLoan, local.Translate("_")) + console.AddItem("deposit_to_controller", DepositToController, local.Translate("_")) console.AddItem("withdraw_from_controller", WithdrawFromController, local.Translate("_")) # Process input parameters @@ -1162,34 +1162,51 @@ def UpdateValidatorSet(args): ColorPrint("UpdateValidatorSet - {green}OK{endc}") #end define -def NewController(args): - if len(args) == 1: - amount = int(args[0]) - else: - amount = 1 - ton.CreateController(amount) - ColorPrint("NewController - {green}OK{endc}") +def NewControllers(args): + ton.CreateControllers() + ColorPrint("NewControllers - {green}OK{endc}") #end define -def GetControllerData(args): - controllerAddr = ton.GetControllerAddress() - data = ton.GetControllerData(controllerAddr) - print(f"GetControllerAddress: {controllerAddr}") - print(f"GetControllerData: {data}") +def PrintControllersList(args): + table = list() + table += [["Address", "Status", "Balance"]] + controllers = ton.GetControllers() + if (controllers is None or len(controllers) == 0): + print("No data") + return + for controllerAddr in controllers: + account = ton.GetAccount(controllerAddr) + table += [[controllerAddr, account.status, account.balance]] + PrintTable(table) #end define -def CreateLoanRequest(args): - controllerAddr = ton.GetControllerAddress() - ton.CreateLoanRequest(controllerAddr) +def GetControllerData(args): + try: + controllerAddr = args[0] + except: + ColorPrint("{red}Bad args. Usage:{endc} get_controller_data ") + return + data = ton.GetControllerData(controllerAddr) + print(f"ControllerData: {data}") #end define -def ReturnUnusedLoan(args): - controllerAddr = ton.GetControllerAddress() - ton.ReturnUnusedLoan(controllerAddr) +def DepositToController(args): + try: + controllerAddr = args[0] + amount = float(args[1]) + except: + ColorPrint("{red}Bad args. Usage:{endc} deposit_to_controller ") + return + ton.DepositToController(controllerAddr, amount) #end define def WithdrawFromController(args): - controllerAddr = ton.GetControllerAddress() + try: + controllerAddr = args[0] + except: + ColorPrint("{red}Bad args. Usage:{endc} withdraw_from_controller ") + return + ton.CheckController(controllerAddr) account = ton.GetAccount(controllerAddr) amount = account.balance-10.1 ton.WithdrawFromController(controllerAddr, amount) From fd1bfd2f9bc6158572f6a6b55ecf81b55de8779f Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Wed, 21 Jun 2023 11:12:11 +0300 Subject: [PATCH 04/43] Update controllers.md --- docs/ru/controllers.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/docs/ru/controllers.md b/docs/ru/controllers.md index 87a7d21e..ec77ffb1 100644 --- a/docs/ru/controllers.md +++ b/docs/ru/controllers.md @@ -10,8 +10,6 @@ > С мая 2021 года Hetzner запретил майнинг на своих серверах, в настоящее время под это правило попадают алгоритмы PoW и PoS. Установка даже обычного узла будет считаться нарушением условий договора. - > **Рекомендуемые провайдеры:** [Amazon](https://aws.amazon.com/), [DigitalOcean](https://www.digitalocean.com/), [Linode](https://www.linode.com/), [Alibaba Cloud](https://alibabacloud.com/), [Latitude](https://www.latitude.sh/). - 2. Установите и синхронизируйте **mytonctrl** в соответствии с описанием в [этой инструкции](https://github.com/ton-blockchain/mytonctrl/blob/master/docs/ru/manual-ubuntu.md) — следуйте **только** пунктам 1, 2 и 3. Вы также можете обратиться к этой [Видеоинструкции](https://ton.org/docs/#/nodes/run-node) для дополнительной помощи. @@ -44,8 +42,6 @@ new_controllers ``` - > (!) Используйте https://tonmon.xyz/, чтобы определить текущую минимальную ставку валидатора. - 9. Введите `controllers_list` чтобы отобразить адреса контроллеров: ``` @@ -55,7 +51,7 @@ kf_lT8QNykLh5PN5ictNX22maiyIf9iK787fXg6nJ_zB-jbN active 0.720866 ``` -10. Совершите депозит валидатора в каждый кнтроллер: +10. Совершите депозит валидатора в каждый контроллер: ``` deposit_to_controller kf89KYOeRPRRDyjt_3bPsz92cKSghRqw64efNr8mT1eeHDaS 10000 From f2b4203105a3faa29d1303ea73bdba7a0fafc19f Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Wed, 21 Jun 2023 11:37:44 +0300 Subject: [PATCH 05/43] Update controllers.md --- docs/ru/controllers.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/docs/ru/controllers.md b/docs/ru/controllers.md index ec77ffb1..c0320146 100644 --- a/docs/ru/controllers.md +++ b/docs/ru/controllers.md @@ -22,7 +22,7 @@ 6. Задайте адрес ликвидного пула, котрый будет одалживать TON для валидации: ``` - set liquid_pool_addr EQCaHqeMgvlZRS6mDA0lzp78CF3QRNWfBQ86rE1SDcK4dijQ + set liquid_pool_addr ``` 7. Задайте параметры кредитования, котрые вам подходят: @@ -32,9 +32,9 @@ set max_interest_percent 1.5 ``` - где `min_loan` - это минимальная сумма кредита который мы готовы получить у ликвидного пула, - `max_loan` - это максимальная сумма кредита который мы готовы получить у ликвидного пула, - `max_interest_percent` - это максимальная процентная ставка ликвидного пула за один цикл валидации на которую мы согласны. + где `41000` - это минимальная сумма кредита который мы готовы получить у ликвидного пула, + `43000` - это максимальная сумма кредита который мы готовы получить у ликвидного пула, + `1.5` - это максимальная процентная ставка ликвидного пула за один цикл валидации на которую мы согласны. 8. Создайте два контроллера одной командой: @@ -60,7 +60,9 @@ где `10000` TON - это сумма депозита. -11. Активируйте режим работы контроллеров: +11. Получите аппрувал контроллеров. У каждого пула может быть своя политика выдачи аппруволов, уточняйте у оператора. + +12. Активируйте режим работы контроллеров: ```bash set useController true From e2f09722b317ffb75d35ce066f398b1aecb3ff6a Mon Sep 17 00:00:00 2001 From: AlexG Date: Wed, 21 Jun 2023 13:27:25 +0400 Subject: [PATCH 06/43] controllers_translate_added - Added controlleres.md en version. - Minor fixes for links in the controllers.md in the ru version. --- docs/en/controllers.md | 83 ++++++++++++++++++++++++++++++++++++++++++ docs/ru/controllers.md | 13 ++++--- 2 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 docs/en/controllers.md diff --git a/docs/en/controllers.md b/docs/en/controllers.md new file mode 100644 index 00000000..52150228 --- /dev/null +++ b/docs/en/controllers.md @@ -0,0 +1,83 @@ +# Controllers + +## Launching a Validator in Controller Mode + +1. Prepare the hardware for the validator - 32 virtual cores, 64GB of memory, 1TB SSD, fixed IP address, and 1Gb/s internet speed. + + To maintain network stability, it is recommended to place validators in different locations around the world, rather than concentrating them in a single data center. You can use [this site](https://status.toncenter.com/) to determine the load on various locations. According to the map, there is a high load on data centers in Europe, especially in Finland, Germany, and Paris. Therefore, using providers such as Hetzner and OVH is not recommended. + + > Ensure your hardware meets or exceeds the specified configuration. Running the validator on inappropriate hardware can harm the network and result in penalties. + > Since May 2021, Hetzner has prohibited mining on its servers. This rule currently applies to both PoW and PoS algorithms. Even installing a regular node will be considered a breach of contract. + +2. Install and synchronize **mytonctrl** according to the description in [this instruction](https://github.com/ton-blockchain/mytonctrl/blob/master/docs/en/manual-ubuntu.md) — follow **only** paragraphs 1, 2, and 3. + + You can also refer to this [Video Tutorial](https://docs.ton.org/participate/run-nodes/full-node#installation) for additional help. + +3. Transfer 1 TON to the validator wallet address, which is displayed in the `wl` list. + +4. Use the `aw` command to activate the validator's wallet. + +5. Transfer enough TON to the validator wallet address. + +6. Set the liquid pool address, which will lend TON for validation: + ``` + set liquid_pool_addr + ``` + +7. Set the lending parameters that acceptable to you: + ``` + set min_loan 41000 + set max_loan 43000 + set max_interest_percent 1.5 + ``` + + where +* `41000` is the minimum loan amount we are willing to receive from the liquid pool, +* `43000` is the maximum loan amount we are willing to receive from the liquid pool, +* `1.5` 1.5 is the maximum interest rate value for the liquid pool per validation cycle, which we have agreed upon. + +8. Create two controllers with a single command: + + ``` + new_controllers + ``` + +9. Enter `controllers_list` to display the controller addresses: + + ``` + controllers_list + Address Status Balance + kf89KYOeRPRRDyjt_3bPsz92cKSghRqw64efNr8mT1eeHDaS active 0.704345 + kf_lT8QNykLh5PN5ictNX22maiyIf9iK787fXg6nJ_zB-jbN active 0.720866 + ``` + +10. Make a validator deposit in each controller: + + +``` +deposit_to_controller kf89KYOeRPRRDyjt_3bPsz92cKSghRqw64efNr8mT1eeHDaS 10000 +deposit_to_controller kf_lT8QNykLh5PN5ictNX22maiyIf9iK787fXg6nJ_zB-jbN 10000 +``` + + +where `10000` TON is the deposit amount. + +11. Get approval for the controllers. Each pool may have its own approval issuance policy, check with the operator. + +12. Set controller mode: + + ```bash + set useController true + set stake null + ``` + +> (!) If you were previously using nominator pools, do not forget to disable them using the `set usePool false` command. + + +## Switching a Regular Validator to Controller Operating Mode + +1. Enter `set stake 0` to stop participating in elections. + +2. Wait until both of your deposits have been returned from the Elector. + +3. Follow the instructions under "Launching a Validator in Controller Mode", beginning with **Step 6**. \ No newline at end of file diff --git a/docs/ru/controllers.md b/docs/ru/controllers.md index c0320146..aff65fd5 100644 --- a/docs/ru/controllers.md +++ b/docs/ru/controllers.md @@ -12,7 +12,7 @@ 2. Установите и синхронизируйте **mytonctrl** в соответствии с описанием в [этой инструкции](https://github.com/ton-blockchain/mytonctrl/blob/master/docs/ru/manual-ubuntu.md) — следуйте **только** пунктам 1, 2 и 3. - Вы также можете обратиться к этой [Видеоинструкции](https://ton.org/docs/#/nodes/run-node) для дополнительной помощи. + Вы также можете обратиться к этой [Видеоинструкции](https://docs.ton.org/participate/run-nodes/full-node#installation) для дополнительной помощи. 3. Переведите 1 TON на адрес кошелька валидатора, который отображается в списке `wl`. @@ -20,21 +20,22 @@ 5. Переведите достаточно TON на адрес кошелька валидатора. -6. Задайте адрес ликвидного пула, котрый будет одалживать TON для валидации: +6. Задайте адрес ликвидного пула, который будет одалживать TON для валидации: ``` set liquid_pool_addr ``` -7. Задайте параметры кредитования, котрые вам подходят: +7. Задайте параметры кредитования, которые вам подходят: ``` set min_loan 41000 set max_loan 43000 set max_interest_percent 1.5 ``` - где `41000` - это минимальная сумма кредита который мы готовы получить у ликвидного пула, - `43000` - это максимальная сумма кредита который мы готовы получить у ликвидного пула, - `1.5` - это максимальная процентная ставка ликвидного пула за один цикл валидации на которую мы согласны. + где +* `41000` - это минимальная сумма кредита который мы готовы получить у ликвидного пула, +* `43000` - это максимальная сумма кредита который мы готовы получить у ликвидного пула, +* `1.5` - это максимальная процентная ставка ликвидного пула за один цикл валидации на которую мы согласны. 8. Создайте два контроллера одной командой: From c292552d7c77cf49a6d542e094f31455a9802717 Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Sat, 1 Jul 2023 14:01:36 +0300 Subject: [PATCH 07/43] add `calculate_annual_controller_percentage` --- mytoncore.py | 21 ++++++++++++++++++--- mytonctrl.py | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+), 3 deletions(-) diff --git a/mytoncore.py b/mytoncore.py index c20f47f6..f05efd96 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -3666,12 +3666,12 @@ def GetControllerAddress(self, controller_id): def CheckController(self, controllerAddr): local.AddLog("start CheckController function", "debug") - now = GetTimestamp() + config34 = self.GetConfig34() controllerData = self.GetControllerData(controllerAddr) saveControllersAddr = local.db.get("controllersAddr", list()) if controllerData["approved"] != -1: raise Exception(f"CheckController error: controller not approved: {controllerAddr}") - if controllerData["borrowed_amount"] > 0 and controllerData["borrowing_time"] > now: + if controllerData["borrowed_amount"] > 0 and config34["startWorkTime"] > controllerData["borrowing_time"]: local.AddLog("CheckController warning: controller has loan. Return unused loan", "warning") self.ReturnUnusedLoan(controllerAddr) if controllerAddr not in saveControllersAddr: @@ -3749,7 +3749,7 @@ def CreateLoanRequest(self, controllerAddr): max_loan = local.db.get("max_loan", 43000) max_interest_percent = local.db.get("max_interest_percent", 1.5) max_interest = int(max_interest_percent/100*65536) - # TODO + # Проверить наличие старого кредита controllerData = self.GetControllerData(controllerAddr) if controllerData["borrowed_amount"] != 0: @@ -3757,6 +3757,11 @@ def CreateLoanRequest(self, controllerAddr): return #end if + # Проверить наличие средств у ликвидного пула + if self.CalculateLoanAmount(min_loan, max_loan, max_interest) == -1: + raise Exception("CreateLoanRequest error: The liquid pool cannot issue the required amount of credit") + #end if + # Проверить хватает ли ставки валидатора min_amount, validator_amount = self.GetControllerRequiredBalanceForLoan(controllerAddr, max_loan, max_interest) if validator_amount < min_amount: @@ -3773,6 +3778,16 @@ def CreateLoanRequest(self, controllerAddr): self.WaitLoan(controllerAddr) #end define + def CalculateLoanAmount(self, min_loan, max_loan, max_interest): + liquid_pool_addr = self.GetLiquidPoolAddr() + cmd = f"runmethodfull {liquid_pool_addr} calculate_loan_amount {min_loan} {max_loan} {max_interest}" + result = self.liteClient.Run(cmd) + data = self.Result2List(result) + if data is None: + return + return result.pop() + #end define + def WaitLoan(self, controllerAddr): local.AddLog("start WaitLoan function", "debug") for i in range(10): diff --git a/mytonctrl.py b/mytonctrl.py index 8ae23805..4aa4baf1 100755 --- a/mytonctrl.py +++ b/mytonctrl.py @@ -75,6 +75,7 @@ def Init(argv): console.AddItem("get_controller_data", GetControllerData, local.Translate("_")) console.AddItem("deposit_to_controller", DepositToController, local.Translate("_")) console.AddItem("withdraw_from_controller", WithdrawFromController, local.Translate("_")) + console.AddItem("calculate_annual_controller_percentage", CalculateAnnualControllerPercentage, local.Translate("_")) # Process input parameters opts, args = getopt.getopt(argv,"hc:w:",["config=","wallets="]) @@ -1212,6 +1213,23 @@ def WithdrawFromController(args): ton.WithdrawFromController(controllerAddr, amount) #end define +def CalculateAnnualControllerPercentage(args): + try: + percentPerRound = float(args[0]) + except: + percentPerRound = ton.GetSettings("max_interest_percent") + config15 = ton.GetConfig(15) + roundPeriod = config15["validators_elected_for"] + rounds = 365 * 24 * 3600 / roundPeriod + yearInterest = (1 + percentPerRound / 100) * rounds + yearInterestPercent = round(yearInterest / 100, 2) + print("roundPeriod", roundPeriod) + print("rounds", rounds) + print("percentPerRound", percentPerRound) + print("yearInterest", yearInterest) + print(f"yearInterestPercent: {yearInterestPercent}%") +#end define + ### ### Start of the program From 6591e3633dd5ca218055db00419306f4961000c7 Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Sat, 1 Jul 2023 16:36:39 +0300 Subject: [PATCH 08/43] bugfix --- mytoncore.py | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/mytoncore.py b/mytoncore.py index f05efd96..5f1f239d 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -3748,7 +3748,7 @@ def CreateLoanRequest(self, controllerAddr): min_loan = local.db.get("min_loan", 41000) max_loan = local.db.get("max_loan", 43000) max_interest_percent = local.db.get("max_interest_percent", 1.5) - max_interest = int(max_interest_percent/100*65536) + max_interest = int(max_interest_percent/100*16777216) # Проверить наличие старого кредита controllerData = self.GetControllerData(controllerAddr) @@ -3758,7 +3758,7 @@ def CreateLoanRequest(self, controllerAddr): #end if # Проверить наличие средств у ликвидного пула - if self.CalculateLoanAmount(min_loan, max_loan, max_interest) == -1: + if self.CalculateLoanAmount(min_loan, max_loan, max_interest) == '-0x1': raise Exception("CreateLoanRequest error: The liquid pool cannot issue the required amount of credit") #end if @@ -3779,13 +3779,19 @@ def CreateLoanRequest(self, controllerAddr): #end define def CalculateLoanAmount(self, min_loan, max_loan, max_interest): - liquid_pool_addr = self.GetLiquidPoolAddr() - cmd = f"runmethodfull {liquid_pool_addr} calculate_loan_amount {min_loan} {max_loan} {max_interest}" - result = self.liteClient.Run(cmd) - data = self.Result2List(result) - if data is None: - return - return result.pop() + data = dict() + data["address"] = liquid_pool_addr + data["method"] = "calculate_loan_amount" + data["stack"] = [ + ["num", min_loan*10**9], + ["num", max_loan*10**9], + ["num", max_interest], + ] + + url = "https://testnet.toncenter.com/api/v2/runGetMethod" + res = requests.post(url, json=data) + result = res.json().get("result").get("stack").pop().pop() + return result #end define def WaitLoan(self, controllerAddr): From a095227feb34b25c2a55bfefc213361306f268ff Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Sat, 1 Jul 2023 17:22:16 +0300 Subject: [PATCH 09/43] bugfix --- mytoncore.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mytoncore.py b/mytoncore.py index 5f1f239d..91e21eb2 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -3780,7 +3780,7 @@ def CreateLoanRequest(self, controllerAddr): def CalculateLoanAmount(self, min_loan, max_loan, max_interest): data = dict() - data["address"] = liquid_pool_addr + data["address"] = self.GetLiquidPoolAddr() data["method"] = "calculate_loan_amount" data["stack"] = [ ["num", min_loan*10**9], From fde74608a77688994a078997f20cf49a6ed61ce5 Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Sun, 2 Jul 2023 21:37:41 +0300 Subject: [PATCH 10/43] bugfix --- mytoncore.py | 38 ++++++++++++++++---------------------- mytonctrl.py | 18 +++++++++++++++--- 2 files changed, 31 insertions(+), 25 deletions(-) diff --git a/mytoncore.py b/mytoncore.py index 91e21eb2..e73b2a7f 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -3666,14 +3666,10 @@ def GetControllerAddress(self, controller_id): def CheckController(self, controllerAddr): local.AddLog("start CheckController function", "debug") - config34 = self.GetConfig34() controllerData = self.GetControllerData(controllerAddr) saveControllersAddr = local.db.get("controllersAddr", list()) if controllerData["approved"] != -1: raise Exception(f"CheckController error: controller not approved: {controllerAddr}") - if controllerData["borrowed_amount"] > 0 and config34["startWorkTime"] > controllerData["borrowing_time"]: - local.AddLog("CheckController warning: controller has loan. Return unused loan", "warning") - self.ReturnUnusedLoan(controllerAddr) if controllerAddr not in saveControllersAddr: raise Exception("CheckController error: controller is not up to date. Use new_controllers") #end define @@ -3750,13 +3746,6 @@ def CreateLoanRequest(self, controllerAddr): max_interest_percent = local.db.get("max_interest_percent", 1.5) max_interest = int(max_interest_percent/100*16777216) - # Проверить наличие старого кредита - controllerData = self.GetControllerData(controllerAddr) - if controllerData["borrowed_amount"] != 0: - local.AddLog("CreateLoanRequest info: loan already taken") - return - #end if - # Проверить наличие средств у ликвидного пула if self.CalculateLoanAmount(min_loan, max_loan, max_interest) == '-0x1': raise Exception("CreateLoanRequest error: The liquid pool cannot issue the required amount of credit") @@ -3764,7 +3753,7 @@ def CreateLoanRequest(self, controllerAddr): # Проверить хватает ли ставки валидатора min_amount, validator_amount = self.GetControllerRequiredBalanceForLoan(controllerAddr, max_loan, max_interest) - if validator_amount < min_amount: + if min_amount > validator_amount: raise Exception("CreateLoanRequest error: too_high_loan_request_amount") #end if @@ -3844,15 +3833,15 @@ def SignElectionRequestWithController(self, controllerAddr, startWorkTime, adnlA return pubkey, fileName #end define - def ControllerUpdateValidatorSet(self): - local.AddLog("start ControllerUpdateValidatorSet function", "debug") + def ControllersUpdateValidatorSet(self): + local.AddLog("start ControllersUpdateValidatorSet function", "debug") controllers = self.GetControllers() for controller in controllers: - self.ControllerUpdateValidatorSetProcess(controller) + self.ControllerUpdateValidatorSet(controller) #end define - def ControllerUpdateValidatorSetProcess(self, controllerAddr): - local.AddLog("start ControllerUpdateValidatorSetProcess function", "debug") + def ControllerUpdateValidatorSet(self, controllerAddr): + local.AddLog("start ControllerUpdateValidatorSet function", "debug") wallet = self.GetValidatorWallet() controllerData = self.GetControllerData(controllerAddr) if controllerData is None: @@ -3868,21 +3857,26 @@ def ControllerUpdateValidatorSetProcess(self, controllerAddr): if (controllerData["state"] == 3 and controllerData["validator_set_changes_count"] < 2 and controllerData["validator_set_change_time"] < config34["startWorkTime"]): - self.ControllerProcessUpdateValidatorSet(controllerAddr, wallet) + self.ControllerUpdateValidatorSetProcess(controllerAddr, wallet) controllerData = self.GetControllerData(controllerAddr) if (returnedStake > 0 and controllerData["state"] == 3 and controllerData["validator_set_changes_count"] >= 2 and timeNow - controllerData["validator_set_change_time"] > controllerData["stake_held_for"] + 60): self.ControllerRecoverStake(controllerAddr) + controllerData = self.GetControllerData(controllerAddr) + if (controllerData["borrowed_amount"] > 0 and + controllerData["stake_amount_sent"] == 0 and + config34["startWorkTime"] > controllerData["borrowing_time"]): + self.ReturnUnusedLoan(controllerAddr) #end define - def ControllerProcessUpdateValidatorSet(self, controllerAddr, wallet): - local.AddLog("start ControllerProcessUpdateValidatorSet function", "debug") + def ControllerUpdateValidatorSetProcess(self, controllerAddr, wallet): + local.AddLog("start ControllerUpdateValidatorSetProcess function", "debug") fileName = self.contractsDir + "jetton_pool/fift-scripts/update_validator_hash.boc" resultFilePath = self.SignBocWithWallet(wallet, fileName, controllerAddr, 1.07) self.SendFile(resultFilePath, wallet) - local.AddLog("ControllerProcessUpdateValidatorSet completed") + local.AddLog("ControllerUpdateValidatorSetProcess completed") #end define def ControllerRecoverStake(self, controllerAddr): @@ -4236,7 +4230,7 @@ def Elections(ton): ton.RecoverStake() ton.ElectionEntry() elif useController == True: - ton.ControllerUpdateValidatorSet() + ton.ControllersUpdateValidatorSet() ton.RecoverStake() ton.ElectionEntry() else: diff --git a/mytonctrl.py b/mytonctrl.py index 4aa4baf1..4304974c 100755 --- a/mytonctrl.py +++ b/mytonctrl.py @@ -76,6 +76,8 @@ def Init(argv): console.AddItem("deposit_to_controller", DepositToController, local.Translate("_")) console.AddItem("withdraw_from_controller", WithdrawFromController, local.Translate("_")) console.AddItem("calculate_annual_controller_percentage", CalculateAnnualControllerPercentage, local.Translate("_")) + console.AddItem("controller_update_validator_set", ControllerUpdateValidatorSet, local.Translate("_")) + # Process input parameters opts, args = getopt.getopt(argv,"hc:w:",["config=","wallets="]) @@ -1152,15 +1154,15 @@ def DeletePool(args): ColorPrint("DeletePool - {green}OK{endc}") #end define -def UpdateValidatorSet(args): +def PoolUpdateValidatorSet(args): try: poolAddr = args[0] except: - ColorPrint("{red}Bad args. Usage:{endc} update_validator_set ") + ColorPrint("{red}Bad args. Usage:{endc} pool_update_validator_set ") return wallet = ton.GetValidatorWallet() ton.PoolUpdateValidatorSet(poolAddr, wallet) - ColorPrint("UpdateValidatorSet - {green}OK{endc}") + ColorPrint("PoolUpdateValidatorSet - {green}OK{endc}") #end define def NewControllers(args): @@ -1230,6 +1232,16 @@ def CalculateAnnualControllerPercentage(args): print(f"yearInterestPercent: {yearInterestPercent}%") #end define +def ControllerUpdateValidatorSet(args): + try: + controllerAddr = args[0] + except: + ColorPrint("{red}Bad args. Usage:{endc} controller_update_validator_set ") + return + ton.ControllerUpdateValidatorSet(controllerAddr) + ColorPrint("ControllerUpdateValidatorSet - {green}OK{endc}") +#end define + ### ### Start of the program From 121ff31bd530f5eed03941e2b33c26bd74dfa97c Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Wed, 5 Jul 2023 22:36:18 +0300 Subject: [PATCH 11/43] add `ton-http-api` service --- docs/en/controllers.md | 25 +++++++++++++------ docs/ru/controllers.md | 27 ++++++++++++++------- mytoncore.py | 2 +- mytoninstaller.py | 19 ++++++++------- scripts/ton_http_api_installer.sh | 40 +++++++++++++++++++++++++++++++ 5 files changed, 88 insertions(+), 25 deletions(-) create mode 100644 scripts/ton_http_api_installer.sh diff --git a/docs/en/controllers.md b/docs/en/controllers.md index 52150228..cfcb7853 100644 --- a/docs/en/controllers.md +++ b/docs/en/controllers.md @@ -19,12 +19,18 @@ 5. Transfer enough TON to the validator wallet address. -6. Set the liquid pool address, which will lend TON for validation: +6. Enable the ton-http-api service: + ``` + mytonctrl -> installer -> enable THA + ``` + Exit installer mode with `Ctrl+C` + +7. Set the liquid pool address, which will lend TON for validation: ``` set liquid_pool_addr ``` -7. Set the lending parameters that acceptable to you: +8. Set the lending parameters that acceptable to you: ``` set min_loan 41000 set max_loan 43000 @@ -36,13 +42,18 @@ * `43000` is the maximum loan amount we are willing to receive from the liquid pool, * `1.5` 1.5 is the maximum interest rate value for the liquid pool per validation cycle, which we have agreed upon. -8. Create two controllers with a single command: +9. Display the annual percentage of profit from the liquid pool: + ``` + calculate_annual_controller_percentage + ``` + +10. Create two controllers with a single command: ``` new_controllers ``` -9. Enter `controllers_list` to display the controller addresses: +11. Enter `controllers_list` to display the controller addresses: ``` controllers_list @@ -51,7 +62,7 @@ kf_lT8QNykLh5PN5ictNX22maiyIf9iK787fXg6nJ_zB-jbN active 0.720866 ``` -10. Make a validator deposit in each controller: +12. Make a validator deposit in each controller: ``` @@ -62,9 +73,9 @@ deposit_to_controller kf_lT8QNykLh5PN5ictNX22maiyIf9iK787fXg6nJ_zB-jbN 10000 where `10000` TON is the deposit amount. -11. Get approval for the controllers. Each pool may have its own approval issuance policy, check with the operator. +13. Get approval for the controllers. Each pool may have its own approval issuance policy, check with the operator. -12. Set controller mode: +14. Set controller mode: ```bash set useController true diff --git a/docs/ru/controllers.md b/docs/ru/controllers.md index aff65fd5..184bcc95 100644 --- a/docs/ru/controllers.md +++ b/docs/ru/controllers.md @@ -20,12 +20,18 @@ 5. Переведите достаточно TON на адрес кошелька валидатора. -6. Задайте адрес ликвидного пула, который будет одалживать TON для валидации: +6. Включите ton-http-api службу: + ``` + mytonctrl -> installer -> enable THA + ``` + Выйдите из режима установщика сочетанием клавиш `Ctrl+C` + +7. Задайте адрес ликвидного пула, который будет одалживать TON для валидации: ``` set liquid_pool_addr ``` -7. Задайте параметры кредитования, которые вам подходят: +8. Задайте параметры кредитования, которые вам подходят: ``` set min_loan 41000 set max_loan 43000 @@ -37,13 +43,18 @@ * `43000` - это максимальная сумма кредита который мы готовы получить у ликвидного пула, * `1.5` - это максимальная процентная ставка ликвидного пула за один цикл валидации на которую мы согласны. -8. Создайте два контроллера одной командой: +9. Отобразите годовой процент прибыли от ликвидного пула: + ``` + calculate_annual_controller_percentage + ``` + +10. Создайте два контроллера одной командой: ``` new_controllers ``` -9. Введите `controllers_list` чтобы отобразить адреса контроллеров: +11. Введите `controllers_list` чтобы отобразить адреса контроллеров: ``` controllers_list @@ -52,7 +63,7 @@ kf_lT8QNykLh5PN5ictNX22maiyIf9iK787fXg6nJ_zB-jbN active 0.720866 ``` -10. Совершите депозит валидатора в каждый контроллер: +12. Совершите депозит валидатора в каждый контроллер: ``` deposit_to_controller kf89KYOeRPRRDyjt_3bPsz92cKSghRqw64efNr8mT1eeHDaS 10000 @@ -61,9 +72,9 @@ где `10000` TON - это сумма депозита. -11. Получите аппрувал контроллеров. У каждого пула может быть своя политика выдачи аппруволов, уточняйте у оператора. +13. Получите аппрувал контроллеров. У каждого пула может быть своя политика выдачи аппруволов, уточняйте у оператора. -12. Активируйте режим работы контроллеров: +14. Активируйте режим работы контроллеров: ```bash set useController true @@ -79,4 +90,4 @@ 2. Дождитесь, когда оба ваших депозита вернутся от электора. -3. Следуйте инструкциям "Запуск валидатора в режиме работы контроллеров", начиная с **6-го шага**. \ No newline at end of file +3. Следуйте инструкциям "Запуск валидатора в режиме работы контроллеров", начиная с **6-го шага**. diff --git a/mytoncore.py b/mytoncore.py index e73b2a7f..cf533361 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -3777,7 +3777,7 @@ def CalculateLoanAmount(self, min_loan, max_loan, max_interest): ["num", max_interest], ] - url = "https://testnet.toncenter.com/api/v2/runGetMethod" + url = "http://127.0.0.1:8801/runGetMethod" res = requests.post(url, json=data) result = res.json().get("result").get("stack").pop().pop() return result diff --git a/mytoninstaller.py b/mytoninstaller.py index e8bd9e58..e0101a55 100644 --- a/mytoninstaller.py +++ b/mytoninstaller.py @@ -31,7 +31,7 @@ def Init(): console.name = "MyTonInstaller" console.color = console.RED console.AddItem("status", Status, "Print TON component status") - console.AddItem("enable", Enable, "Enable some function: 'FN' - Full node, 'VC' - Validator console, 'LS' - Liteserver, 'DS' - DHT-Server, 'JR' - jsonrpc, 'PT' - pyTONv3. Example: 'enable FN'") + console.AddItem("enable", Enable, "Enable some function: 'FN' - Full node, 'VC' - Validator console, 'LS' - Liteserver, 'DS' - DHT-Server, 'JR' - jsonrpc, 'THA' - ton-http-api. Example: 'enable FN'") console.AddItem("update", Enable, "Update some function: 'JR' - jsonrpc. Example: 'update JR'") console.AddItem("plsc", PrintLiteServerConfig, "Print LiteServer config") console.AddItem("clcf", CreateLocalConfigFile, "CreateLocalConfigFile") @@ -97,7 +97,7 @@ def Status(args): def Enable(args): name = args[0] user = local.buffer["user"] - if name == "PT": + if name == "enableTHA": CreateLocalConfigFile(args) args = ["python3", local.buffer["myPath"], "-u", user, "-e", "enable{name}".format(name=name)] RunAsRoot(args) @@ -195,8 +195,8 @@ def Event(name): DangerousRecoveryValidatorConfigFile() if name == "enableJR": EnableJsonRpc() - if name == "enablePT": - EnablePytonv3() + if name == "enableTHA": + EnableTonHttpApi() if name == "clc": ix = sys.argv.index("-i") initBlock_b64 = sys.argv[ix+1] @@ -1000,14 +1000,15 @@ def EnableJsonRpc(): ColorPrint(text) #end define -def EnablePytonv3(): - local.AddLog("start EnablePytonv3 function", "debug") +def EnableTonHttpApi(): + local.AddLog("start EnableTonHttpApi function", "debug") user = local.buffer["user"] - exitCode = RunAsRoot(["bash", "/usr/src/mytonctrl/scripts/pytonv3installer.sh", "-u", user]) + runArgs = ["bash", "/usr/src/mytonctrl/scripts/ton_http_api_installer.sh", "-u", user] + exitCode = RunAsRoot(runArgs) if exitCode == 0: - text = "EnablePytonv3 - {green}OK{endc}" + text = "EnableTonHttpApi - {green}OK{endc}" else: - text = "EnablePytonv3 - {red}Error{endc}" + text = "EnableTonHttpApi - {red}Error{endc}" ColorPrint(text) #end define diff --git a/scripts/ton_http_api_installer.sh b/scripts/ton_http_api_installer.sh new file mode 100644 index 00000000..d76c13cc --- /dev/null +++ b/scripts/ton_http_api_installer.sh @@ -0,0 +1,40 @@ +#!/bin/bash +set -e + +# Проверить sudo +if [ "$(id -u)" != "0" ]; then + echo "Please run script as root" + exit 1 +fi + +# Цвета +COLOR='\033[92m' +ENDC='\033[0m' + +# Установка компонентов python3 +pip3 install virtualenv + +# Подготовить папку с виртуальным окружением +echo -e "${COLOR}[1/4]${ENDC} Preparing the virtual environment" +venv_path="/opt/virtualenv/ton_http_api" +virtualenv ${venv_path} + +# Установка компонентов python3 +echo -e "${COLOR}[2/4]${ENDC} Installing required packages" +user=$(logname) +venv_pip3="${venv_path}/bin/pip3" +${venv_pip3} install ton-http-api +chown -R ${user}:${user} ${venv_path} + +# Прописать автозагрузку +echo -e "${COLOR}[3/4]${ENDC} Add to startup" +venv_ton_http_api="${venv_path}/bin/ton-http-api" +tonlib_path="/usr/bin/ton/tonlib/libtonlibjson.so" +ls_config="/usr/bin/ton/local.config.json" +cmd="from sys import path; path.append('/usr/src/mytonctrl/'); from mypylib.mypylib import Add2Systemd; Add2Systemd(name='ton_http_api', user='${user}', start='${venv_ton_http_api} --host 127.0.0.1 --port 8801 --liteserver-config ${ls_config} --cdll-path ${tonlib_path}')" +python3 -c "${cmd}" +systemctl restart ton_http_api + +# Конец +echo -e "${COLOR}[4/4]${ENDC} ton_http_api service installation complete" +exit 0 From 518da3515a7a061bb0e07df3e355e7c33e828788 Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Wed, 5 Jul 2023 22:41:50 +0300 Subject: [PATCH 12/43] update `controllers.md` --- docs/en/controllers.md | 2 +- docs/ru/controllers.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/en/controllers.md b/docs/en/controllers.md index cfcb7853..46b12c8a 100644 --- a/docs/en/controllers.md +++ b/docs/en/controllers.md @@ -23,7 +23,7 @@ ``` mytonctrl -> installer -> enable THA ``` - Exit installer mode with `Ctrl+C` + Exit installer mode with `Ctrl+D` 7. Set the liquid pool address, which will lend TON for validation: ``` diff --git a/docs/ru/controllers.md b/docs/ru/controllers.md index 184bcc95..d3944549 100644 --- a/docs/ru/controllers.md +++ b/docs/ru/controllers.md @@ -24,7 +24,7 @@ ``` mytonctrl -> installer -> enable THA ``` - Выйдите из режима установщика сочетанием клавиш `Ctrl+C` + Выйдите из режима установщика сочетанием клавиш `Ctrl+D` 7. Задайте адрес ликвидного пула, который будет одалживать TON для валидации: ``` From 8abb5fbaa7165a6ac0919322e29cc094a51883ac Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Sun, 9 Jul 2023 22:31:50 +0300 Subject: [PATCH 13/43] bugfix --- mytoncore.py | 2 +- mytoninstaller.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mytoncore.py b/mytoncore.py index cf533361..8152bb10 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -3835,7 +3835,7 @@ def SignElectionRequestWithController(self, controllerAddr, startWorkTime, adnlA def ControllersUpdateValidatorSet(self): local.AddLog("start ControllersUpdateValidatorSet function", "debug") - controllers = self.GetControllers() + controllers = local.db.get("controllersAddr") for controller in controllers: self.ControllerUpdateValidatorSet(controller) #end define diff --git a/mytoninstaller.py b/mytoninstaller.py index e0101a55..4b0ff5fc 100644 --- a/mytoninstaller.py +++ b/mytoninstaller.py @@ -97,7 +97,7 @@ def Status(args): def Enable(args): name = args[0] user = local.buffer["user"] - if name == "enableTHA": + if name == "THA": CreateLocalConfigFile(args) args = ["python3", local.buffer["myPath"], "-u", user, "-e", "enable{name}".format(name=name)] RunAsRoot(args) From 906cdf78e55d61be57ee854c1292cb60c6c54c6f Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Sun, 9 Jul 2023 22:43:20 +0300 Subject: [PATCH 14/43] withdraw_from_controller bugfix --- mytonctrl.py | 1 - 1 file changed, 1 deletion(-) diff --git a/mytonctrl.py b/mytonctrl.py index 4304974c..70ac139d 100755 --- a/mytonctrl.py +++ b/mytonctrl.py @@ -1209,7 +1209,6 @@ def WithdrawFromController(args): except: ColorPrint("{red}Bad args. Usage:{endc} withdraw_from_controller ") return - ton.CheckController(controllerAddr) account = ton.GetAccount(controllerAddr) amount = account.balance-10.1 ton.WithdrawFromController(controllerAddr, amount) From a8abde06e47a305264676a24240ea8e921d8cf4c Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Sun, 9 Jul 2023 23:42:24 +0300 Subject: [PATCH 15/43] add error display when requested to ton-http-api --- mytoncore.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mytoncore.py b/mytoncore.py index 8152bb10..1ee42392 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -3648,6 +3648,7 @@ def CreateControllers(self): resultFilePath1 = self.SignBocWithWallet(wallet, fileName1, liquid_pool_addr, 1) self.SendFile(resultFilePath1, wallet) local.db["controllersAddr"] = self.GetControllers() + local.dbSave() #end define def GetControllerAddress(self, controller_id): @@ -3779,7 +3780,11 @@ def CalculateLoanAmount(self, min_loan, max_loan, max_interest): url = "http://127.0.0.1:8801/runGetMethod" res = requests.post(url, json=data) - result = res.json().get("result").get("stack").pop().pop() + res_data = res.json() + if res_data.get("ok") is False: + error = res_data.get("error") + raise Exception(error) + result = res_data.get("result").get("stack").pop().pop() return result #end define From aa91b52f0156c710067595f5e28fe837085c32ba Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Mon, 10 Jul 2023 12:49:28 +0300 Subject: [PATCH 16/43] ton_http_api installet bugfix --- mytoninstaller.py | 22 ++++++++++++++++------ scripts/ton_http_api_installer.sh | 4 ++-- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/mytoninstaller.py b/mytoninstaller.py index 4b0ff5fc..a97477d3 100644 --- a/mytoninstaller.py +++ b/mytoninstaller.py @@ -98,7 +98,7 @@ def Enable(args): name = args[0] user = local.buffer["user"] if name == "THA": - CreateLocalConfigFile(args) + CreateLocalConfigFile(args, localhost=True) args = ["python3", local.buffer["myPath"], "-u", user, "-e", "enable{name}".format(name=name)] RunAsRoot(args) #end define @@ -138,7 +138,7 @@ def GetInitBlock(): return initBlock #end define -def CreateLocalConfig(initBlock, localConfigPath=defaultLocalConfigPath): +def CreateLocalConfig(initBlock, localConfigPath=defaultLocalConfigPath, localhost=False): # dirty hack, but GetInitBlock() function uses the same technique from mytoncore import hex2base64 @@ -150,6 +150,9 @@ def CreateLocalConfig(initBlock, localConfigPath=defaultLocalConfigPath): # edit config liteServerConfig = GetLiteServerConfig() + if localhost is True: + liteServerConfig["ip"] = 2130706433 # 127.0.0.1 + localConfigPath = localConfigPath.replace("local", "localhost") data["liteservers"] = [liteServerConfig] data["validator"]["init_block"]["seqno"] = initBlock["seqno"] data["validator"]["init_block"]["root_hash"] = hex2base64(initBlock["rootHash"]) @@ -174,11 +177,15 @@ def PrintLiteServerConfig(args): print(text) #end define -def CreateLocalConfigFile(args): +def CreateLocalConfigFile(args, localhost=False): + if localhost is True: + event_name = "clcl" + else: + event_name = "clc" initBlock = GetInitBlock() initBlock_b64 = dict2b64(initBlock) user = local.buffer["user"] - args = ["python3", local.buffer["myPath"], "-u", user, "-e", "clc", "-i", initBlock_b64] + args = ["python3", local.buffer["myPath"], "-u", user, "-e", event_name, "-i", initBlock_b64] RunAsRoot(args) #end define @@ -197,11 +204,14 @@ def Event(name): EnableJsonRpc() if name == "enableTHA": EnableTonHttpApi() - if name == "clc": + if name in ["clc", "clcl"]: ix = sys.argv.index("-i") initBlock_b64 = sys.argv[ix+1] initBlock = b642dict(initBlock_b64) - CreateLocalConfig(initBlock) + if name == "clcl": + CreateLocalConfig(initBlock, localhost=True) + else: + CreateLocalConfig(initBlock) #end define def General(): diff --git a/scripts/ton_http_api_installer.sh b/scripts/ton_http_api_installer.sh index d76c13cc..b27ef02a 100644 --- a/scripts/ton_http_api_installer.sh +++ b/scripts/ton_http_api_installer.sh @@ -30,8 +30,8 @@ chown -R ${user}:${user} ${venv_path} echo -e "${COLOR}[3/4]${ENDC} Add to startup" venv_ton_http_api="${venv_path}/bin/ton-http-api" tonlib_path="/usr/bin/ton/tonlib/libtonlibjson.so" -ls_config="/usr/bin/ton/local.config.json" -cmd="from sys import path; path.append('/usr/src/mytonctrl/'); from mypylib.mypylib import Add2Systemd; Add2Systemd(name='ton_http_api', user='${user}', start='${venv_ton_http_api} --host 127.0.0.1 --port 8801 --liteserver-config ${ls_config} --cdll-path ${tonlib_path}')" +ls_config="/usr/bin/ton/localhost.config.json" +cmd="from sys import path; path.append('/usr/src/mytonctrl/'); from mypylib.mypylib import Add2Systemd; Add2Systemd(name='ton_http_api', user='${user}', start='${venv_ton_http_api} --host 127.0.0.1 --port 8801 --liteserver-config ${ls_config} --cdll-path ${tonlib_path} --tonlib-keystore /tmp/tonlib_keystore/')" python3 -c "${cmd}" systemctl restart ton_http_api From 446a6a68904ca4930121c5c77712dd2517cd5f81 Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Wed, 12 Jul 2023 15:07:59 +0300 Subject: [PATCH 17/43] add SignElectionRequestWithController log --- mytoncore.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mytoncore.py b/mytoncore.py index 1ee42392..108520ae 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -3830,9 +3830,9 @@ def SignElectionRequestWithController(self, controllerAddr, startWorkTime, adnlA fileName = self.tempDir + str(startWorkTime) + "_validator-query.boc" fiftScript = self.contractsDir + "jetton_pool/fift-scripts/controller-elect-signed.fif" args = [fiftScript, controllerAddr, startWorkTime, maxFactor, adnlAddr, validatorPubkey_b64, validatorSignature, fileName, stake] - print(f"args: {args}") + local.AddLog(f"SignElectionRequestWithController args: {args}", "debug") result = self.fift.Run(args) - print(f"result: {result}") + local.AddLog(f"SignElectionRequestWithController result: {result}", "debug") pubkey = Pars(result, "validator public key ", '\n') fileName = Pars(result, "Saved to file ", '\n') return pubkey, fileName From 318b6371cd7724cc8b36fd25fb33bb1c15ddb29e Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Wed, 12 Jul 2023 15:44:57 +0300 Subject: [PATCH 18/43] update controller balance and stake difference --- mytoncore.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mytoncore.py b/mytoncore.py index 108520ae..31122d5f 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -1501,7 +1501,7 @@ def GetStake(self, account, args=None): if stake is None and usePool: stake = account.balance - 20 if stake is None and useController: - stake = account.balance - 30 + stake = account.balance - 50 if stake is None: sp = stakePercent / 100 if sp > 1 or sp < 0: From c484dca269f6233988c9cfcd686cb1414cfe3d7f Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Sat, 15 Jul 2023 15:33:15 +0300 Subject: [PATCH 19/43] add `add_controller` and `stop_controller` commands --- mytoncore.py | 79 +++++++++++++++++++++++++++++++++++++++++++++------- mytonctrl.py | 72 +++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 133 insertions(+), 18 deletions(-) diff --git a/mytoncore.py b/mytoncore.py index 31122d5f..7a89a00c 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -3706,15 +3706,14 @@ def GetControllerRequiredBalanceForLoan(self, controllerAddr, credit, interest): return result #end define - def GetControllerLastSentStakeTime(self, addrB64): - controllerData = self.GetControllerData(addrB64) - return controllerData["stake_at"] - #end define - def IsControllerReadyToStake(self, addrB64): + stop_controllers_list = local.db.get("stop_controllers_list") + if stop_controllers_list is not None and addrB64 in stop_controllers_list: + return False now = GetTimestamp() config15 = self.GetConfig15() - lastSentStakeTime = self.GetControllerLastSentStakeTime(addrB64) + controllerData = self.GetControllerData(addrB64) + lastSentStakeTime = controllerData["stake_at"] stakeFreezeDelay = config15["validatorsElectedFor"] + config15["stakeHeldFor"] result = lastSentStakeTime + stakeFreezeDelay < now print(f"{addrB64}: {result}. {lastSentStakeTime}, {stakeFreezeDelay}, {now}") @@ -3815,7 +3814,15 @@ def DepositToController(self, controllerAddr, amount): #end define def WithdrawFromController(self, controllerAddr, amount): - local.AddLog("start WithdrawFromController function", "debug") + controllerData = self.GetControllerData(controllerAddr) + if controllerData["state"] == 0: + self.WithdrawFromControllerProcess(controllerAddr, amount) + else: + self.PendWithdrawFromController(controllerAddr, amount) + #end define + + def WithdrawFromControllerProcess(self, controllerAddr, amount): + local.AddLog("start WithdrawFromControllerProcess function", "debug") wallet = self.GetValidatorWallet() fiftScript = self.contractsDir + "jetton_pool/fift-scripts/withdraw-controller.fif" resultFilePath = self.tempDir + self.nodeName + wallet.name + "_withdraw_request.boc" @@ -3825,6 +3832,28 @@ def WithdrawFromController(self, controllerAddr, amount): self.SendFile(resultFilePath, wallet) #end define + def PendWithdrawFromController(self, controllerAddr, amount): + local.AddLog("start PendWithdrawFromController function", "debug") + controllerPendingWithdraws = self.GetControllerPendingWithdraws() + controllerPendingWithdraws[controllerAddr] = amount + local.dbSave() + #end define + + def HandleControllerPendingWithdraw(self, controllerPendingWithdraws, controllerAddr): + amount = controllerPendingWithdraws.get(controllerAddr) + self.WithdrawFromControllerProcess(controllerAddr, amount) + controllerPendingWithdraws.pop(controllerAddr) + #end define + + def GetControllerPendingWithdraws(self): + bname = "controllerPendingWithdraws" + controllerPendingWithdraws = local.db.get(bname) + if controllerPendingWithdraws is None: + controllerPendingWithdraws = dict() + local.db[bname] = controllerPendingWithdraws + return controllerPendingWithdraws + #end define + def SignElectionRequestWithController(self, controllerAddr, startWorkTime, adnlAddr, validatorPubkey_b64, validatorSignature, maxFactor, stake): local.AddLog("start SignElectionRequestWithController function", "debug") fileName = self.tempDir + str(startWorkTime) + "_validator-query.boc" @@ -3841,7 +3870,8 @@ def SignElectionRequestWithController(self, controllerAddr, startWorkTime, adnlA def ControllersUpdateValidatorSet(self): local.AddLog("start ControllersUpdateValidatorSet function", "debug") controllers = local.db.get("controllersAddr") - for controller in controllers: + user_controllers_list = local.db.get("user_controllers_list", list()) + for controller in controllers + user_controllers_list: self.ControllerUpdateValidatorSet(controller) #end define @@ -3857,8 +3887,7 @@ def ControllerUpdateValidatorSet(self, controllerAddr): config34 = self.GetConfig34() fullElectorAddr = self.GetFullElectorAddr() returnedStake = self.GetReturnedStake(fullElectorAddr, controllerAddr) - print(f"Controller returnedStake: {returnedStake}") - pendingWithdraws = self.GetPendingWithdraws() + controllerPendingWithdraws = self.GetControllerPendingWithdraws() if (controllerData["state"] == 3 and controllerData["validator_set_changes_count"] < 2 and controllerData["validator_set_change_time"] < config34["startWorkTime"]): @@ -3874,6 +3903,8 @@ def ControllerUpdateValidatorSet(self, controllerAddr): controllerData["stake_amount_sent"] == 0 and config34["startWorkTime"] > controllerData["borrowing_time"]): self.ReturnUnusedLoan(controllerAddr) + if (controllerData["state"] == 0 and controllerAddr in controllerPendingWithdraws): + self.HandleControllerPendingWithdraw(controllerPendingWithdraws, controllerAddr) #end define def ControllerUpdateValidatorSetProcess(self, controllerAddr, wallet): @@ -3892,6 +3923,34 @@ def ControllerRecoverStake(self, controllerAddr): self.SendFile(resultFilePath, wallet) local.AddLog("ControllerRecoverStake completed") #end define + + def StopController(self, controllerAddr): + stop_controllers_list = local.db.get("stop_controllers_list") + if stop_controllers_list is None: + stop_controllers_list = list() + if controllerAddr not in stop_controllers_list: + stop_controllers_list.append(controllerAddr) + local.db["stop_controllers_list"] = stop_controllers_list + + user_controllers_list = local.db.get("user_controllers_list") + if user_controllers_list is not None and controllerAddr in user_controllers_list: + user_controllers_list.remove(controllerAddr) + local.dbSave() + #end define + + def AddController(self, controllerAddr): + user_controllers_list = local.db.get("user_controllers_list") + if user_controllers_list is None: + user_controllers_list = list() + if controllerAddr not in user_controllers_list: + user_controllers_list.append(controllerAddr) + local.db["user_controllers_list"] = user_controllers_list + + stop_controllers_list = local.db.get("stop_controllers_list") + if stop_controllers_list is not None and controllerAddr in stop_controllers_list: + stop_controllers_list.remove(controllerAddr) + local.dbSave() + #end define def GetNetworkName(self): mainnetValidatorsElectedFor = 65536 diff --git a/mytonctrl.py b/mytonctrl.py index 70ac139d..4cf9bec5 100755 --- a/mytonctrl.py +++ b/mytonctrl.py @@ -77,6 +77,9 @@ def Init(argv): console.AddItem("withdraw_from_controller", WithdrawFromController, local.Translate("_")) console.AddItem("calculate_annual_controller_percentage", CalculateAnnualControllerPercentage, local.Translate("_")) console.AddItem("controller_update_validator_set", ControllerUpdateValidatorSet, local.Translate("_")) + console.AddItem("stop_controller", StopController, local.Translate("_")) + console.AddItem("stop_and_withdraw_controller", StopAndWithdrawController, local.Translate("_")) + console.AddItem("add_controller", AddController, local.Translate("_")) # Process input parameters @@ -1171,15 +1174,31 @@ def NewControllers(args): #end define def PrintControllersList(args): - table = list() - table += [["Address", "Status", "Balance"]] controllers = ton.GetControllers() + controllersAddr = ton.GetSettings("controllersAddr") + user_controllers_list = ton.GetSettings("user_controllers_list") if (controllers is None or len(controllers) == 0): print("No data") return + PrintControllersListProcess(controllers) + if controllers != controllersAddr: + print() + print("old controllers:") + PrintControllersListProcess(controllersAddr) + if user_controllers_list is not None and len(user_controllers_list) > 0: + print() + print("user controllers:") + PrintControllersListProcess(user_controllers_list) +#end define + +def PrintControllersListProcess(controllers): + table = list() + table += [["Address", "Status", "Balance", "Approved", "State"]] for controllerAddr in controllers: account = ton.GetAccount(controllerAddr) - table += [[controllerAddr, account.status, account.balance]] + controllerData = ton.GetControllerData(controllerAddr) + approved = True if controllerData["approved"] == -1 else False + table += [[controllerAddr, account.status, account.balance, approved, controllerData["state"]]] PrintTable(table) #end define @@ -1189,8 +1208,8 @@ def GetControllerData(args): except: ColorPrint("{red}Bad args. Usage:{endc} get_controller_data ") return - data = ton.GetControllerData(controllerAddr) - print(f"ControllerData: {data}") + controllerData = ton.GetControllerData(controllerAddr) + print(json.dumps(controllerData, indent=4)) #end define def DepositToController(args): @@ -1206,11 +1225,13 @@ def DepositToController(args): def WithdrawFromController(args): try: controllerAddr = args[0] + amount = GetItemFromList(args, 1) except: - ColorPrint("{red}Bad args. Usage:{endc} withdraw_from_controller ") + ColorPrint("{red}Bad args. Usage:{endc} withdraw_from_controller [amount]") return - account = ton.GetAccount(controllerAddr) - amount = account.balance-10.1 + if amount is None: + account = ton.GetAccount(controllerAddr) + amount = account.balance-10.1 ton.WithdrawFromController(controllerAddr, amount) #end define @@ -1241,6 +1262,41 @@ def ControllerUpdateValidatorSet(args): ColorPrint("ControllerUpdateValidatorSet - {green}OK{endc}") #end define +def StopController(args): + try: + controllerAddr = args[0] + except: + ColorPrint("{red}Bad args. Usage:{endc} stop_controller ") + return + ton.StopController(controllerAddr) + ColorPrint("StopController - {green}OK{endc}") +#end define + +def StopAndWithdrawController(args): + try: + controllerAddr = args[0] + amount = GetItemFromList(args, 1) + except: + ColorPrint("{red}Bad args. Usage:{endc} stop_and_withdraw_controller [amount]") + return + if amount is None: + account = ton.GetAccount(controllerAddr) + amount = account.balance-10.1 + ton.StopController(controllerAddr) + ton.WithdrawFromController(controllerAddr, amount) + ColorPrint("StopAndWithdrawController - {green}OK{endc}") +#end define + +def AddController(args): + try: + controllerAddr = args[0] + except: + ColorPrint("{red}Bad args. Usage:{endc} add_controller ") + return + ton.AddController(controllerAddr) + ColorPrint("AddController - {green}OK{endc}") +#end define + ### ### Start of the program From a8cd483508ca48fadbf72bac285d617304537012 Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Sat, 15 Jul 2023 21:42:17 +0300 Subject: [PATCH 20/43] add `check_liquid_pool` command --- mytoncore.py | 42 ++++++++++++++++++++++++++++++++++++++++-- mytonctrl.py | 9 ++++++++- 2 files changed, 48 insertions(+), 3 deletions(-) diff --git a/mytoncore.py b/mytoncore.py index 7a89a00c..b3ed3d38 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -760,8 +760,16 @@ def GetWalletVersionFromHash(self, inputHash): arr["v3r2"] = "8a6d73bdd8704894f17d8c76ce6139034b8a51b1802907ca36283417798a219b" arr["v4"] = "7ae380664c513769eaa5c94f9cd5767356e3f7676163baab66a4b73d5edab0e5" arr["hv1"] = "fc8e48ed7f9654ba76757f52cc6031b2214c02fab9e429ffa0340f5575f9f29c" - for version, hash in arr.items(): - if hash == inputHash: + arr["liquid_pool_r1"] = "82bc5760719c34395f80df76c42dc5d287f08f6562c643601ebed6944302dcc2" + arr["liquid_pool_r2"] = "95abec0a66ac63b0fbcf28466eb8240ddcd88f97300691511d9c9975d5521e4a" + arr["liquid_pool_r3"] = "22a023bc75b649ff2b5b183cd0d34cd413e6e27ee6d6ad0787f75ad39787ed4e" + arr["liquid_pool_r4"] = "77282b45fd7cfc72ca68fe97af33ad10078730ceaf55e20534c9526c48d602d2" + arr["controller_r1"] = "0949cf92963dd27bb1e6bf76487807f20409131b6110acbc18b7fbb90280ccf0" + arr["controller_r2"] = "01118b9553151fb9bc81704a4b3e0fc7b899871a527d44435a51574806863e2c" + arr["controller_r3"] = "e4d8ce8ff7b4b60c76b135eb8702ce3c86dc133fcee7d19c7aa18f71d9d91438" + arr["controller_r4"] = "dec125a4850c4ba24668d84252b04c6ad40abf5c9d413a429b56bfff09ea25d4" + for version, codeHash in arr.items(): + if codeHash == inputHash: return version #end for #end define @@ -3089,6 +3097,8 @@ def GetDestinationAddr(self, destination): #end define def AddrFull2AddrB64(self, addrFull, bounceable=True): + if addrFull is None or "None" in addrFull: + return testnet = self.IsTestnet() buff = addrFull.split(':') workchain = int(buff[0]) @@ -3951,6 +3961,34 @@ def AddController(self, controllerAddr): stop_controllers_list.remove(controllerAddr) local.dbSave() #end define + + def CheckLiquidPool(self): + liquid_pool_addr = self.GetLiquidPoolAddr() + account = self.GetAccount(liquid_pool_addr) + history = self.GetAccountHistory(account, 5000) + addrs_list = list() + for message in history: + if message.srcAddr is None or message.value is None: + continue + srcAddrFull = f"{message.srcWorkchain}:{message.srcAddr}" + destAddFull = f"{message.destWorkchain}:{message.destAddr}" + if srcAddrFull == account.addrFull: + fromto = destAddFull + else: + fromto = srcAddrFull + fromto = self.AddrFull2AddrB64(fromto) + if fromto not in addrs_list: + addrs_list.append(fromto) + #end for + + for controllerAddr in addrs_list: + account = self.GetAccount(controllerAddr) + version = self.GetWalletVersionFromHash(account.codeHash) + if version is None or "controller" not in version: + continue + print(f"check controller: {controllerAddr}") + self.ControllerUpdateValidatorSet(controllerAddr) + #end define def GetNetworkName(self): mainnetValidatorsElectedFor = 65536 diff --git a/mytonctrl.py b/mytonctrl.py index 4cf9bec5..a3e7e7bc 100755 --- a/mytonctrl.py +++ b/mytonctrl.py @@ -80,6 +80,7 @@ def Init(argv): console.AddItem("stop_controller", StopController, local.Translate("_")) console.AddItem("stop_and_withdraw_controller", StopAndWithdrawController, local.Translate("_")) console.AddItem("add_controller", AddController, local.Translate("_")) + console.AddItem("check_liquid_pool", CheckLiquidPool, local.Translate("_")) # Process input parameters @@ -679,6 +680,7 @@ def ViewAccountStatus(args): statusTable += [[addrB64, account.status, version, account.balance]] historyTable = GetHistoryTable(addrB64, 10) PrintTable(statusTable) + ColorPrint("{yellow}codeHash: " + account.codeHash + "{endc}") print() PrintTable(historyTable) #end define @@ -702,7 +704,7 @@ def GetHistoryTable(addr, limit): typeText = ColorText("{red}{bold}{endc}") table += [["Time", typeText, "Coins", "From/To"]] for message in history: - if message.srcAddr is None: + if message.srcAddr is None or message.value is None: continue srcAddrFull = f"{message.srcWorkchain}:{message.srcAddr}" destAddFull = f"{message.destWorkchain}:{message.destAddr}" @@ -1297,6 +1299,11 @@ def AddController(args): ColorPrint("AddController - {green}OK{endc}") #end define +def CheckLiquidPool(args): + ton.CheckLiquidPool() + ColorPrint("CheckLiquidPool - {green}OK{endc}") +#end define + ### ### Start of the program From 987b09e00493a7882153f9ff14224e91fb543b3c Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Tue, 18 Jul 2023 12:08:05 +0300 Subject: [PATCH 21/43] Add seamless transition to new controllers This method is not completely seamless, as it only automatically returns the stake to the validator's account. The validator will still need to create new controllers, add a stake to them, and wait for approval from the liquid pool. --- mytoncore.py | 19 +++++++++++++++++-- mytonctrl.py | 3 --- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/mytoncore.py b/mytoncore.py index b3ed3d38..2a825fd2 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -3657,6 +3657,15 @@ def CreateControllers(self): time.sleep(10) resultFilePath1 = self.SignBocWithWallet(wallet, fileName1, liquid_pool_addr, 1) self.SendFile(resultFilePath1, wallet) + + # Доработать старые контроллеры + old_controllers = local.db.get("controllersAddr". list()) + local.db["old_controllers"] = old_controllers.copy() + for controllerAddr in old_controllers + self.WithdrawFromController(controllerAddr) + #end for + + # Сохранить новые контроллеры local.db["controllersAddr"] = self.GetControllers() local.dbSave() #end define @@ -3823,7 +3832,7 @@ def DepositToController(self, controllerAddr, amount): self.SendFile(resultFilePath, wallet) #end define - def WithdrawFromController(self, controllerAddr, amount): + def WithdrawFromController(self, controllerAddr, amount=None): controllerData = self.GetControllerData(controllerAddr) if controllerData["state"] == 0: self.WithdrawFromControllerProcess(controllerAddr, amount) @@ -3833,6 +3842,11 @@ def WithdrawFromController(self, controllerAddr, amount): def WithdrawFromControllerProcess(self, controllerAddr, amount): local.AddLog("start WithdrawFromControllerProcess function", "debug") + if amount is None: + account = self.GetAccount(controllerAddr) + amount = account.balance-10.1 + #end if + wallet = self.GetValidatorWallet() fiftScript = self.contractsDir + "jetton_pool/fift-scripts/withdraw-controller.fif" resultFilePath = self.tempDir + self.nodeName + wallet.name + "_withdraw_request.boc" @@ -3881,7 +3895,8 @@ def ControllersUpdateValidatorSet(self): local.AddLog("start ControllersUpdateValidatorSet function", "debug") controllers = local.db.get("controllersAddr") user_controllers_list = local.db.get("user_controllers_list", list()) - for controller in controllers + user_controllers_list: + old_controllers = local.db.get("old_controllers", list()) + for controller in controllers + user_controllers_list + old_controllers: self.ControllerUpdateValidatorSet(controller) #end define diff --git a/mytonctrl.py b/mytonctrl.py index a3e7e7bc..9ee62a1d 100755 --- a/mytonctrl.py +++ b/mytonctrl.py @@ -1231,9 +1231,6 @@ def WithdrawFromController(args): except: ColorPrint("{red}Bad args. Usage:{endc} withdraw_from_controller [amount]") return - if amount is None: - account = ton.GetAccount(controllerAddr) - amount = account.balance-10.1 ton.WithdrawFromController(controllerAddr, amount) #end define From da61de8088b0018b033d5852fa0f4bb3c96def11 Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Tue, 18 Jul 2023 16:51:01 +0300 Subject: [PATCH 22/43] Update mytoncore.py --- mytoncore.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mytoncore.py b/mytoncore.py index 2a825fd2..84e31ab1 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -3661,7 +3661,7 @@ def CreateControllers(self): # Доработать старые контроллеры old_controllers = local.db.get("controllersAddr". list()) local.db["old_controllers"] = old_controllers.copy() - for controllerAddr in old_controllers + for controllerAddr in old_controllers: self.WithdrawFromController(controllerAddr) #end for From 3dfd068b9ffbc3be67718d236e262c501cbc9aa2 Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Tue, 18 Jul 2023 20:55:04 +0300 Subject: [PATCH 23/43] controllerData bugfix --- mytoncore.py | 4 ++++ mytonctrl.py | 5 +++-- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/mytoncore.py b/mytoncore.py index 84e31ab1..4080ffc5 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -3688,6 +3688,8 @@ def CheckController(self, controllerAddr): local.AddLog("start CheckController function", "debug") controllerData = self.GetControllerData(controllerAddr) saveControllersAddr = local.db.get("controllersAddr", list()) + if controllerData is None: + raise Exception(f"CheckController error: controller not initialized. Use new_controllers") if controllerData["approved"] != -1: raise Exception(f"CheckController error: controller not approved: {controllerAddr}") if controllerAddr not in saveControllersAddr: @@ -3732,6 +3734,8 @@ def IsControllerReadyToStake(self, addrB64): now = GetTimestamp() config15 = self.GetConfig15() controllerData = self.GetControllerData(addrB64) + if controllerData is None: + return lastSentStakeTime = controllerData["stake_at"] stakeFreezeDelay = config15["validatorsElectedFor"] + config15["stakeHeldFor"] result = lastSentStakeTime + stakeFreezeDelay < now diff --git a/mytonctrl.py b/mytonctrl.py index 9ee62a1d..c1123730 100755 --- a/mytonctrl.py +++ b/mytonctrl.py @@ -1199,8 +1199,9 @@ def PrintControllersListProcess(controllers): for controllerAddr in controllers: account = ton.GetAccount(controllerAddr) controllerData = ton.GetControllerData(controllerAddr) - approved = True if controllerData["approved"] == -1 else False - table += [[controllerAddr, account.status, account.balance, approved, controllerData["state"]]] + approved = True if controllerData and controllerData["approved"] == -1 else False + state = controllerData["state"] if controllerData else None + table += [[controllerAddr, account.status, account.balance, approved, state]] PrintTable(table) #end define From e421d4824f234a130d8fc28be0833bb662e8a52e Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Wed, 19 Jul 2023 14:28:29 +0300 Subject: [PATCH 24/43] add error text for controller --- mytoncore.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mytoncore.py b/mytoncore.py index 4080ffc5..96d90642 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -3735,7 +3735,7 @@ def IsControllerReadyToStake(self, addrB64): config15 = self.GetConfig15() controllerData = self.GetControllerData(addrB64) if controllerData is None: - return + raise Exception(f"IsControllerReadyToStake error: controller not initialized. Use new_controllers") lastSentStakeTime = controllerData["stake_at"] stakeFreezeDelay = config15["validatorsElectedFor"] + config15["stakeHeldFor"] result = lastSentStakeTime + stakeFreezeDelay < now From 47055a1558c9a37ca7dd0d6e740a1c03dc3c9dca Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Wed, 19 Jul 2023 17:00:47 +0300 Subject: [PATCH 25/43] bugfix --- mytoncore.py | 27 ++++++++++++++++----------- mytonctrl.py | 7 ++++--- 2 files changed, 20 insertions(+), 14 deletions(-) diff --git a/mytoncore.py b/mytoncore.py index 96d90642..9e8bdcd7 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -1718,7 +1718,7 @@ def PoolUpdateValidatorSet(self, pool, wallet): poolData = self.GetPoolData(poolAddr) if poolData is None: return - #en if + #end if timeNow = int(time.time()) config34 = self.GetConfig34() @@ -3642,6 +3642,12 @@ def GetLiquidPoolAddr(self): #end define def CreateControllers(self): + new_controllers = self.GetControllers() + old_controllers = local.db.get("controllersAddr", list()) + if new_controllers == old_controllers: + return + #end if + local.AddLog("start CreateControllers function", "debug") wallet = self.GetValidatorWallet() liquid_pool_addr = self.GetLiquidPoolAddr() @@ -3658,15 +3664,9 @@ def CreateControllers(self): resultFilePath1 = self.SignBocWithWallet(wallet, fileName1, liquid_pool_addr, 1) self.SendFile(resultFilePath1, wallet) - # Доработать старые контроллеры - old_controllers = local.db.get("controllersAddr". list()) - local.db["old_controllers"] = old_controllers.copy() - for controllerAddr in old_controllers: - self.WithdrawFromController(controllerAddr) - #end for - # Сохранить новые контроллеры - local.db["controllersAddr"] = self.GetControllers() + local.db["old_controllers"] = old_controllers + local.db["controllersAddr"] = new_controllers local.dbSave() #end define @@ -3845,12 +3845,14 @@ def WithdrawFromController(self, controllerAddr, amount=None): #end define def WithdrawFromControllerProcess(self, controllerAddr, amount): - local.AddLog("start WithdrawFromControllerProcess function", "debug") if amount is None: account = self.GetAccount(controllerAddr) amount = account.balance-10.1 + if amount < 3: + return #end if + local.AddLog("start WithdrawFromControllerProcess function", "debug") wallet = self.GetValidatorWallet() fiftScript = self.contractsDir + "jetton_pool/fift-scripts/withdraw-controller.fif" resultFilePath = self.tempDir + self.nodeName + wallet.name + "_withdraw_request.boc" @@ -3907,10 +3909,11 @@ def ControllersUpdateValidatorSet(self): def ControllerUpdateValidatorSet(self, controllerAddr): local.AddLog("start ControllerUpdateValidatorSet function", "debug") wallet = self.GetValidatorWallet() + controllers = self.GetControllers() controllerData = self.GetControllerData(controllerAddr) if controllerData is None: return - #en if + #end if timeNow = int(time.time()) config34 = self.GetConfig34() @@ -3934,6 +3937,8 @@ def ControllerUpdateValidatorSet(self, controllerAddr): self.ReturnUnusedLoan(controllerAddr) if (controllerData["state"] == 0 and controllerAddr in controllerPendingWithdraws): self.HandleControllerPendingWithdraw(controllerPendingWithdraws, controllerAddr) + if controllerAddr not in controllers: + self.WithdrawFromController(controllerAddr) #end define def ControllerUpdateValidatorSetProcess(self, controllerAddr, wallet): diff --git a/mytonctrl.py b/mytonctrl.py index c1123730..fce1691f 100755 --- a/mytonctrl.py +++ b/mytonctrl.py @@ -70,7 +70,8 @@ def Init(argv): console.AddItem("withdraw_from_pool", WithdrawFromPool, local.Translate("withdraw_from_pool_cmd")) console.AddItem("delete_pool", DeletePool, local.Translate("delete_pool_cmd")) - console.AddItem("new_controllers", NewControllers, local.Translate("_")) + console.AddItem("create_controllers", CreateControllers, local.Translate("_")) + console.AddItem("update_controllers", CreateControllers, local.Translate("_")) console.AddItem("controllers_list", PrintControllersList, local.Translate("_")) console.AddItem("get_controller_data", GetControllerData, local.Translate("_")) console.AddItem("deposit_to_controller", DepositToController, local.Translate("_")) @@ -1170,9 +1171,9 @@ def PoolUpdateValidatorSet(args): ColorPrint("PoolUpdateValidatorSet - {green}OK{endc}") #end define -def NewControllers(args): +def CreateControllers(args): ton.CreateControllers() - ColorPrint("NewControllers - {green}OK{endc}") + ColorPrint("CreateControllers - {green}OK{endc}") #end define def PrintControllersList(args): From 2c5217b940b7c90ab040ac0a761673e14239ba94 Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Wed, 19 Jul 2023 20:47:43 +0300 Subject: [PATCH 26/43] rename controllers vars --- mytoncore.py | 42 ++++++++++++++++++++---------------------- mytonctrl.py | 23 +++++++++++++++-------- 2 files changed, 35 insertions(+), 30 deletions(-) diff --git a/mytoncore.py b/mytoncore.py index 9e8bdcd7..48d67506 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -3643,7 +3643,7 @@ def GetLiquidPoolAddr(self): def CreateControllers(self): new_controllers = self.GetControllers() - old_controllers = local.db.get("controllersAddr", list()) + old_controllers = local.db.get("using_controllers", list()) if new_controllers == old_controllers: return #end if @@ -3666,7 +3666,7 @@ def CreateControllers(self): # Сохранить новые контроллеры local.db["old_controllers"] = old_controllers - local.db["controllersAddr"] = new_controllers + local.db["using_controllers"] = new_controllers local.dbSave() #end define @@ -3687,12 +3687,12 @@ def GetControllerAddress(self, controller_id): def CheckController(self, controllerAddr): local.AddLog("start CheckController function", "debug") controllerData = self.GetControllerData(controllerAddr) - saveControllersAddr = local.db.get("controllersAddr", list()) + using_controllers = local.db.get("using_controllers", list()) if controllerData is None: raise Exception(f"CheckController error: controller not initialized. Use new_controllers") if controllerData["approved"] != -1: raise Exception(f"CheckController error: controller not approved: {controllerAddr}") - if controllerAddr not in saveControllersAddr: + if controllerAddr not in using_controllers: raise Exception("CheckController error: controller is not up to date. Use new_controllers") #end define @@ -3720,11 +3720,9 @@ def GetControllerRequiredBalanceForLoan(self, controllerAddr, credit, interest): data = self.Result2List(result) if data is None: return - result_vars = ["min_amount", "validator_amount"] - result = dict() - for name in result_vars: - result[name] = data.pop(0) - return result + min_amount = data[0] + validator_amount = data[1] + return min_amount, validator_amount #end define def IsControllerReadyToStake(self, addrB64): @@ -3777,7 +3775,7 @@ def CreateLoanRequest(self, controllerAddr): # Проверить хватает ли ставки валидатора min_amount, validator_amount = self.GetControllerRequiredBalanceForLoan(controllerAddr, max_loan, max_interest) if min_amount > validator_amount: - raise Exception("CreateLoanRequest error: too_high_loan_request_amount") + raise Exception("CreateLoanRequest error: Validator stake is too low. Use deposit_to_controller") #end if wallet = self.GetValidatorWallet() @@ -3899,10 +3897,10 @@ def SignElectionRequestWithController(self, controllerAddr, startWorkTime, adnlA def ControllersUpdateValidatorSet(self): local.AddLog("start ControllersUpdateValidatorSet function", "debug") - controllers = local.db.get("controllersAddr") - user_controllers_list = local.db.get("user_controllers_list", list()) + using_controllers = local.db.get("using_controllers") + user_controllers = local.db.get("user_controllers", list()) old_controllers = local.db.get("old_controllers", list()) - for controller in controllers + user_controllers_list + old_controllers: + for controller in using_controllers + user_controllers + old_controllers: self.ControllerUpdateValidatorSet(controller) #end define @@ -3966,19 +3964,19 @@ def StopController(self, controllerAddr): stop_controllers_list.append(controllerAddr) local.db["stop_controllers_list"] = stop_controllers_list - user_controllers_list = local.db.get("user_controllers_list") - if user_controllers_list is not None and controllerAddr in user_controllers_list: - user_controllers_list.remove(controllerAddr) + user_controllers = local.db.get("user_controllers") + if user_controllers is not None and controllerAddr in user_controllers: + user_controllers.remove(controllerAddr) local.dbSave() #end define def AddController(self, controllerAddr): - user_controllers_list = local.db.get("user_controllers_list") - if user_controllers_list is None: - user_controllers_list = list() - if controllerAddr not in user_controllers_list: - user_controllers_list.append(controllerAddr) - local.db["user_controllers_list"] = user_controllers_list + user_controllers = local.db.get("user_controllers") + if user_controllers is None: + user_controllers = list() + if controllerAddr not in user_controllers: + user_controllers.append(controllerAddr) + local.db["user_controllers"] = user_controllers stop_controllers_list = local.db.get("stop_controllers_list") if stop_controllers_list is not None and controllerAddr in stop_controllers_list: diff --git a/mytonctrl.py b/mytonctrl.py index fce1691f..a70db3c6 100755 --- a/mytonctrl.py +++ b/mytonctrl.py @@ -117,6 +117,10 @@ def Init(argv): def PreUp(): CheckMytonctrlUpdate() # CheckTonUpdate() + buff = ton.GetSettings("using_controllers") + if buff is None or len(buff) == 0: + using_controllers = ton.GetSettings("controllersAddr") + ton.SetSettings("using_controllers", using_controllers) #end define def Installer(args): @@ -1177,17 +1181,20 @@ def CreateControllers(args): #end define def PrintControllersList(args): - controllers = ton.GetControllers() - controllersAddr = ton.GetSettings("controllersAddr") + new_controllers = ton.GetControllers() + using_controllers = ton.GetSettings("using_controllers") + old_controllers = ton.GetSettings("old_controllers") user_controllers_list = ton.GetSettings("user_controllers_list") - if (controllers is None or len(controllers) == 0): - print("No data") - return - PrintControllersListProcess(controllers) - if controllers != controllersAddr: + print("using controllers:") + PrintControllersListProcess(using_controllers) + if new_controllers != using_controllers: + print() + print("new controllers:") + PrintControllersListProcess(new_controllers) + if old_controllers is not None and len(old_controllers) > 0: print() print("old controllers:") - PrintControllersListProcess(controllersAddr) + PrintControllersListProcess(old_controllers) if user_controllers_list is not None and len(user_controllers_list) > 0: print() print("user controllers:") From 42976f56f3cfbdf450f0c481a744b6d79215aa5d Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Thu, 27 Jul 2023 13:35:57 +0300 Subject: [PATCH 27/43] fix a defaulted loan --- mytoncore.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/mytoncore.py b/mytoncore.py index 48d67506..f352b8e8 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -3766,6 +3766,13 @@ def CreateLoanRequest(self, controllerAddr): max_loan = local.db.get("max_loan", 43000) max_interest_percent = local.db.get("max_interest_percent", 1.5) max_interest = int(max_interest_percent/100*16777216) + + # Проверить наличие действующего кредита + controllerData = self.GetControllerData(controllerAddr) + if controllerData["borrowed_amount"] > 0: + local.AddLog("CreateLoanRequest warning: past loan found", "warning") + return + #end define # Проверить наличие средств у ликвидного пула if self.CalculateLoanAmount(min_loan, max_loan, max_interest) == '-0x1': @@ -3930,7 +3937,6 @@ def ControllerUpdateValidatorSet(self, controllerAddr): self.ControllerRecoverStake(controllerAddr) controllerData = self.GetControllerData(controllerAddr) if (controllerData["borrowed_amount"] > 0 and - controllerData["stake_amount_sent"] == 0 and config34["startWorkTime"] > controllerData["borrowing_time"]): self.ReturnUnusedLoan(controllerAddr) if (controllerData["state"] == 0 and controllerAddr in controllerPendingWithdraws): From ac484ec0be559e3605c48c2d53e24690c5e91723 Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Wed, 2 Aug 2023 22:07:46 +0300 Subject: [PATCH 28/43] bugfix --- mytoncore.py | 3 ++- mytonctrl.py | 8 ++++---- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/mytoncore.py b/mytoncore.py index f352b8e8..442db6e0 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -3936,7 +3936,8 @@ def ControllerUpdateValidatorSet(self, controllerAddr): timeNow - controllerData["validator_set_change_time"] > controllerData["stake_held_for"] + 60): self.ControllerRecoverStake(controllerAddr) controllerData = self.GetControllerData(controllerAddr) - if (controllerData["borrowed_amount"] > 0 and + if (controllerData["state"] == 0 and + controllerData["borrowed_amount"] > 0 and config34["startWorkTime"] > controllerData["borrowing_time"]): self.ReturnUnusedLoan(controllerAddr) if (controllerData["state"] == 0 and controllerAddr in controllerPendingWithdraws): diff --git a/mytonctrl.py b/mytonctrl.py index a70db3c6..33cb5596 100755 --- a/mytonctrl.py +++ b/mytonctrl.py @@ -117,10 +117,10 @@ def Init(argv): def PreUp(): CheckMytonctrlUpdate() # CheckTonUpdate() - buff = ton.GetSettings("using_controllers") - if buff is None or len(buff) == 0: - using_controllers = ton.GetSettings("controllersAddr") - ton.SetSettings("using_controllers", using_controllers) + usePool = ton.GetSettings("usePool") + useController = ton.GetSettings("useController") + if usePool == True and useController == True: + local.AddLog("usePool == True and useController == True", "error") #end define def Installer(args): From b3be3007cd686f79092b30113c7309cf2f8a2eee Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Mon, 21 Aug 2023 13:21:49 +0300 Subject: [PATCH 29/43] WithdrawFromControllerProcess bugfix --- mytoncore.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mytoncore.py b/mytoncore.py index 442db6e0..a4ff4bb8 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -3853,7 +3853,7 @@ def WithdrawFromControllerProcess(self, controllerAddr, amount): if amount is None: account = self.GetAccount(controllerAddr) amount = account.balance-10.1 - if amount < 3: + if int(amount) < 3: return #end if From a82ffd8c88507dd068874541a265fb0da686373a Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Thu, 14 Sep 2023 19:14:53 +0300 Subject: [PATCH 30/43] update `mypylib` --- README.Ru.md | 20 +- README.md | 105 ++++-- mypyconsole | 2 +- mypylib | 2 +- mytoncore.py | 878 +++++++++++++++++++--------------------------- mytonctrl.py | 636 ++++++++++++++++++--------------- mytoninstaller.py | 595 +++++++++++++++---------------- translate.json | 263 +++++++++----- 8 files changed, 1250 insertions(+), 1251 deletions(-) diff --git a/README.Ru.md b/README.Ru.md index 34ebe4e2..91acd3d9 100644 --- a/README.Ru.md +++ b/README.Ru.md @@ -1,6 +1,6 @@ ## Что это Данная консольная программа является оберткой над `fift`, `lite-client` и `validator-engine-console`. Она была создана для облегчения управления кошельками, доменами и валидатором на операционной системе `Linux`. -![](https://raw.githubusercontent.com/ton-blockchain/mytonctrl/master/screens/mytonctrl-status_ru.png) +![](screens/mytonctrl-status_ru.png) ## Функционал - [x] Показать статус сети TON @@ -42,14 +42,16 @@ - [x] Отправлять статистику валидатора на https://toncenter.com ## Список проверенных операционных систем -``` -Ubuntu 16.04 LTS (Xenial Xerus) - Error: TON compilation error -Ubuntu 18.04 LTS (Bionic Beaver) - OK -Ubuntu 20.04 LTS (Focal Fossa) - OK -Debian 8 - Error: Unable to locate package libgsl-dev -Debian 9 - Error: TON compilation error -Debian 10 - OK -``` +| Operating System | Status | +|-------------------------------|----------------------------| +| Ubuntu 16.04 LTS (Xenial Xerus) | Error: TON compilation error | +| Ubuntu 18.04 LTS (Bionic Beaver) | OK | +| Ubuntu 20.04 LTS (Focal Fossa) | OK | +| Ubuntu 22.04 LTS (Jammy Jellyfish) | OK | +| Debian 8 | Error: Unable to locate package libgsl-dev | +| Debian 9 | Error: TON compilation error | +| Debian 10 | OK | + ## Описание установочных скриптов - `toninstaller.sh` - Данный скрипт клонирует исходники `TON` и `mytonctrl` в папки `/usr/src/ton` и `/usr/src/mytonctrl`, компилирует программы из исходников и прописывает их в `/usr/bin/`. diff --git a/README.md b/README.md index b159e703..a41b61d4 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,34 @@ -[Данный текст доступен на русском языке.](https://github.com/ton-blockchain/mytonctrl/blob/master/README.Ru.md) +![GitHub stars](https://img.shields.io/github/stars/ton-blockchain/mytonctrl?style=flat-square&logo=github) ![GitHub forks](https://img.shields.io/github/forks/ton-blockchain/mytonctrl?style=flat-square&logo=github) ![GitHub issues](https://img.shields.io/github/issues/ton-blockchain/mytonctrl?style=flat-square&logo=github) ![GitHub pull requests](https://img.shields.io/github/issues-pr/ton-blockchain/mytonctrl?style=flat-square&logo=github) ![GitHub last commit](https://img.shields.io/github/last-commit/ton-blockchain/mytonctrl?style=flat-square&logo=github) ![GitHub license](https://img.shields.io/github/license/ton-blockchain/mytonctrl?style=flat-square&logo=github) -## What is it? -This console is a wrapper over `fift`,`lite-client` and `validator-engine-console`. It was created to facilitate wallet, domain and validator management on Linux OS. + +# MyTonCtrl +[Данный текст доступен на русском языке.](README.Ru.md) -![](https://raw.githubusercontent.com/ton-blockchain/mytonctrl/master/screens/mytonctrl-status.png) + +## Contents -## Functionality +- [What is MyTonCtrl?](#what-is-myttonctrl) +- [Functionality](#functionality) + - [List of tested operating systems](#list-of-tested-operating-systems) +- [Installation](#installation) + - [Installation scripts overview](#installation-scripts-overview) + - [Installation modes](#installation-modes) + - [Installation for Ubuntu](#installation-for-ubuntu) + - [Installation for Debian](#installation-for-debian) +- [MyTonCtrl Documentation](#mytonctrl-documentation) +- [Telemetry](#telemetry) +- [MyTonCtrl installer mode](#mytonctrl-installer-mode) + - [Web admin panel](#web-admin-panel) + - [Local copy of toncenter](#local-copy-of-toncenter) +- [Useful links](#useful-links) + + +# What is MyTonCtrl? +MyTonCtrl is a console application that serves as a convenient wrapper for `fift`, `lite-client`, and `validator-engine-console`. It has been specifically developed to streamline wallet, domain, and validator management tasks on the Linux operating system. + +![MyTonCtrl Status](screens/mytonctrl-status.png) + +# Functionality - [x] Show TON network status - [x] Management of local wallets - [x] Create local wallet @@ -45,48 +68,61 @@ This console is a wrapper over `fift`,`lite-client` and `validator-engine-consol - [x] Send validator statistics to https://toncenter.com ## List of tested operating systems -``` -Ubuntu 16.04 LTS (Xenial Xerus) - Error: TON compilation error -Ubuntu 18.04 LTS (Bionic Beaver) - OK -Ubuntu 20.04 LTS (Focal Fossa) - OK -Debian 8 - Error: Unable to locate package libgsl-dev -Debian 9 - Error: TON compilation error -Debian 10 - OK -``` - +| Operating System | Status | +|-------------------------------|----------------------------| +| Ubuntu 16.04 LTS (Xenial Xerus) | Error: TON compilation error | +| Ubuntu 18.04 LTS (Bionic Beaver) | OK | +| Ubuntu 20.04 LTS (Focal Fossa) | OK | +| Ubuntu 22.04 LTS (Jammy Jellyfish) | OK | +| Debian 8 | Error: Unable to locate package libgsl-dev | +| Debian 9 | Error: TON compilation error | +| Debian 10 | OK | + +# Installation ## Installation scripts overview - `toninstaller.sh`: clones `TON` and` mytonctrl` sources to `/usr/src/ton` and`/usr/src/mytonctrl` folders, compiles programs from sources and writes them to `/usr/bin/`. - `mytoninstaller.py`: configures the validator and `mytonctrl`; generates validator connection keys. ## Installation modes -There are two installation modes: `lite` and` full`. They both **compile** and install `TON` components. However the `lite` version does not configure or run the node/validator. +There are two installation modes: `lite` and`full`. They both **compile** and install `TON` components. However the `lite` version does not configure or run the node/validator. ## Installation for Ubuntu 1. Download and execute the `install.sh` script in the desired installation mode. During installation the script prompts you for the superuser password several times. -```sh -wget https://raw.githubusercontent.com/ton-blockchain/mytonctrl/master/scripts/install.sh -sudo bash install.sh -m -``` + ```sh + wget https://raw.githubusercontent.com/ton-blockchain/mytonctrl/master/scripts/install.sh + sudo bash install.sh -m + ``` 2. Done. You can try to run the `mytonctrl` console now. -```sh -mytonctrl -``` + ```sh + mytonctrl + ``` ## Installation for Debian 1. Download and execute the `install.sh` script in the desired installation mode. During installation the script prompts you for the superuser password several times. -```sh -wget https://raw.githubusercontent.com/ton-blockchain/mytonctrl/master/scripts/install.sh -su root -c 'bash install.sh -m ' -``` + ```sh + wget https://raw.githubusercontent.com/ton-blockchain/mytonctrl/master/scripts/install.sh + su root -c 'bash install.sh -m ' + ``` 2. Done. You can try to run the `mytonctrl` console now. -```sh -mytonctrl -``` + ```sh + mytonctrl + ``` -## Telemetry +# MyTonCtrl Documentation + +This repository contains the following technical documents for MyTonCtrl, categorized by language. Simply click the links below to navigate to the document you're interested in. + +| | FAQ | Import Wallets | Ubuntu Manual | Nominator Pool | +|:-:|:---:|:-------------:|:-------------:|:--------------:| +| **English (EN)** | [Link](./docs/en/FAQ.md) | [Link](./docs/en/import-wallets.md) | [Link](./docs/en/manual-ubuntu.md) | [Link](./docs/en/nominator-pool.md) | +| **Russian (RU)** | [Link](./docs/ru/FAQ.md) | [Link](./docs/ru/import-wallets.md) | [Link](./docs/ru/manual-ubuntu.md) | [Link](./docs/ru/nominator-pool.md) | +| **Traditional Chinese** | [Link](./docs/zh_TW/FAQ.md) | [Link](./docs/zh_TW/import-wallets.md) | [Link](./docs/zh_TW/manual-ubuntu.md) | [Link](./docs/zh_TW/nominator-pool.md) | + + +# Telemetry By default, `mytonctrl` sends validator statistics to the https://toncenter.com server. It is necessary to identify network abnormalities, as well as to quickly give feedback to developers. To disable telemetry during installation, use the `-t` flag: @@ -99,6 +135,8 @@ To disable telemetry after installation, do the following: MyTonCtrl> set sendTelemetry false ``` +# MyTonCtrl installer mode + ## Web admin panel To control the node/validator through the browser, you need to install an additional module: `mytonctrl` -> `installer` -> `enable JR` @@ -111,11 +149,10 @@ git: https://github.com/igroman787/mtc-jsonrpc ## Local copy of toncenter To set up a local https://toncenter.com copy on your server, install an additional module: -`mytonctrl` ->` installer` -> `enable PT` +`mytonctrl` ->`installer` -> `enable PT` Ready. A local copy of toncenter is available at `http://:8000` git: https://github.com/igroman787/pytonv3 -## Useful links -1. https://github.com/ton-blockchain/mytonctrl/blob/master/docs/en/manual-ubuntu.md -2. https://ton.org/docs/ +# Useful links +* https://docs.ton.org/ \ No newline at end of file diff --git a/mypyconsole b/mypyconsole index 3538607e..a8e8969a 160000 --- a/mypyconsole +++ b/mypyconsole @@ -1 +1 @@ -Subproject commit 3538607e412598cace37232c5941673bcdc56ded +Subproject commit a8e8969a6cac6bf96a34655504278d273adad98a diff --git a/mypylib b/mypylib index 8727d55f..1d8fd217 160000 --- a/mypylib +++ b/mypylib @@ -1 +1 @@ -Subproject commit 8727d55f87c56e70ff7d71e293f219136aef5f7c +Subproject commit 1d8fd2172639b7c6d61ded311d2c3a47d60c16b0 diff --git a/mytoncore.py b/mytoncore.py index a4ff4bb8..3a782973 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -8,6 +8,7 @@ import requests import re from mypylib.mypylib import * +from functions.session_stats import read_session_stats local = MyPyClass(__file__) @@ -22,7 +23,8 @@ def __init__(self): def Run(self, cmd, **kwargs): index = kwargs.get("index") - timeout = kwargs.get("timeout", 3) + liteclient_timeout = local.db.liteclient_timeout if local.db.liteclient_timeout else 3 + timeout = kwargs.get("timeout", liteclient_timeout) useLocalLiteServer = kwargs.get("useLocalLiteServer", True) validatorStatus = self.ton.GetValidatorStatus() validatorOutOfSync = validatorStatus.get("outOfSync") @@ -44,7 +46,7 @@ def Run(self, cmd, **kwargs): output = process.stdout.decode("utf-8") err = process.stderr.decode("utf-8") if len(err) > 0: - local.AddLog("args: {args}".format(args=args), "error") + local.add_log("args: {args}".format(args=args), "error") raise Exception("LiteClient error: {err}".format(err=err)) return output #end define @@ -59,7 +61,8 @@ def __init__(self): #end define def Run(self, cmd, **kwargs): - timeout = kwargs.get("timeout", 3) + console_timeout = local.db.console_timeout if local.db.console_timeout else 3 + timeout = kwargs.get("timeout", console_timeout) if self.appPath is None or self.privKeyPath is None or self.pubKeyPath is None: raise Exception("ValidatorConsole error: Validator console is not settings") args = [self.appPath, "-k", self.privKeyPath, "-p", self.pubKeyPath, "-a", self.addr, "-v", "0", "--cmd", cmd] @@ -67,7 +70,7 @@ def Run(self, cmd, **kwargs): output = process.stdout.decode("utf-8") err = process.stderr.decode("utf-8") if len(err) > 0: - local.AddLog("args: {args}".format(args=args), "error") + local.add_log("args: {args}".format(args=args), "error") raise Exception("ValidatorConsole error: {err}".format(err=err)) return output #end define @@ -81,7 +84,8 @@ def __init__(self): #end define def Run(self, args, **kwargs): - timeout = kwargs.get("timeout", 3) + fift_timeout = local.db.fift_timeout if local.db.fift_timeout else 3 + timeout = kwargs.get("timeout", fift_timeout) for i in range(len(args)): args[i] = str(args[i]) includePath = self.libsPath + ':' + self.smartcontsPath @@ -90,7 +94,7 @@ def Run(self, args, **kwargs): output = process.stdout.decode("utf-8") err = process.stderr.decode("utf-8") if len(err) > 0: - local.AddLog("args: {args}".format(args=args), "error") + local.add_log("args: {args}".format(args=args), "error") raise Exception("Fift error: {err}".format(err=err)) return output #end define @@ -290,15 +294,14 @@ def Init(self): def Refresh(self): if self.dbFile: - local.dbLoad(self.dbFile) - else: - local.dbLoad() + local.load_db(self.dbFile) + #end if if not self.walletsDir: - self.walletsDir = local.buffer.get("myWorkDir") + "wallets/" - self.contractsDir = local.buffer.get("myWorkDir") + "contracts/" - self.poolsDir = local.buffer.get("myWorkDir") + "pools/" - self.tempDir = local.buffer.get("myTempDir") + self.walletsDir = local.buffer.my_work_dir + "wallets/" + self.contractsDir = local.buffer.my_work_dir + "contracts/" + self.poolsDir = local.buffer.my_work_dir + "pools/" + self.tempDir = local.buffer.my_temp_dir self.nodeName = local.db.get("nodeName") if self.nodeName is None: @@ -337,18 +340,19 @@ def Refresh(self): #end define def CheckConfigFile(self, fift, liteClient): - mconfigPath = local.buffer.get("localdbFileName") - backupPath = mconfigPath + ".backup" + mconfig_path = local.buffer.db_path + backup_path = mconfig_path + ".backup" if fift is None or liteClient is None: - local.AddLog("The config file is broken", "warning") - if os.path.isfile(backupPath): - local.AddLog("Restoring the configuration file", "info") - args = ["cp", backupPath, mconfigPath] + local.add_log("The config file is broken", "warning") + print(f"local.db: {local.db}") + if os.path.isfile(backup_path): + local.add_log("Restoring the configuration file", "info") + args = ["cp", backup_path, mconfig_path] subprocess.run(args) self.Refresh() - elif os.path.isfile(backupPath) == False: - local.AddLog("Create backup config file", "info") - args = ["cp", mconfigPath, backupPath] + elif os.path.isfile(backup_path) == False: + local.add_log("Create backup config file", "info") + args = ["cp", mconfig_path, backup_path] subprocess.run(args) #end define @@ -384,7 +388,7 @@ def GetVarFromWorkerOutput(self, text, search): #end define def GetSeqno(self, wallet): - local.AddLog("start GetSeqno function", "debug") + local.add_log("start GetSeqno function", "debug") cmd = "runmethodfull {addr} seqno".format(addr=wallet.addrB64) result = self.liteClient.Run(cmd) if "cannot run any methods" in result: @@ -393,13 +397,13 @@ def GetSeqno(self, wallet): return 0 seqno = self.GetVarFromWorkerOutput(result, "result") seqno = seqno.replace(' ', '') - seqno = Pars(seqno, '[', ']') + seqno = parse(seqno, '[', ']') seqno = int(seqno) return seqno #end define def GetAccount(self, inputAddr): - #local.AddLog("start GetAccount function", "debug") + #local.add_log("start GetAccount function", "debug") workchain, addr = self.ParseInputAddr(inputAddr) account = Account(workchain, addr) cmd = "getaccount {inputAddr}".format(inputAddr=inputAddr) @@ -422,15 +426,15 @@ def GetAccount(self, inputAddr): code = self.GetBody(code) data = self.GetBody(data) codeHash = self.GetCodeHash(code) - status = Pars(state, "account_", '\n') + status = parse(state, "account_", '\n') account.workchain = int(workchain) account.addr = xhex2hex(address) account.addrB64 = self.AddrFull2AddrB64(addrFull) account.addrFull = addrFull account.status = status account.balance = ng2g(value) - account.lt = Pars(result, "lt = ", ' ') - account.hash = Pars(result, "hash = ", '\n') + account.lt = parse(result, "lt = ", ' ') + account.hash = parse(result, "hash = ", '\n') account.codeHash = codeHash return account #end define @@ -444,7 +448,7 @@ def GetCodeHash(self, code): #end define def GetAccountHistory(self, account, limit): - local.AddLog("start GetAccountHistory function", "debug") + local.add_log("start GetAccountHistory function", "debug") addr = f"{account.workchain}:{account.addr}" lt = account.lt transHash = account.hash @@ -467,7 +471,7 @@ def LastTransDump(self, addr, lt, transHash, count=10): for key, item in data.items(): if "transaction #" not in key: continue - block_str = Pars(key, "from block ", ' ') + block_str = parse(key, "from block ", ' ') description = self.GetKeyFromDict(item, "description") type = self.GetVar(description, "trans_") time = self.GetVarFromDict(item, "time") @@ -574,7 +578,7 @@ def GetBody(self, buff): for item in arr: if "x{" not in item: continue - buff = Pars(item, '{', '}') + buff = parse(item, '{', '}') buff = buff.replace('_', '') if len(buff)%2 == 1: buff = "0" + buff @@ -592,7 +596,7 @@ def GetBodyFromDict(self, buff): for item in buff: if "x{" not in item: continue - buff = Pars(item, '{', '}') + buff = parse(item, '{', '}') buff = buff.replace('_', '') if len(buff)%2 == 1: buff = "0" + buff @@ -624,7 +628,7 @@ def GetDomainAddr(self, domainName): result = self.liteClient.Run(cmd) if "not found" in result: raise Exception("GetDomainAddr error: domain \"{domainName}\" not found".format(domainName=domainName)) - resolver = Pars(result, "next resolver", '\n') + resolver = parse(result, "next resolver", '\n') buff = resolver.replace(' ', '') buffList = buff.split('=') fullHexAddr = buffList[0] @@ -633,7 +637,7 @@ def GetDomainAddr(self, domainName): #end define def GetDomainEndTime(self, domainName): - local.AddLog("start GetDomainEndTime function", "debug") + local.add_log("start GetDomainEndTime function", "debug") buff = domainName.split('.') subdomain = buff.pop(0) dnsDomain = ".".join(buff) @@ -641,28 +645,28 @@ def GetDomainEndTime(self, domainName): cmd = "runmethodfull {addr} getexpiration \"{subdomain}\"".format(addr=dnsAddr, subdomain=subdomain) result = self.liteClient.Run(cmd) - result = Pars(result, "result:", '\n') - result = Pars(result, "[", "]") + result = parse(result, "result:", '\n') + result = parse(result, "[", "]") result = result.replace(' ', '') result = int(result) return result #end define def GetDomainAdnlAddr(self, domainName): - local.AddLog("start GetDomainAdnlAddr function", "debug") + local.add_log("start GetDomainAdnlAddr function", "debug") cmd = "dnsresolve {domainName} 1".format(domainName=domainName) result = self.liteClient.Run(cmd) lines = result.split('\n') for line in lines: if "adnl address" in line: - adnlAddr = Pars(line, "=", "\n") + adnlAddr = parse(line, "=", "\n") adnlAddr = adnlAddr.replace(' ', '') adnlAddr = adnlAddr return adnlAddr #end define def GetLocalWallet(self, walletName, version=None, subwallet=None): - #local.AddLog("start GetLocalWallet function", "debug") + local.add_log("start GetLocalWallet function", "debug") if walletName is None: return None walletPath = self.walletsDir + walletName @@ -674,7 +678,7 @@ def GetLocalWallet(self, walletName, version=None, subwallet=None): #end define def GetWalletFromFile(self, filePath, version): - #local.AddLog("start GetWalletFromFile function", "debug") + local.add_log("start GetWalletFromFile function", "debug") # Check input args if (".addr" in filePath): filePath = filePath.replace(".addr", '') @@ -693,7 +697,7 @@ def GetWalletFromFile(self, filePath, version): #end define def GetHighWalletFromFile(self, filePath, subwallet, version): - local.AddLog("start GetHighWalletFromFile function", "debug") + local.add_log("start GetHighWalletFromFile function", "debug") # Check input args if (".addr" in filePath): filePath = filePath.replace(".addr", '') @@ -725,7 +729,7 @@ def AddrFile2Object(self, object): #end define def WalletVersion2Wallet(self, wallet): - #local.AddLog("start WalletVersion2Wallet function", "debug") + local.add_log("start WalletVersion2Wallet function", "debug") if wallet.version is not None: return walletsVersionList = self.GetWalletsVersionList() @@ -734,7 +738,7 @@ def WalletVersion2Wallet(self, wallet): if version is None: version = self.GetWalletVersionFromHash(account.codeHash) if version is None: - local.AddLog("Wallet version not found: " + wallet.addrB64, "warning") + local.add_log("Wallet version not found: " + wallet.addrB64, "warning") return #end if @@ -745,11 +749,11 @@ def WalletVersion2Wallet(self, wallet): def SetWalletVersion(self, addrB64, version): walletsVersionList = self.GetWalletsVersionList() walletsVersionList[addrB64] = version - local.dbSave() + local.save() #end define def GetWalletVersionFromHash(self, inputHash): - #local.AddLog("start GetWalletVersionFromHash function", "debug") + local.add_log("start GetWalletVersionFromHash function", "debug") arr = dict() arr["v1r1"] = "d670136510daff4fee1889b8872c4c1e89872ffa1fe58a23a5f5d99cef8edf32" arr["v1r2"] = "2705a31a7ac162295c8aed0761cc6e031ab65521dd7b4a14631099e02de99e18" @@ -768,8 +772,8 @@ def GetWalletVersionFromHash(self, inputHash): arr["controller_r2"] = "01118b9553151fb9bc81704a4b3e0fc7b899871a527d44435a51574806863e2c" arr["controller_r3"] = "e4d8ce8ff7b4b60c76b135eb8702ce3c86dc133fcee7d19c7aa18f71d9d91438" arr["controller_r4"] = "dec125a4850c4ba24668d84252b04c6ad40abf5c9d413a429b56bfff09ea25d4" - for version, codeHash in arr.items(): - if codeHash == inputHash: + for version, hash in arr.items(): + if hash == inputHash: return version #end for #end define @@ -791,7 +795,7 @@ def GetFullConfigAddr(self): return buff #end if - local.AddLog("start GetFullConfigAddr function", "debug") + local.add_log("start GetFullConfigAddr function", "debug") result = self.liteClient.Run("getconfig 0") configAddr_hex = self.GetVarFromWorkerOutput(result, "config_addr:x") fullConfigAddr = "-1:{configAddr_hex}".format(configAddr_hex=configAddr_hex) @@ -810,7 +814,7 @@ def GetFullElectorAddr(self): #end if # Get data - local.AddLog("start GetFullElectorAddr function", "debug") + local.add_log("start GetFullElectorAddr function", "debug") result = self.liteClient.Run("getconfig 1") electorAddr_hex = self.GetVarFromWorkerOutput(result, "elector_addr:x") fullElectorAddr = "-1:{electorAddr_hex}".format(electorAddr_hex=electorAddr_hex) @@ -828,7 +832,7 @@ def GetFullMinterAddr(self): return buff #end if - local.AddLog("start GetFullMinterAddr function", "debug") + local.add_log("start GetFullMinterAddr function", "debug") result = self.liteClient.Run("getconfig 2") minterAddr_hex = self.GetVarFromWorkerOutput(result, "minter_addr:x") fullMinterAddr = "-1:{minterAddr_hex}".format(minterAddr_hex=minterAddr_hex) @@ -846,7 +850,7 @@ def GetFullDnsRootAddr(self): return buff #end if - local.AddLog("start GetFullDnsRootAddr function", "debug") + local.add_log("start GetFullDnsRootAddr function", "debug") result = self.liteClient.Run("getconfig 4") dnsRootAddr_hex = self.GetVarFromWorkerOutput(result, "dns_root_addr:x") fullDnsRootAddr = "-1:{dnsRootAddr_hex}".format(dnsRootAddr_hex=dnsRootAddr_hex) @@ -864,12 +868,12 @@ def GetActiveElectionId(self, fullElectorAddr): return buff #end if - local.AddLog("start GetActiveElectionId function", "debug") + local.add_log("start GetActiveElectionId function", "debug") cmd = "runmethodfull {fullElectorAddr} active_election_id".format(fullElectorAddr=fullElectorAddr) result = self.liteClient.Run(cmd) activeElectionId = self.GetVarFromWorkerOutput(result, "result") activeElectionId = activeElectionId.replace(' ', '') - activeElectionId = Pars(activeElectionId, '[', ']') + activeElectionId = parse(activeElectionId, '[', ']') activeElectionId = int(activeElectionId) # Set buffer @@ -878,26 +882,26 @@ def GetActiveElectionId(self, fullElectorAddr): #end define def GetValidatorsElectedFor(self): - local.AddLog("start GetValidatorsElectedFor function", "debug") + local.add_log("start GetValidatorsElectedFor function", "debug") config15 = self.GetConfig15() return config15["validatorsElectedFor"] #end define def GetMinStake(self): - local.AddLog("start GetMinStake function", "debug") + local.add_log("start GetMinStake function", "debug") config17 = self.GetConfig17() return config17["minStake"] #end define def GetRootWorkchainEnabledTime(self): - local.AddLog("start GetRootWorkchainEnabledTime function", "debug") + local.add_log("start GetRootWorkchainEnabledTime function", "debug") config12 = self.GetConfig(12) enabledTime = config12["workchains"]["root"]["node"]["value"]["enabled_since"] return enabledTime #end define def GetTotalValidators(self): - local.AddLog("start GetTotalValidators function", "debug") + local.add_log("start GetTotalValidators function", "debug") config34 = self.GetConfig34() result = config34["totalValidators"] return result @@ -920,7 +924,7 @@ def GetInitBlock_new(self): #block = self.GetLastBlock() #cmd = f"gethead {block}" #result = self.liteClient.Run(cmd) - #seqno = Pars(result, "prev_key_block_seqno=", '\n') + #seqno = parse(result, "prev_key_block_seqno=", '\n') statesDir = "/var/ton-work/db/archive/states" os.chdir(statesDir) files = filter(os.path.isfile, os.listdir(statesDir)) @@ -941,7 +945,7 @@ def GetInitBlock(self): block = self.GetLastBlock() cmd = f"gethead {block}" result = self.liteClient.Run(cmd) - seqno = Pars(result, "prev_key_block_seqno=", '\n') + seqno = parse(result, "prev_key_block_seqno=", '\n') data = self.GetBlockHead(-1, 8000000000000000, seqno) return data #end define @@ -959,7 +963,7 @@ def GetBlock(self, workchain, shardchain, seqno): cmd = "byseqno {workchain}:{shardchain} {seqno}" cmd = cmd.format(workchain=workchain, shardchain=shardchain, seqno=seqno) result = self.liteClient.Run(cmd) - block_str = Pars(result, "block header of ", ' ') + block_str = parse(result, "block header of ", ' ') block = Block(block_str) return block #end define @@ -1041,30 +1045,30 @@ def GetValidatorStatus(self): return buff #end if - # local.AddLog("start GetValidatorStatus function", "debug") + # local.add_log("start GetValidatorStatus function", "debug") validatorStatus = dict() try: validatorStatus["isWorking"] = True result = self.validatorConsole.Run("getstats") - validatorStatus["unixtime"] = int(Pars(result, "unixtime", '\n')) - validatorStatus["masterchainblocktime"] = int(Pars(result, "masterchainblocktime", '\n')) - validatorStatus["stateserializermasterchainseqno"] = int(Pars(result, "stateserializermasterchainseqno", '\n')) - validatorStatus["shardclientmasterchainseqno"] = int(Pars(result, "shardclientmasterchainseqno", '\n')) - buff = Pars(result, "masterchainblock", '\n') + validatorStatus["unixtime"] = int(parse(result, "unixtime", '\n')) + validatorStatus["masterchainblocktime"] = int(parse(result, "masterchainblocktime", '\n')) + validatorStatus["stateserializermasterchainseqno"] = int(parse(result, "stateserializermasterchainseqno", '\n')) + validatorStatus["shardclientmasterchainseqno"] = int(parse(result, "shardclientmasterchainseqno", '\n')) + buff = parse(result, "masterchainblock", '\n') validatorStatus["masterchainblock"] = self.GVS_GetItemFromBuff(buff) - buff = Pars(result, "gcmasterchainblock", '\n') + buff = parse(result, "gcmasterchainblock", '\n') validatorStatus["gcmasterchainblock"] = self.GVS_GetItemFromBuff(buff) - buff = Pars(result, "keymasterchainblock", '\n') + buff = parse(result, "keymasterchainblock", '\n') validatorStatus["keymasterchainblock"] = self.GVS_GetItemFromBuff(buff) - buff = Pars(result, "rotatemasterchainblock", '\n') + buff = parse(result, "rotatemasterchainblock", '\n') validatorStatus["rotatemasterchainblock"] = self.GVS_GetItemFromBuff(buff) validatorStatus["transNum"] = local.buffer.get("transNum", -1) validatorStatus["blocksNum"] = local.buffer.get("blocksNum", -1) validatorStatus["masterBlocksNum"] = local.buffer.get("masterBlocksNum", -1) except Exception as ex: - local.AddLog(f"GetValidatorStatus warning: {ex}", "warning") + local.add_log(f"GetValidatorStatus warning: {ex}", "warning") validatorStatus["isWorking"] = False - validatorStatus["unixtime"] = GetTimestamp() + validatorStatus["unixtime"] = get_timestamp() validatorStatus["masterchainblocktime"] = 0 validatorStatus["outOfSync"] = validatorStatus["unixtime"] - validatorStatus["masterchainblocktime"] @@ -1094,7 +1098,7 @@ def GetConfig(self, configId): #end if text = "start GetConfig function ({})".format(configId) - local.AddLog(text, "debug") + local.add_log(text, "debug") cmd = "getconfig {configId}".format(configId=configId) result = self.liteClient.Run(cmd) start = result.find("ConfigParam") @@ -1133,22 +1137,22 @@ def GetConfig32(self): return buff #end if - local.AddLog("start GetConfig32 function", "debug") + local.add_log("start GetConfig32 function", "debug") config32 = dict() result = self.liteClient.Run("getconfig 32") - config32["totalValidators"] = int(Pars(result, "total:", ' ')) - config32["startWorkTime"] = int(Pars(result, "utime_since:", ' ')) - config32["endWorkTime"] = int(Pars(result, "utime_until:", ' ')) + config32["totalValidators"] = int(parse(result, "total:", ' ')) + config32["startWorkTime"] = int(parse(result, "utime_since:", ' ')) + config32["endWorkTime"] = int(parse(result, "utime_until:", ' ')) lines = result.split('\n') validators = list() for line in lines: if "public_key:" in line: - validatorAdnlAddr = Pars(line, "adnl_addr:x", ')') - pubkey = Pars(line, "pubkey:x", ')') + validatorAdnlAddr = parse(line, "adnl_addr:x", ')') + pubkey = parse(line, "pubkey:x", ')') if config32["totalValidators"] > 1: - validatorWeight = int(Pars(line, "weight:", ' ')) + validatorWeight = int(parse(line, "weight:", ' ')) else: - validatorWeight = int(Pars(line, "weight:", ')')) + validatorWeight = int(parse(line, "weight:", ')')) buff = dict() buff["adnlAddr"] = validatorAdnlAddr buff["pubkey"] = pubkey @@ -1169,23 +1173,23 @@ def GetConfig34(self): return buff #end if - local.AddLog("start GetConfig34 function", "debug") + local.add_log("start GetConfig34 function", "debug") config34 = dict() result = self.liteClient.Run("getconfig 34") - config34["totalValidators"] = int(Pars(result, "total:", ' ')) - config34["startWorkTime"] = int(Pars(result, "utime_since:", ' ')) - config34["endWorkTime"] = int(Pars(result, "utime_until:", ' ')) - config34["totalWeight"] = int(Pars(result, "total_weight:", ' ')) + config34["totalValidators"] = int(parse(result, "total:", ' ')) + config34["startWorkTime"] = int(parse(result, "utime_since:", ' ')) + config34["endWorkTime"] = int(parse(result, "utime_until:", ' ')) + config34["totalWeight"] = int(parse(result, "total_weight:", ' ')) lines = result.split('\n') validators = list() for line in lines: if "public_key:" in line: - validatorAdnlAddr = Pars(line, "adnl_addr:x", ')') - pubkey = Pars(line, "pubkey:x", ')') + validatorAdnlAddr = parse(line, "adnl_addr:x", ')') + pubkey = parse(line, "pubkey:x", ')') if config34["totalValidators"] > 1: - validatorWeight = int(Pars(line, "weight:", ' ')) + validatorWeight = int(parse(line, "weight:", ' ')) else: - validatorWeight = int(Pars(line, "weight:", ')')) + validatorWeight = int(parse(line, "weight:", ')')) buff = dict() buff["adnlAddr"] = validatorAdnlAddr buff["pubkey"] = pubkey @@ -1206,20 +1210,20 @@ def GetConfig36(self): return buff #end if - local.AddLog("start GetConfig36 function", "debug") + local.add_log("start GetConfig36 function", "debug") config36 = dict() try: result = self.liteClient.Run("getconfig 36") - config36["totalValidators"] = int(Pars(result, "total:", ' ')) - config36["startWorkTime"] = int(Pars(result, "utime_since:", ' ')) - config36["endWorkTime"] = int(Pars(result, "utime_until:", ' ')) + config36["totalValidators"] = int(parse(result, "total:", ' ')) + config36["startWorkTime"] = int(parse(result, "utime_since:", ' ')) + config36["endWorkTime"] = int(parse(result, "utime_until:", ' ')) lines = result.split('\n') validators = list() for line in lines: if "public_key:" in line: - validatorAdnlAddr = Pars(line, "adnl_addr:x", ')') - pubkey = Pars(line, "pubkey:x", ')') - validatorWeight = Pars(line, "weight:", ' ') + validatorAdnlAddr = parse(line, "adnl_addr:x", ')') + pubkey = parse(line, "pubkey:x", ')') + validatorWeight = parse(line, "weight:", ' ') buff = dict() buff["adnlAddr"] = validatorAdnlAddr buff["pubkey"] = pubkey @@ -1236,21 +1240,21 @@ def GetConfig36(self): #end define def CreateNewKey(self): - local.AddLog("start CreateNewKey function", "debug") + local.add_log("start CreateNewKey function", "debug") result = self.validatorConsole.Run("newkey") - key = Pars(result, "created new key ", '\n') + key = parse(result, "created new key ", '\n') return key #end define def GetPubKeyBase64(self, key): - local.AddLog("start GetPubKeyBase64 function", "debug") + local.add_log("start GetPubKeyBase64 function", "debug") result = self.validatorConsole.Run("exportpub " + key) - validatorPubkey_b64 = Pars(result, "got public key: ", '\n') + validatorPubkey_b64 = parse(result, "got public key: ", '\n') return validatorPubkey_b64 #end define def GetPubKey(self, key): - local.AddLog("start GetPubKey function", "debug") + local.add_log("start GetPubKey function", "debug") pubkey_b64 = self.GetPubKeyBase64(key) buff = pubkey_b64.encode("utf-8") buff = base64.b64decode(buff) @@ -1261,7 +1265,7 @@ def GetPubKey(self, key): #end define def AddKeyToValidator(self, key, startWorkTime, endWorkTime): - local.AddLog("start AddKeyToValidator function", "debug") + local.add_log("start AddKeyToValidator function", "debug") output = False cmd = "addpermkey {key} {startWorkTime} {endWorkTime}".format(key=key, startWorkTime=startWorkTime, endWorkTime=endWorkTime) result = self.validatorConsole.Run(cmd) @@ -1271,7 +1275,7 @@ def AddKeyToValidator(self, key, startWorkTime, endWorkTime): #end define def AddKeyToTemp(self, key, endWorkTime): - local.AddLog("start AddKeyToTemp function", "debug") + local.add_log("start AddKeyToTemp function", "debug") output = False result = self.validatorConsole.Run("addtempkey {key} {key} {endWorkTime}".format(key=key, endWorkTime=endWorkTime)) if ("success" in result): @@ -1280,7 +1284,7 @@ def AddKeyToTemp(self, key, endWorkTime): #end define def AddAdnlAddrToValidator(self, adnlAddr): - local.AddLog("start AddAdnlAddrToValidator function", "debug") + local.add_log("start AddAdnlAddrToValidator function", "debug") output = False result = self.validatorConsole.Run("addadnl {adnlAddr} 0".format(adnlAddr=adnlAddr)) if ("success" in result): @@ -1294,7 +1298,7 @@ def GetAdnlAddr(self): #end define def AttachAdnlAddrToValidator(self, adnlAddr, key, endWorkTime): - local.AddLog("start AttachAdnlAddrToValidator function", "debug") + local.add_log("start AttachAdnlAddrToValidator function", "debug") output = False result = self.validatorConsole.Run("addvalidatoraddr {key} {adnlAddr} {endWorkTime}".format(adnlAddr=adnlAddr, key=key, endWorkTime=endWorkTime)) if ("success" in result): @@ -1303,11 +1307,11 @@ def AttachAdnlAddrToValidator(self, adnlAddr, key, endWorkTime): #end define def CreateConfigProposalRequest(self, offerHash, validatorIndex): - local.AddLog("start CreateConfigProposalRequest function", "debug") + local.add_log("start CreateConfigProposalRequest function", "debug") fileName = self.tempDir + self.nodeName + "proposal_validator-to-sign.req" args = ["config-proposal-vote-req.fif", "-i", validatorIndex, offerHash, fileName] result = self.fift.Run(args) - fileName = Pars(result, "Saved to file ", '\n') + fileName = parse(result, "Saved to file ", '\n') resultList = result.split('\n') i = 0 start_index = 0 @@ -1321,11 +1325,11 @@ def CreateConfigProposalRequest(self, offerHash, validatorIndex): #end define def CreateComplaintRequest(self, electionId , complaintHash, validatorIndex): - local.AddLog("start CreateComplaintRequest function", "debug") + local.add_log("start CreateComplaintRequest function", "debug") fileName = self.tempDir + "complaint_validator-to-sign.req" args = ["complaint-vote-req.fif", validatorIndex, electionId, complaintHash, fileName] result = self.fift.Run(args) - fileName = Pars(result, "Saved to file ", '\n') + fileName = parse(result, "Saved to file ", '\n') resultList = result.split('\n') i = 0 start_index = 0 @@ -1339,20 +1343,20 @@ def CreateComplaintRequest(self, electionId , complaintHash, validatorIndex): #end define def PrepareComplaint(self, electionId, inputFileName): - local.AddLog("start PrepareComplaint function", "debug") + local.add_log("start PrepareComplaint function", "debug") fileName = self.tempDir + "complaint-msg-body.boc" args = ["envelope-complaint.fif", electionId, inputFileName, fileName] result = self.fift.Run(args) - fileName = Pars(result, "Saved to file ", ')') + fileName = parse(result, "Saved to file ", ')') return fileName #end define def CreateElectionRequest(self, addrB64, startWorkTime, adnlAddr, maxFactor): - local.AddLog("start CreateElectionRequest function", "debug") + local.add_log("start CreateElectionRequest function", "debug") fileName = self.tempDir + self.nodeName + str(startWorkTime) + "_validator-to-sign.bin" args = ["validator-elect-req.fif", addrB64, startWorkTime, maxFactor, adnlAddr, fileName] result = self.fift.Run(args) - fileName = Pars(result, "Saved to file ", '\n') + fileName = parse(result, "Saved to file ", '\n') resultList = result.split('\n') i = 0 start_index = 0 @@ -1366,25 +1370,25 @@ def CreateElectionRequest(self, addrB64, startWorkTime, adnlAddr, maxFactor): #end define def GetValidatorSignature(self, validatorKey, var1): - local.AddLog("start GetValidatorSignature function", "debug") + local.add_log("start GetValidatorSignature function", "debug") cmd = "sign {validatorKey} {var1}".format(validatorKey=validatorKey, var1=var1) result = self.validatorConsole.Run(cmd) - validatorSignature = Pars(result, "got signature ", '\n') + validatorSignature = parse(result, "got signature ", '\n') return validatorSignature #end define def SignElectionRequestWithValidator(self, wallet, startWorkTime, adnlAddr, validatorPubkey_b64, validatorSignature, maxFactor): - local.AddLog("start SignElectionRequestWithValidator function", "debug") + local.add_log("start SignElectionRequestWithValidator function", "debug") fileName = self.tempDir + self.nodeName + str(startWorkTime) + "_validator-query.boc" args = ["validator-elect-signed.fif", wallet.addrB64, startWorkTime, maxFactor, adnlAddr, validatorPubkey_b64, validatorSignature, fileName] result = self.fift.Run(args) - pubkey = Pars(result, "validator public key ", '\n') - fileName = Pars(result, "Saved to file ", '\n') + pubkey = parse(result, "validator public key ", '\n') + fileName = parse(result, "Saved to file ", '\n') return pubkey, fileName #end define def SignBocWithWallet(self, wallet, bocPath, dest, coins, **kwargs): - local.AddLog("start SignBocWithWallet function", "debug") + local.add_log("start SignBocWithWallet function", "debug") flags = kwargs.get("flags", list()) subwalletDefault = 698983191 + wallet.workchain # 0x29A9A317 + workchain subwallet = kwargs.get("subwallet", subwalletDefault) @@ -1401,7 +1405,7 @@ def SignBocWithWallet(self, wallet, bocPath, dest, coins, **kwargs): if bounceable == False and destAccount.status == "active": flags += ["-b"] text = "Find non-bounceable flag, but destination account already active. Using bounceable flag" - local.AddLog(text, "warning") + local.add_log(text, "warning") elif "-n" not in flags and bounceable == True and destAccount.status != "active": raise Exception("Find bounceable flag, but destination account is not active. Use non-bounceable address or flag -n") #end if @@ -1422,12 +1426,12 @@ def SignBocWithWallet(self, wallet, bocPath, dest, coins, **kwargs): if flags: args += flags result = self.fift.Run(args) - resultFilePath = Pars(result, "Saved to file ", ")") + resultFilePath = parse(result, "Saved to file ", ")") return resultFilePath #end define def SendFile(self, filePath, wallet=None, **kwargs): - local.AddLog("start SendFile function: " + filePath, "debug") + local.add_log("start SendFile function: " + filePath, "debug") timeout = kwargs.get("timeout", 30) remove = kwargs.get("remove", True) duplicateSendfile = local.db.get("duplicateSendfile", True) @@ -1446,7 +1450,7 @@ def SendFile(self, filePath, wallet=None, **kwargs): #end define def WaitTransaction(self, wallet, timeout=30): - local.AddLog("start WaitTransaction function", "debug") + local.add_log("start WaitTransaction function", "debug") timesleep = 3 steps = timeout // timesleep for i in range(steps): @@ -1458,23 +1462,23 @@ def WaitTransaction(self, wallet, timeout=30): #end define def GetReturnedStake(self, fullElectorAddr, inputAddr): - local.AddLog("start GetReturnedStake function", "debug") + local.add_log("start GetReturnedStake function", "debug") workchain, addr = self.ParseInputAddr(inputAddr) cmd = f"runmethodfull {fullElectorAddr} compute_returned_stake 0x{addr}" result = self.liteClient.Run(cmd) returnedStake = self.GetVarFromWorkerOutput(result, "result") returnedStake = returnedStake.replace(' ', '') - returnedStake = Pars(returnedStake, '[', ']') + returnedStake = parse(returnedStake, '[', ']') returnedStake = ng2g(returnedStake) return returnedStake #end define def ProcessRecoverStake(self): - local.AddLog("start ProcessRecoverStake function", "debug") + local.add_log("start ProcessRecoverStake function", "debug") resultFilePath = self.tempDir + self.nodeName + "recover-query" args = ["recover-stake.fif", resultFilePath] result = self.fift.Run(args) - resultFilePath = Pars(result, "Saved to file ", '\n') + resultFilePath = parse(result, "Saved to file ", '\n') return resultFilePath #end define @@ -1484,7 +1488,6 @@ def GetStake(self, account, args=None): useController = local.db.get("useController") stakePercent = local.db.get("stakePercent", 99) vconfig = self.GetValidatorConfig() - validators = vconfig.get("validators") config17 = self.GetConfig17() # Check if optional arguments have been passed to us @@ -1498,7 +1501,7 @@ def GetStake(self, account, args=None): # Stake was a number stake = int(desiredStake) else: - local.AddLog("Specified stake must be a percentage or whole number", "error") + local.add_log("Specified stake must be a percentage or whole number", "error") return # Limit stake to maximum available amount minus 10 (for transaction fees) @@ -1513,25 +1516,25 @@ def GetStake(self, account, args=None): if stake is None: sp = stakePercent / 100 if sp > 1 or sp < 0: - local.AddLog("Wrong stakePercent value. Using default stake.", "warning") - elif len(validators) == 0: + local.add_log("Wrong stakePercent value. Using default stake.", "warning") + elif len(vconfig.validators) == 0: stake = int(account.balance*sp/2) - elif len(validators) > 0: + elif len(vconfig.validators) > 0: stake = int(account.balance*sp) #end if # Check if we have enough coins if stake > config17["maxStake"]: text = "Stake is greater than the maximum value. Will be used the maximum stake." - local.AddLog(text, "warning") + local.add_log(text, "warning") stake = config17["maxStake"] if config17["minStake"] > stake: text = "Stake less than the minimum stake. Minimum stake: {minStake}".format(minStake=config17["minStake"]) - #local.AddLog(text, "error") + #local.add_log(text, "error") raise Exception(text) if stake > account.balance: text = "Don't have enough coins. stake: {stake}, account balance: {balance}".format(stake=stake, balance=account.balance) - #local.AddLog(text, "error") + #local.add_log(text, "error") raise Exception(text) #end if @@ -1549,7 +1552,7 @@ def GetMaxFactor(self): #end define def GetValidatorWallet(self, mode="stake"): - #local.AddLog("start GetValidatorWallet function", "debug") + local.add_log("start GetValidatorWallet function", "debug") walletName = local.db.get("validatorWalletName") wallet = self.GetLocalWallet(walletName) if wallet is None: @@ -1563,12 +1566,12 @@ def ElectionEntry(self, args=None): wallet = self.GetValidatorWallet() addrB64 = wallet.addrB64 - local.AddLog("start ElectionEntry function", "debug") + local.add_log("start ElectionEntry function", "debug") # Check if validator is not synchronized validatorStatus = self.GetValidatorStatus() validatorOutOfSync = validatorStatus.get("outOfSync") if validatorOutOfSync > 60: - local.AddLog("Validator is not synchronized", "error") + local.add_log("Validator is not synchronized", "error") return #end if @@ -1578,7 +1581,7 @@ def ElectionEntry(self, args=None): # Check if elections started if (startWorkTime == 0): - local.AddLog("Elections have not yet begun", "info") + local.add_log("Elections have not yet begun", "info") return #end if @@ -1594,7 +1597,7 @@ def ElectionEntry(self, args=None): # Check if election entry already completed entries = self.GetElectionEntries() if adnlAddr in entries: - local.AddLog("Elections entry already completed", "info") + local.add_log("Elections entry already completed", "info") return #end if @@ -1630,7 +1633,7 @@ def ElectionEntry(self, args=None): if usePool: var1 = self.CreateElectionRequest(pool.addrB64, startWorkTime, adnlAddr, maxFactor) validatorSignature = self.GetValidatorSignature(validatorKey, var1) - validatorPubkey, resultFilePath = self.SignElectionRequestWithPool(pool, startWorkTime, adnlAddr, validatorPubkey_b64, validatorSignature, maxFactor, stake) + validatorPubkey, resultFilePath = self.SignElectionRequestWithPoolWithValidator(pool, startWorkTime, adnlAddr, validatorPubkey_b64, validatorSignature, maxFactor, stake) # Send boc file to TON resultFilePath = self.SignBocWithWallet(wallet, resultFilePath, pool.addrB64, 1.3) @@ -1656,15 +1659,14 @@ def ElectionEntry(self, args=None): # Save vars to json file self.SaveElectionVarsToJsonFile(wallet=wallet, account=account, stake=stake, maxFactor=maxFactor, fullElectorAddr=fullElectorAddr, startWorkTime=startWorkTime, validatorsElectedFor=validatorsElectedFor, endWorkTime=endWorkTime, validatorKey=validatorKey, validatorPubkey_b64=validatorPubkey_b64, adnlAddr=adnlAddr, var1=var1, validatorSignature=validatorSignature, validatorPubkey=validatorPubkey) - local.AddLog("ElectionEntry completed. Start work time: " + str(startWorkTime)) + local.add_log("ElectionEntry completed. Start work time: " + str(startWorkTime)) #end define def GetValidatorKeyByTime(self, startWorkTime, endWorkTime): - local.AddLog("start GetValidatorKeyByTime function", "debug") + local.add_log("start GetValidatorKeyByTime function", "debug") # Check temp key vconfig = self.GetValidatorConfig() - validators = vconfig.get("validators") - for item in validators: + for item in vconfig.validators: if item.get("election_date") == startWorkTime: validatorKey_b64 = item.get("id") validatorKey = base64.b64decode(validatorKey_b64).hex() @@ -1681,31 +1683,31 @@ def GetValidatorKeyByTime(self, startWorkTime, endWorkTime): def RecoverStake(self): wallet = self.GetValidatorWallet() - local.AddLog("start RecoverStake function", "debug") + local.add_log("start RecoverStake function", "debug") fullElectorAddr = self.GetFullElectorAddr() returnedStake = self.GetReturnedStake(fullElectorAddr, wallet.addrB64) if returnedStake == 0: - local.AddLog("You have nothing on the return stake", "debug") + local.add_log("You have nothing on the return stake", "debug") return #end if resultFilePath = self.ProcessRecoverStake() resultFilePath = self.SignBocWithWallet(wallet, resultFilePath, fullElectorAddr, 1) self.SendFile(resultFilePath, wallet) - local.AddLog("RecoverStake completed") + local.add_log("RecoverStake completed") #end define def PoolRecoverStake(self, poolAddr): wallet = self.GetValidatorWallet() - local.AddLog("start PoolRecoverStake function", "debug") + local.add_log("start PoolRecoverStake function", "debug") resultFilePath = self.PoolProcessRecoverStake() resultFilePath = self.SignBocWithWallet(wallet, resultFilePath, poolAddr, 1.2) self.SendFile(resultFilePath, wallet) - local.AddLog("PoolRecoverStake completed") + local.add_log("PoolRecoverStake completed") #end define def PoolsUpdateValidatorSet(self): - local.AddLog("start PoolsUpdateValidatorSet function", "debug") + local.add_log("start PoolsUpdateValidatorSet function", "debug") wallet = self.GetValidatorWallet() pools = self.GetPools() for pool in pools: @@ -1713,7 +1715,7 @@ def PoolsUpdateValidatorSet(self): #end define def PoolUpdateValidatorSet(self, pool, wallet): - local.AddLog("start PoolUpdateValidatorSet function", "debug") + local.add_log("start PoolUpdateValidatorSet function", "debug") poolAddr = pool.addrB64 poolData = self.GetPoolData(poolAddr) if poolData is None: @@ -1744,32 +1746,32 @@ def PoolUpdateValidatorSet(self, pool, wallet): #end define def PoolProcessUpdateValidatorSet(self, poolAddr, wallet): - local.AddLog("start PoolProcessUpdateValidatorSet function", "debug") + local.add_log("start PoolProcessUpdateValidatorSet function", "debug") resultFilePath = self.tempDir + "pool-update-validator-set-query.boc" fiftScript = self.contractsDir + "nominator-pool/func/update-validator-set.fif" args = [fiftScript, resultFilePath] result = self.fift.Run(args) - resultFilePath = Pars(result, "Saved to file ", '\n') + resultFilePath = parse(result, "Saved to file ", '\n') resultFilePath = self.SignBocWithWallet(wallet, resultFilePath, poolAddr, 1.1) self.SendFile(resultFilePath, wallet) - local.AddLog("PoolProcessUpdateValidatorSet completed") + local.add_log("PoolProcessUpdateValidatorSet completed") #end define def PoolWithdrawRequests(self, pool, wallet): - local.AddLog("start PoolWithdrawRequests function", "debug") + local.add_log("start PoolWithdrawRequests function", "debug") resultFilePath = self.PoolProcessWihtdrawRequests() resultFilePath = self.SignBocWithWallet(wallet, resultFilePath, pool.addrB64, 10) self.SendFile(resultFilePath, wallet) - local.AddLog("PoolWithdrawRequests completed") + local.add_log("PoolWithdrawRequests completed") #end define def PoolProcessWihtdrawRequests(self): - local.AddLog("start PoolProcessWihtdrawRequests function", "debug") + local.add_log("start PoolProcessWihtdrawRequests function", "debug") resultFilePath = self.tempDir + "pool-withdraw-requests-query.boc" fiftScript = self.contractsDir + "nominator-pool/func/process-withdraw-requests.fif" args = [fiftScript, resultFilePath] result = self.fift.Run(args) - resultFilePath = Pars(result, "Saved to file ", '\n') + resultFilePath = parse(result, "Saved to file ", '\n') return resultFilePath #end define @@ -1785,7 +1787,7 @@ def HasPoolWithdrawRequests(self, pool): #end define def SaveElectionVarsToJsonFile(self, **kwargs): - local.AddLog("start SaveElectionVarsToJsonFile function", "debug") + local.add_log("start SaveElectionVarsToJsonFile function", "debug") fileName = self.tempDir + self.nodeName + str(kwargs.get("startWorkTime")) + "_ElectionEntry.json" wallet = kwargs.get("wallet") account = kwargs.get("account") @@ -1800,12 +1802,12 @@ def SaveElectionVarsToJsonFile(self, **kwargs): #ned define def CreateWallet(self, name, workchain=0, version="v1", **kwargs): - local.AddLog("start CreateWallet function", "debug") + local.add_log("start CreateWallet function", "debug") subwalletDefault = 698983191 + workchain # 0x29A9A317 + workchain subwallet = kwargs.get("subwallet", subwalletDefault) walletPath = self.walletsDir + name if os.path.isfile(walletPath + ".pk") and "v3" not in version: - local.AddLog("CreateWallet error: Wallet already exists: " + name, "warning") + local.add_log("CreateWallet error: Wallet already exists: " + name, "warning") else: if "v1" in version: fiftScript = "new-wallet.fif" @@ -1830,10 +1832,10 @@ def CreateHighWallet(self, name, **kwargs): subwalletDefault = 698983191 + workchain # 0x29A9A317 + workchain subwallet = kwargs.get("subwallet", subwalletDefault) version = kwargs.get("version", "hv1") - local.AddLog("start CreateHighWallet function", "debug") + local.add_log("start CreateHighWallet function", "debug") walletPath = self.walletsDir + name if os.path.isfile(walletPath + ".pk") and os.path.isfile(walletPath + str(subwallet) + ".addr"): - local.AddLog("CreateHighWallet error: Wallet already exists: " + name + str(subwallet), "warning") + local.add_log("CreateHighWallet error: Wallet already exists: " + name + str(subwallet), "warning") else: args = ["new-highload-wallet.fif", workchain, subwallet, walletPath] result = self.fift.Run(args) @@ -1846,12 +1848,12 @@ def CreateHighWallet(self, name, **kwargs): #end define def ActivateWallet(self, wallet): - local.AddLog("start ActivateWallet function", "debug") + local.add_log("start ActivateWallet function", "debug") account = self.GetAccount(wallet.addrB64) if account.status == "empty": raise Exception("ActivateWallet error: account status is empty") elif account.status == "active": - local.AddLog("ActivateWallet warning: account status is active", "warning") + local.add_log("ActivateWallet warning: account status is active", "warning") else: self.SendFile(wallet.bocFilePath, wallet, remove=False) #end define @@ -1887,7 +1889,7 @@ def ExportWallet(self, walletName): #end define def GetWalletsNameList(self): - local.AddLog("start GetWalletsNameList function", "debug") + local.add_log("start GetWalletsNameList function", "debug") walletsNameList = list() for fileName in os.listdir(self.walletsDir): if fileName.endswith(".addr"): @@ -1900,7 +1902,7 @@ def GetWalletsNameList(self): #end define def GetWallets(self): - local.AddLog("start GetWallets function", "debug") + local.add_log("start GetWallets function", "debug") wallets = list() walletsNameList = self.GetWalletsNameList() for walletName in walletsNameList: @@ -1910,7 +1912,7 @@ def GetWallets(self): #end define def GenerateWalletName(self): - local.AddLog("start GenerateWalletName function", "debug") + local.add_log("start GenerateWalletName function", "debug") index = 1 index_str = str(index).rjust(3, '0') walletPrefix = "wallet_" @@ -1932,7 +1934,7 @@ def GenerateWalletName(self): #end define def WalletsCheck(self): - local.AddLog("start WalletsCheck function", "debug") + local.add_log("start WalletsCheck function", "debug") wallets = self.GetWallets() for wallet in wallets: if os.path.isfile(wallet.bocFilePath): @@ -1942,16 +1944,16 @@ def WalletsCheck(self): #end define def GetValidatorConfig(self): - local.AddLog("start GetValidatorConfig function", "debug") + #local.add_log("start GetValidatorConfig function", "debug") result = self.validatorConsole.Run("getconfig") - text = Pars(result, "---------", "--------") + text = parse(result, "---------", "--------") vconfig = json.loads(text) - return vconfig + return Dict(vconfig) #end define def GetOverlaysStats(self): - local.AddLog("start GetOverlaysStats function", "debug") - resultFilePath = local.buffer.get("myTempDir") + "getoverlaysstats.json" + local.add_log("start GetOverlaysStats function", "debug") + resultFilePath = local.buffer.my_temp_dir + "getoverlaysstats.json" result = self.validatorConsole.Run(f"getoverlaysstatsjson {resultFilePath}") if "wrote stats" not in result: raise Exception(f"GetOverlaysStats error: {result}") @@ -1969,13 +1971,13 @@ def GetWalletId(self, wallet): result = self.GetVarFromWorkerOutput(result, "result") if result is None or "error" in result: return subwalletDefault - subwallet = Pars(result, '[', ']') + subwallet = parse(result, '[', ']') subwallet = int(subwallet) return subwallet #end define def MoveCoins(self, wallet, dest, coins, **kwargs): - local.AddLog("start MoveCoins function", "debug") + local.add_log("start MoveCoins function", "debug") flags = kwargs.get("flags", list()) timeout = kwargs.get("timeout", 30) subwallet = kwargs.get("subwallet") @@ -2006,13 +2008,13 @@ def MoveCoins(self, wallet, dest, coins, **kwargs): if bounceable == False and destAccount.status == "active": flags += ["-b"] text = "Find non-bounceable flag, but destination account already active. Using bounceable flag" - local.AddLog(text, "warning") + local.add_log(text, "warning") elif "-n" not in flags and bounceable == True and destAccount.status != "active": raise Exception("Find bounceable flag, but destination account is not active. Use non-bounceable address or flag -n") #end if seqno = self.GetSeqno(wallet) - resultFilePath = local.buffer.get("myTempDir") + wallet.name + "_wallet-query" + resultFilePath = local.buffer.my_temp_dir + wallet.name + "_wallet-query" if "v1" in wallet.version: fiftScript = "wallet.fif" args = [fiftScript, wallet.path, dest, seqno, coins, "-m", mode, resultFilePath] @@ -2025,12 +2027,12 @@ def MoveCoins(self, wallet, dest, coins, **kwargs): if flags: args += flags result = self.fift.Run(args) - savedFilePath = Pars(result, "Saved to file ", ")") + savedFilePath = parse(result, "Saved to file ", ")") self.SendFile(savedFilePath, wallet, timeout=timeout) #end define def MoveCoinsThroughProxy(self, wallet, dest, coins): - local.AddLog("start MoveCoinsThroughProxy function", "debug") + local.add_log("start MoveCoinsThroughProxy function", "debug") wallet1 = self.CreateWallet("proxy_wallet1", 0) wallet2 = self.CreateWallet("proxy_wallet2", 0) self.MoveCoins(wallet, wallet1.addrB64_init, coins) @@ -2043,16 +2045,16 @@ def MoveCoinsThroughProxy(self, wallet, dest, coins): #end define def MoveCoinsFromHW(self, wallet, destList, **kwargs): - local.AddLog("start MoveCoinsFromHW function", "debug") + local.add_log("start MoveCoinsFromHW function", "debug") flags = kwargs.get("flags") timeout = kwargs.get("timeout", 30) if len(destList) == 0: - local.AddLog("MoveCoinsFromHW warning: destList is empty, break function", "warning") + local.add_log("MoveCoinsFromHW warning: destList is empty, break function", "warning") return #end if - orderFilePath = local.buffer.get("myTempDir") + wallet.name + "_order.txt" + orderFilePath = local.buffer.my_temp_dir + wallet.name + "_order.txt" lines = list() for dest, coins in destList: lines.append("SEND {dest} {coins}".format(dest=dest, coins=coins)) @@ -2066,23 +2068,22 @@ def MoveCoinsFromHW(self, wallet, destList, **kwargs): elif "v2" in wallet.version: fiftScript = "highload-wallet-v2.fif" seqno = self.GetSeqno(wallet) - resultFilePath = local.buffer.get("myTempDir") + wallet.name + "_wallet-query" + resultFilePath = local.buffer.my_temp_dir + wallet.name + "_wallet-query" args = [fiftScript, wallet.path, wallet.subwallet, seqno, orderFilePath, resultFilePath] if flags: args += flags result = self.fift.Run(args) - savedFilePath = Pars(result, "Saved to file ", ")") + savedFilePath = parse(result, "Saved to file ", ")") self.SendFile(savedFilePath, wallet, timeout=timeout) #end define def GetValidatorKey(self): vconfig = self.GetValidatorConfig() - validators = vconfig["validators"] - for validator in validators: + for validator in vconfig.validators: validatorId = validator["id"] key_bytes = base64.b64decode(validatorId) validatorKey = key_bytes.hex().upper() - timestamp = GetTimestamp() + timestamp = get_timestamp() if timestamp > validator["election_date"]: return validatorKey raise Exception("GetValidatorKey error: validator key not found. Are you sure you are a validator?") @@ -2116,7 +2117,7 @@ def GetElectionEntries(self, past=False): #end if # Get raw data - local.AddLog("start GetElectionEntries function", "debug") + local.add_log("start GetElectionEntries function", "debug") cmd = "runmethodfull {fullElectorAddr} participant_list_extended".format(fullElectorAddr=fullElectorAddr) result = self.liteClient.Run(cmd) rawElectionEntries = self.Result2List(result) @@ -2157,7 +2158,7 @@ def GetElectionEntries(self, past=False): #end define def GetSaveElections(self): - timestamp = GetTimestamp() + timestamp = get_timestamp() saveElections = local.db.get("saveElections") if saveElections is None: saveElections = dict() @@ -2178,7 +2179,7 @@ def GetSaveElectionEntries(self, electionId): #end define def GetOffers(self): - local.AddLog("start GetOffers function", "debug") + local.add_log("start GetOffers function", "debug") fullConfigAddr = self.GetFullConfigAddr() # Get raw data cmd = "runmethodfull {fullConfigAddr} list_proposals".format(fullConfigAddr=fullConfigAddr) @@ -2230,7 +2231,7 @@ def GetOffers(self): #end define def GetOfferDiff(self, offerHash): - local.AddLog("start GetOfferDiff function", "debug") + local.add_log("start GetOfferDiff function", "debug") offer = self.GetOffer(offerHash) configId = offer["config"]["id"] configValue = offer["config"]["value"] @@ -2327,7 +2328,7 @@ def GetComplaints(self, electionId=None, past=False): #end if # Get raw data - local.AddLog("start GetComplaints function", "debug") + local.add_log("start GetComplaints function", "debug") cmd = "runmethodfull {fullElectorAddr} list_complaints {electionId}".format(fullElectorAddr=fullElectorAddr, electionId=electionId) result = self.liteClient.Run(cmd) rawComplaints = self.Result2List(result) @@ -2394,7 +2395,7 @@ def GetComplaints(self, electionId=None, past=False): #end define def GetSaveComplaints(self): - timestamp = GetTimestamp() + timestamp = get_timestamp() saveComplaints = local.db.get("saveComplaints") if type(saveComplaints) is not dict: saveComplaints = dict() @@ -2418,7 +2419,7 @@ def GetAdnlFromPubkey(self, inputPubkey): #end define def GetComplaintsNumber(self): - local.AddLog("start GetComplaintsNumber function", "debug") + local.add_log("start GetComplaintsNumber function", "debug") result = dict() complaints = self.GetComplaints() votedComplaints = self.GetVotedComplaints() @@ -2436,7 +2437,7 @@ def GetComplaintsNumber(self): #end define def GetComplaint(self, electionId, complaintHash): - local.AddLog("start GetComplaint function", "debug") + local.add_log("start GetComplaint function", "debug") complaints = self.GetComplaints(electionId) for key, item in complaints.items(): if complaintHash == item.get("hash"): @@ -2445,25 +2446,25 @@ def GetComplaint(self, electionId, complaintHash): #end define def SignProposalVoteRequestWithValidator(self, offerHash, validatorIndex, validatorPubkey_b64, validatorSignature): - local.AddLog("start SignProposalVoteRequestWithValidator function", "debug") + local.add_log("start SignProposalVoteRequestWithValidator function", "debug") fileName = self.tempDir + self.nodeName + "proposal_vote-msg-body.boc" args = ["config-proposal-vote-signed.fif", "-i", validatorIndex, offerHash, validatorPubkey_b64, validatorSignature, fileName] result = self.fift.Run(args) - fileName = Pars(result, "Saved to file ", '\n') + fileName = parse(result, "Saved to file ", '\n') return fileName #end define def SignComplaintVoteRequestWithValidator(self, complaintHash, electionId, validatorIndex, validatorPubkey_b64, validatorSignature): - local.AddLog("start SignComplaintRequestWithValidator function", "debug") + local.add_log("start SignComplaintRequestWithValidator function", "debug") fileName = self.tempDir + "complaint_vote-msg-body.boc" args = ["complaint-vote-signed.fif", validatorIndex, electionId, complaintHash, validatorPubkey_b64, validatorSignature, fileName] result = self.fift.Run(args) - fileName = Pars(result, "Saved to file ", '\n') + fileName = parse(result, "Saved to file ", '\n') return fileName #end define def VoteOffer(self, offerHash): - local.AddLog("start VoteOffer function", "debug") + local.add_log("start VoteOffer function", "debug") fullConfigAddr = self.GetFullConfigAddr() wallet = self.GetValidatorWallet(mode="vote") validatorKey = self.GetValidatorKey() @@ -2471,7 +2472,7 @@ def VoteOffer(self, offerHash): validatorIndex = self.GetValidatorIndex() offer = self.GetOffer(offerHash) if validatorIndex in offer.get("votedValidators"): - local.AddLog("Proposal already has been voted", "debug") + local.add_log("Proposal already has been voted", "debug") return var1 = self.CreateConfigProposalRequest(offerHash, validatorIndex) validatorSignature = self.GetValidatorSignature(validatorKey, var1) @@ -2482,7 +2483,7 @@ def VoteOffer(self, offerHash): #end define def VoteComplaint(self, electionId, complaintHash): - local.AddLog("start VoteComplaint function", "debug") + local.add_log("start VoteComplaint function", "debug") complaintHash = int(complaintHash) fullElectorAddr = self.GetFullElectorAddr() wallet = self.GetValidatorWallet(mode="vote") @@ -2493,7 +2494,7 @@ def VoteComplaint(self, electionId, complaintHash): votedValidators = complaint.get("votedValidators") pubkey = complaint.get("pubkey") if validatorIndex in votedValidators: - local.AddLog("Complaint already has been voted", "info") + local.add_log("Complaint already has been voted", "info") return var1 = self.CreateComplaintRequest(electionId, complaintHash, validatorIndex) validatorSignature = self.GetValidatorSignature(validatorKey, var1) @@ -2504,7 +2505,7 @@ def VoteComplaint(self, electionId, complaintHash): #end define def SaveComplaints(self, electionId): - local.AddLog("start SaveComplaints function", "debug") + local.add_log("start SaveComplaints function", "debug") filePrefix = self.tempDir + "scheck_" cmd = "savecomplaints {electionId} {filePrefix}".format(electionId=electionId, filePrefix=filePrefix) result = self.liteClient.Run(cmd) @@ -2524,7 +2525,7 @@ def SaveComplaints(self, electionId): #end define def CheckComplaint(self, filePath): - local.AddLog("start CheckComplaint function", "debug") + local.add_log("start CheckComplaint function", "debug") cmd = "loadproofcheck {filePath}".format(filePath=filePath) result = self.liteClient.Run(cmd, timeout=30) lines = result.split('\n') @@ -2560,7 +2561,7 @@ def GetValidatorsLoad(self, start, end, saveCompFiles=False): #end if text = "start GetValidatorsLoad function ({}, {})".format(start, end) - local.AddLog(text, "debug") + local.add_log(text, "debug") if saveCompFiles is True: filePrefix = self.tempDir + f"checkload_{start}_{end}" else: @@ -2642,7 +2643,7 @@ def GetValidatorsList(self, past=False): return buff #end if - timestamp = GetTimestamp() + timestamp = get_timestamp() end = timestamp - 60 start = end - 2000 config = self.GetConfig34() @@ -2673,16 +2674,14 @@ def GetValidatorsList(self, past=False): #end define def CheckValidators(self, start, end): - local.AddLog("start CheckValidators function", "debug") + local.add_log("start CheckValidators function", "debug") electionId = start complaints = self.GetComplaints(electionId) data = self.GetValidatorsLoad(start, end, saveCompFiles=True) fullElectorAddr = self.GetFullElectorAddr() wallet = self.GetValidatorWallet(mode="vote") - # Check wallet and balance - if wallet is None: - raise Exception("Validator wallet not fond") + # Check balance account = self.GetAccount(wallet.addrB64) if account.balance < 300: raise Exception("Validator wallet balance must be greater than 300") @@ -2700,11 +2699,11 @@ def CheckValidators(self, start, end): fileName = self.PrepareComplaint(electionId, fileName) fileName = self.SignBocWithWallet(wallet, fileName, fullElectorAddr, 300) self.SendFile(fileName, wallet) - local.AddLog("var1: {}, var2: {}, pubkey: {}, election_id: {}".format(var1, var2, pubkey, electionId), "debug") + local.add_log("var1: {}, var2: {}, pubkey: {}, election_id: {}".format(var1, var2, pubkey, electionId), "debug") #end define def GetOffer(self, offerHash): - local.AddLog("start GetOffer function", "debug") + local.add_log("start GetOffer function", "debug") offers = self.GetOffers() for offer in offers: if offerHash == offer.get("hash"): @@ -2713,7 +2712,7 @@ def GetOffer(self, offerHash): #end define def GetOffersNumber(self): - local.AddLog("start GetOffersNumber function", "debug") + local.add_log("start GetOffersNumber function", "debug") result = dict() offers = self.GetOffers() saveOffers = self.GetSaveOffers() @@ -2739,12 +2738,12 @@ def GetValidatorIndex(self, adnlAddr=None): if adnlAddr == searchAdnlAddr: return index index += 1 - local.AddLog("GetValidatorIndex warning: index not found.", "warning") + local.add_log("GetValidatorIndex warning: index not found.", "warning") return -1 #end define def GetValidatorEfficiency(self, adnlAddr=None): - local.AddLog("start GetValidatorEfficiency function", "debug") + local.add_log("start GetValidatorEfficiency function", "debug") validators = self.GetValidatorsList() if adnlAddr is None: adnlAddr = self.GetAdnlAddr() @@ -2753,7 +2752,27 @@ def GetValidatorEfficiency(self, adnlAddr=None): if adnlAddr == searchAdnlAddr: efficiency = validator.get("efficiency") return efficiency - local.AddLog("GetValidatorEfficiency warning: efficiency not found.", "warning") + local.add_log("GetValidatorEfficiency warning: efficiency not found.", "warning") + #end define + + def GetValidatorEfficiency2(self): + config34 = self.GetConfig34() + validator_uptime = get_service_uptime("validator") + current_round_time = int(time.time()) - config34.get("startWorkTime") + data1 = read_session_stats(600) + data2 = read_session_stats(current_round_time) + data3 = read_session_stats(validator_uptime) + + efficiency1 = 0 + efficiency2 = 0 + efficiency3 = 0 + if data1.my_need_blocks > 0: + efficiency1 = round(data1.my_blocks/data1.my_need_blocks*100, 2) + if data2.my_need_blocks > 0: + efficiency2 = round(data2.my_blocks/data2.my_need_blocks*100, 2) + if data3.my_need_blocks > 0: + efficiency3 = round(data3.my_blocks/data3.my_need_blocks*100, 2) + return [efficiency1, efficiency2, efficiency3] #end define def GetDbUsage(self): @@ -2763,7 +2782,7 @@ def GetDbUsage(self): #end define def GetDbSize(self, exceptions="log"): - local.AddLog("start GetDbSize function", "debug") + local.add_log("start GetDbSize function", "debug") exceptions = exceptions.split() totalSize = 0 path = "/var/ton-work/" @@ -2780,7 +2799,7 @@ def GetDbSize(self, exceptions="log"): #end define def Result2List(self, text): - buff = Pars(text, "result:", "\n") + buff = parse(text, "result:", "\n") if buff is None or "error" in buff: return buff = buff.replace(')', ']') @@ -2914,8 +2933,18 @@ def GetItemFromDict(self, data, search): return None #end define + def GetDomainFromAuction(self, walletName, addr): + wallet = self.GetLocalWallet(walletName) + bocPath = local.buffer.my_temp_dir + "get_dns_data.boc" + bocData = bytes.fromhex("b5ee9c7241010101000e0000182fcb26a20000000000000000f36cae4d") + with open(bocPath, 'wb') as file: + file.write(bocData) + resultFilePath = self.SignBocWithWallet(wallet, bocPath, addr, 0.1) + self.SendFile(resultFilePath, wallet) + #end define + def NewDomain(self, domain): - local.AddLog("start NewDomain function", "debug") + local.add_log("start NewDomain function", "debug") domainName = domain["name"] buff = domainName.split('.') subdomain = buff.pop(0) @@ -2934,7 +2963,7 @@ def NewDomain(self, domain): fileName = self.tempDir + "dns-msg-body.boc" args = ["auto-dns.fif", dnsAddr, "add", subdomain, expireInSec, "owner", wallet.addrB64, "cat", catId, "adnl", domain["adnlAddr"], "-o", fileName] result = self.fift.Run(args) - resultFilePath = Pars(result, "Saved to file ", ')') + resultFilePath = parse(result, "Saved to file ", ')') resultFilePath = self.SignBocWithWallet(wallet, resultFilePath, dnsAddr, 1.7) self.SendFile(resultFilePath, wallet) self.AddDomain(domain) @@ -2945,7 +2974,7 @@ def AddDomain(self, domain): local.db["domains"] = list() #end if local.db["domains"].append(domain) - local.dbSave() + local.save() #end define def GetDomains(self): @@ -2969,7 +2998,7 @@ def DeleteDomain(self, domainName): for domain in domains: if (domainName == domain.get("name")): domains.remove(domain) - local.dbSave() + local.save() return raise Exception("DeleteDomain error: Domain not found") #end define @@ -2985,7 +3014,7 @@ def GetAutoTransferRules(self): def AddAutoTransferRule(self, rule): autoTransferRules = self.GetAutoTransferRules() autoTransferRules.append(rule) - local.dbSave() + local.save() #end define def AddBookmark(self, bookmark): @@ -2993,7 +3022,7 @@ def AddBookmark(self, bookmark): local.db["bookmarks"] = list() #end if local.db["bookmarks"].append(bookmark) - local.dbSave() + local.save() #end define def GetBookmarks(self): @@ -3022,7 +3051,7 @@ def DeleteBookmark(self, name, type): bookmarkName = bookmark.get("name") if (type == bookmarkType and name == bookmarkName): bookmarks.remove(bookmark) - local.dbSave() + local.save() return raise Exception("DeleteBookmark error: Bookmark not found") #end define @@ -3042,7 +3071,7 @@ def WriteBookmarkData(self, bookmark): if endTime == 0: data = "free" else: - data = Timestamp2Datetime(endTime, "%d.%m.%Y") + data = timestamp2datetime(endTime, "%d.%m.%Y") else: data = "null" bookmark["data"] = data @@ -3063,7 +3092,7 @@ def AddSaveOffer(self, offer): saveOffers = self.GetSaveOffers() if offerHash not in saveOffers: saveOffers[offerHash] = offerPseudohash - local.dbSave() + local.save() #end define def GetVotedComplaints(self): @@ -3080,7 +3109,7 @@ def AddVotedComplaints(self, complaint): votedComplaints = self.GetVotedComplaints() if pseudohash not in votedComplaints: votedComplaints[pseudohash] = complaint - local.dbSave() + local.save() #end define def GetDestinationAddr(self, destination): @@ -3148,7 +3177,7 @@ def ParseAddrB64(self, addrB64): networkTestnet = self.IsTestnet() if testnet != networkTestnet: text = f"ParseAddrB64 warning: testnet flag do not match. Addr: {testnet}, Network: {networkTestnet}" - local.AddLog(text, "warning") + local.add_log(text, "warning") #end if # get wc and addr @@ -3231,7 +3260,7 @@ def GetStatistics(self, name, statistics=None): #end define def GetSettings(self, name): - local.dbLoad() + #local.load_db() result = local.db.get(name) return result #end define @@ -3241,7 +3270,7 @@ def SetSettings(self, name, data): data = json.loads(data) except: pass local.db[name] = data - local.dbSave() + local.save() #end define def Tlb2Json(self, text): @@ -3315,7 +3344,7 @@ def Tlb2Json(self, text): #end define def SignShardOverlayCert(self, adnl, pubkey): - local.AddLog("start SignShardOverlayCert function", "debug") + local.add_log("start SignShardOverlayCert function", "debug") fileName = self.tempDir + pubkey + ".cert" cmd = "signshardoverlaycert {workchain} {shardprefix} {pubkey} {expireat} {maxsize} {outfile}" cmd = cmd.format(workchain=-1, shardprefix=-9223372036854775808, pubkey=pubkey, expireat=172800, maxsize=8192, outfile=fileName) @@ -3337,7 +3366,7 @@ def SignShardOverlayCert(self, adnl, pubkey): #end define def ImportShardOverlayCert(self): - local.AddLog("start ImportShardOverlayCert function", "debug") + local.add_log("start ImportShardOverlayCert function", "debug") adnlAddr = self.GetAdnlAddr() pubkey = self.GetPubKey(adnlAddr) adnl = pubkey # adnl = adnlAddr @@ -3362,7 +3391,7 @@ def ImportShardOverlayCert(self): # Check certificate if cert is None: - local.AddLog("ImportShardOverlayCert warning: certificate not found", "warning") + local.add_log("ImportShardOverlayCert warning: certificate not found", "warning") return #end if @@ -3374,7 +3403,7 @@ def ImportShardOverlayCert(self): #end define def ImportCertificate(self, pubkey, fileName): - local.AddLog("start ImportCertificate function", "debug") + local.add_log("start ImportCertificate function", "debug") cmd = "importshardoverlaycert {workchain} {shardprefix} {pubkey} {certfile}" cmd = cmd.format(workchain=-1, shardprefix=-9223372036854775808, pubkey=pubkey, certfile=fileName) result = self.validatorConsole.Run(cmd) @@ -3390,7 +3419,7 @@ def GetValidatorsWalletsList(self): #end define def DownloadContract(self, url, branch=None): - local.AddLog("start DownloadContract function", "debug") + local.add_log("start DownloadContract function", "debug") buff = url.split('/') gitPath = self.contractsDir + buff[-1] + '/' @@ -3422,7 +3451,7 @@ def DownloadContract(self, url, branch=None): #end define def CreatePool(self, poolName, validatorRewardSharePercent, maxNominatorsCount, minValidatorStake, minNominatorStake): - local.AddLog("start CreatePool function", "debug") + local.add_log("start CreatePool function", "debug") validatorRewardShare = int(validatorRewardSharePercent * 100) contractPath = self.contractsDir + "nominator-pool/" if not os.path.isdir(contractPath): @@ -3431,7 +3460,7 @@ def CreatePool(self, poolName, validatorRewardSharePercent, maxNominatorsCount, filePath = self.poolsDir + poolName if os.path.isfile(filePath + ".addr"): - local.AddLog("CreatePool warning: Pool already exists: " + filePath, "warning") + local.add_log("CreatePool warning: Pool already exists: " + filePath, "warning") return #end if @@ -3453,7 +3482,7 @@ def CreatePool(self, poolName, validatorRewardSharePercent, maxNominatorsCount, #end define def ActivatePool(self, pool, ex=True): - local.AddLog("start ActivatePool function", "debug") + local.add_log("start ActivatePool function", "debug") for i in range(10): time.sleep(3) account = self.GetAccount(pool.addrB64) @@ -3466,7 +3495,7 @@ def ActivatePool(self, pool, ex=True): def DepositToPool(self, walletName, poolAddr, amount): wallet = self.GetLocalWallet(walletName) - bocPath = local.buffer.get("myTempDir") + wallet.name + "validator-deposit-query.boc" + bocPath = local.buffer.my_temp_dir + wallet.name + "validator-deposit-query.boc" fiftScript = self.contractsDir + "nominator-pool/func/validator-deposit.fif" args = [fiftScript, bocPath] result = self.fift.Run(args) @@ -3474,18 +3503,18 @@ def DepositToPool(self, walletName, poolAddr, amount): self.SendFile(resultFilePath, wallet) #end define - def WithdrawFromPool(self, walletName, poolAddr, amount): + def WithdrawFromPool(self, poolAddr, amount): poolData = self.GetPoolData(poolAddr) if poolData["state"] == 0: - self.WithdrawFromPoolProcess(walletName, poolAddr, amount) + self.WithdrawFromPoolProcess(poolAddr, amount) else: - self.PendWithdrawFromPool(walletName, poolAddr, amount) + self.PendWithdrawFromPool(poolAddr, amount) #end define - def WithdrawFromPoolProcess(self, walletName, poolAddr, amount): - local.AddLog("start WithdrawFromPoolProcess function", "debug") - wallet = self.GetLocalWallet(walletName) - bocPath = local.buffer.get("myTempDir") + wallet.name + "validator-withdraw-query.boc" + def WithdrawFromPoolProcess(self, poolAddr, amount): + local.add_log("start WithdrawFromPoolProcess function", "debug") + wallet = self.GetValidatorWallet() + bocPath = local.buffer.my_temp_dir + wallet.name + "validator-withdraw-query.boc" fiftScript = self.contractsDir + "nominator-pool/func/validator-withdraw.fif" args = [fiftScript, amount, bocPath] result = self.fift.Run(args) @@ -3493,16 +3522,16 @@ def WithdrawFromPoolProcess(self, walletName, poolAddr, amount): self.SendFile(resultFilePath, wallet) #end define - def PendWithdrawFromPool(self, walletName, poolAddr, amount): - local.AddLog("start PendWithdrawFromPool function", "debug") + def PendWithdrawFromPool(self, poolAddr, amount): + local.add_log("start PendWithdrawFromPool function", "debug") pendingWithdraws = self.GetPendingWithdraws() - pendingWithdraws[poolAddr] = (walletName, amount) - local.dbSave() + pendingWithdraws[poolAddr] = amount + local.save() #end define def HandlePendingWithdraw(self, pendingWithdraws, poolAddr): - walletName, amount = pendingWithdraws.get(poolAddr) - self.WithdrawFromPoolProcess(walletName, poolAddr, amount) + amount = pendingWithdraws.get(poolAddr) + self.WithdrawFromPoolProcess(poolAddr, amount) pendingWithdraws.pop(poolAddr) #end define @@ -3515,29 +3544,29 @@ def GetPendingWithdraws(self): return pendingWithdraws #end define - def SignElectionRequestWithPool(self, pool, startWorkTime, adnlAddr, validatorPubkey_b64, validatorSignature, maxFactor, stake): - local.AddLog("start SignElectionRequestWithPool function", "debug") + def SignElectionRequestWithPoolWithValidator(self, pool, startWorkTime, adnlAddr, validatorPubkey_b64, validatorSignature, maxFactor, stake): + local.add_log("start SignElectionRequestWithPoolWithValidator function", "debug") fileName = self.tempDir + str(startWorkTime) + "_validator-query.boc" fiftScript = self.contractsDir + "nominator-pool/func/validator-elect-signed.fif" args = [fiftScript, pool.addrB64, startWorkTime, maxFactor, adnlAddr, validatorPubkey_b64, validatorSignature, fileName, stake] result = self.fift.Run(args) - pubkey = Pars(result, "validator public key ", '\n') - fileName = Pars(result, "Saved to file ", '\n') + pubkey = parse(result, "validator public key ", '\n') + fileName = parse(result, "Saved to file ", '\n') return pubkey, fileName #end define def PoolProcessRecoverStake(self): - local.AddLog("start PoolProcessRecoverStake function", "debug") + local.add_log("start PoolProcessRecoverStake function", "debug") resultFilePath = self.tempDir + "recover-query.boc" fiftScript = self.contractsDir + "nominator-pool/func/recover-stake.fif" args = [fiftScript, resultFilePath] result = self.fift.Run(args) - resultFilePath = Pars(result, "Saved to file ", '\n') + resultFilePath = parse(result, "Saved to file ", '\n') return resultFilePath #end define def GetLocalPool(self, poolName): - local.AddLog("start GetLocalPool function", "debug") + local.add_log("start GetLocalPool function", "debug") if poolName is None: return None filePath = self.poolsDir + poolName @@ -3553,7 +3582,7 @@ def GetLocalPool(self, poolName): #end define def GetPoolsNameList(self): - local.AddLog("start GetPoolsNameList function", "debug") + local.add_log("start GetPoolsNameList function", "debug") poolsNameList = list() for fileName in os.listdir(self.poolsDir): if fileName.endswith(".addr"): @@ -3564,7 +3593,7 @@ def GetPoolsNameList(self): #end define def GetPools(self): - local.AddLog("start GetPools function", "debug") + local.add_log("start GetPools function", "debug") pools = list() poolsNameList = self.GetPoolsNameList() for poolName in poolsNameList: @@ -3589,7 +3618,7 @@ def GetPoolLastSentStakeTime(self, addrB64): #end define def IsPoolReadyToStake(self, addrB64): - now = GetTimestamp() + now = get_timestamp() config15 = self.GetConfig15() lastSentStakeTime = self.GetPoolLastSentStakeTime(addrB64) stakeFreezeDelay = config15["validatorsElectedFor"] + config15["stakeHeldFor"] @@ -3605,7 +3634,7 @@ def IsPoolReadyToVote(self, addrB64): #end define def GetPoolData(self, addrB64): - local.AddLog("start GetPoolData function", "debug") + local.add_log("start GetPoolData function", "debug") cmd = f"runmethodfull {addrB64} get_pool_data" result = self.liteClient.Run(cmd) data = self.Result2List(result) @@ -4034,7 +4063,7 @@ def GetNetworkName(self): #end define def GetFunctionBuffer(self, name, timeout=10): - timestamp = GetTimestamp() + timestamp = get_timestamp() buff = local.buffer.get(name) if buff is None: return @@ -4048,7 +4077,7 @@ def GetFunctionBuffer(self, name, timeout=10): def SetFunctionBuffer(self, name, data): buff = dict() - buff["time"] = GetTimestamp() + buff["time"] = get_timestamp() buff["data"] = data local.buffer[name] = buff #end define @@ -4093,209 +4122,6 @@ def IsHash(self, inputHash): #end define #end class -class TonBlocksScanner(): - def __init__(self, ton, **kwargs): - self.ton = ton - self.prevMasterBlock = None - self.prevShardsBlock = dict() - self.blocksNum = 0 - self.transNum = 0 - self.nbr = kwargs.get("nbr") #NewBlockReaction - self.ntr = kwargs.get("ntr") #NewTransReaction - self.nmr = kwargs.get("nmr") #NewMessageReaction - self.local = kwargs.get("local") - self.sync = kwargs.get("sync", False) - self.delay = 0 - self.working = False - self.closing = False - #end define - - def Run(self): - self.StartThread(self.ScanBlocks, args=()) - self.StartThread(self.ThreadBalancing, args=()) - self.StartThread(self.StatusReading, args=()) - #end define - - def StartThread(self, func, args): - threading.Thread(target=func, args=args, name=func.__name__, daemon=True).start() - #end define - - def StartWithMode(self, func, args): - if self.sync: - func(*args) - else: - self.StartThread(func, args) - #end define - - def AddLog(self, text, type): - if self.local: - self.local.AddLog(text, type) - else: - print(text) - #end define - - def Try(self, func, **kwargs): - args = kwargs.get("args", tuple()) - for step in range(10): - time.sleep(step) - try: - result = func(*args) - return result - except Exception as ex: - err = ex - text = f"{func.__name__} step: {step}, error: {err}" - self.AddLog(text, "error") - raise Exception(err) - #end define - - def SetStartBlock(self, workchain, shardchain, seqno): - workchainType = type(workchain) - shardchainType = type(shardchain) - seqnoType = type(seqno) - if workchainType != int: - raise Exception(f"SetStartBlock error: workchain type mast be int, not {workchainType}") - if shardchainType != str: - raise Exception(f"SetStartBlock error: shardchain type mast be str, not {shardchainType}") - if seqnoType != int: - raise Exception(f"SetStartBlock error: seqno type mast be int, not {seqnoType}") - #end if - - block = Block() - block.workchain = workchain - block.shardchain = shardchain - block.seqno = seqno - if workchain == -1: - self.prevMasterBlock = block - else: - self.SetShardPrevBlock(block) - self.sync = True - #end define - - def ThreadBalancing(self): - while True: - tnum = threading.active_count() - if tnum > 100: - self.delay += 0.1 - elif tnum > 50: - self.delay += 0.01 - elif tnum < 50: - self.delay -= 0.1 - elif tnum < 100: - self.delay -= 0.01 - if self.delay < 0: - self.delay = 0 - if self.closing is True: - exit() - time.sleep(0.1) - #end define - - def StatusReading(self): - while True: - validatorStatus = self.ton.GetValidatorStatus() - validatorOutOfSync = validatorStatus.get("outOfSync") - if self.ton.liteClient.pubkeyPath is None: - self.working = False - self.closing = True - text = "TonBlocksScanner error: local liteserver is not configured, stop thread." - self.AddLog(text, "error") - exit() - if validatorOutOfSync > 20: - self.working = False - text = f"TonBlocksScanner warning: local liteserver is out of sync: {validatorOutOfSync}." - self.AddLog(text, "warning") - else: - self.working = True - time.sleep(10) - #end define - - def ScanBlocks(self): - while True: - if self.working is True: - self.ScanBlock() - if self.closing is True: - exit() - time.sleep(1) - #end define - - def ScanBlock(self): - block = self.Try(self.ton.GetLastBlock) - self.StartThread(self.SearchMissBlocks, args=(block, self.prevMasterBlock)) - if block != self.prevMasterBlock: - self.StartWithMode(self.ReadBlock, args=(block,)) - self.prevMasterBlock = block - #end define - - def ReadBlock(self, block): - self.StartWithMode(self.NewBlockReaction, args=(block,)) - shards = self.Try(self.ton.GetShards, args=(block,)) - for shard in shards: - self.StartThread(self.ReadShard, args=(shard,)) - #end define - - def ReadShard(self, shard): - block = shard.get("block") - prevBlock = self.GetShardPrevBlock(block.shardchain) - self.StartThread(self.SearchMissBlocks, args=(block, prevBlock)) - if block != prevBlock: - self.StartWithMode(self.NewBlockReaction, args=(block,)) - self.SetShardPrevBlock(block) - #end define - - def SearchMissBlocks(self, block, prevBlock): - if prevBlock is None: - return - diff = block.seqno - prevBlock.seqno - #for i in range(1, diff): - for i in range(diff-1, 0, -1): - workchain = block.workchain - shardchain = block.shardchain - seqno = block.seqno - i - self.StartWithMode(self.SearchBlock, args=(workchain, shardchain, seqno)) - #end define - - def SearchBlock(self, workchain, shardchain, seqno): - if self.delay != 0: - time.sleep(self.delay) - block = self.Try(self.ton.GetBlock, args=(workchain, shardchain, seqno)) - self.StartWithMode(self.NewBlockReaction, args=(block,)) - #end define - - def GetShardPrevBlock(self, shardchain): - prevBlock = self.prevShardsBlock.get(shardchain) - return prevBlock - #end define - - def SetShardPrevBlock(self, prevBlock): - self.prevShardsBlock[prevBlock.shardchain] = prevBlock - #end define - - def NewBlockReaction(self, block): - #print(f"{bcolors.green} block: {bcolors.endc} {block}") - self.blocksNum += 1 - if self.nbr: - self.StartThread(self.nbr, args=(block,)) - transactions = self.Try(self.ton.GetTransactions, args=(block,)) - for trans in transactions: - self.StartWithMode(self.NewTransReaction, args=(trans,)) - #end define - - def NewTransReaction(self, trans): - #print(f"{bcolors.magenta} trans: {bcolors.endc} {self.transNum}", "debug") - self.transNum += 1 - if self.ntr: - self.StartThread(self.ntr, args=(trans,)) - messageList = self.Try(self.ton.GetTrans, args=(trans,)) - for message in messageList: - self.NewMessageReaction(message) - #end define - - def NewMessageReaction(self, message): - if self.nmr: - self.StartThread(self.nmr, args=(message,)) - #print(f"{bcolors.yellow} message: {bcolors.endc} {message}") - #end define -#end class - def ng2g(ng): if ng is None: return @@ -4310,18 +4136,19 @@ def Init(): Event(eventName) #end if - local.Run() + local.run() # statistics - local.buffer["transData"] = dict() - local.buffer["network"] = [None]*15*6 - local.buffer["diskio"] = [None]*15*6 + local.buffer.blocksData = dict() + local.buffer.transData = dict() + local.buffer.network = [None]*15*6 + local.buffer.diskio = [None]*15*6 # scan blocks - local.buffer["masterBlocksList"] = list() - local.buffer["prevShardsBlock"] = dict() - local.buffer["blocksNum"] = 0 - local.buffer["transNum"] = 0 + local.buffer.masterBlocksList = list() + local.buffer.prevShardsBlock = dict() + local.buffer.blocksNum = 0 + local.buffer.transNum = 0 #end define def Event(eventName): @@ -4329,11 +4156,11 @@ def Event(eventName): EnableVcEvent() elif eventName == "validator down": ValidatorDownEvent() - local.Exit() + local.exit() #end define def EnableVcEvent(): - local.AddLog("start EnableVcEvent function", "debug") + local.add_log("start EnableVcEvent function", "debug") # Создать новый кошелек для валидатора ton = MyTonCore() wallet = ton.CreateWallet("validator_wallet_001", -1) @@ -4345,12 +4172,12 @@ def EnableVcEvent(): local.db["adnlAddr"] = adnlAddr # Сохранить - local.dbSave() + local.save() #end define def ValidatorDownEvent(): - local.AddLog("start ValidatorDownEvent function", "debug") - local.AddLog("Validator is down", "error") + local.add_log("start ValidatorDownEvent function", "debug") + local.add_log("Validator is down", "error") #end define def Elections(ton): @@ -4369,17 +4196,17 @@ def Elections(ton): ton.ElectionEntry() #end define -def Statistics(scanner): +def Statistics(): ReadNetworkData() SaveNetworkStatistics() - ReadTransData(scanner) + #ReadTransData(scanner) SaveTransStatistics() ReadDiskData() SaveDiskStatistics() #end define def ReadDiskData(): - timestamp = GetTimestamp() + timestamp = get_timestamp() disks = GetDisksList() buff = psutil.disk_io_counters(perdisk=True) data = dict() @@ -4393,12 +4220,12 @@ def ReadDiskData(): data[name]["writeCount"] = buff[name].write_count #end for - local.buffer["diskio"].pop(0) - local.buffer["diskio"].append(data) + local.buffer.diskio.pop(0) + local.buffer.diskio.append(data) #end define def SaveDiskStatistics(): - data = local.buffer["diskio"] + data = local.buffer.diskio data = data[::-1] zerodata = data[0] buff1 = data[1*6-1] @@ -4468,24 +4295,23 @@ def GetDisksList(): #end define def ReadNetworkData(): - timestamp = GetTimestamp() - interfaceName = GetInternetInterfaceName() + timestamp = get_timestamp() + interfaceName = get_internet_interface_name() buff = psutil.net_io_counters(pernic=True) buff = buff[interfaceName] data = dict() - data = dict() data["timestamp"] = timestamp data["bytesRecv"] = buff.bytes_recv data["bytesSent"] = buff.bytes_sent data["packetsSent"] = buff.packets_sent data["packetsRecv"] = buff.packets_recv - local.buffer["network"].pop(0) - local.buffer["network"].append(data) + local.buffer.network.pop(0) + local.buffer.network.append(data) #end define def SaveNetworkStatistics(): - data = local.buffer["network"] + data = local.buffer.network data = data[::-1] zerodata = data[0] buff1 = data[1*6-1] @@ -4530,7 +4356,7 @@ def CalculateNetworkStatistics(zerodata, data): #end define def ReadTransData(scanner): - transData = local.buffer.get("transData") + transData = local.buffer.transData SetToTimeData(transData, scanner.transNum) ShortTimeData(transData) #end define @@ -4585,13 +4411,13 @@ def GetItemFromTimeData(data, timeneed): def GetTps(timediff): - data = local.buffer["transData"] + data = local.buffer.transData tps = GetDataPerSecond(data, timediff) return tps #end define def GetBps(timediff): - data = local.buffer["blocksData"] + data = local.buffer.blocksData bps = GetDataPerSecond(data, timediff) return bps #end define @@ -4646,7 +4472,9 @@ def GetSwapInfo(): #end define def GetValidatorProcessInfo(): - pid = GetServicePid("validator") + pid = get_service_pid("validator") + if pid == None or pid == 0: + return p = psutil.Process(pid) mem = p.memory_info() result = dict() @@ -4675,7 +4503,7 @@ def Telemetry(ton): data["adnlAddr"] = ton.GetAdnlAddr() data["validatorStatus"] = ton.GetValidatorStatus() data["cpuNumber"] = psutil.cpu_count() - data["cpuLoad"] = GetLoadAvg() + data["cpuLoad"] = get_load_avg() data["netLoad"] = ton.GetStatistics("netLoadAvg") data["tps"] = ton.GetStatistics("tpsAvg") data["disksLoad"] = ton.GetStatistics("disksLoadAvg") @@ -4687,16 +4515,20 @@ def Telemetry(ton): data["swap"] = GetSwapInfo() data["uname"] = GetUname() data["vprocess"] = GetValidatorProcessInfo() - elections = local.TryFunction(ton.GetElectionEntries) - complaints = local.TryFunction(ton.GetComplaints) + elections = local.try_function(ton.GetElectionEntries) + complaints = local.try_function(ton.GetComplaints) # Get git hashes gitHashes = dict() - gitHashes["mytonctrl"] = GetGitHash("/usr/src/mytonctrl") + gitHashes["mytonctrl"] = get_git_hash("/usr/src/mytonctrl") gitHashes["validator"] = GetBinGitHash("/usr/bin/ton/validator-engine/validator-engine") data["gitHashes"] = gitHashes data["stake"] = local.db.get("stake") + # Get validator config + vconfig = ton.GetValidatorConfig() + data["fullnode_adnl"] = vconfig.fullnode + # Send data to toncenter server liteUrl_default = "https://telemetry.toncenter.com/report_status" liteUrl = local.db.get("telemetryLiteUrl", liteUrl_default) @@ -4704,7 +4536,7 @@ def Telemetry(ton): resp = requests.post(liteUrl, data=output, timeout=3) #end define -def GetBinGitHash(path): +def GetBinGitHash(path, short=False): if not os.path.isfile(path): return args = [path, "--version"] @@ -4715,6 +4547,8 @@ def GetBinGitHash(path): buff = output.split(' ') start = buff.index("Commit:") + 1 result = buff[start].replace(',', '') + if short is True: + result = result[:7] return result #end define @@ -4761,15 +4595,15 @@ def Slashing(ton): #end if # Creating complaints - slashTime = local.buffer.get("slashTime") + slash_time = local.buffer.slash_time config32 = ton.GetConfig32() start = config32.get("startWorkTime") end = config32.get("endWorkTime") - local.AddLog("slashTime {}, start {}, end {}".format(slashTime, start, end), "debug") - if slashTime != start: + local.add_log("slash_time {}, start {}, end {}".format(slash_time, start, end), "debug") + if slash_time != start: end -= 60 ton.CheckValidators(start, end) - local.buffer["slashTime"] = start + local.buffer.slash_time = start #end define def ScanLiteServers(ton): @@ -4795,22 +4629,20 @@ def ScanLiteServers(ton): #end define def General(): - local.AddLog("start General function", "debug") + local.add_log("start General function", "debug") ton = MyTonCore() - scanner = TonBlocksScanner(ton, local=local) - #scanner.Run() # Запустить потоки - local.StartCycle(Elections, sec=600, args=(ton, )) - local.StartCycle(Statistics, sec=10, args=(scanner,)) - local.StartCycle(Offers, sec=600, args=(ton, )) - local.StartCycle(Complaints, sec=600, args=(ton, )) - local.StartCycle(Slashing, sec=600, args=(ton, )) - local.StartCycle(Domains, sec=600, args=(ton, )) - local.StartCycle(Telemetry, sec=60, args=(ton, )) - local.StartCycle(OverlayTelemetry, sec=7200, args=(ton, )) - local.StartCycle(ScanLiteServers, sec=60, args=(ton,)) - Sleep() + local.start_cycle(Elections, sec=600, args=(ton, )) + local.start_cycle(Statistics, sec=10) + local.start_cycle(Offers, sec=600, args=(ton, )) + local.start_cycle(Complaints, sec=600, args=(ton, )) + local.start_cycle(Slashing, sec=600, args=(ton, )) + local.start_cycle(Domains, sec=600, args=(ton, )) + local.start_cycle(Telemetry, sec=60, args=(ton, )) + local.start_cycle(OverlayTelemetry, sec=7200, args=(ton, )) + local.start_cycle(ScanLiteServers, sec=60, args=(ton,)) + thr_sleep() #end define def Dec2HexAddr(dec): diff --git a/mytonctrl.py b/mytonctrl.py index 33cb5596..36267433 100755 --- a/mytonctrl.py +++ b/mytonctrl.py @@ -12,76 +12,77 @@ def Init(argv): # Load translate table - local.InitTranslator(local.buffer.get("myDir") + "translate.json") + local.init_translator(local.buffer.my_dir + "translate.json") # Create user console console.name = "MyTonCtrl" console.startFunction = PreUp - console.AddItem("update", Update, local.Translate("update_cmd")) - console.AddItem("upgrade", Upgrade, local.Translate("upgrade_cmd")) - console.AddItem("installer", Installer, local.Translate("installer_cmd")) - console.AddItem("status", PrintStatus, local.Translate("status_cmd")) - console.AddItem("seqno", Seqno, local.Translate("seqno_cmd")) - console.AddItem("getconfig", GetConfig, local.Translate("getconfig_cmd")) - - console.AddItem("nw", CreatNewWallet, local.Translate("nw_cmd")) - console.AddItem("aw", ActivateWallet, local.Translate("aw_cmd")) - console.AddItem("wl", PrintWalletsList, local.Translate("wl_cmd")) - console.AddItem("iw", ImportWallet, local.Translate("iw_cmd")) - console.AddItem("swv", SetWalletVersion, local.Translate("swv_cmd")) - console.AddItem("ew", ExportWallet, local.Translate("ex_cmd")) - console.AddItem("dw", DeleteWallet, local.Translate("dw_cmd")) - - console.AddItem("vas", ViewAccountStatus, local.Translate("vas_cmd")) - console.AddItem("vah", ViewAccountHistory, local.Translate("vah_cmd")) - console.AddItem("mg", MoveCoins, local.Translate("mg_cmd")) - console.AddItem("mgtp", MoveCoinsThroughProxy, local.Translate("mgtp_cmd")) - - console.AddItem("nb", CreatNewBookmark, local.Translate("nb_cmd")) - console.AddItem("bl", PrintBookmarksList, local.Translate("bl_cmd")) - console.AddItem("db", DeleteBookmark, local.Translate("db_cmd")) - - console.AddItem("nd", NewDomain, local.Translate("nd_cmd")) - console.AddItem("dl", PrintDomainsList, local.Translate("dl_cmd")) - console.AddItem("vds", ViewDomainStatus, local.Translate("vds_cmd")) - console.AddItem("dd", DeleteDomain, local.Translate("dd_cmd")) - - console.AddItem("ol", PrintOffersList, local.Translate("ol_cmd")) - console.AddItem("vo", VoteOffer, local.Translate("vo_cmd")) - console.AddItem("od", OfferDiff, local.Translate("od_cmd")) - - console.AddItem("el", PrintElectionEntriesList, local.Translate("el_cmd")) - console.AddItem("ve", VoteElectionEntry, local.Translate("ve_cmd")) - console.AddItem("vl", PrintValidatorList, local.Translate("vl_cmd")) - console.AddItem("cl", PrintComplaintsList, local.Translate("cl_cmd")) - console.AddItem("vc", VoteComplaint, local.Translate("vc_cmd")) - - console.AddItem("get", GetSettings, local.Translate("get_cmd")) - console.AddItem("set", SetSettings, local.Translate("set_cmd")) - console.AddItem("xrestart", Xrestart, local.Translate("xrestart_cmd")) - console.AddItem("xlist", Xlist, local.Translate("xlist_cmd")) - - console.AddItem("new_pool", NewPool, local.Translate("new_pool_cmd")) - console.AddItem("pools_list", PrintPoolsList, local.Translate("pools_list_cmd")) - console.AddItem("get_pool_data", GetPoolData, local.Translate("get_pool_data_cmd")) - console.AddItem("activate_pool", ActivatePool, local.Translate("activate_pool_cmd")) - console.AddItem("deposit_to_pool", DepositToPool, local.Translate("deposit_to_pool_cmd")) - console.AddItem("withdraw_from_pool", WithdrawFromPool, local.Translate("withdraw_from_pool_cmd")) - console.AddItem("delete_pool", DeletePool, local.Translate("delete_pool_cmd")) + console.AddItem("update", Update, local.translate("update_cmd")) + console.AddItem("upgrade", Upgrade, local.translate("upgrade_cmd")) + console.AddItem("installer", Installer, local.translate("installer_cmd")) + console.AddItem("status", PrintStatus, local.translate("status_cmd")) + console.AddItem("seqno", Seqno, local.translate("seqno_cmd")) + console.AddItem("getconfig", GetConfig, local.translate("getconfig_cmd")) + + console.AddItem("nw", CreatNewWallet, local.translate("nw_cmd")) + console.AddItem("aw", ActivateWallet, local.translate("aw_cmd")) + console.AddItem("wl", PrintWalletsList, local.translate("wl_cmd")) + console.AddItem("iw", ImportWallet, local.translate("iw_cmd")) + console.AddItem("swv", SetWalletVersion, local.translate("swv_cmd")) + console.AddItem("ew", ExportWallet, local.translate("ex_cmd")) + console.AddItem("dw", DeleteWallet, local.translate("dw_cmd")) + + console.AddItem("vas", ViewAccountStatus, local.translate("vas_cmd")) + console.AddItem("vah", ViewAccountHistory, local.translate("vah_cmd")) + console.AddItem("mg", MoveCoins, local.translate("mg_cmd")) + console.AddItem("mgtp", MoveCoinsThroughProxy, local.translate("mgtp_cmd")) + + console.AddItem("nb", CreatNewBookmark, local.translate("nb_cmd")) + console.AddItem("bl", PrintBookmarksList, local.translate("bl_cmd")) + console.AddItem("db", DeleteBookmark, local.translate("db_cmd")) + + console.AddItem("nd", NewDomain, local.translate("nd_cmd")) + console.AddItem("dl", PrintDomainsList, local.translate("dl_cmd")) + console.AddItem("vds", ViewDomainStatus, local.translate("vds_cmd")) + console.AddItem("dd", DeleteDomain, local.translate("dd_cmd")) + console.AddItem("gdfa", GetDomainFromAuction, local.translate("gdfa_cmd")) + + console.AddItem("ol", PrintOffersList, local.translate("ol_cmd")) + console.AddItem("vo", VoteOffer, local.translate("vo_cmd")) + console.AddItem("od", OfferDiff, local.translate("od_cmd")) + + console.AddItem("el", PrintElectionEntriesList, local.translate("el_cmd")) + console.AddItem("ve", VoteElectionEntry, local.translate("ve_cmd")) + console.AddItem("vl", PrintValidatorList, local.translate("vl_cmd")) + console.AddItem("cl", PrintComplaintsList, local.translate("cl_cmd")) + console.AddItem("vc", VoteComplaint, local.translate("vc_cmd")) + + console.AddItem("get", GetSettings, local.translate("get_cmd")) + console.AddItem("set", SetSettings, local.translate("set_cmd")) + console.AddItem("xrestart", Xrestart, local.translate("xrestart_cmd")) + console.AddItem("xlist", Xlist, local.translate("xlist_cmd")) + + console.AddItem("new_pool", NewPool, local.translate("new_pool_cmd")) + console.AddItem("pools_list", PrintPoolsList, local.translate("pools_list_cmd")) + console.AddItem("get_pool_data", GetPoolData, local.translate("get_pool_data_cmd")) + console.AddItem("activate_pool", ActivatePool, local.translate("activate_pool_cmd")) + console.AddItem("deposit_to_pool", DepositToPool, local.translate("deposit_to_pool_cmd")) + console.AddItem("withdraw_from_pool", WithdrawFromPool, local.translate("withdraw_from_pool_cmd")) + console.AddItem("delete_pool", DeletePool, local.translate("delete_pool_cmd")) - console.AddItem("create_controllers", CreateControllers, local.Translate("_")) - console.AddItem("update_controllers", CreateControllers, local.Translate("_")) - console.AddItem("controllers_list", PrintControllersList, local.Translate("_")) - console.AddItem("get_controller_data", GetControllerData, local.Translate("_")) - console.AddItem("deposit_to_controller", DepositToController, local.Translate("_")) - console.AddItem("withdraw_from_controller", WithdrawFromController, local.Translate("_")) - console.AddItem("calculate_annual_controller_percentage", CalculateAnnualControllerPercentage, local.Translate("_")) - console.AddItem("controller_update_validator_set", ControllerUpdateValidatorSet, local.Translate("_")) - console.AddItem("stop_controller", StopController, local.Translate("_")) - console.AddItem("stop_and_withdraw_controller", StopAndWithdrawController, local.Translate("_")) - console.AddItem("add_controller", AddController, local.Translate("_")) - console.AddItem("check_liquid_pool", CheckLiquidPool, local.Translate("_")) + console.AddItem("create_controllers", CreateControllers, local.translate("_")) + console.AddItem("update_controllers", CreateControllers, local.translate("_")) + console.AddItem("controllers_list", PrintControllersList, local.translate("_")) + console.AddItem("get_controller_data", GetControllerData, local.translate("_")) + console.AddItem("deposit_to_controller", DepositToController, local.translate("_")) + console.AddItem("withdraw_from_controller", WithdrawFromController, local.translate("_")) + console.AddItem("calculate_annual_controller_percentage", CalculateAnnualControllerPercentage, local.translate("_")) + console.AddItem("controller_update_validator_set", ControllerUpdateValidatorSet, local.translate("_")) + console.AddItem("stop_controller", StopController, local.translate("_")) + console.AddItem("stop_and_withdraw_controller", StopAndWithdrawController, local.translate("_")) + console.AddItem("add_controller", AddController, local.translate("_")) + console.AddItem("check_liquid_pool", CheckLiquidPool, local.translate("_")) # Process input parameters @@ -109,13 +110,14 @@ def Init(argv): ton.walletsDir = wallets #end for - local.db["config"]["logLevel"] = "debug" - local.db["config"]["isLocaldbSaving"] = True - local.Run() + local.db.config.logLevel = "debug" + local.db.config.isLocaldbSaving = False + local.run() #end define def PreUp(): CheckMytonctrlUpdate() + check_vport() # CheckTonUpdate() usePool = ton.GetSettings("usePool") useController = ton.GetSettings("useController") @@ -134,6 +136,52 @@ def GetItemFromList(data, index): except: pass #end define +def check_vport(): + vconfig = ton.GetValidatorConfig() + addr = vconfig.addrs.pop() + ip = int2ip(addr.ip) + with socket.socket(socket.AF_INET, socket.SOCK_DGRAM) as client_socket: + result = client_socket.connect_ex((ip, addr.port)) + if result != 0: + color_print(local.translate("vport_error")) +#end define + +def check_git(input_args, default_repo, text): + src_dir = "/usr/src" + git_path = f"{src_dir}/{default_repo}" + default_author = "ton-blockchain" + default_branch = "master" + + # Get author, repo, branch + local_author, local_repo = get_git_author_and_repo(git_path) + local_branch = get_git_branch(git_path) + + # Set author, repo, branch + data = GetAuthorRepoBranchFromArgs(input_args) + need_author = data.get("author") + need_repo = data.get("repo") + need_branch = data.get("branch") + + # Check if remote repo is different from default + if ((need_author is None and local_author != default_author) or + (need_repo is None and local_repo != default_repo)): + remote_url = f"https://github.com/{local_author}/{local_repo}/tree/{need_branch if need_branch else local_branch}" + raise Exception(f"{text} error: You are on {remote_url} remote url, to {text} to the tip use `{text} {remote_url}` command") + elif need_branch is None and local_branch != default_branch: + raise Exception(f"{text} error: You are on {local_branch} branch, to {text} to the tip of {local_branch} branch use `{text} {local_branch}` command") + #end if + + if need_author is None: + need_author = local_author + if need_repo is None: + need_repo = local_repo + if need_branch is None: + need_branch = local_branch + #end if + + return need_author, need_repo, need_branch +#end define + def GetAuthorRepoBranchFromArgs(args): data = dict() arg1 = GetItemFromList(args, 0) @@ -155,76 +203,65 @@ def GetAuthorRepoBranchFromArgs(args): #end define def Update(args): - # add safe directory to git - gitPath = "/usr/src/mytonctrl" - subprocess.run(["git", "config", "--global", "--add", "safe.directory", gitPath]) - - # Get author, repo, branch - author, repo = GetGitAuthorAndRepo(gitPath) - branch = GetGitBranch(gitPath) - - # Set author, repo, branch - data = GetAuthorRepoBranchFromArgs(args) - author = data.get("author", author) - repo = data.get("repo", repo) - branch = data.get("branch", branch) + repo = "mytonctrl" + author, repo, branch = check_git(args, repo, "update") # Run script runArgs = ["bash", "/usr/src/mytonctrl/scripts/update.sh", "-a", author, "-r", repo, "-b", branch] - exitCode = RunAsRoot(runArgs) + exitCode = run_as_root(runArgs) if exitCode == 0: text = "Update - {green}OK{endc}" else: text = "Update - {red}Error{endc}" - ColorPrint(text) - local.Exit() + color_print(text) + local.exit() #end define def Upgrade(args): - # add safe directory to git - gitPath = "/usr/src/ton" - subprocess.run(["git", "config", "--global", "--add", "safe.directory", gitPath]) - - # Get author, repo, branch - author, repo = GetGitAuthorAndRepo(gitPath) - branch = GetGitBranch(gitPath) - - # Set author, repo, branch - data = GetAuthorRepoBranchFromArgs(args) - author = data.get("author", author) - repo = data.get("repo", repo) - branch = data.get("branch", branch) + repo = "ton" + author, repo, branch = check_git(args, repo, "upgrade") + + # bugfix if the files are in the wrong place + liteClient = ton.GetSettings("liteClient") + configPath = liteClient.get("configPath") + pubkeyPath = liteClient.get("liteServer").get("pubkeyPath") + if "ton-lite-client-test1" in configPath: + liteClient["configPath"] = configPath.replace("lite-client/ton-lite-client-test1.config.json", "global.config.json") + if "/usr/bin/ton" in pubkeyPath: + liteClient["liteServer"]["pubkeyPath"] = "/var/ton-work/keys/liteserver.pub" + ton.SetSettings("liteClient", liteClient) + validatorConsole = ton.GetSettings("validatorConsole") + privKeyPath = validatorConsole.get("privKeyPath") + pubKeyPath = validatorConsole.get("pubKeyPath") + if "/usr/bin/ton" in privKeyPath: + validatorConsole["privKeyPath"] = "/var/ton-work/keys/client" + if "/usr/bin/ton" in pubKeyPath: + validatorConsole["pubKeyPath"] = "/var/ton-work/keys/server.pub" + ton.SetSettings("validatorConsole", validatorConsole) # Run script runArgs = ["bash", "/usr/src/mytonctrl/scripts/upgrade.sh", "-a", author, "-r", repo, "-b", branch] - exitCode = RunAsRoot(runArgs) + exitCode = run_as_root(runArgs) + exitCode += run_as_root(["python3", "/usr/src/mytonctrl/scripts/upgrade.py"]) if exitCode == 0: text = "Upgrade - {green}OK{endc}" else: text = "Upgrade - {red}Error{endc}" - ColorPrint(text) + color_print(text) #end define def CheckMytonctrlUpdate(): - gitPath = local.buffer.get("myDir") - result = CheckGitUpdate(gitPath) + git_path = local.buffer.my_dir + result = check_git_update(git_path) if result is True: - ColorPrint(local.Translate("mytonctrl_update_available")) + color_print(local.translate("mytonctrl_update_available")) #end define def CheckTonUpdate(): - gitPath = "/usr/src/ton" - result = CheckGitUpdate(gitPath) + git_path = "/usr/src/ton" + result = check_git_update(git_path) if result is True: - ColorPrint(local.Translate("ton_update_available")) -#end define - -def PrintTest(args): - print(json.dumps(local.buffer, indent=2)) -#end define - -def sl(args): - Slashing(ton) + color_print(local.translate("ton_update_available")) #end define def PrintStatus(args): @@ -238,9 +275,11 @@ def PrintStatus(args): totalValidators = config34["totalValidators"] onlineValidators = None validatorEfficiency = None + validatorEfficiency2 = None if opt != "fast": onlineValidators = ton.GetOnlineValidators() validatorEfficiency = ton.GetValidatorEfficiency() + validatorEfficiency2 = ton.GetValidatorEfficiency2() if onlineValidators: onlineValidators = len(onlineValidators) oldStartWorkTime = config36.get("startWorkTime") @@ -271,7 +310,7 @@ def PrintStatus(args): else: validatorAccount = None PrintTonStatus(startWorkTime, totalValidators, onlineValidators, shardsNumber, offersNumber, complaintsNumber, tpsAvg) - PrintLocalStatus(adnlAddr, validatorIndex, validatorEfficiency, validatorWallet, validatorAccount, validatorStatus, dbSize, dbUsage, memoryInfo, swapInfo, netLoadAvg, disksLoadAvg, disksLoadPercentAvg) + PrintLocalStatus(adnlAddr, validatorIndex, validatorEfficiency, validatorEfficiency2, validatorWallet, validatorAccount, validatorStatus, dbSize, dbUsage, memoryInfo, swapInfo, netLoadAvg, disksLoadAvg, disksLoadPercentAvg) PrintTonConfig(fullConfigAddr, fullElectorAddr, config15, config17) PrintTimes(rootWorkchainEnabledTime_int, startWorkTime, oldStartWorkTime, config15) #end define @@ -285,28 +324,28 @@ def PrintTonStatus(startWorkTime, totalValidators, onlineValidators, shardsNumbe allOffers = offersNumber.get("all") newComplaints = complaintsNumber.get("new") allComplaints = complaintsNumber.get("all") - tps1_text = bcolors.Green(tps1) - tps5_text = bcolors.Green(tps5) - tps15_text = bcolors.Green(tps15) - tps_text = local.Translate("ton_status_tps").format(tps1_text, tps5_text, tps15_text) + tps1_text = bcolors.green_text(tps1) + tps5_text = bcolors.green_text(tps5) + tps15_text = bcolors.green_text(tps15) + tps_text = local.translate("ton_status_tps").format(tps1_text, tps5_text, tps15_text) onlineValidators_text = GetColorInt(onlineValidators, border=allValidators*2/3, logic="more") - allValidators_text = bcolors.Yellow(allValidators) - validators_text = local.Translate("ton_status_validators").format(onlineValidators_text, allValidators_text) - shards_text = local.Translate("ton_status_shards").format(bcolors.Green(shardsNumber)) - newOffers_text = bcolors.Green(newOffers) - allOffers_text = bcolors.Yellow(allOffers) - offers_text = local.Translate("ton_status_offers").format(newOffers_text, allOffers_text) - newComplaints_text = bcolors.Green(newComplaints) - allComplaints_text = bcolors.Yellow(allComplaints) - complaints_text = local.Translate("ton_status_complaints").format(newComplaints_text, allComplaints_text) + allValidators_text = bcolors.yellow_text(allValidators) + validators_text = local.translate("ton_status_validators").format(onlineValidators_text, allValidators_text) + shards_text = local.translate("ton_status_shards").format(bcolors.green_text(shardsNumber)) + newOffers_text = bcolors.green_text(newOffers) + allOffers_text = bcolors.yellow_text(allOffers) + offers_text = local.translate("ton_status_offers").format(newOffers_text, allOffers_text) + newComplaints_text = bcolors.green_text(newComplaints) + allComplaints_text = bcolors.yellow_text(allComplaints) + complaints_text = local.translate("ton_status_complaints").format(newComplaints_text, allComplaints_text) if startWorkTime == 0: - election_text = bcolors.Yellow("closed") + election_text = bcolors.yellow_text("closed") else: - election_text = bcolors.Green("open") - election_text = local.Translate("ton_status_election").format(election_text) + election_text = bcolors.green_text("open") + election_text = local.translate("ton_status_election").format(election_text) - ColorPrint(local.Translate("ton_status_head")) + color_print(local.translate("ton_status_head")) print(tps_text) print(validators_text) print(shards_text) @@ -316,13 +355,13 @@ def PrintTonStatus(startWorkTime, totalValidators, onlineValidators, shardsNumbe print() #end define -def PrintLocalStatus(adnlAddr, validatorIndex, validatorEfficiency, validatorWallet, validatorAccount, validatorStatus, dbSize, dbUsage, memoryInfo, swapInfo, netLoadAvg, disksLoadAvg, disksLoadPercentAvg): +def PrintLocalStatus(adnlAddr, validatorIndex, validatorEfficiency, validatorEfficiency2, validatorWallet, validatorAccount, validatorStatus, dbSize, dbUsage, memoryInfo, swapInfo, netLoadAvg, disksLoadAvg, disksLoadPercentAvg): if validatorWallet is None: return walletAddr = validatorWallet.addrB64 walletBalance = validatorAccount.balance cpuNumber = psutil.cpu_count() - loadavg = GetLoadAvg() + loadavg = get_load_avg() cpuLoad1 = loadavg[0] cpuLoad5 = loadavg[1] cpuLoad15 = loadavg[2] @@ -332,19 +371,21 @@ def PrintLocalStatus(adnlAddr, validatorIndex, validatorEfficiency, validatorWal validatorOutOfSync = validatorStatus.get("outOfSync") validatorIndex_text = GetColorInt(validatorIndex, 0, logic="more") - validatorIndex_text = local.Translate("local_status_validator_index").format(validatorIndex_text) + validatorIndex_text = local.translate("local_status_validator_index").format(validatorIndex_text) validatorEfficiency_text = GetColorInt(validatorEfficiency, 10, logic="more", ending=" %") - validatorEfficiency_text = local.Translate("local_status_validator_efficiency").format(validatorEfficiency_text) - adnlAddr_text = local.Translate("local_status_adnl_addr").format(bcolors.Yellow(adnlAddr)) - walletAddr_text = local.Translate("local_status_wallet_addr").format(bcolors.Yellow(walletAddr)) - walletBalance_text = local.Translate("local_status_wallet_balance").format(bcolors.Green(walletBalance)) + validatorEfficiency_text = local.translate("local_status_validator_efficiency").format(validatorEfficiency_text) + validatorEfficiency2_text = f"{bcolors.cyan}{validatorEfficiency2}{bcolors.endc}" + validatorEfficiency2_text = local.translate("local_status_validator_efficiency_ver2").format(validatorEfficiency2_text) + adnlAddr_text = local.translate("local_status_adnl_addr").format(bcolors.yellow_text(adnlAddr)) + walletAddr_text = local.translate("local_status_wallet_addr").format(bcolors.yellow_text(walletAddr)) + walletBalance_text = local.translate("local_status_wallet_balance").format(bcolors.green_text(walletBalance)) # CPU status - cpuNumber_text = bcolors.Yellow(cpuNumber) + cpuNumber_text = bcolors.yellow_text(cpuNumber) cpuLoad1_text = GetColorInt(cpuLoad1, cpuNumber, logic="less") cpuLoad5_text = GetColorInt(cpuLoad5, cpuNumber, logic="less") cpuLoad15_text = GetColorInt(cpuLoad15, cpuNumber, logic="less") - cpuLoad_text = local.Translate("local_status_cpu_load").format(cpuNumber_text, cpuLoad1_text, cpuLoad5_text, cpuLoad15_text) + cpuLoad_text = local.translate("local_status_cpu_load").format(cpuNumber_text, cpuLoad1_text, cpuLoad5_text, cpuLoad15_text) # Memory status ramUsage = memoryInfo.get("usage") @@ -359,20 +400,20 @@ def PrintLocalStatus(adnlAddr, validatorIndex, validatorEfficiency, validatorWal ramLoad_text = ramLoad_text.format(cyan=bcolors.cyan, default=bcolors.default, endc=bcolors.endc, data=ramUsage_text, percent=ramUsagePercent_text) swapLoad_text = "{cyan}swap:[{default}{data}, {percent}{cyan}]{endc}" swapLoad_text = swapLoad_text.format(cyan=bcolors.cyan, default=bcolors.default, endc=bcolors.endc, data=swapUsage_text, percent=swapUsagePercent_text) - memoryLoad_text = local.Translate("local_status_memory").format(ramLoad_text, swapLoad_text) + memoryLoad_text = local.translate("local_status_memory").format(ramLoad_text, swapLoad_text) # Network status netLoad1_text = GetColorInt(netLoad1, 300, logic="less") netLoad5_text = GetColorInt(netLoad5, 300, logic="less") netLoad15_text = GetColorInt(netLoad15, 300, logic="less") - netLoad_text = local.Translate("local_status_net_load").format(netLoad1_text, netLoad5_text, netLoad15_text) + netLoad_text = local.translate("local_status_net_load").format(netLoad1_text, netLoad5_text, netLoad15_text) # Disks status disksLoad_data = list() for key, item in disksLoadAvg.items(): - diskLoad1_text = bcolors.Green(item[0]) - diskLoad5_text = bcolors.Green(item[1]) - diskLoad15_text = bcolors.Green(item[2]) + diskLoad1_text = bcolors.green_text(item[0]) + diskLoad5_text = bcolors.green_text(item[1]) + diskLoad15_text = bcolors.green_text(item[2]) diskLoadPercent1_text = GetColorInt(disksLoadPercentAvg[key][0], 80, logic="less", ending="%") diskLoadPercent5_text = GetColorInt(disksLoadPercentAvg[key][1], 80, logic="less", ending="%") diskLoadPercent15_text = GetColorInt(disksLoadPercentAvg[key][2], 80, logic="less", ending="%") @@ -381,41 +422,43 @@ def PrintLocalStatus(adnlAddr, validatorIndex, validatorEfficiency, validatorWal disksLoad_buff = buff.format(diskLoad15_text, diskLoadPercent15_text) disksLoad_data.append(disksLoad_buff) disksLoad_data = ", ".join(disksLoad_data) - disksLoad_text = local.Translate("local_status_disks_load").format(disksLoad_data) + disksLoad_text = local.translate("local_status_disks_load").format(disksLoad_data) # Thread status - mytoncoreStatus_bool = GetServiceStatus("mytoncore") - validatorStatus_bool = GetServiceStatus("validator") - mytoncoreUptime = GetServiceUptime("mytoncore") - validatorUptime = GetServiceUptime("validator") - mytoncoreUptime_text = bcolors.Green(time2human(mytoncoreUptime)) - validatorUptime_text = bcolors.Green(time2human(validatorUptime)) + mytoncoreStatus_bool = get_service_status("mytoncore") + validatorStatus_bool = get_service_status("validator") + mytoncoreUptime = get_service_uptime("mytoncore") + validatorUptime = get_service_uptime("validator") + mytoncoreUptime_text = bcolors.green_text(time2human(mytoncoreUptime)) + validatorUptime_text = bcolors.green_text(time2human(validatorUptime)) mytoncoreStatus = GetColorStatus(mytoncoreStatus_bool) validatorStatus = GetColorStatus(validatorStatus_bool) - mytoncoreStatus_text = local.Translate("local_status_mytoncore_status").format(mytoncoreStatus, mytoncoreUptime_text) - validatorStatus_text = local.Translate("local_status_validator_status").format(validatorStatus, validatorUptime_text) - validatorOutOfSync_text = local.Translate("local_status_validator_out_of_sync").format(GetColorInt(validatorOutOfSync, 20, logic="less", ending=" s")) + mytoncoreStatus_text = local.translate("local_status_mytoncore_status").format(mytoncoreStatus, mytoncoreUptime_text) + validatorStatus_text = local.translate("local_status_validator_status").format(validatorStatus, validatorUptime_text) + validatorOutOfSync_text = local.translate("local_status_validator_out_of_sync").format(GetColorInt(validatorOutOfSync, 20, logic="less", ending=" s")) dbSize_text = GetColorInt(dbSize, 1000, logic="less", ending=" Gb") dbUsage_text = GetColorInt(dbUsage, 80, logic="less", ending="%") - dbStatus_text = local.Translate("local_status_db").format(dbSize_text, dbUsage_text) + dbStatus_text = local.translate("local_status_db").format(dbSize_text, dbUsage_text) # Mytonctrl and validator git hash mtcGitPath = "/usr/src/mytonctrl" validatorGitPath = "/usr/src/ton" - mtcGitHash = GetGitHash(mtcGitPath, short=True) - validatorGitHash = GetGitHash(validatorGitPath, short=True) - mtcGitBranch = GetGitBranch(mtcGitPath) - validatorGitBranch = GetGitBranch(validatorGitPath) - mtcGitHash_text = bcolors.Yellow(mtcGitHash) - validatorGitHash_text = bcolors.Yellow(validatorGitHash) - mtcGitBranch_text = bcolors.Yellow(mtcGitBranch) - validatorGitBranch_text = bcolors.Yellow(validatorGitBranch) - mtcVersion_text = local.Translate("local_status_version_mtc").format(mtcGitHash_text, mtcGitBranch_text) - validatorVersion_text = local.Translate("local_status_version_validator").format(validatorGitHash_text, validatorGitBranch_text) - - ColorPrint(local.Translate("local_status_head")) + validatorBinGitPath = "/usr/bin/ton/validator-engine/validator-engine" + mtcGitHash = get_git_hash(mtcGitPath, short=True) + validatorGitHash = GetBinGitHash(validatorBinGitPath, short=True) + mtcGitBranch = get_git_branch(mtcGitPath) + validatorGitBranch = get_git_branch(validatorGitPath) + mtcGitHash_text = bcolors.yellow_text(mtcGitHash) + validatorGitHash_text = bcolors.yellow_text(validatorGitHash) + mtcGitBranch_text = bcolors.yellow_text(mtcGitBranch) + validatorGitBranch_text = bcolors.yellow_text(validatorGitBranch) + mtcVersion_text = local.translate("local_status_version_mtc").format(mtcGitHash_text, mtcGitBranch_text) + validatorVersion_text = local.translate("local_status_version_validator").format(validatorGitHash_text, validatorGitBranch_text) + + color_print(local.translate("local_status_head")) print(validatorIndex_text) print(validatorEfficiency_text) + print(validatorEfficiency2_text) print(adnlAddr_text) print(walletAddr_text) print(walletBalance_text) @@ -435,25 +478,25 @@ def PrintLocalStatus(adnlAddr, validatorIndex, validatorEfficiency, validatorWal def GetColorInt(data, border, logic, ending=None): if data is None: - result = bcolors.Green("n/a") + result = bcolors.green_text("n/a") elif logic == "more": if data >= border: - result = bcolors.Green(data, ending) + result = bcolors.green_text(data, ending) else: - result = bcolors.Red(data, ending) + result = bcolors.red_text(data, ending) elif logic == "less": if data <= border: - result = bcolors.Green(data, ending) + result = bcolors.green_text(data, ending) else: - result = bcolors.Red(data, ending) + result = bcolors.red_text(data, ending) return result #end define def GetColorStatus(input): if input == True: - result = bcolors.Green("working") + result = bcolors.green_text("working") else: - result = bcolors.Red("not working") + result = bcolors.red_text("not working") return result #end define @@ -465,18 +508,18 @@ def PrintTonConfig(fullConfigAddr, fullElectorAddr, config15, config17): minStake = config17["minStake"] maxStake = config17["maxStake"] - fullConfigAddr_text = local.Translate("ton_config_configurator_addr").format(bcolors.Yellow(fullConfigAddr)) - fullElectorAddr_text = local.Translate("ton_config_elector_addr").format(bcolors.Yellow(fullElectorAddr)) - validatorsElectedFor_text = bcolors.Yellow(validatorsElectedFor) - electionsStartBefore_text = bcolors.Yellow(electionsStartBefore) - electionsEndBefore_text = bcolors.Yellow(electionsEndBefore) - stakeHeldFor_text = bcolors.Yellow(stakeHeldFor) - elections_text = local.Translate("ton_config_elections").format(validatorsElectedFor_text, electionsStartBefore_text, electionsEndBefore_text, stakeHeldFor_text) - minStake_text = bcolors.Yellow(minStake) - maxStake_text = bcolors.Yellow(maxStake) - stake_text = local.Translate("ton_config_stake").format(minStake_text, maxStake_text) - - ColorPrint(local.Translate("ton_config_head")) + fullConfigAddr_text = local.translate("ton_config_configurator_addr").format(bcolors.yellow_text(fullConfigAddr)) + fullElectorAddr_text = local.translate("ton_config_elector_addr").format(bcolors.yellow_text(fullElectorAddr)) + validatorsElectedFor_text = bcolors.yellow_text(validatorsElectedFor) + electionsStartBefore_text = bcolors.yellow_text(electionsStartBefore) + electionsEndBefore_text = bcolors.yellow_text(electionsEndBefore) + stakeHeldFor_text = bcolors.yellow_text(stakeHeldFor) + elections_text = local.translate("ton_config_elections").format(validatorsElectedFor_text, electionsStartBefore_text, electionsEndBefore_text, stakeHeldFor_text) + minStake_text = bcolors.yellow_text(minStake) + maxStake_text = bcolors.yellow_text(maxStake) + stake_text = local.translate("ton_config_stake").format(minStake_text, maxStake_text) + + color_print(local.translate("ton_config_head")) print(fullConfigAddr_text) print(fullElectorAddr_text) print(elections_text) @@ -501,22 +544,22 @@ def PrintTimes(rootWorkchainEnabledTime_int, startWorkTime, oldStartWorkTime, co startNextElection = startElection + validatorsElectedFor # timestamp to datetime - rootWorkchainEnabledTime = Timestamp2Datetime(rootWorkchainEnabledTime_int) - startValidationTime = Timestamp2Datetime(startValidation) - endValidationTime = Timestamp2Datetime(endValidation) - startElectionTime = Timestamp2Datetime(startElection) - endElectionTime = Timestamp2Datetime(endElection) - startNextElectionTime = Timestamp2Datetime(startNextElection) + rootWorkchainEnabledTime = timestamp2datetime(rootWorkchainEnabledTime_int) + startValidationTime = timestamp2datetime(startValidation) + endValidationTime = timestamp2datetime(endValidation) + startElectionTime = timestamp2datetime(startElection) + endElectionTime = timestamp2datetime(endElection) + startNextElectionTime = timestamp2datetime(startNextElection) # datetime to color text - rootWorkchainEnabledTime_text = local.Translate("times_root_workchain_enabled_time").format(bcolors.Yellow(rootWorkchainEnabledTime)) - startValidationTime_text = local.Translate("times_start_validation_time").format(GetColorTime(startValidationTime, startValidation)) - endValidationTime_text = local.Translate("times_end_validation_time").format(GetColorTime(endValidationTime, endValidation)) - startElectionTime_text = local.Translate("times_start_election_time").format(GetColorTime(startElectionTime, startElection)) - endElectionTime_text = local.Translate("times_end_election_time").format(GetColorTime(endElectionTime, endElection)) - startNextElectionTime_text = local.Translate("times_start_next_election_time").format(GetColorTime(startNextElectionTime, startNextElection)) - - ColorPrint(local.Translate("times_head")) + rootWorkchainEnabledTime_text = local.translate("times_root_workchain_enabled_time").format(bcolors.yellow_text(rootWorkchainEnabledTime)) + startValidationTime_text = local.translate("times_start_validation_time").format(GetColorTime(startValidationTime, startValidation)) + endValidationTime_text = local.translate("times_end_validation_time").format(GetColorTime(endValidationTime, endValidation)) + startElectionTime_text = local.translate("times_start_election_time").format(GetColorTime(startElectionTime, startElection)) + endElectionTime_text = local.translate("times_end_election_time").format(GetColorTime(endElectionTime, endElection)) + startNextElectionTime_text = local.translate("times_start_next_election_time").format(GetColorTime(startNextElectionTime, startNextElection)) + + color_print(local.translate("times_head")) print(rootWorkchainEnabledTime_text) print(startValidationTime_text) print(endValidationTime_text) @@ -526,11 +569,11 @@ def PrintTimes(rootWorkchainEnabledTime_int, startWorkTime, oldStartWorkTime, co #end define def GetColorTime(datetime, timestamp): - newTimestamp = GetTimestamp() + newTimestamp = get_timestamp() if timestamp > newTimestamp: - result = bcolors.Green(datetime) + result = bcolors.green_text(datetime) else: - result = bcolors.Yellow(datetime) + result = bcolors.yellow_text(datetime) return result #end define @@ -538,7 +581,7 @@ def Seqno(args): try: walletName = args[0] except: - ColorPrint("{red}Bad args. Usage:{endc} seqno ") + color_print("{red}Bad args. Usage:{endc} seqno ") return wallet = ton.GetLocalWallet(walletName) seqno = ton.GetSeqno(wallet) @@ -561,13 +604,13 @@ def CreatNewWallet(args): else: subwallet = 698983191 + workchain # 0x29A9A317 + workchain except: - ColorPrint("{red}Bad args. Usage:{endc} nw [ ]") + color_print("{red}Bad args. Usage:{endc} nw [ ]") return wallet = ton.CreateWallet(walletName, workchain, version, subwallet=subwallet) table = list() table += [["Name", "Workchain", "Address"]] table += [[wallet.name, wallet.workchain, wallet.addrB64_init]] - PrintTable(table) + print_table(table) #end define def ActivateWallet(args): @@ -580,10 +623,10 @@ def ActivateWallet(args): else: wallet = ton.GetLocalWallet(walletName) if not os.path.isfile(wallet.bocFilePath): - local.AddLog("Wallet {walletName} already activated".format(walletName=walletName), "warning") + local.add_log("Wallet {walletName} already activated".format(walletName=walletName), "warning") return ton.ActivateWallet(wallet) - ColorPrint("ActivateWallet - {green}OK{endc}") + color_print("ActivateWallet - {green}OK{endc}") #end define def PrintWalletsList(args): @@ -598,24 +641,24 @@ def PrintWalletsList(args): if account.status != "active": wallet.addrB64 = wallet.addrB64_init table += [[wallet.name, account.status, account.balance, wallet.version, wallet.workchain, wallet.addrB64]] - PrintTable(table) + print_table(table) #end define def ImportWalletFromFile(args): try: filePath = args[0] except: - ColorPrint("{red}Bad args. Usage:{endc} iw ") + color_print("{red}Bad args. Usage:{endc} iw ") return if (".addr" in filePath): filePath = filePath.replace(".addr", '') if (".pk" in filePath): filePath = filePath.replace(".pk", '') if os.path.isfile(filePath + ".addr") == False: - local.AddLog("ImportWalletFromFile error: Address file not found: " + filePath, "error") + local.add_log("ImportWalletFromFile error: Address file not found: " + filePath, "error") return if os.path.isfile(filePath + ".pk") == False: - local.AddLog("ImportWalletFromFile error: Private key not found: " + filePath, "error") + local.add_log("ImportWalletFromFile error: Private key not found: " + filePath, "error") return if '/' in filePath: walletName = filePath[filePath.rfind('/')+1:] @@ -623,7 +666,7 @@ def ImportWalletFromFile(args): walletName = filePath copyfile(filePath + ".addr", ton.walletsDir + walletName + ".addr") copyfile(filePath + ".pk", ton.walletsDir + walletName + ".pk") - ColorPrint("ImportWalletFromFile - {green}OK{endc}") + color_print("ImportWalletFromFile - {green}OK{endc}") #end define def ImportWallet(args): @@ -631,7 +674,7 @@ def ImportWallet(args): addr = args[0] key = args[1] except: - ColorPrint("{red}Bad args. Usage:{endc} iw ") + color_print("{red}Bad args. Usage:{endc} iw ") return name = ton.ImportWallet(addr, key) print("Wallet name:", name) @@ -642,17 +685,17 @@ def SetWalletVersion(args): addr = args[0] version = args[1] except: - ColorPrint("{red}Bad args. Usage:{endc} swv ") + color_print("{red}Bad args. Usage:{endc} swv ") return ton.SetWalletVersion(addr, version) - ColorPrint("SetWalletVersion - {green}OK{endc}") + color_print("SetWalletVersion - {green}OK{endc}") #end define def ExportWallet(args): try: name = args[0] except: - ColorPrint("{red}Bad args. Usage:{endc} ew ") + color_print("{red}Bad args. Usage:{endc} ew ") return addr, key = ton.ExportWallet(name) print("Wallet name:", name) @@ -664,18 +707,21 @@ def DeleteWallet(args): try: walletName = args[0] except: - ColorPrint("{red}Bad args. Usage:{endc} dw ") + color_print("{red}Bad args. Usage:{endc} dw ") + return + if input("Are you sure you want to delete this wallet (yes/no): ") != "yes": + print("Cancel wallet deletion") return wallet = ton.GetLocalWallet(walletName) wallet.Delete() - ColorPrint("DeleteWallet - {green}OK{endc}") + color_print("DeleteWallet - {green}OK{endc}") #end define def ViewAccountStatus(args): try: addrB64 = args[0] except: - ColorPrint("{red}Bad args. Usage:{endc} vas ") + color_print("{red}Bad args. Usage:{endc} vas ") return addrB64 = ton.GetDestinationAddr(addrB64) account = ton.GetAccount(addrB64) @@ -684,10 +730,9 @@ def ViewAccountStatus(args): statusTable += [["Address", "Status", "Version", "Balance"]] statusTable += [[addrB64, account.status, version, account.balance]] historyTable = GetHistoryTable(addrB64, 10) - PrintTable(statusTable) - ColorPrint("{yellow}codeHash: " + account.codeHash + "{endc}") + print_table(statusTable) print() - PrintTable(historyTable) + print_table(historyTable) #end define def ViewAccountHistory(args): @@ -695,10 +740,10 @@ def ViewAccountHistory(args): addr = args[0] limit = int(args[1]) except: - ColorPrint("{red}Bad args. Usage:{endc} vah ") + color_print("{red}Bad args. Usage:{endc} vah ") return table = GetHistoryTable(addr, limit) - PrintTable(table) + print_table(table) #end define def GetHistoryTable(addr, limit): @@ -706,7 +751,7 @@ def GetHistoryTable(addr, limit): account = ton.GetAccount(addr) history = ton.GetAccountHistory(account, limit) table = list() - typeText = ColorText("{red}{bold}{endc}") + typeText = color_text("{red}{bold}{endc}") table += [["Time", typeText, "Coins", "From/To"]] for message in history: if message.srcAddr is None or message.value is None: @@ -714,13 +759,13 @@ def GetHistoryTable(addr, limit): srcAddrFull = f"{message.srcWorkchain}:{message.srcAddr}" destAddFull = f"{message.destWorkchain}:{message.destAddr}" if srcAddrFull == account.addrFull: - type = ColorText("{red}{bold}>>>{endc}") + type = color_text("{red}{bold}>>>{endc}") fromto = destAddFull else: - type = ColorText("{blue}{bold}<<<{endc}") + type = color_text("{blue}{bold}<<<{endc}") fromto = srcAddrFull fromto = ton.AddrFull2AddrB64(fromto) - #datetime = Timestamp2Datetime(message.time, "%Y.%m.%d %H:%M:%S") + #datetime = timestamp2datetime(message.time, "%Y.%m.%d %H:%M:%S") datetime = timeago(message.time) table += [[datetime, type, message.value, fromto]] return table @@ -733,12 +778,12 @@ def MoveCoins(args): amount = args[2] flags = args[3:] except: - ColorPrint("{red}Bad args. Usage:{endc} mg ") + color_print("{red}Bad args. Usage:{endc} mg ") return wallet = ton.GetLocalWallet(walletName) destination = ton.GetDestinationAddr(destination) ton.MoveCoins(wallet, destination, amount, flags=flags) - ColorPrint("MoveCoins - {green}OK{endc}") + color_print("MoveCoins - {green}OK{endc}") #end define def MoveCoinsThroughProxy(args): @@ -747,12 +792,12 @@ def MoveCoinsThroughProxy(args): destination = args[1] amount = args[2] except: - ColorPrint("{red}Bad args. Usage:{endc} mgtp ") + color_print("{red}Bad args. Usage:{endc} mgtp ") return wallet = ton.GetLocalWallet(walletName) destination = ton.GetDestinationAddr(destination) ton.MoveCoinsThroughProxy(wallet, destination, amount) - ColorPrint("MoveCoinsThroughProxy - {green}OK{endc}") + color_print("MoveCoinsThroughProxy - {green}OK{endc}") #end define def CreatNewBookmark(args): @@ -760,7 +805,7 @@ def CreatNewBookmark(args): name = args[0] addr = args[1] except: - ColorPrint("{red}Bad args. Usage:{endc} nb ") + color_print("{red}Bad args. Usage:{endc} nb ") return if ton.IsAddr(addr): type = "account" @@ -773,7 +818,7 @@ def CreatNewBookmark(args): bookmark["type"] = type bookmark["addr"] = addr ton.AddBookmark(bookmark) - ColorPrint("CreatNewBookmark - {green}OK{endc}") + color_print("CreatNewBookmark - {green}OK{endc}") #end define def PrintBookmarksList(args): @@ -789,7 +834,7 @@ def PrintBookmarksList(args): addr = item.get("addr") data = item.get("data") table += [[name, type, addr, data]] - PrintTable(table) + print_table(table) #end define def DeleteBookmark(args): @@ -797,10 +842,10 @@ def DeleteBookmark(args): name = args[0] type = args[1] except: - ColorPrint("{red}Bad args. Usage:{endc} db ") + color_print("{red}Bad args. Usage:{endc} db ") return ton.DeleteBookmark(name, type) - ColorPrint("DeleteBookmark - {green}OK{endc}") + color_print("DeleteBookmark - {green}OK{endc}") #end define def PrintOffersList(args): @@ -823,20 +868,20 @@ def PrintOffersList(args): if "hash" not in args: hash = Reduct(hash) if isPassed == True: - isPassed = bcolors.Green("true") + isPassed = bcolors.green_text("true") if isPassed == False: - isPassed = bcolors.Red("false") + isPassed = bcolors.red_text("false") table += [[hash, votedValidators, wl, approvedPercent_text, isPassed]] - PrintTable(table) + print_table(table) #end define def VoteOffer(args): if len(args) == 0: - ColorPrint("{red}Bad args. Usage:{endc} vo ") + color_print("{red}Bad args. Usage:{endc} vo ") return for offerHash in args: ton.VoteOffer(offerHash) - ColorPrint("VoteOffer - {green}OK{endc}") + color_print("VoteOffer - {green}OK{endc}") #end define def OfferDiff(args): @@ -844,7 +889,7 @@ def OfferDiff(args): offerHash = args[0] offerHash = offerHash except: - ColorPrint("{red}Bad args. Usage:{endc} od ") + color_print("{red}Bad args. Usage:{endc} od ") return ton.GetOfferDiff(offerHash) #end define @@ -854,7 +899,7 @@ def GetConfig(args): configId = args[0] configId = int(configId) except: - ColorPrint("{red}Bad args. Usage:{endc} gc ") + color_print("{red}Bad args. Usage:{endc} gc ") return data = ton.GetConfig(configId) text = json.dumps(data, indent=2) @@ -883,11 +928,11 @@ def PrintComplaintsList(args): if "adnl" not in args: adnl = Reduct(adnl) if isPassed == True: - isPassed = bcolors.Green("true") + isPassed = bcolors.green_text("true") if isPassed == False: - isPassed = bcolors.Red("false") + isPassed = bcolors.red_text("false") table += [[electionId, adnl, Fine_text, votedValidators, approvedPercent_text, isPassed]] - PrintTable(table) + print_table(table) #end define def VoteComplaint(args): @@ -895,10 +940,10 @@ def VoteComplaint(args): electionId = args[0] complaintHash = args[1] except: - ColorPrint("{red}Bad args. Usage:{endc} vc ") + color_print("{red}Bad args. Usage:{endc} vc ") return ton.VoteComplaint(electionId, complaintHash) - ColorPrint("VoteComplaint - {green}OK{endc}") + color_print("VoteComplaint - {green}OK{endc}") #end define def NewDomain(args): @@ -907,14 +952,14 @@ def NewDomain(args): walletName = args[1] adnlAddr = args[2] except: - ColorPrint("{red}Bad args. Usage:{endc} nd ") + color_print("{red}Bad args. Usage:{endc} nd ") return domain = dict() domain["name"] = domainName domain["adnlAddr"] = adnlAddr domain["walletName"] = walletName ton.NewDomain(domain) - ColorPrint("NewDomain - {green}OK{endc}") + color_print("NewDomain - {green}OK{endc}") #end define def PrintDomainsList(args): @@ -928,36 +973,47 @@ def PrintDomainsList(args): domainName = item.get("name") walletName = item.get("walletName") endTime = item.get("endTime") - endTime = Timestamp2Datetime(endTime, "%d.%m.%Y") + endTime = timestamp2datetime(endTime, "%d.%m.%Y") adnlAddr = item.get("adnlAddr") table += [[domainName, walletName, endTime, adnlAddr]] - PrintTable(table) + print_table(table) #end define def ViewDomainStatus(args): try: domainName = args[0] except: - ColorPrint("{red}Bad args. Usage:{endc} vds ") + color_print("{red}Bad args. Usage:{endc} vds ") return domain = ton.GetDomain(domainName) endTime = domain.get("endTime") - endTime = Timestamp2Datetime(endTime, "%d.%m.%Y") + endTime = timestamp2datetime(endTime, "%d.%m.%Y") adnlAddr = domain.get("adnlAddr") table = list() table += [["Domain", "Expiration date", "ADNL address"]] table += [[domainName, endTime, adnlAddr]] - PrintTable(table) + print_table(table) #end define def DeleteDomain(args): try: domainName = args[0] except: - ColorPrint("{red}Bad args. Usage:{endc} dd ") + color_print("{red}Bad args. Usage:{endc} dd ") return ton.DeleteDomain(domainName) - ColorPrint("DeleteDomain - {green}OK{endc}") + color_print("DeleteDomain - {green}OK{endc}") +#end define + +def GetDomainFromAuction(args): + try: + walletName = args[0] + addr = args[1] + except: + color_print("{red}Bad args. Usage:{endc} gdfa ") + return + ton.GetDomainFromAuction(walletName, addr) + color_print("GetDomainFromAuction - {green}OK{endc}") #end define def PrintElectionEntriesList(args): @@ -982,12 +1038,12 @@ def PrintElectionEntriesList(args): if "wallet" not in args: walletAddr = Reduct(walletAddr) table += [[adnl, pubkey, walletAddr, stake, maxFactor]] - PrintTable(table) + print_table(table) #end define def VoteElectionEntry(args): Elections(ton) - ColorPrint("VoteElectionEntry - {green}OK{endc}") + color_print("VoteElectionEntry - {green}OK{endc}") #end define def PrintValidatorList(args): @@ -1014,11 +1070,11 @@ def PrintValidatorList(args): if "offline" in args and online != False: continue if online == True: - online = bcolors.Green("true") + online = bcolors.green_text("true") if online == False: - online = bcolors.Red("false") + online = bcolors.red_text("false") table += [[adnl, pubkey, walletAddr, efficiency, online]] - PrintTable(table) + print_table(table) #end define def Reduct(item): @@ -1035,7 +1091,7 @@ def GetSettings(args): try: name = args[0] except: - ColorPrint("{red}Bad args. Usage:{endc} get ") + color_print("{red}Bad args. Usage:{endc} get ") return result = ton.GetSettings(name) print(json.dumps(result, indent=2)) @@ -1046,28 +1102,28 @@ def SetSettings(args): name = args[0] value = args[1] except: - ColorPrint("{red}Bad args. Usage:{endc} set ") + color_print("{red}Bad args. Usage:{endc} set ") return result = ton.SetSettings(name, value) - ColorPrint("SetSettings - {green}OK{endc}") + color_print("SetSettings - {green}OK{endc}") #end define def Xrestart(inputArgs): if len(inputArgs) < 2: - ColorPrint("{red}Bad args. Usage:{endc} xrestart ") + color_print("{red}Bad args. Usage:{endc} xrestart ") return args = ["python3", "/usr/src/mytonctrl/scripts/xrestart.py"] args += inputArgs - exitCode = RunAsRoot(args) + exitCode = run_as_root(args) if exitCode == 0: text = "Xrestart - {green}OK{endc}" else: text = "Xrestart - {red}Error{endc}" - ColorPrint(text) + color_print(text) #end define def Xlist(args): - ColorPrint("Xlist - {green}OK{endc}") + color_print("Xlist - {green}OK{endc}") #end define def NewPool(args): @@ -1078,24 +1134,24 @@ def NewPool(args): minValidatorStake = int(args[3]) minNominatorStake = int(args[4]) except: - ColorPrint("{red}Bad args. Usage:{endc} new_pool ") + color_print("{red}Bad args. Usage:{endc} new_pool ") return ton.CreatePool(poolName, validatorRewardSharePercent, maxNominatorsCount, minValidatorStake, minNominatorStake) - ColorPrint("NewPool - {green}OK{endc}") + color_print("NewPool - {green}OK{endc}") #end define def ActivatePool(args): try: poolName = args[0] except: - ColorPrint("{red}Bad args. Usage:{endc} activate_pool ") + color_print("{red}Bad args. Usage:{endc} activate_pool ") return pool = ton.GetLocalPool(poolName) if not os.path.isfile(pool.bocFilePath): - local.AddLog(f"Pool {poolName} already activated", "warning") + local.add_log(f"Pool {poolName} already activated", "warning") return ton.ActivatePool(pool) - ColorPrint("ActivatePool - {green}OK{endc}") + color_print("ActivatePool - {green}OK{endc}") #end define def PrintPoolsList(args): @@ -1110,14 +1166,14 @@ def PrintPoolsList(args): if account.status != "active": pool.addrB64 = pool.addrB64_init table += [[pool.name, account.status, account.balance, pool.addrB64]] - PrintTable(table) + print_table(table) #end define def GetPoolData(args): try: poolName = args[0] except: - ColorPrint("{red}Bad args. Usage:{endc} get_pool_data ") + color_print("{red}Bad args. Usage:{endc} get_pool_data ") return if ton.IsAddr(poolName): poolAddr = poolName @@ -1134,45 +1190,43 @@ def DepositToPool(args): pollAddr = args[1] amount = float(args[2]) except: - ColorPrint("{red}Bad args. Usage:{endc} deposit_to_pool ") + color_print("{red}Bad args. Usage:{endc} deposit_to_pool ") return ton.DepositToPool(walletName, pollAddr, amount) - ColorPrint("DepositToPool - {green}OK{endc}") + color_print("DepositToPool - {green}OK{endc}") #end define def WithdrawFromPool(args): try: - walletName = args[0] - poolAddr = args[1] - amount = float(args[2]) + poolAddr = args[0] + amount = float(args[1]) except: - ColorPrint("{red}Bad args. Usage:{endc} withdraw_from_pool ") + color_print("{red}Bad args. Usage:{endc} withdraw_from_pool ") return - poolAddr = ton.GetDestinationAddr(poolAddr) - ton.WithdrawFromPool(walletName, poolAddr, amount) - ColorPrint("WithdrawFromPool - {green}OK{endc}") + ton.WithdrawFromPool(poolAddr, amount) + color_print("WithdrawFromPool - {green}OK{endc}") #end define def DeletePool(args): try: poolName = args[0] except: - ColorPrint("{red}Bad args. Usage:{endc} delete_pool ") + color_print("{red}Bad args. Usage:{endc} delete_pool ") return pool = ton.GetLocalPool(poolName) pool.Delete() - ColorPrint("DeletePool - {green}OK{endc}") + color_print("DeletePool - {green}OK{endc}") #end define def PoolUpdateValidatorSet(args): try: poolAddr = args[0] except: - ColorPrint("{red}Bad args. Usage:{endc} pool_update_validator_set ") + color_print("{red}Bad args. Usage:{endc} pool_update_validator_set ") return wallet = ton.GetValidatorWallet() ton.PoolUpdateValidatorSet(poolAddr, wallet) - ColorPrint("PoolUpdateValidatorSet - {green}OK{endc}") + color_print("PoolUpdateValidatorSet - {green}OK{endc}") #end define def CreateControllers(args): diff --git a/mytoninstaller.py b/mytoninstaller.py index a97477d3..6b5916c9 100644 --- a/mytoninstaller.py +++ b/mytoninstaller.py @@ -13,19 +13,19 @@ def Init(): - local.db["config"]["isStartOnlyOneProcess"] = False - local.db["config"]["logLevel"] = "debug" - local.db["config"]["isIgnorLogWarning"] = True # disable warning - local.Run() - local.db["config"]["isIgnorLogWarning"] = False # enable warning + local.db.config.isStartOnlyOneProcess = False + local.db.config.logLevel = "debug" + local.db.config.isIgnorLogWarning = True # disable warning + local.run() + local.db.config.isIgnorLogWarning = False # enable warning # create variables user = os.environ.get("USER", "root") - local.buffer["user"] = user - local.buffer["vuser"] = "validator" - local.buffer["cport"] = random.randint(2000, 65000) - local.buffer["lport"] = random.randint(2000, 65000) + local.buffer.user = user + local.buffer.vuser = "validator" + local.buffer.cport = random.randint(2000, 65000) + local.buffer.lport = random.randint(2000, 65000) # Create user console console.name = "MyTonInstaller" @@ -42,49 +42,43 @@ def Init(): #end define def Refresh(): - user = local.buffer["user"] - local.buffer["mconfigPath"] = "/home/{user}/.local/share/mytoncore/mytoncore.db".format(user=user) + user = local.buffer.user + local.buffer.mconfig_path = "/home/{user}/.local/share/mytoncore/mytoncore.db".format(user=user) if user == 'root': - local.buffer["mconfigPath"] = "/usr/local/bin/mytoncore/mytoncore.db" + local.buffer.mconfig_path = "/usr/local/bin/mytoncore/mytoncore.db" #end if # create variables - binDir = "/usr/bin/" - srcDir = "/usr/src/" - tonWorkDir = "/var/ton-work/" - tonBinDir = binDir + "ton/" - tonSrcDir = srcDir + "ton/" - local.buffer["binDir"] = binDir - local.buffer["srcDir"] = srcDir - local.buffer["tonWorkDir"] = tonWorkDir - local.buffer["tonBinDir"] = tonBinDir - local.buffer["tonSrcDir"] = tonSrcDir - tonDbDir = tonWorkDir + "db/" - keysDir = tonWorkDir + "keys/" - local.buffer["tonDbDir"] = tonDbDir - local.buffer["keysDir"] = keysDir - local.buffer["tonLogPath"] = tonWorkDir + "log" - local.buffer["validatorAppPath"] = tonBinDir + "validator-engine/validator-engine" - local.buffer["globalConfigPath"] = tonBinDir + "global.config.json" - local.buffer["vconfigPath"] = tonDbDir + "config.json" + bin_dir = "/usr/bin/" + src_dir = "/usr/src/" + ton_work_dir = "/var/ton-work/" + ton_bin_dir = bin_dir + "ton/" + ton_src_dir = src_dir + "ton/" + local.buffer.bin_dir = bin_dir + local.buffer.src_dir = src_dir + local.buffer.ton_work_dir = ton_work_dir + local.buffer.ton_bin_dir = ton_bin_dir + local.buffer.ton_src_dir = ton_src_dir + ton_db_dir = ton_work_dir + "db/" + keys_dir = ton_work_dir + "keys/" + local.buffer.ton_db_dir = ton_db_dir + local.buffer.keys_dir = keys_dir + local.buffer.ton_log_path = ton_work_dir + "log" + local.buffer.validator_app_path = ton_bin_dir + "validator-engine/validator-engine" + local.buffer.global_config_path = ton_bin_dir + "global.config.json" + local.buffer.vconfig_path = ton_db_dir + "config.json" #end define def Status(args): - vconfigPath = local.buffer["vconfigPath"] - - user = local.buffer["user"] - mconfigPath = local.buffer["mconfigPath"] - - tonBinDir = local.buffer["tonBinDir"] - keysDir = local.buffer["keysDir"] - server_key = keysDir + "server" - client_key = keysDir + "client" - liteserver_key = keysDir + "liteserver" + keys_dir = local.buffer.keys_dir + server_key = keys_dir + "server" + client_key = keys_dir + "client" + liteserver_key = keys_dir + "liteserver" liteserver_pubkey = liteserver_key + ".pub" - fnStatus = os.path.isfile(vconfigPath) - mtcStatus = os.path.isfile(mconfigPath) + fnStatus = os.path.isfile(local.buffer.vconfig_path) + mtcStatus = os.path.isfile(local.buffer.mconfig_path) vcStatus = os.path.isfile(server_key) or os.path.isfile(client_key) lsStatus = os.path.isfile(liteserver_pubkey) @@ -96,38 +90,39 @@ def Status(args): def Enable(args): name = args[0] - user = local.buffer["user"] if name == "THA": CreateLocalConfigFile(args, localhost=True) - args = ["python3", local.buffer["myPath"], "-u", user, "-e", "enable{name}".format(name=name)] - RunAsRoot(args) + args = ["python3", local.buffer.my_path, "-u", local.buffer.user, "-e", "enable{name}".format(name=name)] + run_as_root(args) #end define def DRVCF(args): - user = local.buffer["user"] - args = ["python3", local.buffer["myPath"], "-u", user, "-e", "drvcf"] - RunAsRoot(args) + args = ["python3", local.buffer.my_path, "-u", local.buffer.user, "-e", "drvcf"] + run_as_root(args) +#end define + +def get_own_ip(): + requests.packages.urllib3.util.connection.HAS_IPV6 = False + ip = requests.get("https://ifconfig.me/ip").text + return ip #end define def GetLiteServerConfig(): - keysDir = local.buffer["keysDir"] - liteserver_key = keysDir + "liteserver" + keys_dir = local.buffer.keys_dir + liteserver_key = keys_dir + "liteserver" liteserver_pubkey = liteserver_key + ".pub" - result = dict() + result = Dict() file = open(liteserver_pubkey, 'rb') data = file.read() file.close() key = base64.b64encode(data[4:]) - ip = requests.get("https://ifconfig.me").text - mconfigPath = local.buffer["mconfigPath"] - mconfig = GetConfig(path=mconfigPath) - liteClient = mconfig.get("liteClient") - liteServer = liteClient.get("liteServer") - result["ip"] = ip2int(ip) - result["port"] = liteServer.get("port") - result["id"] = dict() - result["id"]["@type"]= "pub.ed25519" - result["id"]["key"]= key.decode() + ip = get_own_ip() + mconfig = GetConfig(path=local.buffer.mconfig_path) + result.ip = ip2int(ip) + result.port = mconfig.liteClient.liteServer.port + result.id = Dict() + result.id["@type"]= "pub.ed25519" + result.id.key= key.decode() return result #end define @@ -165,7 +160,7 @@ def CreateLocalConfig(initBlock, localConfigPath=defaultLocalConfigPath, localho file.close() # chown - user = local.buffer["user"] + user = local.buffer.user args = ["chown", "-R", user + ':' + user, localConfigPath] print("Local config file created:", localConfigPath) @@ -184,9 +179,8 @@ def CreateLocalConfigFile(args, localhost=False): event_name = "clc" initBlock = GetInitBlock() initBlock_b64 = dict2b64(initBlock) - user = local.buffer["user"] - args = ["python3", local.buffer["myPath"], "-u", user, "-e", event_name, "-i", initBlock_b64] - RunAsRoot(args) + args = ["python3", local.buffer.my_path, "-u", local.buffer.user, "-e", event_name, "-i", initBlock_b64] + run_as_root(args) #end define def Event(name): @@ -202,9 +196,9 @@ def Event(name): DangerousRecoveryValidatorConfigFile() if name == "enableJR": EnableJsonRpc() - if name == "enableTHA": - EnableTonHttpApi() - if name in ["clc", "clcl"]: + if name == "enablePT": + EnablePytonv3() + if name == "clc": ix = sys.argv.index("-i") initBlock_b64 = sys.argv[ix+1] initBlock = b642dict(initBlock_b64) @@ -218,7 +212,7 @@ def General(): if "-u" in sys.argv: ux = sys.argv.index("-u") user = sys.argv[ux+1] - local.buffer["user"] = user + local.buffer.user = user Refresh() if "-e" in sys.argv: ex = sys.argv.index("-e") @@ -230,11 +224,11 @@ def General(): if "-t" in sys.argv: mx = sys.argv.index("-t") telemetry = sys.argv[mx+1] - local.buffer["telemetry"] = Str2Bool(telemetry) + local.buffer.telemetry = Str2Bool(telemetry) if "--dump" in sys.argv: mx = sys.argv.index("--dump") dump = sys.argv[mx+1] - local.buffer["dump"] = Str2Bool(dump) + local.buffer.dump = Str2Bool(dump) #end if # Создать настройки для mytoncore.py @@ -260,22 +254,22 @@ def Str2Bool(str): #end define def FirstNodeSettings(): - local.AddLog("start FirstNodeSettings fuction", "debug") + local.add_log("start FirstNodeSettings fuction", "debug") # Создать переменные - user = local.buffer["user"] - vuser = local.buffer["vuser"] - tonWorkDir = local.buffer["tonWorkDir"] - tonDbDir = local.buffer["tonDbDir"] - keysDir = local.buffer["keysDir"] - tonLogPath = local.buffer["tonLogPath"] - validatorAppPath = local.buffer["validatorAppPath"] - globalConfigPath = local.buffer["globalConfigPath"] - vconfigPath = local.buffer["vconfigPath"] + user = local.buffer.user + vuser = local.buffer.vuser + ton_work_dir = local.buffer.ton_work_dir + ton_db_dir = local.buffer.ton_db_dir + keys_dir = local.buffer.keys_dir + tonLogPath = local.buffer.ton_log_path + validatorAppPath = local.buffer.validator_app_path + globalConfigPath = local.buffer.global_config_path + vconfig_path = local.buffer.vconfig_path # Проверить конфигурацию - if os.path.isfile(vconfigPath): - local.AddLog("Validators config.json already exist. Break FirstNodeSettings fuction", "warning") + if os.path.isfile(vconfig_path): + local.add_log("Validators config.json already exist. Break FirstNodeSettings fuction", "warning") return #end if @@ -284,38 +278,38 @@ def FirstNodeSettings(): text = file.read() file.close() if vuser not in text: - local.AddLog("Creating new user: " + vuser, "debug") + local.add_log("Creating new user: " + vuser, "debug") args = ["/usr/sbin/useradd", "-d", "/dev/null", "-s", "/dev/null", vuser] subprocess.run(args) #end if # Подготовить папки валидатора - os.makedirs(tonDbDir, exist_ok=True) - os.makedirs(keysDir, exist_ok=True) + os.makedirs(ton_db_dir, exist_ok=True) + os.makedirs(keys_dir, exist_ok=True) # Прописать автозагрузку cpus = psutil.cpu_count() - 1 - cmd = "{validatorAppPath} --threads {cpus} --daemonize --global-config {globalConfigPath} --db {tonDbDir} --logname {tonLogPath} --state-ttl 604800 --verbosity 1" - cmd = cmd.format(validatorAppPath=validatorAppPath, globalConfigPath=globalConfigPath, tonDbDir=tonDbDir, tonLogPath=tonLogPath, cpus=cpus) - Add2Systemd(name="validator", user=vuser, start=cmd) # post="/usr/bin/python3 /usr/src/mytonctrl/mytoncore.py -e \"validator down\"" + cmd = "{validatorAppPath} --threads {cpus} --daemonize --global-config {globalConfigPath} --db {ton_db_dir} --logname {tonLogPath} --state-ttl 604800 --verbosity 1" + cmd = cmd.format(validatorAppPath=validatorAppPath, globalConfigPath=globalConfigPath, ton_db_dir=ton_db_dir, tonLogPath=tonLogPath, cpus=cpus) + add2systemd(name="validator", user=vuser, start=cmd) # post="/usr/bin/python3 /usr/src/mytonctrl/mytoncore.py -e \"validator down\"" # Получить внешний ip адрес - ip = requests.get("https://ifconfig.me").text + ip = get_own_ip() vport = random.randint(2000, 65000) addr = "{ip}:{vport}".format(ip=ip, vport=vport) - local.AddLog("Use addr: " + addr, "debug") + local.add_log("Use addr: " + addr, "debug") # Первый запуск - local.AddLog("First start validator - create config.json", "debug") - args = [validatorAppPath, "--global-config", globalConfigPath, "--db", tonDbDir, "--ip", addr, "--logname", tonLogPath] + local.add_log("First start validator - create config.json", "debug") + args = [validatorAppPath, "--global-config", globalConfigPath, "--db", ton_db_dir, "--ip", addr, "--logname", tonLogPath] subprocess.run(args) # Скачать дамп DownloadDump() # chown 1 - local.AddLog("Chown ton-work dir", "debug") - args = ["chown", "-R", vuser + ':' + vuser, tonWorkDir] + local.add_log("Chown ton-work dir", "debug") + args = ["chown", "-R", vuser + ':' + vuser, ton_work_dir] subprocess.run(args) # start validator @@ -323,12 +317,12 @@ def FirstNodeSettings(): #end define def DownloadDump(): - dump = local.buffer["dump"] + dump = local.buffer.dump if dump == False: return #end if - local.AddLog("start DownloadDump fuction", "debug") + local.add_log("start DownloadDump fuction", "debug") url = "https://dump.ton.org" dumpSize = requests.get(url + "/dumps/latest.size.archive.txt").text print("dumpSize:", dumpSize) @@ -348,17 +342,17 @@ def DownloadDump(): #end define def FirstMytoncoreSettings(): - local.AddLog("start FirstMytoncoreSettings fuction", "debug") - user = local.buffer["user"] + local.add_log("start FirstMytoncoreSettings fuction", "debug") + user = local.buffer.user # Прописать mytoncore.py в автозагрузку - Add2Systemd(name="mytoncore", user=user, start="/usr/bin/python3 /usr/src/mytonctrl/mytoncore.py") + add2systemd(name="mytoncore", user=user, start="/usr/bin/python3 /usr/src/mytonctrl/mytoncore.py") # Проверить конфигурацию path = "/home/{user}/.local/share/mytoncore/mytoncore.db".format(user=user) path2 = "/usr/local/bin/mytoncore/mytoncore.db" if os.path.isfile(path) or os.path.isfile(path2): - local.AddLog("mytoncore.db already exist. Break FirstMytoncoreSettings fuction", "warning") + local.add_log("mytoncore.db already exist. Break FirstMytoncoreSettings fuction", "warning") return #end if @@ -372,47 +366,42 @@ def FirstMytoncoreSettings(): subprocess.run(args) # Подготовить папку mytoncore - mconfigPath = local.buffer["mconfigPath"] - mconfigDir = GetDirFromPath(mconfigPath) + mconfig_path = local.buffer.mconfig_path + mconfigDir = get_dir_from_path(mconfig_path) os.makedirs(mconfigDir, exist_ok=True) # create variables - srcDir = local.buffer["srcDir"] - tonBinDir = local.buffer["tonBinDir"] - tonSrcDir = local.buffer["tonSrcDir"] + src_dir = local.buffer.src_dir + ton_bin_dir = local.buffer.ton_bin_dir + ton_src_dir = local.buffer.ton_src_dir # general config - mconfig = dict() - mconfig["config"] = dict() - mconfig["config"]["logLevel"] = "debug" - mconfig["config"]["isLocaldbSaving"] = True + mconfig = Dict() + mconfig.config = Dict() + mconfig.config.logLevel = "debug" + mconfig.config.isLocaldbSaving = True # fift - fift = dict() - fift["appPath"] = tonBinDir + "crypto/fift" - fift["libsPath"] = tonSrcDir + "crypto/fift/lib" - fift["smartcontsPath"] = tonSrcDir + "crypto/smartcont" - mconfig["fift"] = fift + fift = Dict() + fift.appPath = ton_bin_dir + "crypto/fift" + fift.libsPath = ton_src_dir + "crypto/fift/lib" + fift.smartcontsPath = ton_src_dir + "crypto/smartcont" + mconfig.fift = fift # lite-client - liteClient = dict() - liteClient["appPath"] = tonBinDir + "lite-client/lite-client" - liteClient["configPath"] = tonBinDir + "global.config.json" - mconfig["liteClient"] = liteClient - - # miner - miner = dict() - miner["appPath"] = tonBinDir + "crypto/pow-miner" - mconfig["miner"] = miner + liteClient = Dict() + liteClient.appPath = ton_bin_dir + "lite-client/lite-client" + liteClient.configPath = ton_bin_dir + "global.config.json" + mconfig.liteClient = liteClient # Telemetry - mconfig["sendTelemetry"] = local.buffer["telemetry"] + mconfig.sendTelemetry = local.buffer.telemetry # Записать настройки в файл - SetConfig(path=mconfigPath, data=mconfig) + SetConfig(path=mconfig_path, data=mconfig) # chown 1 - args = ["chown", user + ':' + user, mconfigDir, mconfigPath] + args = ["chown", user + ':' + user, mconfigDir, mconfig_path] subprocess.run(args) # start mytoncore @@ -420,26 +409,26 @@ def FirstMytoncoreSettings(): #end define def EnableValidatorConsole(): - local.AddLog("start EnableValidatorConsole function", "debug") + local.add_log("start EnableValidatorConsole function", "debug") # Create variables - user = local.buffer["user"] - vuser = local.buffer["vuser"] - cport = local.buffer["cport"] - srcDir = local.buffer["srcDir"] - tonDbDir = local.buffer["tonDbDir"] - tonBinDir = local.buffer["tonBinDir"] - vconfigPath = local.buffer["vconfigPath"] - generate_random_id = tonBinDir + "utils/generate-random-id" - keysDir = local.buffer["keysDir"] - client_key = keysDir + "client" - server_key = keysDir + "server" + user = local.buffer.user + vuser = local.buffer.vuser + cport = local.buffer.cport + src_dir = local.buffer.src_dir + ton_db_dir = local.buffer.ton_db_dir + ton_bin_dir = local.buffer.ton_bin_dir + vconfig_path = local.buffer.vconfig_path + generate_random_id = ton_bin_dir + "utils/generate-random-id" + keys_dir = local.buffer.keys_dir + client_key = keys_dir + "client" + server_key = keys_dir + "server" client_pubkey = client_key + ".pub" server_pubkey = server_key + ".pub" # Check if key exist if os.path.isfile(server_key) or os.path.isfile(client_key): - local.AddLog("Server or client key already exist. Break EnableValidatorConsole fuction", "warning") + local.add_log("Server or client key already exist. Break EnableValidatorConsole fuction", "warning") return #end if @@ -452,7 +441,7 @@ def EnableValidatorConsole(): server_key_b64 = output_arr[1].replace('\n', '') # move key - newKeyPath = tonDbDir + "/keyring/" + server_key_hex + newKeyPath = ton_db_dir + "/keyring/" + server_key_hex args = ["mv", server_key, newKeyPath] subprocess.run(args) @@ -473,41 +462,41 @@ def EnableValidatorConsole(): subprocess.run(args) # read vconfig - vconfig = GetConfig(path=vconfigPath) + vconfig = GetConfig(path=vconfig_path) # prepare config - control = dict() - control["id"] = server_key_b64 - control["port"] = cport - allowed = dict() - allowed["id"] = client_key_b64 - allowed["permissions"] = 15 - control["allowed"] = [allowed] # fix me - vconfig["control"].append(control) + control = Dict() + control.id = server_key_b64 + control.port = cport + allowed = Dict() + allowed.id = client_key_b64 + allowed.permissions = 15 + control.allowed = [allowed] # fix me + vconfig.control.append(control) # write vconfig - SetConfig(path=vconfigPath, data=vconfig) + SetConfig(path=vconfig_path, data=vconfig) # restart validator StartValidator() # read mconfig - mconfigPath = local.buffer["mconfigPath"] - mconfig = GetConfig(path=mconfigPath) + mconfig_path = local.buffer.mconfig_path + mconfig = GetConfig(path=mconfig_path) # edit mytoncore config file - validatorConsole = dict() - validatorConsole["appPath"] = tonBinDir + "validator-engine-console/validator-engine-console" - validatorConsole["privKeyPath"] = client_key - validatorConsole["pubKeyPath"] = server_pubkey - validatorConsole["addr"] = "127.0.0.1:{cport}".format(cport=cport) - mconfig["validatorConsole"] = validatorConsole + validatorConsole = Dict() + validatorConsole.appPath = ton_bin_dir + "validator-engine-console/validator-engine-console" + validatorConsole.privKeyPath = client_key + validatorConsole.pubKeyPath = server_pubkey + validatorConsole.addr = "127.0.0.1:{cport}".format(cport=cport) + mconfig.validatorConsole = validatorConsole # write mconfig - SetConfig(path=mconfigPath, data=mconfig) + SetConfig(path=mconfig_path, data=mconfig) # Подтянуть событие в mytoncore.py - cmd = "python3 {srcDir}mytonctrl/mytoncore.py -e \"enableVC\"".format(srcDir=srcDir) + cmd = "python3 {src_dir}mytonctrl/mytoncore.py -e \"enableVC\"".format(src_dir=src_dir) args = ["su", "-l", user, "-c", cmd] subprocess.run(args) @@ -516,29 +505,29 @@ def EnableValidatorConsole(): #end define def EnableLiteServer(): - local.AddLog("start EnableLiteServer function", "debug") + local.add_log("start EnableLiteServer function", "debug") # Create variables - user = local.buffer["user"] - vuser = local.buffer["vuser"] - lport = local.buffer["lport"] - srcDir = local.buffer["srcDir"] - tonDbDir = local.buffer["tonDbDir"] - keysDir = local.buffer["keysDir"] - tonBinDir = local.buffer["tonBinDir"] - vconfigPath = local.buffer["vconfigPath"] - generate_random_id = tonBinDir + "utils/generate-random-id" - liteserver_key = keysDir + "liteserver" + user = local.buffer.user + vuser = local.buffer.vuser + lport = local.buffer.lport + src_dir = local.buffer.src_dir + ton_db_dir = local.buffer.ton_db_dir + keys_dir = local.buffer.keys_dir + ton_bin_dir = local.buffer.ton_bin_dir + vconfig_path = local.buffer.vconfig_path + generate_random_id = ton_bin_dir + "utils/generate-random-id" + liteserver_key = keys_dir + "liteserver" liteserver_pubkey = liteserver_key + ".pub" # Check if key exist if os.path.isfile(liteserver_pubkey): - local.AddLog("Liteserver key already exist. Break EnableLiteServer fuction", "warning") + local.add_log("Liteserver key already exist. Break EnableLiteServer fuction", "warning") return #end if # generate liteserver key - local.AddLog("generate liteserver key", "debug") + local.add_log("generate liteserver key", "debug") args = [generate_random_id, "--mode", "keys", "--name", liteserver_key] process = subprocess.run(args, stdout=subprocess.PIPE) output = process.stdout.decode("utf-8") @@ -547,56 +536,56 @@ def EnableLiteServer(): liteserver_key_b64 = output_arr[1].replace('\n', '') # move key - local.AddLog("move key", "debug") - newKeyPath = tonDbDir + "/keyring/" + liteserver_key_hex + local.add_log("move key", "debug") + newKeyPath = ton_db_dir + "/keyring/" + liteserver_key_hex args = ["mv", liteserver_key, newKeyPath] subprocess.run(args) # chown 1 - local.AddLog("chown 1", "debug") + local.add_log("chown 1", "debug") args = ["chown", vuser + ':' + vuser, newKeyPath] subprocess.run(args) # chown 2 - local.AddLog("chown 2", "debug") + local.add_log("chown 2", "debug") args = ["chown", user + ':' + user, liteserver_pubkey] subprocess.run(args) # read vconfig - local.AddLog("read vconfig", "debug") - vconfig = GetConfig(path=vconfigPath) + local.add_log("read vconfig", "debug") + vconfig = GetConfig(path=vconfig_path) # prepare vconfig - local.AddLog("prepare vconfig", "debug") - liteserver = dict() - liteserver["id"] = liteserver_key_b64 - liteserver["port"] = lport - vconfig["liteservers"].append(liteserver) + local.add_log("prepare vconfig", "debug") + liteserver = Dict() + liteserver.id = liteserver_key_b64 + liteserver.port = lport + vconfig.liteservers.append(liteserver) # write vconfig - local.AddLog("write vconfig", "debug") - SetConfig(path=vconfigPath, data=vconfig) + local.add_log("write vconfig", "debug") + SetConfig(path=vconfig_path, data=vconfig) # restart validator StartValidator() # edit mytoncore config file # read mconfig - local.AddLog("read mconfig", "debug") - mconfigPath = local.buffer["mconfigPath"] - mconfig = GetConfig(path=mconfigPath) + local.add_log("read mconfig", "debug") + mconfig_path = local.buffer.mconfig_path + mconfig = GetConfig(path=mconfig_path) # edit mytoncore config file - local.AddLog("edit mytoncore config file", "debug") - liteServer = dict() - liteServer["pubkeyPath"] = liteserver_pubkey - liteServer["ip"] = "127.0.0.1" - liteServer["port"] = lport - mconfig["liteClient"]["liteServer"] = liteServer + local.add_log("edit mytoncore config file", "debug") + liteServer = Dict() + liteServer.pubkeyPath = liteserver_pubkey + liteServer.ip = "127.0.0.1" + liteServer.port = lport + mconfig.liteClient.liteServer = liteServer # write mconfig - local.AddLog("write mconfig", "debug") - SetConfig(path=mconfigPath, data=mconfig) + local.add_log("write mconfig", "debug") + SetConfig(path=mconfig_path, data=mconfig) # restart mytoncore StartMytoncore() @@ -604,18 +593,18 @@ def EnableLiteServer(): def StartValidator(): # restart validator - local.AddLog("Start/restart validator service", "debug") + local.add_log("Start/restart validator service", "debug") args = ["systemctl", "restart", "validator"] subprocess.run(args) # sleep 10 sec - local.AddLog("sleep 10 sec", "debug") + local.add_log("sleep 10 sec", "debug") time.sleep(10) #end define def StartMytoncore(): # restart mytoncore - local.AddLog("Start/restart mytoncore service", "debug") + local.add_log("Start/restart mytoncore service", "debug") args = ["systemctl", "restart", "mytoncore"] subprocess.run(args) #end define @@ -625,7 +614,7 @@ def GetConfig(**kwargs): file = open(path, 'rt') text = file.read() file.close() - config = json.loads(text) + config = Dict(json.loads(text)) return config #end define @@ -641,48 +630,48 @@ def SetConfig(**kwargs): #end define def BackupVconfig(): - local.AddLog("Backup validator config file 'config.json' to 'config.json.backup'", "debug") - vconfigPath = local.buffer["vconfigPath"] - backupPath = vconfigPath + ".backup" - args = ["cp", vconfigPath, backupPath] + local.add_log("Backup validator config file 'config.json' to 'config.json.backup'", "debug") + vconfig_path = local.buffer.vconfig_path + backupPath = vconfig_path + ".backup" + args = ["cp", vconfig_path, backupPath] subprocess.run(args) #end define def BackupMconfig(): - local.AddLog("Backup mytoncore config file 'mytoncore.db' to 'mytoncore.db.backup'", "debug") - mconfigPath = local.buffer["mconfigPath"] - backupPath = mconfigPath + ".backup" - args = ["cp", mconfigPath, backupPath] + local.add_log("Backup mytoncore config file 'mytoncore.db' to 'mytoncore.db.backup'", "debug") + mconfig_path = local.buffer.mconfig_path + backupPath = mconfig_path + ".backup" + args = ["cp", mconfig_path, backupPath] subprocess.run(args) #end define def GetPortsFromVconfig(): - vconfigPath = local.buffer["vconfigPath"] + vconfig_path = local.buffer.vconfig_path # read vconfig - local.AddLog("read vconfig", "debug") - vconfig = GetConfig(path=vconfigPath) + local.add_log("read vconfig", "debug") + vconfig = GetConfig(path=vconfig_path) # read mconfig - local.AddLog("read mconfig", "debug") - mconfigPath = local.buffer["mconfigPath"] - mconfig = GetConfig(path=mconfigPath) + local.add_log("read mconfig", "debug") + mconfig_path = local.buffer.mconfig_path + mconfig = GetConfig(path=mconfig_path) # edit mytoncore config file - local.AddLog("edit mytoncore config file", "debug") - mconfig["liteClient"]["liteServer"]["port"] = mconfig["liteservers"][0]["port"] - mconfig["validatorConsole"]["addr"] = "127.0.0.1:{}".format(mconfig["control"][0]["port"]) + local.add_log("edit mytoncore config file", "debug") + mconfig.liteClient.liteServer.port = mconfig.liteservers[0].port + mconfig.validatorConsole.addr = f"127.0.0.1:{mconfig.control[0].port}" # write mconfig - local.AddLog("write mconfig", "debug") - SetConfig(path=mconfigPath, data=mconfig) + local.add_log("write mconfig", "debug") + SetConfig(path=mconfig_path, data=mconfig) # restart mytoncore StartMytoncore() #end define def DangerousRecoveryValidatorConfigFile(): - local.AddLog("start DangerousRecoveryValidatorConfigFile function", "info") + local.add_log("start DangerousRecoveryValidatorConfigFile function", "info") # install and import cryptography library args = ["pip3", "install", "cryptography"] @@ -702,30 +691,30 @@ def DangerousRecoveryValidatorConfigFile(): #end for # Create config object - vconfig = dict() + vconfig = Dict() vconfig["@type"] = "engine.validator.config" - vconfig["out_port"] = 3278 + vconfig.out_port = 3278 # Create addrs object - buffer = dict() - buffer["@type"] = "engine.addr" - buffer["ip"] = ip2int(requests.get("https://ifconfig.me").text) - buffer["port"] = None - buffer["categories"] = [0, 1, 2, 3] - buffer["priority_categories"] = [] - vconfig["addrs"] = [buffer] + buff = Dict() + buff["@type"] = "engine.addr" + buff.ip = ip2int(get_own_ip()) + buff.port = None + buff.categories = [0, 1, 2, 3] + buff.priority_categories = [] + vconfig.addrs = [buff] # Get liteserver fragment - mconfigPath = local.buffer["mconfigPath"] - mconfig = GetConfig(path=mconfigPath) - lkey = mconfig["liteClient"]["liteServer"]["pubkeyPath"] - lport = mconfig["liteClient"]["liteServer"]["port"] + mconfig_path = local.buffer.mconfig_path + mconfig = GetConfig(path=mconfig_path) + lkey = mconfig.liteClient.liteServer.pubkeyPath + lport = mconfig.liteClient.liteServer.port # Read lite server pubkey file = open(lkey, 'rb') data = file.read() file.close() - lsPubkey = data[4:] + ls_pubkey = data[4:] # Search lite server priv key for item in keyring: @@ -737,21 +726,21 @@ def DangerousRecoveryValidatorConfigFile(): privkeyObject = Ed25519PrivateKey.from_private_bytes(peivkey) pubkeyObject = privkeyObject.public_key() pubkey = pubkeyObject.public_bytes(encoding=serialization.Encoding.Raw, format=serialization.PublicFormat.Raw) - if pubkey == lsPubkey: - lsId = hex2b64(item) - keys.remove(lsId) + if pubkey == ls_pubkey: + ls_id = hex2b64(item) + keys.remove(ls_id) #end for # Create LS object - buffer = dict() - buffer["@type"] = "engine.liteServer" - buffer["id"] = lsId - buffer["port"] = lport - vconfig["liteservers"] = [buffer] + buff = Dict() + buff["@type"] = "engine.liteServer" + buff.id = ls_id + buff.port = lport + vconfig.liteservers = [buff] # Get validator-console fragment - ckey = mconfig["validatorConsole"]["pubKeyPath"] - addr = mconfig["validatorConsole"]["addr"] + ckey = mconfig.validatorConsole.pubKeyPath + addr = mconfig.validatorConsole.addr buff = addr.split(':') cport = int(buff[1]) @@ -777,16 +766,16 @@ def DangerousRecoveryValidatorConfigFile(): #end for # Create VC object - buffer = dict() - buffer2 = dict() - buffer["@type"] = "engine.controlInterface" - buffer["id"] = vcId - buffer["port"] = cport - buffer2["@type"] = "engine.controlProcess" - buffer2["id"] = None - buffer2["permissions"] = 15 - buffer["allowed"] = buffer2 - vconfig["control"] = [buffer] + buff = Dict() + buff2 = Dict() + buff["@type"] = "engine.controlInterface" + buff.id = vcId + buff.port = cport + buff2["@type"] = "engine.controlProcess" + buff2.id = None + buff2.permissions = 15 + buff.allowed = buff2 + vconfig.control = [buff] # Get dht fragment files = os.listdir("/var/ton-work/db") @@ -806,32 +795,32 @@ def DangerousRecoveryValidatorConfigFile(): #end for # Create dht object - buffer = dict() - buffer["@type"] = "engine.dht" - buffer["id"] = dhtId - vconfig["dht"] = [buffer] + buff = Dict() + buff["@type"] = "engine.dht" + buff.id = dhtId + vconfig.dht = [buff] # Create adnl object - adnl2 = dict() + adnl2 = Dict() adnl2["@type"] = "engine.adnl" - adnl2["id"] = dhtId - adnl2["category"] = 0 + adnl2.id = dhtId + adnl2.category = 0 # Create adnl object adnlId = hex2b64(mconfig["adnlAddr"]) keys.remove(adnlId) - adnl3 = dict() + adnl3 = Dict() adnl3["@type"] = "engine.adnl" - adnl3["id"] = adnlId - adnl3["category"] = 0 + adnl3.id = adnlId + adnl3.category = 0 # Create adnl object - adnl1 = dict() + adnl1 = Dict() adnl1["@type"] = "engine.adnl" - adnl1["id"] = keys.pop(0) - adnl1["category"] = 1 + adnl1.id = keys.pop(0) + adnl1.category = 1 - vconfig["adnl"] = [adnl1, adnl2, adnl3] + vconfig.adnl = [adnl1, adnl2, adnl3] # Get dumps from tmp dumps = list() @@ -855,23 +844,23 @@ def DangerousRecoveryValidatorConfigFile(): file.close() dump = json.loads(data) vkey = hex2b64(dump["validatorKey"]) - temp_key = dict() + temp_key = Dict() temp_key["@type"] = "engine.validatorTempKey" - temp_key["key"] = vkey - temp_key["expire_at"] = dump["endWorkTime"] - adnl_addr = dict() + temp_key.key = vkey + temp_key.expire_at = dump["endWorkTime"] + adnl_addr = Dict() adnl_addr["@type"] = "engine.validatorAdnlAddress" - adnl_addr["id"] = adnlId - adnl_addr["expire_at"] = dump["endWorkTime"] + adnl_addr.id = adnlId + adnl_addr.expire_at = dump["endWorkTime"] # Create validator object - validator = dict() + validator = Dict() validator["@type"] = "engine.validator" - validator["id"] = vkey - validator["temp_keys"] = [temp_key] - validator["adnl_addrs"] = [adnl_addr] - validator["election_date"] = dump["startWorkTime"] - validator["expire_at"] = dump["endWorkTime"] + validator.id = vkey + validator.temp_keys = [temp_key] + validator.adnl_addrs = [adnl_addr] + validator.election_date = dump["startWorkTime"] + validator.expire_at = dump["endWorkTime"] if vkey in keys: validators.append(validator) keys.remove(vkey) @@ -879,7 +868,7 @@ def DangerousRecoveryValidatorConfigFile(): #end while # Add validators object to vconfig - vconfig["validators"] = validators + vconfig.validators = validators print("vconfig:", json.dumps(vconfig, indent=4)) @@ -901,8 +890,8 @@ def b642hex(input): #end define def CreateSymlinks(): - local.AddLog("start CreateSymlinks fuction", "debug") - cport = local.buffer["cport"] + local.add_log("start CreateSymlinks fuction", "debug") + cport = local.buffer.cport mytonctrl_file = "/usr/bin/mytonctrl" fift_file = "/usr/bin/fift" @@ -937,18 +926,18 @@ def CreateSymlinks(): #end define def EnableDhtServer(): - local.AddLog("start EnableDhtServer function", "debug") - vuser = local.buffer["vuser"] - tonBinDir = local.buffer["tonBinDir"] - globalConfigPath = local.buffer["globalConfigPath"] - dht_server = tonBinDir + "dht-server/dht-server" - generate_random_id = tonBinDir + "utils/generate-random-id" + local.add_log("start EnableDhtServer function", "debug") + vuser = local.buffer.vuser + ton_bin_dir = local.buffer.ton_bin_dir + globalConfigPath = local.buffer.global_config_path + dht_server = ton_bin_dir + "dht-server/dht-server" + generate_random_id = ton_bin_dir + "utils/generate-random-id" tonDhtServerDir = "/var/ton-dht-server/" tonDhtKeyringDir = tonDhtServerDir + "keyring/" # Проверить конфигурацию if os.path.isfile("/var/ton-dht-server/config.json"): - local.AddLog("DHT-Server config.json already exist. Break EnableDhtServer fuction", "warning") + local.add_log("DHT-Server config.json already exist. Break EnableDhtServer fuction", "warning") return #end if @@ -958,10 +947,10 @@ def EnableDhtServer(): # Прописать автозагрузку cmd = "{dht_server} -C {globalConfigPath} -D {tonDhtServerDir}" cmd = cmd.format(dht_server=dht_server, globalConfigPath=globalConfigPath, tonDhtServerDir=tonDhtServerDir) - Add2Systemd(name="dht-server", user=vuser, start=cmd) + add2systemd(name="dht-server", user=vuser, start=cmd) # Получить внешний ip адрес - ip = requests.get("https://ifconfig.me").text + ip = get_own_ip() port = random.randint(2000, 65000) addr = "{ip}:{port}".format(ip=ip, port=port) @@ -1000,26 +989,24 @@ def SetWebPassword(args): #end define def EnableJsonRpc(): - local.AddLog("start EnableJsonRpc function", "debug") - user = local.buffer["user"] - exitCode = RunAsRoot(["bash", "/usr/src/mytonctrl/scripts/jsonrpcinstaller.sh", "-u", user]) + local.add_log("start EnableJsonRpc function", "debug") + user = local.buffer.user + exitCode = run_as_root(["bash", "/usr/src/mytonctrl/scripts/jsonrpcinstaller.sh", "-u", user]) if exitCode == 0: text = "EnableJsonRpc - {green}OK{endc}" else: text = "EnableJsonRpc - {red}Error{endc}" - ColorPrint(text) + color_print(text) #end define def EnableTonHttpApi(): - local.AddLog("start EnableTonHttpApi function", "debug") - user = local.buffer["user"] - runArgs = ["bash", "/usr/src/mytonctrl/scripts/ton_http_api_installer.sh", "-u", user] - exitCode = RunAsRoot(runArgs) + local.add_log("start EnableTonHttpApi function", "debug") + exitCode = run_as_root(["bash", "/usr/src/mytonctrl/scripts/ton_http_api_installer.sh", "-u", local.buffer.user]) if exitCode == 0: text = "EnableTonHttpApi - {green}OK{endc}" else: text = "EnableTonHttpApi - {red}Error{endc}" - ColorPrint(text) + color_print(text) #end define def str2b64(s): @@ -1060,5 +1047,5 @@ def b642dict(b64): General() else: console.Run() - local.Exit() + local.exit() #end if diff --git a/translate.json b/translate.json index b5913621..60350335 100644 --- a/translate.json +++ b/translate.json @@ -1,326 +1,413 @@ { "update_cmd": { "en": "Pull mytonctrl update", - "ru": "Подтянуть обновление mytonctrl" + "ru": "Подтянуть обновление mytonctrl", + "zh_TW": "拉取 mytonctrl 更新" }, "upgrade_cmd": { "en": "Pull up the source code and recompile the TON components", - "ru": "Подтянуть исходный код и перекомпилировать компоненты TON" + "ru": "Подтянуть исходный код и перекомпилировать компоненты TON", + "zh_TW": "拉取源碼並重新編譯 TON 組件" }, "status_cmd": { "en": "Show TON status", - "ru": "Показать статус TON" + "ru": "Показать статус TON", + "zh_TW": "顯示 TON 狀態" }, "seqno_cmd": { "en": "Get seqno wallet", - "ru": "Получить seqno кошелька" + "ru": "Получить seqno кошелька", + "zh_TW": "取得 seqno 錢包" }, "getconfig_cmd": { "en": "Get config", - "ru": "Получить конфигурацию" + "ru": "Получить конфигурацию", + "zh_TW": "取得設定" }, "nw_cmd": { "en": "Create a new local wallet", - "ru": "Создать новый локальный кошелек" + "ru": "Создать новый локальный кошелек", + "zh_TW": "創建新的本地錢包" }, "aw_cmd": { "en": "Activate local wallet", - "ru": "Активировать локальный кошелек" + "ru": "Активировать локальный кошелек", + "zh_TW": "啟動本地錢包" }, "wl_cmd": { "en": "Show wallet list", - "ru": "Показать локальные кошельки" + "ru": "Показать локальные кошельки", + "zh_TW": "顯示錢包列表" }, "iw_cmd": { "en": "Import wallet", - "ru": "Импортировать кошелек" + "ru": "Импортировать кошелек", + "zh_TW": "匯入錢包" }, "swv_cmd": { "en": "Set wallet version", - "ru": "Установить версию кошелька" + "ru": "Установить версию кошелька", + "zh_TW": "設定錢包版本" }, "ex_cmd": { "en": "Export wallet", - "ru": "Экспортировать кошелек" + "ru": "Экспортировать кошелек", + "zh_TW": "匯出錢包" }, "swa_cmd": { "en": "Save wallet address to file", - "ru": "Сохранить адрес кошелька в файл" + "ru": "Сохранить адрес кошелька в файл", + "zh_TW": "將錢包地址儲存到檔案" }, "dw_cmd": { "en": "Delete local wallet", - "ru": "Удалить локальный кошелек" + "ru": "Удалить локальный кошелек", + "zh_TW": "刪除本地錢包" }, "vas_cmd": { "en": "View account status", - "ru": "Показать статус аккаунта" + "ru": "Показать статус аккаунта", + "zh_TW": "查看帳戶狀態" }, "vah_cmd": { "en": "View account history", - "ru": "Показать историю аккаунта" + "ru": "Показать историю аккаунта", + "zh_TW": "查看帳戶歷史" }, "mg_cmd": { "en": "Move coins to account", - "ru": "Перевод монет на кошелек" + "ru": "Перевод монет на кошелек", + "zh_TW": "將幣轉移到帳戶" }, "mgtp_cmd": { "en": "Move coins through proxy", - "ru": "Перевод монет через прокси" + "ru": "Перевод монет через прокси", + "zh_TW": "透過代理轉移幣" }, "nb_cmd": { "en": "Create new bookmark", - "ru": "Добавить аккаунт в закладки" + "ru": "Добавить аккаунт в закладки", + "zh_TW": "建立新的書籤" }, "bl_cmd": { "en": "Show bookmark list", - "ru": "Показать закладки" + "ru": "Показать закладки", + "zh_TW": "顯示書籤列表" }, "db_cmd": { "en": "Delete bookmark", - "ru": "Удалить закладку" + "ru": "Удалить закладку", + "zh_TW": "刪除書籤" }, "nd_cmd": { "en": "New domain", - "ru": "Арендовать новый домен" + "ru": "Арендовать новый домен", + "zh_TW": "新建域名" }, "dl_cmd": { "en": "Show domain list", - "ru": "Показать арендованные домены" + "ru": "Показать арендованные домены", + "zh_TW": "顯示域名列表" }, "vds_cmd": { "en": "View domain status", - "ru": "Показать статус домена" + "ru": "Показать статус домена", + "zh_TW": "查看域名狀態" }, "dd_cmd": { "en": "Delete domain", - "ru": "Удалить домен" + "ru": "Удалить домен", + "zh_TW": "刪除域名" }, "ol_cmd": { "en": "Show offers list", - "ru": "Показать действующие предложения" + "ru": "Показать действующие предложения", + "zh_TW": "顯示優惠列表" }, "vo_cmd": { "en": "Vote for offer", - "ru": "Голосовать за предложение" + "ru": "Голосовать за предложение", + "zh_TW": "投票支持優惠" }, "od_cmd": { "en": "Show offer diff", - "ru": "Показать разницу предложений" + "ru": "Показать разницу предложений", + "zh_TW": "顯示優惠差異" }, "cl_cmd": { "en": "Show complaints list", - "ru": "Показать действующие жалобы" + "ru": "Показать действующие жалобы", + "zh_TW": "顯示投訴列表" }, "vc_cmd": { "en": "Vote for complaint", - "ru": "Голосовать за жалобу" + "ru": "Голосовать за жалобу", + "zh_TW": "投票支持投訴" }, "el_cmd": { "en": "Show election entries list", - "ru": "Показать действующие выборы" + "ru": "Показать действующие выборы", + "zh_TW": "顯示選舉入口列表" }, "ve_cmd": { "en": "Vote election entry", - "ru": "Голосовать в выборах" + "ru": "Голосовать в выборах", + "zh_TW": "投票選舉入口" }, "vl_cmd": { "en": "Show active validators", - "ru": "Показать действующие валидаторы" + "ru": "Показать действующие валидаторы", + "zh_TW": "顯示活躍的驗證者" }, "get_cmd": { "en": "Get settings", - "ru": "Посмотреть настройки" + "ru": "Посмотреть настройки", + "zh_TW": "獲取設定" }, "set_cmd": { "en": "Set settings", - "ru": "Задать настройки" + "ru": "Задать настройки", + "zh_TW": "設定設定" }, "hr_cmd": { "en": "Get mining hashrate", - "ru": "Получить хешрейт сервера" + "ru": "Получить хешрейт сервера", + "zh_TW": "獲取挖礦哈希率" }, "mo_cmd": { "en": "Enable mining", - "ru": "Включить майнинг" + "ru": "Включить майнинг", + "zh_TW": "啟用挖礦" }, "moff_cmd": { "en": "Disable mining", - "ru": "Выключить майнинг" + "ru": "Выключить майнинг", + "zh_TW": "禁用挖礦" }, "installer_cmd": { "en": "Run the installer of TON modules", - "ru": "Запустить установщик модулей TON" + "ru": "Запустить установщик модулей TON", + "zh_TW": "執行 TON 模組的安裝程序" }, "ton_status_head": { "en": "{cyan}===[ TON network status ]==={endc}", - "ru": "{cyan}===[ Статус сети TON ]==={endc}" + "ru": "{cyan}===[ Статус сети TON ]==={endc}", + "zh_TW": "{cyan}===[ TON 網路狀態 ]==={endc}" }, "ton_status_tps": { "en": "Transactions per second (TPS): {0}, {1}, {2}", - "ru": "Транзакций в секунду (TPS): {0}, {1}, {2}" + "ru": "Транзакций в секунду (TPS): {0}, {1}, {2}", + "zh_TW": "每秒交易數 (TPS): {0}, {1}, {2}" }, "ton_status_validators": { "en": "Number of validators: {0}({1})", - "ru": "Количество валидаторов: {0}({1})" + "ru": "Количество валидаторов: {0}({1})", + "zh_TW": "驗證者數量: {0}({1})" }, "ton_status_shards": { "en": "Number of shardchains: {0}", - "ru": "Количесвто шардчейнов: {0}" + "ru": "Количесвто шардчейнов: {0}", + "zh_TW": "分片鏈數量: {0}" }, "ton_status_offers": { "en": "Number of offers: {0}({1})", - "ru": "Действующие предложения: {0}({1})" + "ru": "Действующие предложения: {0}({1})", + "zh_TW": "優惠數量: {0}({1})" }, "ton_status_complaints": { "en": "Number of complaints: {0}({1})", - "ru": "Действующие жалобы: {0}({1})" + "ru": "Действующие жалобы: {0}({1})", + "zh_TW": "投訴數量: {0}({1})" }, "ton_status_election": { "en": "Election status: {0}", - "ru": "Статус выборов: {0}" + "ru": "Статус выборов: {0}", + "zh_TW": "選舉狀態: {0}" }, "local_status_head": { "en": "{cyan}===[ Local validator status ]==={endc}", - "ru": "{cyan}===[ Статус локального валидатора ]==={endc}" + "ru": "{cyan}===[ Статус локального валидатора ]==={endc}", + "zh_TW": "{cyan}===[ 本地驗證者狀態 ]==={endc}" }, "local_status_validator_index": { "en": "Validator index: {0}", - "ru": "Индекс валидатора: {0}" + "ru": "Индекс валидатора: {0}", + "zh_TW": "驗證者索引: {0}" }, "local_status_validator_efficiency": { "en": "Validator efficiency: {0}", - "ru": "Эффективность валидатора: {0}" + "ru": "Эффективность валидатора: {0}", + "zh_TW": "驗證者效率: {0}" + }, + "local_status_validator_efficiency_ver2": { + "en": "Validator efficiency, ver.2: {0}", + "ru": "Эффективность валидатора, вер.2: {0}", + "zh_TW": "驗證器效率,版本2: {0}" }, "local_status_adnl_addr": { "en": "ADNL address of local validator: {0}", - "ru": "ADNL адрес локального валидатора: {0}" + "ru": "ADNL адрес локального валидатора: {0}", + "zh_TW": "本地驗證者的 ADNL 地址: {0}" }, "local_status_wallet_addr": { "en": "Local validator wallet address: {0}", - "ru": "Адрес кошелька локального валидатора: {0}" + "ru": "Адрес кошелька локального валидатора: {0}", + "zh_TW": "本地驗證者錢包地址: {0}" }, "local_status_wallet_balance": { "en": "Local validator wallet balance: {0}", - "ru": "Баланс кошелька локального валидатора: {0}" + "ru": "Баланс кошелька локального валидатора: {0}", + "zh_TW": "本地驗證者錢包餘額: {0}" }, "local_status_cpu_load": { "en": "Load average[{0}]: {1}, {2}, {3}", - "ru": "Средняя нагрузка[{0}]: {1}, {2}, {3}" + "ru": "Средняя нагрузка[{0}]: {1}, {2}, {3}", + "zh_TW": "平均負載[{0}]: {1}, {2}, {3}" }, "local_status_memory": { "en": "Memory load: {0}, {1}", - "ru": "Загрузка памяти: {0}, {1}" + "ru": "Загрузка памяти: {0}, {1}", + "zh_TW": "記憶體負載: {0}, {1}" }, "local_status_net_load": { "en": "Network load average (Mbit/s): {0}, {1}, {2}", - "ru": "Средняя нагрузка сети (Mbit/s): {0}, {1}, {2}" + "ru": "Средняя нагрузка сети (Mbit/s): {0}, {1}, {2}", + "zh_TW": "網絡平均負載 (Mbit/s): {0}, {1}, {2}" }, "local_status_disks_load": { "en": "Disks load average (MB/s): {0}", - "ru": "Средняя нагрузка дисков (MB/s): {0}" + "ru": "Средняя нагрузка дисков (MB/s): {0}", + "zh_TW": "磁碟平均負載 (MB/s): {0}" }, "local_status_mytoncore_status": { "en": "Mytoncore status: {0}, {1}", - "ru": "Статус ядра mytoncore: {0}, {1}" + "ru": "Статус ядра mytoncore: {0}, {1}", + "zh_TW": "Mytoncore 狀態: {0}, {1}" }, "local_status_validator_status": { "en": "Local validator status: {0}, {1}", - "ru": "Статус локального валидатора: {0}, {1}" + "ru": "Статус локального валидатора: {0}, {1}", + "zh_TW": "本地驗證者狀態: {0}, {1}" }, "local_status_validator_out_of_sync": { "en": "Local validator out of sync: {0}", - "ru": "Рассинхронизация локального валидатора: {0}" + "ru": "Рассинхронизация локального валидатора: {0}", + "zh_TW": "本地驗證者不同步: {0}" }, "local_status_db": { "en": "Local validator database size: {0}, {1}", - "ru": "Размер БД локального валидатора: {0}, {1}" + "ru": "Размер БД локального валидатора: {0}, {1}", + "zh_TW": "本地驗證者數據庫大小: {0}, {1}" }, "local_status_version_mtc": { "en": "Version mytonctrl: {0} ({1})", - "ru": "Версия mytonctrl: {0} ({1})" + "ru": "Версия mytonctrl: {0} ({1})", + "zh_TW": "mytonctrl 版本: {0} ({1})" }, "local_status_version_validator": { "en": "Version validator: {0} ({1})", - "ru": "Версия валидатора: {0} ({1})" + "ru": "Версия валидатора: {0} ({1})", + "zh_TW": "驗證者版本: {0} ({1})" }, "ton_config_head": { "en": "{cyan}===[ TON network configuration ]==={endc}", - "ru": "{cyan}===[ Конфигурация сети TON ]==={endc}" + "ru": "{cyan}===[ Конфигурация сети TON ]==={endc}", + "zh_TW": "{cyan}===[ TON 網絡配置 ]==={endc}" }, "ton_config_configurator_addr": { "en": "Configurator address: {0}", - "ru": "Адрес конфигуратора: {0}" + "ru": "Адрес конфигуратора: {0}", + "zh_TW": "配置器地址: {0}" }, "ton_config_elector_addr": { "en": "Elector address: {0}", - "ru": "Адрес электора: {0}" + "ru": "Адрес электора: {0}", + "zh_TW": "選舉人地址: {0}" }, "ton_config_elections": { "en": "Validation period: {0}, Duration of elections: {1}-{2}, Hold period: {3}", - "ru": "Период валидации: {0}, Длительность выборов: {1}-{2}, Период удержания ставки: {3}" + "ru": "Период валидации: {0}, Длительность выборов: {1}-{2}, Период удержания ставки: {3}", + "zh_TW": "驗證期間: {0}, 選舉期間: {1}-{2}, 持有期間: {3}" }, "ton_config_stake": { "en": "Minimum stake: {0}, Maximum stake: {1}", - "ru": "Минимальная ставка: {0}, Максимальная ставка: {1}" + "ru": "Минимальная ставка: {0}, Максимальная ставка: {1}", + "zh_TW": "最小賭注: {0}, 最大賭注: {1}" }, "times_head": { "en": "{cyan}===[ TON timestamps ]==={endc}", - "ru": "{cyan}===[ Временные метки TON ]==={endc}" + "ru": "{cyan}===[ Временные метки TON ]==={endc}", + "zh_TW": "{cyan}===[ TON 時間戳 ]==={endc}" }, "times_root_workchain_enabled_time": { "en": "TON network was launched: {0}", - "ru": "TON сеть была запущена: {0}" + "ru": "TON сеть была запущена: {0}", + "zh_TW": "TON 網絡啟動時間: {0}" }, "times_start_validation_time": { "en": "Start of the validation cycle: {0}", - "ru": "Начало цикла валидации: {0}" + "ru": "Начало цикла валидации: {0}", + "zh_TW": "驗證週期開始: {0}" }, "times_end_validation_time": { "en": "End of the validation cycle: {0}", - "ru": "Конец цикла валидации: {0}" + "ru": "Конец цикла валидации: {0}", + "zh_TW": "驗證週期結束: {0}" }, "times_start_election_time": { "en": "Start of elections: {0}", - "ru": "Начало выборов: {0}" + "ru": "Начало выборов: {0}", + "zh_TW": "選舉開始: {0}" }, "times_end_election_time": { "en": "End of elections: {0}", - "ru": "Конец выборов: {0}" + "ru": "Конец выборов: {0}", + "zh_TW": "選舉結束: {0}" }, "times_start_next_election_time": { "en": "Beginning of the next elections: {0}", - "ru": "Начало следующих выборов: {0}" + "ru": "Начало следующих выборов: {0}", + "zh_TW": "下一次選舉開始: {0}" }, "mytonctrl_update_available": { "en": "{green}MyTonCtrl update available. {red}Please update it with `update` command.{endc}", - "ru": "{green}Доступно обновление MyTonCtrl. {red}Пожалуйста, обновите его с помощью команды `update`.{endc}" + "ru": "{green}Доступно обновление MyTonCtrl. {red}Пожалуйста, обновите его с помощью команды `update`.{endc}", + "zh_TW": "{green}MyTonCtrl 有可用更新. {red}請使用 `update` 命令進行更新.{endc}" }, "ton_update_available": { "en": "{green}TON update available. {red}Please update it with `upgrade` command.{endc}", - "ru": "{green}Доступно обновление TON. {red}Пожалуйста, обновите его с помощью команды `upgrade`.{endc}" + "ru": "{green}Доступно обновление TON. {red}Пожалуйста, обновите его с помощью команды `upgrade`.{endc}", + "zh_TW": "{green}TON 有可用更新. {red}請使用 `upgrade` 命令進行更新.{endc}" }, - "test": { - "en": "001", - "ru": "002" + "vport_error": { + "en": "{red}Error - UDP port of the validator is not accessible from the outside.{endc}", + "ru": "{red}Ошибка - UDP порт валидатора недоступен извне.{endc}", + "zh_TW": "{red}錯誤 - 驗證器的 UDP 端口無法從外部訪問.{endc}" }, - "000": { + "000a": { "en": "001", - "ru": "002" + "ru": "002", + "zh_TW": "003" }, - "000": { + "000b": { "en": "001", - "ru": "002" + "ru": "002", + "zh_TW": "003" }, - "000": { + "000c": { "en": "001", - "ru": "002" + "ru": "002", + "zh_TW": "003" }, - "000": { + "000d": { "en": "001", - "ru": "002" + "ru": "002", + "zh_TW": "003" }, - "000": { + "000e": { "en": "001", - "ru": "002" + "ru": "002", + "zh_TW": "003" } + } From 25df7de3fd49796a6cf8d7942dbc16cfd7c49715 Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Thu, 14 Sep 2023 20:37:57 +0300 Subject: [PATCH 31/43] Create session_stats.py --- functions/session_stats.py | 136 +++++++++++++++++++++++++++++++++++++ 1 file changed, 136 insertions(+) create mode 100644 functions/session_stats.py diff --git a/functions/session_stats.py b/functions/session_stats.py new file mode 100644 index 00000000..ba08b06e --- /dev/null +++ b/functions/session_stats.py @@ -0,0 +1,136 @@ +#!/usr/bin/env python3 +# -*- coding: utf_8 -*- + +import os +import sys +import time +import json +sys.path.append("/usr/src/mytonctrl/") +from mypylib.mypylib import Dict + +def read_session_stats(need_time_period): + #print(f"read_session_stats: {need_time_period}") + file_path = "/var/ton-work/log.session-stats" + average_block_time = calculate_average_block_time(file_path) + need_blocks = int(need_time_period/average_block_time) + + lines = read_last_lines(file_path, need_lines=need_blocks) + #lines = read_all_lines(file_path) + data = lines2data(lines) + + result = Dict() + result.my_blocks = 0 + result.my_need_blocks = 0 + result.all_master_blocks = 0 + result.all_blocks = len(data) + for buff in data: + if buff.id.workchain == -1: + result.all_master_blocks += 1 + first_producer = buff.rounds[0].producers[0] + if buff.self != first_producer.id: + continue + result.my_need_blocks += 1 + if buff.self == buff.creator: + result.my_blocks += 1 + #end for + return result +#end define + +def calculate_average_block_time(file_path): + blocks = 100 + lines = read_last_lines(file_path, need_lines=blocks) + data = lines2data(lines) + first_block, last_block = get_first_last_block(data) + + diff = int(last_block.timestamp) - int(first_block.timestamp) + average_block_time = round(diff/blocks, 2) + #print("average_block_time:", average_block_time) + return average_block_time +#end define + +def get_first_last_block(data, last_index=-1): + first_block = data[0] + last_block = data[last_index] + if first_block.id.workchain == last_block.id.workchain: + blocks = int(last_block.id.seqno) - int(first_block.id.seqno) + else: + first_block, last_block = get_first_last_block(data, last_index=last_index-1) + return first_block, last_block +#end define + +def lines2data(lines): + #start = time.time() + data = list() + for line in lines: + try: + buff = json.loads(line) + data.append(Dict(buff)) + except json.decoder.JSONDecodeError: + pass + #end for + + #end = time.time() + #diff = round(end - start, 2) + #print(f"lines2data completed in {diff} seconds") + return data +#end define + +def read_all_lines(file_path): + #start = time.time() + with open(file_path, 'rt') as file: + text = file.read() + #end with + lines = text.split('\n') + + #end = time.time() + #diff = round(end - start, 2) + #print(f"read_all_lines completed in {diff} seconds") + return lines +#end define + +def read_last_lines(file_path, need_lines): + lines = list() + max_lines = 30000 + if need_lines < 1: + return lines + elif need_lines > max_lines: + need_lines = max_lines + #print(f"read_last_lines: {need_lines}") + #start = time.time() + with open(file_path, 'rb') as file: + find_last_lines(file, need_lines) + for i in range(need_lines): + line = file.readline().decode() + lines.append(line) + #end with + + + #end = time.time() + #diff = round(end - start, 2) + #print(f"read_last_lines {len(lines)} completed in {diff} seconds") + return lines +#end define + +def find_last_lines(file, need_lines): + # catch OSError in case of a one line file + try: + find_lines = 0 + #file.seek(-2, os.SEEK_END) + #while find_lines != need_lines: + # if file.read(1) == b'\n': + # find_lines += 1 + # file.seek(-2, os.SEEK_CUR) + + file.seek(-100, os.SEEK_END) + while find_lines != need_lines: + if b'\n' in file.read(100): + find_lines += 1 + file.seek(-200, os.SEEK_CUR) + except OSError: + file.seek(0) +#end define + + + + + From f2ece1063e74472ae838c0c6b4ed90ead6a8f83a Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Thu, 14 Sep 2023 20:40:53 +0300 Subject: [PATCH 32/43] Update mytoncore.py --- mytoncore.py | 46 +++++++++++++++++++++++----------------------- 1 file changed, 23 insertions(+), 23 deletions(-) diff --git a/mytoncore.py b/mytoncore.py index 3a782973..58de8b6b 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -3677,7 +3677,7 @@ def CreateControllers(self): return #end if - local.AddLog("start CreateControllers function", "debug") + local.add_log("start CreateControllers function", "debug") wallet = self.GetValidatorWallet() liquid_pool_addr = self.GetLiquidPoolAddr() contractPath = self.contractsDir + "jetton_pool/" @@ -3696,7 +3696,7 @@ def CreateControllers(self): # Сохранить новые контроллеры local.db["old_controllers"] = old_controllers local.db["using_controllers"] = new_controllers - local.dbSave() + local.save() #end define def GetControllerAddress(self, controller_id): @@ -3714,7 +3714,7 @@ def GetControllerAddress(self, controller_id): #end define def CheckController(self, controllerAddr): - local.AddLog("start CheckController function", "debug") + local.add_log("start CheckController function", "debug") controllerData = self.GetControllerData(controllerAddr) using_controllers = local.db.get("using_controllers", list()) if controllerData is None: @@ -3726,7 +3726,7 @@ def CheckController(self, controllerAddr): #end define def GetControllers(self): - local.AddLog("start GetControllers function", "debug") + local.add_log("start GetControllers function", "debug") controller0 = self.GetControllerAddress(controller_id=0) controller1 = self.GetControllerAddress(controller_id=1) controllers = [controller0, controller1] @@ -3790,7 +3790,7 @@ def GetControllerData(self, controllerAddr): #end define def CreateLoanRequest(self, controllerAddr): - local.AddLog("start CreateLoanRequest function", "debug") + local.add_log("start CreateLoanRequest function", "debug") min_loan = local.db.get("min_loan", 41000) max_loan = local.db.get("max_loan", 43000) max_interest_percent = local.db.get("max_interest_percent", 1.5) @@ -3799,7 +3799,7 @@ def CreateLoanRequest(self, controllerAddr): # Проверить наличие действующего кредита controllerData = self.GetControllerData(controllerAddr) if controllerData["borrowed_amount"] > 0: - local.AddLog("CreateLoanRequest warning: past loan found", "warning") + local.add_log("CreateLoanRequest warning: past loan found", "warning") return #end define @@ -3845,7 +3845,7 @@ def CalculateLoanAmount(self, min_loan, max_loan, max_interest): #end define def WaitLoan(self, controllerAddr): - local.AddLog("start WaitLoan function", "debug") + local.add_log("start WaitLoan function", "debug") for i in range(10): time.sleep(3) controllerData = self.GetControllerData(controllerAddr) @@ -3855,7 +3855,7 @@ def WaitLoan(self, controllerAddr): #end define def ReturnUnusedLoan(self, controllerAddr): - local.AddLog("start ReturnUnusedLoan function", "debug") + local.add_log("start ReturnUnusedLoan function", "debug") wallet = self.GetValidatorWallet() fileName = self.contractsDir + "jetton_pool/fift-scripts/return_unused_loan.boc" resultFilePath = self.SignBocWithWallet(wallet, fileName, controllerAddr, 1.05) @@ -3863,7 +3863,7 @@ def ReturnUnusedLoan(self, controllerAddr): #end define def DepositToController(self, controllerAddr, amount): - local.AddLog("start DepositToController function", "debug") + local.add_log("start DepositToController function", "debug") wallet = self.GetValidatorWallet() fileName = self.contractsDir + "jetton_pool/fift-scripts/top-up.boc" resultFilePath = self.SignBocWithWallet(wallet, fileName, controllerAddr, amount) @@ -3886,7 +3886,7 @@ def WithdrawFromControllerProcess(self, controllerAddr, amount): return #end if - local.AddLog("start WithdrawFromControllerProcess function", "debug") + local.add_log("start WithdrawFromControllerProcess function", "debug") wallet = self.GetValidatorWallet() fiftScript = self.contractsDir + "jetton_pool/fift-scripts/withdraw-controller.fif" resultFilePath = self.tempDir + self.nodeName + wallet.name + "_withdraw_request.boc" @@ -3897,10 +3897,10 @@ def WithdrawFromControllerProcess(self, controllerAddr, amount): #end define def PendWithdrawFromController(self, controllerAddr, amount): - local.AddLog("start PendWithdrawFromController function", "debug") + local.add_log("start PendWithdrawFromController function", "debug") controllerPendingWithdraws = self.GetControllerPendingWithdraws() controllerPendingWithdraws[controllerAddr] = amount - local.dbSave() + local.save() #end define def HandleControllerPendingWithdraw(self, controllerPendingWithdraws, controllerAddr): @@ -3919,20 +3919,20 @@ def GetControllerPendingWithdraws(self): #end define def SignElectionRequestWithController(self, controllerAddr, startWorkTime, adnlAddr, validatorPubkey_b64, validatorSignature, maxFactor, stake): - local.AddLog("start SignElectionRequestWithController function", "debug") + local.add_log("start SignElectionRequestWithController function", "debug") fileName = self.tempDir + str(startWorkTime) + "_validator-query.boc" fiftScript = self.contractsDir + "jetton_pool/fift-scripts/controller-elect-signed.fif" args = [fiftScript, controllerAddr, startWorkTime, maxFactor, adnlAddr, validatorPubkey_b64, validatorSignature, fileName, stake] - local.AddLog(f"SignElectionRequestWithController args: {args}", "debug") + local.add_log(f"SignElectionRequestWithController args: {args}", "debug") result = self.fift.Run(args) - local.AddLog(f"SignElectionRequestWithController result: {result}", "debug") + local.add_log(f"SignElectionRequestWithController result: {result}", "debug") pubkey = Pars(result, "validator public key ", '\n') fileName = Pars(result, "Saved to file ", '\n') return pubkey, fileName #end define def ControllersUpdateValidatorSet(self): - local.AddLog("start ControllersUpdateValidatorSet function", "debug") + local.add_log("start ControllersUpdateValidatorSet function", "debug") using_controllers = local.db.get("using_controllers") user_controllers = local.db.get("user_controllers", list()) old_controllers = local.db.get("old_controllers", list()) @@ -3941,7 +3941,7 @@ def ControllersUpdateValidatorSet(self): #end define def ControllerUpdateValidatorSet(self, controllerAddr): - local.AddLog("start ControllerUpdateValidatorSet function", "debug") + local.add_log("start ControllerUpdateValidatorSet function", "debug") wallet = self.GetValidatorWallet() controllers = self.GetControllers() controllerData = self.GetControllerData(controllerAddr) @@ -3976,20 +3976,20 @@ def ControllerUpdateValidatorSet(self, controllerAddr): #end define def ControllerUpdateValidatorSetProcess(self, controllerAddr, wallet): - local.AddLog("start ControllerUpdateValidatorSetProcess function", "debug") + local.add_log("start ControllerUpdateValidatorSetProcess function", "debug") fileName = self.contractsDir + "jetton_pool/fift-scripts/update_validator_hash.boc" resultFilePath = self.SignBocWithWallet(wallet, fileName, controllerAddr, 1.07) self.SendFile(resultFilePath, wallet) - local.AddLog("ControllerUpdateValidatorSetProcess completed") + local.add_log("ControllerUpdateValidatorSetProcess completed") #end define def ControllerRecoverStake(self, controllerAddr): wallet = self.GetValidatorWallet() - local.AddLog("start ControllerRecoverStake function", "debug") + local.add_log("start ControllerRecoverStake function", "debug") fileName = self.contractsDir + "jetton_pool/fift-scripts/recover_stake.boc" resultFilePath = self.SignBocWithWallet(wallet, fileName, controllerAddr, 1.04) self.SendFile(resultFilePath, wallet) - local.AddLog("ControllerRecoverStake completed") + local.add_log("ControllerRecoverStake completed") #end define def StopController(self, controllerAddr): @@ -4003,7 +4003,7 @@ def StopController(self, controllerAddr): user_controllers = local.db.get("user_controllers") if user_controllers is not None and controllerAddr in user_controllers: user_controllers.remove(controllerAddr) - local.dbSave() + local.save() #end define def AddController(self, controllerAddr): @@ -4017,7 +4017,7 @@ def AddController(self, controllerAddr): stop_controllers_list = local.db.get("stop_controllers_list") if stop_controllers_list is not None and controllerAddr in stop_controllers_list: stop_controllers_list.remove(controllerAddr) - local.dbSave() + local.save() #end define def CheckLiquidPool(self): From 351c15d1c4765593117caf3ab0635d03a3834677 Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Thu, 14 Sep 2023 20:42:15 +0300 Subject: [PATCH 33/43] Update mytonctrl.py --- mytonctrl.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mytonctrl.py b/mytonctrl.py index 36267433..19f2fc2e 100755 --- a/mytonctrl.py +++ b/mytonctrl.py @@ -1264,7 +1264,7 @@ def PrintControllersListProcess(controllers): approved = True if controllerData and controllerData["approved"] == -1 else False state = controllerData["state"] if controllerData else None table += [[controllerAddr, account.status, account.balance, approved, state]] - PrintTable(table) + print_table(table) #end define def GetControllerData(args): From e995600ebd243b05e3f8ccfa2e3eac9972809f5b Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Thu, 14 Sep 2023 22:05:26 +0300 Subject: [PATCH 34/43] Update mytonctrl.py --- mytonctrl.py | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/mytonctrl.py b/mytonctrl.py index 19f2fc2e..87c47567 100755 --- a/mytonctrl.py +++ b/mytonctrl.py @@ -1231,7 +1231,7 @@ def PoolUpdateValidatorSet(args): def CreateControllers(args): ton.CreateControllers() - ColorPrint("CreateControllers - {green}OK{endc}") + color_print("CreateControllers - {green}OK{endc}") #end define def PrintControllersList(args): @@ -1271,7 +1271,7 @@ def GetControllerData(args): try: controllerAddr = args[0] except: - ColorPrint("{red}Bad args. Usage:{endc} get_controller_data ") + color_print("{red}Bad args. Usage:{endc} get_controller_data ") return controllerData = ton.GetControllerData(controllerAddr) print(json.dumps(controllerData, indent=4)) @@ -1282,7 +1282,7 @@ def DepositToController(args): controllerAddr = args[0] amount = float(args[1]) except: - ColorPrint("{red}Bad args. Usage:{endc} deposit_to_controller ") + color_print("{red}Bad args. Usage:{endc} deposit_to_controller ") return ton.DepositToController(controllerAddr, amount) #end define @@ -1292,7 +1292,7 @@ def WithdrawFromController(args): controllerAddr = args[0] amount = GetItemFromList(args, 1) except: - ColorPrint("{red}Bad args. Usage:{endc} withdraw_from_controller [amount]") + color_print("{red}Bad args. Usage:{endc} withdraw_from_controller [amount]") return ton.WithdrawFromController(controllerAddr, amount) #end define @@ -1318,20 +1318,20 @@ def ControllerUpdateValidatorSet(args): try: controllerAddr = args[0] except: - ColorPrint("{red}Bad args. Usage:{endc} controller_update_validator_set ") + color_print("{red}Bad args. Usage:{endc} controller_update_validator_set ") return ton.ControllerUpdateValidatorSet(controllerAddr) - ColorPrint("ControllerUpdateValidatorSet - {green}OK{endc}") + color_print("ControllerUpdateValidatorSet - {green}OK{endc}") #end define def StopController(args): try: controllerAddr = args[0] except: - ColorPrint("{red}Bad args. Usage:{endc} stop_controller ") + color_print("{red}Bad args. Usage:{endc} stop_controller ") return ton.StopController(controllerAddr) - ColorPrint("StopController - {green}OK{endc}") + color_print("StopController - {green}OK{endc}") #end define def StopAndWithdrawController(args): @@ -1339,29 +1339,29 @@ def StopAndWithdrawController(args): controllerAddr = args[0] amount = GetItemFromList(args, 1) except: - ColorPrint("{red}Bad args. Usage:{endc} stop_and_withdraw_controller [amount]") + color_print("{red}Bad args. Usage:{endc} stop_and_withdraw_controller [amount]") return if amount is None: account = ton.GetAccount(controllerAddr) amount = account.balance-10.1 ton.StopController(controllerAddr) ton.WithdrawFromController(controllerAddr, amount) - ColorPrint("StopAndWithdrawController - {green}OK{endc}") + color_print("StopAndWithdrawController - {green}OK{endc}") #end define def AddController(args): try: controllerAddr = args[0] except: - ColorPrint("{red}Bad args. Usage:{endc} add_controller ") + color_print("{red}Bad args. Usage:{endc} add_controller ") return ton.AddController(controllerAddr) - ColorPrint("AddController - {green}OK{endc}") + color_print("AddController - {green}OK{endc}") #end define def CheckLiquidPool(args): ton.CheckLiquidPool() - ColorPrint("CheckLiquidPool - {green}OK{endc}") + color_print("CheckLiquidPool - {green}OK{endc}") #end define From 5866bb17e3a33c295ce03df87170b2974d82f619 Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Thu, 25 Jan 2024 16:38:08 +0300 Subject: [PATCH 35/43] debug CalculateLoanAmount --- mytoncore.py | 9 +++++++++ mytonctrl.py | 7 +++++++ 2 files changed, 16 insertions(+) diff --git a/mytoncore.py b/mytoncore.py index 58de8b6b..49a03299 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -3833,6 +3833,7 @@ def CalculateLoanAmount(self, min_loan, max_loan, max_interest): ["num", max_loan*10**9], ["num", max_interest], ] + print(f"CalculateLoanAmount data: {data}") url = "http://127.0.0.1:8801/runGetMethod" res = requests.post(url, json=data) @@ -3843,6 +3844,14 @@ def CalculateLoanAmount(self, min_loan, max_loan, max_interest): result = res_data.get("result").get("stack").pop().pop() return result #end define + + def CalculateLoanAmount_test(): + min_loan = local.db.get("min_loan", 41000) + max_loan = local.db.get("max_loan", 43000) + max_interest_percent = local.db.get("max_interest_percent", 1.5) + max_interest = int(max_interest_percent/100*16777216) + return self.CalculateLoanAmount(min_loan, max_loan, max_interest) + #end define def WaitLoan(self, controllerAddr): local.add_log("start WaitLoan function", "debug") diff --git a/mytonctrl.py b/mytonctrl.py index 87c47567..dedfbbc1 100755 --- a/mytonctrl.py +++ b/mytonctrl.py @@ -83,6 +83,8 @@ def Init(argv): console.AddItem("stop_and_withdraw_controller", StopAndWithdrawController, local.translate("_")) console.AddItem("add_controller", AddController, local.translate("_")) console.AddItem("check_liquid_pool", CheckLiquidPool, local.translate("_")) + console.AddItem("test_calculate_loan_amount", CalculateLoanAmount_test, local.translate("_")) + # Process input parameters @@ -1364,6 +1366,11 @@ def CheckLiquidPool(args): color_print("CheckLiquidPool - {green}OK{endc}") #end define +def CalculateLoanAmount_test(args): + t = ton.CalculateLoanAmount_test() + print(t) +#end define + ### ### Start of the program From 56a1039a7b377ecaec3a76507362d6cfb3ed87a4 Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Thu, 25 Jan 2024 16:47:01 +0300 Subject: [PATCH 36/43] debug CalculateLoanAmount --- mytoncore.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mytoncore.py b/mytoncore.py index 49a03299..abf8fd32 100755 --- a/mytoncore.py +++ b/mytoncore.py @@ -3845,7 +3845,7 @@ def CalculateLoanAmount(self, min_loan, max_loan, max_interest): return result #end define - def CalculateLoanAmount_test(): + def CalculateLoanAmount_test(self): min_loan = local.db.get("min_loan", 41000) max_loan = local.db.get("max_loan", 43000) max_interest_percent = local.db.get("max_interest_percent", 1.5) From 80374904982b225e29bc26c0276ae3dd0511c907 Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Thu, 25 Jan 2024 17:27:35 +0300 Subject: [PATCH 37/43] bugfix --- mytoninstaller.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mytoninstaller.py b/mytoninstaller.py index 6b5916c9..1499bd7b 100644 --- a/mytoninstaller.py +++ b/mytoninstaller.py @@ -196,8 +196,8 @@ def Event(name): DangerousRecoveryValidatorConfigFile() if name == "enableJR": EnableJsonRpc() - if name == "enablePT": - EnablePytonv3() + if name == "enableTHA": + EnableTonHttpApi() if name == "clc": ix = sys.argv.index("-i") initBlock_b64 = sys.argv[ix+1] From 9c574c364226064a8a5244389a374b3448e3b274 Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Thu, 25 Jan 2024 17:33:12 +0300 Subject: [PATCH 38/43] bugfix --- scripts/ton_http_api_installer.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/ton_http_api_installer.sh b/scripts/ton_http_api_installer.sh index b27ef02a..9327f870 100644 --- a/scripts/ton_http_api_installer.sh +++ b/scripts/ton_http_api_installer.sh @@ -31,7 +31,7 @@ echo -e "${COLOR}[3/4]${ENDC} Add to startup" venv_ton_http_api="${venv_path}/bin/ton-http-api" tonlib_path="/usr/bin/ton/tonlib/libtonlibjson.so" ls_config="/usr/bin/ton/localhost.config.json" -cmd="from sys import path; path.append('/usr/src/mytonctrl/'); from mypylib.mypylib import Add2Systemd; Add2Systemd(name='ton_http_api', user='${user}', start='${venv_ton_http_api} --host 127.0.0.1 --port 8801 --liteserver-config ${ls_config} --cdll-path ${tonlib_path} --tonlib-keystore /tmp/tonlib_keystore/')" +cmd="from sys import path; path.append('/usr/src/mytonctrl/'); from mypylib.mypylib import add2systemd; add2systemd(name='ton_http_api', user='${user}', start='${venv_ton_http_api} --host 127.0.0.1 --port 8801 --liteserver-config ${ls_config} --cdll-path ${tonlib_path} --tonlib-keystore /tmp/tonlib_keystore/')" python3 -c "${cmd}" systemctl restart ton_http_api From 41d522d6a28d2939ce2d27353acc741f37ff6d10 Mon Sep 17 00:00:00 2001 From: Igroman787 <27614297+igroman787@users.noreply.github.com> Date: Thu, 25 Jan 2024 17:39:54 +0300 Subject: [PATCH 39/43] bugfix --- mytoninstaller.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mytoninstaller.py b/mytoninstaller.py index 1499bd7b..f3726178 100644 --- a/mytoninstaller.py +++ b/mytoninstaller.py @@ -198,7 +198,7 @@ def Event(name): EnableJsonRpc() if name == "enableTHA": EnableTonHttpApi() - if name == "clc": + if name in ["clc", "clcl"]: ix = sys.argv.index("-i") initBlock_b64 = sys.argv[ix+1] initBlock = b642dict(initBlock_b64) From 4c1243c8392aa10f637e73087d08f3b252179561 Mon Sep 17 00:00:00 2001 From: yungwine Date: Thu, 29 Feb 2024 12:33:41 +0700 Subject: [PATCH 40/43] improve save_offers db storage --- mytoncore/mytoncore.py | 34 +++++++++++++++++++++------------- 1 file changed, 21 insertions(+), 13 deletions(-) diff --git a/mytoncore/mytoncore.py b/mytoncore/mytoncore.py index bbc73c29..ba769aee 100644 --- a/mytoncore/mytoncore.py +++ b/mytoncore/mytoncore.py @@ -2043,6 +2043,11 @@ def GetSaveElectionEntries(self, electionId): return result #end define + def calculate_offer_pseudohash(self, offer_hash: str, param_id: int): + config_val = self.GetConfig(param_id) + pseudohash_bytes = offer_hash.encode() + json.dumps(config_val, sort_keys=True).encode() + return hashlib.sha256(pseudohash_bytes).hexdigest() + def GetOffers(self): self.local.add_log("start GetOffers function", "debug") fullConfigAddr = self.GetFullConfigAddr() @@ -2087,9 +2092,7 @@ def GetOffers(self): item["approvedPercent"] = round(availableWeight / totalWeight * 100, 3) item["isPassed"] = (weightRemaining < 0) #item["pseudohash"] = hashlib.sha256(param_val.encode()).hexdigest() - config_val = self.GetConfig(param_id) - pseudohash_bytes = hash.encode() + json.dumps(config_val, sort_keys=True).encode() - item["pseudohash"] = hashlib.sha256(pseudohash_bytes).hexdigest() + item['pseudohash'] = self.calculate_offer_pseudohash(hash, param_id) offers.append(item) #end for return offers @@ -2345,7 +2348,7 @@ def VoteOffer(self, offerHash): resultFilePath = self.SignProposalVoteRequestWithValidator(offerHash, validatorIndex, validatorPubkey_b64, validatorSignature) resultFilePath = self.SignBocWithWallet(wallet, resultFilePath, fullConfigAddr, 1.5) self.SendFile(resultFilePath, wallet) - self.AddSaveOffer(offer) + self.add_save_offer(offer) #end define def VoteComplaint(self, electionId, complaintHash): @@ -2968,9 +2971,14 @@ def WriteBookmarkData(self, bookmark): def offers_gc(self, save_offers): current_offers = self.GetOffers() current_offers_hashes = [offer.get("hash") for offer in current_offers] - for offer in list(save_offers.keys()): - if offer not in current_offers_hashes: - save_offers.pop(offer) + for offer_hash, offer in list(save_offers.items()): + if offer_hash not in current_offers_hashes: + if isinstance(offer, list): + param_id = offer[1] + if offer[0] != self.calculate_offer_pseudohash(offer_hash, param_id): # param has been changed so no need to keep anymore + save_offers.pop(offer) + else: # old version of offer in db + save_offers.pop(offer) return save_offers def GetSaveOffers(self): @@ -2983,12 +2991,12 @@ def GetSaveOffers(self): return save_offers #end define - def AddSaveOffer(self, offer): - offerHash = offer.get("hash") - offerPseudohash = offer.get("pseudohash") - saveOffers = self.GetSaveOffers() - if offerHash not in saveOffers: - saveOffers[offerHash] = offerPseudohash + def add_save_offer(self, offer): + offer_hash = offer.get("hash") + offer_pseudohash = offer.get("pseudohash") + save_offers = self.GetSaveOffers() + if offer_hash not in save_offers: + save_offers[offer_hash] = [offer_pseudohash, offer.get('config', {}).get("id")] self.local.save() #end define From 229adf190e478e3c6114fb02d7b346f5e7a5a491 Mon Sep 17 00:00:00 2001 From: yungwine Date: Thu, 29 Feb 2024 12:38:41 +0700 Subject: [PATCH 41/43] bugfix --- mytoncore/mytoncore.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mytoncore/mytoncore.py b/mytoncore/mytoncore.py index ba769aee..a7e0df54 100644 --- a/mytoncore/mytoncore.py +++ b/mytoncore/mytoncore.py @@ -2975,7 +2975,8 @@ def offers_gc(self, save_offers): if offer_hash not in current_offers_hashes: if isinstance(offer, list): param_id = offer[1] - if offer[0] != self.calculate_offer_pseudohash(offer_hash, param_id): # param has been changed so no need to keep anymore + if param_id is not None and offer[0] != self.calculate_offer_pseudohash(offer_hash, param_id): + # param has been changed so no need to keep anymore save_offers.pop(offer) else: # old version of offer in db save_offers.pop(offer) From 319be9a04d0d7cb184671c4f23ce43a46084c0f1 Mon Sep 17 00:00:00 2001 From: yungwine Date: Thu, 29 Feb 2024 13:27:17 +0700 Subject: [PATCH 42/43] bugfix --- mytoncore/mytoncore.py | 104 +++++++++++++++++++++-------------------- 1 file changed, 53 insertions(+), 51 deletions(-) diff --git a/mytoncore/mytoncore.py b/mytoncore/mytoncore.py index 34759285..a6d0765c 100644 --- a/mytoncore/mytoncore.py +++ b/mytoncore/mytoncore.py @@ -1292,6 +1292,7 @@ def ProcessRecoverStake(self): def GetStake(self, account, args=None): stake = self.local.db.get("stake") usePool = self.local.db.get("usePool") + useController = self.local.db.get("useController") stakePercent = self.local.db.get("stakePercent", 99) vconfig = self.GetValidatorConfig() validators = vconfig.get("validators") @@ -1408,6 +1409,7 @@ def GetValidatorWallet(self, mode="stake"): def ElectionEntry(self, args=None): usePool = self.local.db.get("usePool") + useController = self.local.db.get("useController") wallet = self.GetValidatorWallet() addrB64 = wallet.addrB64 if wallet is None: @@ -1500,9 +1502,9 @@ def ElectionEntry(self, args=None): resultFilePath = self.SignBocWithWallet(wallet, resultFilePath, pool.addrB64, 1.3) self.SendFile(resultFilePath, wallet) elif useController: - var1 = self.CreateElectionRequest(controllerAddr, startWorkTime, adnlAddr, maxFactor) + var1 = self.CreateElectionRequest(controllerAddr, startWorkTime, adnl_addr, maxFactor) validatorSignature = self.GetValidatorSignature(validatorKey, var1) - validatorPubkey, resultFilePath = self.SignElectionRequestWithController(controllerAddr, startWorkTime, adnlAddr, validatorPubkey_b64, validatorSignature, maxFactor, stake) + validatorPubkey, resultFilePath = self.SignElectionRequestWithController(controllerAddr, startWorkTime, adnl_addr, validatorPubkey_b64, validatorSignature, maxFactor, stake) # Send boc file to TON resultFilePath = self.SignBocWithWallet(wallet, resultFilePath, controllerAddr, 1.03) @@ -3691,7 +3693,7 @@ def GetPoolData(self, addrB64): #end define def GetLiquidPoolAddr(self): - liquid_pool_addr = local.db.get("liquid_pool_addr") + liquid_pool_addr = self.local.db.get("liquid_pool_addr") if liquid_pool_addr is None: raise Exception("GetLiquidPoolAddr error: liquid_pool_addr not set") return liquid_pool_addr @@ -3699,12 +3701,12 @@ def GetLiquidPoolAddr(self): def CreateControllers(self): new_controllers = self.GetControllers() - old_controllers = local.db.get("using_controllers", list()) + old_controllers = self.local.db.get("using_controllers", list()) if new_controllers == old_controllers: return #end if - local.add_log("start CreateControllers function", "debug") + self.local.add_log("start CreateControllers function", "debug") wallet = self.GetValidatorWallet() liquid_pool_addr = self.GetLiquidPoolAddr() contractPath = self.contractsDir + "jetton_pool/" @@ -3721,9 +3723,9 @@ def CreateControllers(self): self.SendFile(resultFilePath1, wallet) # Сохранить новые контроллеры - local.db["old_controllers"] = old_controllers - local.db["using_controllers"] = new_controllers - local.save() + self.local.db["old_controllers"] = old_controllers + self.local.db["using_controllers"] = new_controllers + self.local.save() #end define def GetControllerAddress(self, controller_id): @@ -3741,9 +3743,9 @@ def GetControllerAddress(self, controller_id): #end define def CheckController(self, controllerAddr): - local.add_log("start CheckController function", "debug") + self.local.add_log("start CheckController function", "debug") controllerData = self.GetControllerData(controllerAddr) - using_controllers = local.db.get("using_controllers", list()) + using_controllers = self.local.db.get("using_controllers", list()) if controllerData is None: raise Exception(f"CheckController error: controller not initialized. Use new_controllers") if controllerData["approved"] != -1: @@ -3753,7 +3755,7 @@ def CheckController(self, controllerAddr): #end define def GetControllers(self): - local.add_log("start GetControllers function", "debug") + self.local.add_log("start GetControllers function", "debug") controller0 = self.GetControllerAddress(controller_id=0) controller1 = self.GetControllerAddress(controller_id=1) controllers = [controller0, controller1] @@ -3782,10 +3784,10 @@ def GetControllerRequiredBalanceForLoan(self, controllerAddr, credit, interest): #end define def IsControllerReadyToStake(self, addrB64): - stop_controllers_list = local.db.get("stop_controllers_list") + stop_controllers_list = self.local.db.get("stop_controllers_list") if stop_controllers_list is not None and addrB64 in stop_controllers_list: return False - now = GetTimestamp() + now = get_timestamp() config15 = self.GetConfig15() controllerData = self.GetControllerData(addrB64) if controllerData is None: @@ -3817,16 +3819,16 @@ def GetControllerData(self, controllerAddr): #end define def CreateLoanRequest(self, controllerAddr): - local.add_log("start CreateLoanRequest function", "debug") - min_loan = local.db.get("min_loan", 41000) - max_loan = local.db.get("max_loan", 43000) - max_interest_percent = local.db.get("max_interest_percent", 1.5) + self.local.add_log("start CreateLoanRequest function", "debug") + min_loan = self.local.db.get("min_loan", 41000) + max_loan = self.local.db.get("max_loan", 43000) + max_interest_percent = self.local.db.get("max_interest_percent", 1.5) max_interest = int(max_interest_percent/100*16777216) # Проверить наличие действующего кредита controllerData = self.GetControllerData(controllerAddr) if controllerData["borrowed_amount"] > 0: - local.add_log("CreateLoanRequest warning: past loan found", "warning") + self.local.add_log("CreateLoanRequest warning: past loan found", "warning") return #end define @@ -3873,15 +3875,15 @@ def CalculateLoanAmount(self, min_loan, max_loan, max_interest): #end define def CalculateLoanAmount_test(self): - min_loan = local.db.get("min_loan", 41000) - max_loan = local.db.get("max_loan", 43000) - max_interest_percent = local.db.get("max_interest_percent", 1.5) + min_loan = self.local.db.get("min_loan", 41000) + max_loan = self.local.db.get("max_loan", 43000) + max_interest_percent = self.local.db.get("max_interest_percent", 1.5) max_interest = int(max_interest_percent/100*16777216) return self.CalculateLoanAmount(min_loan, max_loan, max_interest) #end define def WaitLoan(self, controllerAddr): - local.add_log("start WaitLoan function", "debug") + self.local.add_log("start WaitLoan function", "debug") for i in range(10): time.sleep(3) controllerData = self.GetControllerData(controllerAddr) @@ -3891,7 +3893,7 @@ def WaitLoan(self, controllerAddr): #end define def ReturnUnusedLoan(self, controllerAddr): - local.add_log("start ReturnUnusedLoan function", "debug") + self.local.add_log("start ReturnUnusedLoan function", "debug") wallet = self.GetValidatorWallet() fileName = self.contractsDir + "jetton_pool/fift-scripts/return_unused_loan.boc" resultFilePath = self.SignBocWithWallet(wallet, fileName, controllerAddr, 1.05) @@ -3899,7 +3901,7 @@ def ReturnUnusedLoan(self, controllerAddr): #end define def DepositToController(self, controllerAddr, amount): - local.add_log("start DepositToController function", "debug") + self.local.add_log("start DepositToController function", "debug") wallet = self.GetValidatorWallet() fileName = self.contractsDir + "jetton_pool/fift-scripts/top-up.boc" resultFilePath = self.SignBocWithWallet(wallet, fileName, controllerAddr, amount) @@ -3922,7 +3924,7 @@ def WithdrawFromControllerProcess(self, controllerAddr, amount): return #end if - local.add_log("start WithdrawFromControllerProcess function", "debug") + self.local.add_log("start WithdrawFromControllerProcess function", "debug") wallet = self.GetValidatorWallet() fiftScript = self.contractsDir + "jetton_pool/fift-scripts/withdraw-controller.fif" resultFilePath = self.tempDir + self.nodeName + wallet.name + "_withdraw_request.boc" @@ -3933,10 +3935,10 @@ def WithdrawFromControllerProcess(self, controllerAddr, amount): #end define def PendWithdrawFromController(self, controllerAddr, amount): - local.add_log("start PendWithdrawFromController function", "debug") + self.local.add_log("start PendWithdrawFromController function", "debug") controllerPendingWithdraws = self.GetControllerPendingWithdraws() controllerPendingWithdraws[controllerAddr] = amount - local.save() + self.local.save() #end define def HandleControllerPendingWithdraw(self, controllerPendingWithdraws, controllerAddr): @@ -3947,37 +3949,37 @@ def HandleControllerPendingWithdraw(self, controllerPendingWithdraws, controller def GetControllerPendingWithdraws(self): bname = "controllerPendingWithdraws" - controllerPendingWithdraws = local.db.get(bname) + controllerPendingWithdraws = self.local.db.get(bname) if controllerPendingWithdraws is None: controllerPendingWithdraws = dict() - local.db[bname] = controllerPendingWithdraws + self.local.db[bname] = controllerPendingWithdraws return controllerPendingWithdraws #end define def SignElectionRequestWithController(self, controllerAddr, startWorkTime, adnlAddr, validatorPubkey_b64, validatorSignature, maxFactor, stake): - local.add_log("start SignElectionRequestWithController function", "debug") + self.local.add_log("start SignElectionRequestWithController function", "debug") fileName = self.tempDir + str(startWorkTime) + "_validator-query.boc" fiftScript = self.contractsDir + "jetton_pool/fift-scripts/controller-elect-signed.fif" args = [fiftScript, controllerAddr, startWorkTime, maxFactor, adnlAddr, validatorPubkey_b64, validatorSignature, fileName, stake] - local.add_log(f"SignElectionRequestWithController args: {args}", "debug") + self.local.add_log(f"SignElectionRequestWithController args: {args}", "debug") result = self.fift.Run(args) - local.add_log(f"SignElectionRequestWithController result: {result}", "debug") - pubkey = Pars(result, "validator public key ", '\n') - fileName = Pars(result, "Saved to file ", '\n') + self.local.add_log(f"SignElectionRequestWithController result: {result}", "debug") + pubkey = parse(result, "validator public key ", '\n') + fileName = parse(result, "Saved to file ", '\n') return pubkey, fileName #end define def ControllersUpdateValidatorSet(self): - local.add_log("start ControllersUpdateValidatorSet function", "debug") - using_controllers = local.db.get("using_controllers") - user_controllers = local.db.get("user_controllers", list()) - old_controllers = local.db.get("old_controllers", list()) + self.local.add_log("start ControllersUpdateValidatorSet function", "debug") + using_controllers = self.local.db.get("using_controllers") + user_controllers = self.local.db.get("user_controllers", list()) + old_controllers = self.local.db.get("old_controllers", list()) for controller in using_controllers + user_controllers + old_controllers: self.ControllerUpdateValidatorSet(controller) #end define def ControllerUpdateValidatorSet(self, controllerAddr): - local.add_log("start ControllerUpdateValidatorSet function", "debug") + self.local.add_log("start ControllerUpdateValidatorSet function", "debug") wallet = self.GetValidatorWallet() controllers = self.GetControllers() controllerData = self.GetControllerData(controllerAddr) @@ -4012,48 +4014,48 @@ def ControllerUpdateValidatorSet(self, controllerAddr): #end define def ControllerUpdateValidatorSetProcess(self, controllerAddr, wallet): - local.add_log("start ControllerUpdateValidatorSetProcess function", "debug") + self.local.add_log("start ControllerUpdateValidatorSetProcess function", "debug") fileName = self.contractsDir + "jetton_pool/fift-scripts/update_validator_hash.boc" resultFilePath = self.SignBocWithWallet(wallet, fileName, controllerAddr, 1.07) self.SendFile(resultFilePath, wallet) - local.add_log("ControllerUpdateValidatorSetProcess completed") + self.local.add_log("ControllerUpdateValidatorSetProcess completed") #end define def ControllerRecoverStake(self, controllerAddr): wallet = self.GetValidatorWallet() - local.add_log("start ControllerRecoverStake function", "debug") + self.local.add_log("start ControllerRecoverStake function", "debug") fileName = self.contractsDir + "jetton_pool/fift-scripts/recover_stake.boc" resultFilePath = self.SignBocWithWallet(wallet, fileName, controllerAddr, 1.04) self.SendFile(resultFilePath, wallet) - local.add_log("ControllerRecoverStake completed") + self.local.add_log("ControllerRecoverStake completed") #end define def StopController(self, controllerAddr): - stop_controllers_list = local.db.get("stop_controllers_list") + stop_controllers_list = self.local.db.get("stop_controllers_list") if stop_controllers_list is None: stop_controllers_list = list() if controllerAddr not in stop_controllers_list: stop_controllers_list.append(controllerAddr) - local.db["stop_controllers_list"] = stop_controllers_list + self.local.db["stop_controllers_list"] = stop_controllers_list - user_controllers = local.db.get("user_controllers") + user_controllers = self.local.db.get("user_controllers") if user_controllers is not None and controllerAddr in user_controllers: user_controllers.remove(controllerAddr) - local.save() + self.local.save() #end define def AddController(self, controllerAddr): - user_controllers = local.db.get("user_controllers") + user_controllers = self.local.db.get("user_controllers") if user_controllers is None: user_controllers = list() if controllerAddr not in user_controllers: user_controllers.append(controllerAddr) - local.db["user_controllers"] = user_controllers + self.local.db["user_controllers"] = user_controllers - stop_controllers_list = local.db.get("stop_controllers_list") + stop_controllers_list = self.local.db.get("stop_controllers_list") if stop_controllers_list is not None and controllerAddr in stop_controllers_list: stop_controllers_list.remove(controllerAddr) - local.save() + self.local.save() #end define def CheckLiquidPool(self): From 0db8293c14fda61f1b2e73fa594514f887cf220e Mon Sep 17 00:00:00 2001 From: yungwine Date: Thu, 29 Feb 2024 13:57:48 +0700 Subject: [PATCH 43/43] add controllecrs to mytonctrl.py --- mytonctrl/mytonctrl.py | 153 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 153 insertions(+) diff --git a/mytonctrl/mytonctrl.py b/mytonctrl/mytonctrl.py index b4a7768a..2b47e6a6 100755 --- a/mytonctrl/mytonctrl.py +++ b/mytonctrl/mytonctrl.py @@ -138,6 +138,20 @@ def inject_globals(func): console.AddItem("activate_single_pool", inject_globals(activate_single_pool), local.translate("activate_single_pool_cmd")) console.AddItem("import_pool", inject_globals(import_pool), local.translate("import_pool_cmd")) + console.AddItem("create_controllers", inject_globals(CreateControllers), local.translate("_")) + console.AddItem("update_controllers", inject_globals(CreateControllers), local.translate("_")) + console.AddItem("controllers_list", inject_globals(PrintControllersList), local.translate("_")) + console.AddItem("get_controller_data", inject_globals(GetControllerData), local.translate("_")) + console.AddItem("deposit_to_controller", inject_globals(DepositToController), local.translate("_")) + console.AddItem("withdraw_from_controller", inject_globals(WithdrawFromController), local.translate("_")) + console.AddItem("calculate_annual_controller_percentage", inject_globals(CalculateAnnualControllerPercentage), local.translate("_")) + console.AddItem("controller_update_validator_set", inject_globals(ControllerUpdateValidatorSet), local.translate("_")) + console.AddItem("stop_controller", inject_globals(StopController), local.translate("_")) + console.AddItem("stop_and_withdraw_controller", inject_globals(StopAndWithdrawController), local.translate("_")) + console.AddItem("add_controller", inject_globals(AddController), local.translate("_")) + console.AddItem("check_liquid_pool", inject_globals(CheckLiquidPool), local.translate("_")) + console.AddItem("test_calculate_loan_amount", inject_globals(CalculateLoanAmount_test), local.translate("_")) + # console.AddItem("pt", inject_globals(PrintTest), "PrintTest") # console.AddItem("sl", inject_globals(sl), "sl") console.AddItem("cleanup", inject_globals(cleanup_validator_db), local.translate("cleanup_cmd")) @@ -1489,6 +1503,145 @@ def import_pool(ton, args): color_print("import_pool - {green}OK{endc}") #end define +def CreateControllers(ton, args): + ton.CreateControllers() + color_print("CreateControllers - {green}OK{endc}") +#end define + +def PrintControllersList(ton, args): + new_controllers = ton.GetControllers() + using_controllers = ton.GetSettings("using_controllers") + old_controllers = ton.GetSettings("old_controllers") + user_controllers_list = ton.GetSettings("user_controllers_list") + print("using controllers:") + PrintControllersListProcess(ton, using_controllers) + if new_controllers != using_controllers: + print() + print("new controllers:") + PrintControllersListProcess(ton, new_controllers) + if old_controllers is not None and len(old_controllers) > 0: + print() + print("old controllers:") + PrintControllersListProcess(ton, old_controllers) + if user_controllers_list is not None and len(user_controllers_list) > 0: + print() + print("user controllers:") + PrintControllersListProcess(ton, user_controllers_list) +#end define + +def PrintControllersListProcess(ton, controllers): + table = list() + table += [["Address", "Status", "Balance", "Approved", "State"]] + for controllerAddr in controllers: + account = ton.GetAccount(controllerAddr) + controllerData = ton.GetControllerData(controllerAddr) + approved = True if controllerData and controllerData["approved"] == -1 else False + state = controllerData["state"] if controllerData else None + table += [[controllerAddr, account.status, account.balance, approved, state]] + print_table(table) +#end define + +def GetControllerData(ton, args): + try: + controllerAddr = args[0] + except: + color_print("{red}Bad args. Usage:{endc} get_controller_data ") + return + controllerData = ton.GetControllerData(controllerAddr) + print(json.dumps(controllerData, indent=4)) +#end define + +def DepositToController(ton, args): + try: + controllerAddr = args[0] + amount = float(args[1]) + except: + color_print("{red}Bad args. Usage:{endc} deposit_to_controller ") + return + ton.DepositToController(controllerAddr, amount) +#end define + +def WithdrawFromController(ton, args): + try: + controllerAddr = args[0] + amount = GetItemFromList(args, 1) + except: + color_print("{red}Bad args. Usage:{endc} withdraw_from_controller [amount]") + return + ton.WithdrawFromController(controllerAddr, amount) +#end define + +def CalculateAnnualControllerPercentage(ton, args): + try: + percentPerRound = float(args[0]) + except: + percentPerRound = ton.GetSettings("max_interest_percent") + config15 = ton.GetConfig(15) + roundPeriod = config15["validators_elected_for"] + rounds = 365 * 24 * 3600 / roundPeriod + yearInterest = (1 + percentPerRound / 100) * rounds + yearInterestPercent = round(yearInterest / 100, 2) + print("roundPeriod", roundPeriod) + print("rounds", rounds) + print("percentPerRound", percentPerRound) + print("yearInterest", yearInterest) + print(f"yearInterestPercent: {yearInterestPercent}%") +#end define + +def ControllerUpdateValidatorSet(ton, args): + try: + controllerAddr = args[0] + except: + color_print("{red}Bad args. Usage:{endc} controller_update_validator_set ") + return + ton.ControllerUpdateValidatorSet(controllerAddr) + color_print("ControllerUpdateValidatorSet - {green}OK{endc}") +#end define + +def StopController(ton, args): + try: + controllerAddr = args[0] + except: + color_print("{red}Bad args. Usage:{endc} stop_controller ") + return + ton.StopController(controllerAddr) + color_print("StopController - {green}OK{endc}") +#end define + +def StopAndWithdrawController(ton, args): + try: + controllerAddr = args[0] + amount = GetItemFromList(args, 1) + except: + color_print("{red}Bad args. Usage:{endc} stop_and_withdraw_controller [amount]") + return + if amount is None: + account = ton.GetAccount(controllerAddr) + amount = account.balance-10.1 + ton.StopController(controllerAddr) + ton.WithdrawFromController(controllerAddr, amount) + color_print("StopAndWithdrawController - {green}OK{endc}") +#end define + +def AddController(ton, args): + try: + controllerAddr = args[0] + except: + color_print("{red}Bad args. Usage:{endc} add_controller ") + return + ton.AddController(controllerAddr) + color_print("AddController - {green}OK{endc}") +#end define + +def CheckLiquidPool(ton, args): + ton.CheckLiquidPool() + color_print("CheckLiquidPool - {green}OK{endc}") +#end define + +def CalculateLoanAmount_test(ton, args): + t = ton.CalculateLoanAmount_test() + print(t) + ### ### Start of the program