Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 41 additions & 1 deletion modules/validator.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from mypylib.mypylib import color_print
from mypylib.mypylib import color_print, get_timestamp
from modules.module import MtcModule
from mytonctrl.utils import timestamp2utcdatetime, GetColorInt


class ValidatorModule(MtcModule):
Expand Down Expand Up @@ -32,7 +33,46 @@ def vote_complaint(self, args):
self.ton.VoteComplaint(election_id, complaint_hash)
color_print("VoteComplaint - {green}OK{endc}")

def find_myself(self, validators: list) -> dict:
adnl_addr = self.ton.GetAdnlAddr()
for validator in validators:
if validator.get("adnlAddr") == adnl_addr:
return validator
return None

def check_efficiency(self, args):
self.local.add_log("start GetValidatorEfficiency function", "debug")
validators = self.ton.GetValidatorsList(past=True)
validator = self.find_myself(validators)
config32 = self.ton.GetConfig32()
if validator:
efficiency = GetColorInt(validator["efficiency"], 90, logic="more", ending=" %")
expected = validator['blocks_expected']
created = validator['blocks_created']
print('#' * 30)
print(
f"Previous round efficiency: {efficiency} ({created} blocks created / {expected} blocks expected) from {timestamp2utcdatetime(config32['startWorkTime'])} to {timestamp2utcdatetime(config32['endWorkTime'])}")
print('#' * 30)
else:
print("Couldn't find this validator in the past round")
validators = self.ton.GetValidatorsList()
validator = self.find_myself(validators)
config34 = self.ton.GetConfig34()
if validator:
efficiency = GetColorInt(validator["efficiency"], 90, logic="more", ending=" %")
expected = validator['blocks_expected']
created = validator['blocks_created']
print('#' * 30)
print(
f"Current round efficiency: {efficiency} ({created} blocks created / {expected} blocks expected) from {timestamp2utcdatetime(config34['startWorkTime'])} to {timestamp2utcdatetime(int(get_timestamp()))}")
print('#' * 30)
else:
print("Couldn't find this validator in the current round")

# end define

def add_console_commands(self, console):
console.AddItem("vo", self.vote_offer, self.local.translate("vo_cmd"))
console.AddItem("ve", self.vote_election_entry, self.local.translate("ve_cmd"))
console.AddItem("vc", self.vote_complaint, self.local.translate("vc_cmd"))
console.AddItem("check_ef", self.check_efficiency, self.local.translate("check_ef_cmd"))
1 change: 1 addition & 0 deletions mytoncore/functions.py
Original file line number Diff line number Diff line change
Expand Up @@ -521,6 +521,7 @@ def Slashing(local, ton):
def save_past_events(local, ton):
local.try_function(ton.GetElectionEntries)
local.try_function(ton.GetComplaints)
local.try_function(ton.GetValidatorsList, args=[True]) # cache past vl


def ScanLiteServers(local, ton):
Expand Down
49 changes: 44 additions & 5 deletions mytoncore/mytoncore.py
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,7 @@ def GetConfig32(self):
config32 = dict()
result = self.liteClient.Run("getconfig 32")
config32["totalValidators"] = int(parse(result, "total:", ' '))
config32["mainValidators"] = int(parse(result, "main:", ' '))
config32["startWorkTime"] = int(parse(result, "utime_since:", ' '))
config32["endWorkTime"] = int(parse(result, "utime_until:", ' '))
lines = result.split('\n')
Expand Down Expand Up @@ -952,6 +953,7 @@ def GetConfig34(self):
config34 = dict()
result = self.liteClient.Run("getconfig 34")
config34["totalValidators"] = int(parse(result, "total:", ' '))
config34["mainValidators"] = int(parse(result, "main:", ' '))
config34["startWorkTime"] = int(parse(result, "utime_since:", ' '))
config34["endWorkTime"] = int(parse(result, "utime_until:", ' '))
config34["totalWeight"] = int(parse(result, "total_weight:", ' '))
Expand Down Expand Up @@ -2320,6 +2322,19 @@ def GetSaveComplaints(self):
return saveComplaints
#end define

def GetSaveVl(self):
timestamp = get_timestamp()
save_vl = self.local.db.get("saveValidatorsLoad")
if save_vl is None:
save_vl = dict()
self.local.db["saveValidatorsLoad"] = save_vl
for key, item in list(save_vl.items()):
diff_time = timestamp - int(key)
if diff_time > 172800: # 48 hours
save_vl.pop(key)
return save_vl
#end define

def GetAdnlFromPubkey(self, inputPubkey):
config32 = self.GetConfig32()
validators = config32["validators"]
Expand Down Expand Up @@ -2467,12 +2482,17 @@ def get_valid_complaints(self, complaints: dict, election_id: int):
pseudohash = pubkey + str(election_id)
if pseudohash == complaint['pseudohash']:
exists = True
vid = item['id']
break

if not exists:
self.local.add_log(f"complaint {complaint['hash_hex']} declined: complaint info was not found, probably it's wrong", "info")
continue

if vid >= config32['mainValidators']:
self.local.add_log(f"complaint {complaint['hash_hex']} declined: complaint created for non masterchain validator", "info")
continue

# check complaint fine value
if complaint['suggestedFine'] != 101: # https://github.com/ton-blockchain/ton/blob/5847897b3758bc9ea85af38e7be8fc867e4c133a/lite-client/lite-client.cpp#L3708
self.local.add_log(f"complaint {complaint['hash_hex']} declined: complaint fine value is {complaint['suggestedFine']} ton", "info")
Expand All @@ -2486,7 +2506,7 @@ def get_valid_complaints(self, complaints: dict, election_id: int):

def GetOnlineValidators(self):
onlineValidators = list()
validators = self.GetValidatorsList()
validators = self.GetValidatorsList(fast=True)
for validator in validators:
online = validator.get("online")
if online is True:
Expand All @@ -2503,7 +2523,6 @@ def GetValidatorsLoad(self, start, end, saveCompFiles=False) -> dict:
if buff:
return buff
#end if

text = "start GetValidatorsLoad function ({}, {})".format(start, end)
self.local.add_log(text, "debug")
if saveCompFiles is True:
Expand Down Expand Up @@ -2579,7 +2598,7 @@ def GetValidatorsLoad(self, start, end, saveCompFiles=False) -> dict:
return data
#end define

def GetValidatorsList(self, past=False):
def GetValidatorsList(self, past=False, fast=False):
# Get buffer
bname = "validatorsList" + str(past)
buff = self.GetFunctionBuffer(bname, timeout=60)
Expand All @@ -2589,13 +2608,20 @@ def GetValidatorsList(self, past=False):

timestamp = get_timestamp()
end = timestamp - 60
start = end - 2000
config = self.GetConfig34()
if fast:
start = end - 1000
else:
start = config.get("startWorkTime")
if past:
config = self.GetConfig32()
start = config.get("startWorkTime")
end = config.get("endWorkTime") - 60
save_vl = self.GetSaveVl()
if start in save_vl:
return save_vl[start]
#end if

validatorsLoad = self.GetValidatorsLoad(start, end)
validators = config["validators"]
electionId = config.get("startWorkTime")
Expand All @@ -2608,12 +2634,22 @@ def GetValidatorsList(self, past=False):
validator["wr"] = validatorsLoad[vid]["wr"]
validator["efficiency"] = validatorsLoad[vid]["efficiency"]
validator["online"] = validatorsLoad[vid]["online"]
validator["blocks_created"] = validatorsLoad[vid]["masterBlocksCreated"] + validatorsLoad[vid]["workBlocksCreated"]
validator["blocks_expected"] = validatorsLoad[vid]["masterBlocksExpected"] + validatorsLoad[vid]["workBlocksExpected"]
validator["is_masterchain"] = False
if vid < config["mainValidators"]:
validator["is_masterchain"] = True
if not validator["is_masterchain"]:
validator["efficiency"] = round(validator["wr"] * 100, 2)
if saveElectionEntries and adnlAddr in saveElectionEntries:
validator["walletAddr"] = saveElectionEntries[adnlAddr]["walletAddr"]
#end for

# Set buffer
self.SetFunctionBuffer(bname, validators)
if past:
save_vl = self.GetSaveVl()
save_vl[start] = validators
return validators
#end define

Expand All @@ -2625,6 +2661,7 @@ def CheckValidators(self, start, end):
data = self.GetValidatorsLoad(start, end, saveCompFiles=True)
fullElectorAddr = self.GetFullElectorAddr()
wallet = self.GetValidatorWallet(mode="vote")
config = self.GetConfig32()

# Check wallet and balance
if wallet is None:
Expand All @@ -2642,6 +2679,8 @@ def CheckValidators(self, start, end):
pseudohash = pubkey + str(electionId)
if pseudohash in valid_complaints:
continue
if item['id'] >= config['mainValidators']: # do not create complaints for non-masterchain validators
continue
# Create complaint
fileName = self.remove_proofs_from_complaint(fileName)
fileName = self.PrepareComplaint(electionId, fileName)
Expand Down Expand Up @@ -3463,7 +3502,7 @@ def ImportCertificate(self, pubkey, fileName):

def GetValidatorsWalletsList(self):
result = list()
vl = self.GetValidatorsList()
vl = self.GetValidatorsList(fast=True)
for item in vl:
walletAddr = item["walletAddr"]
result.append(walletAddr)
Expand Down
32 changes: 9 additions & 23 deletions mytonctrl/mytonctrl.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
)
from mytoncore.telemetry import is_host_virtual
from mytonctrl.migrate import run_migrations
from mytonctrl.utils import GetItemFromList, timestamp2utcdatetime, fix_git_config
from mytonctrl.utils import GetItemFromList, timestamp2utcdatetime, fix_git_config, GetColorInt

import sys, getopt, os

Expand Down Expand Up @@ -578,7 +578,7 @@ def PrintStatus(local, ton, args):

if opt != "fast":
onlineValidators = ton.GetOnlineValidators()
validator_efficiency = ton.GetValidatorEfficiency()
# validator_efficiency = ton.GetValidatorEfficiency()
if onlineValidators:
onlineValidators = len(onlineValidators)

Expand Down Expand Up @@ -761,7 +761,7 @@ def PrintLocalStatus(local, adnlAddr, validatorIndex, validatorEfficiency, valid

color_print(local.translate("local_status_head"))
print(validatorIndex_text)
print(validatorEfficiency_text)
# print(validatorEfficiency_text)
print(adnlAddr_text)
print(fullnode_adnl_text)
print(walletAddr_text)
Expand All @@ -781,22 +781,6 @@ def PrintLocalStatus(local, adnlAddr, validatorIndex, validatorEfficiency, valid
print()
#end define

def GetColorInt(data, border, logic, ending=None):
if data is None:
result = "n/a"
elif logic == "more":
if data >= border:
result = bcolors.green_text(data, ending)
else:
result = bcolors.red_text(data, ending)
elif logic == "less":
if data <= border:
result = bcolors.green_text(data, ending)
else:
result = bcolors.red_text(data, ending)
return result
#end define

def GetColorStatus(input):
if input == True:
result = bcolors.green_text("working")
Expand Down Expand Up @@ -873,6 +857,7 @@ def PrintTimes(local, rootWorkchainEnabledTime_int, startWorkTime, oldStartWorkT
print(startNextElectionTime_text)
#end define


def GetColorTime(datetime, timestamp):
newTimestamp = get_timestamp()
if timestamp > newTimestamp:
Expand Down Expand Up @@ -1344,7 +1329,8 @@ def PrintElectionEntriesList(ton, args):

def PrintValidatorList(ton, args):
past = "past" in args
data = ton.GetValidatorsList(past=past)
fast = "fast" in args
data = ton.GetValidatorsList(past=past, fast=fast)
if (data is None or len(data) == 0):
print("No data")
return
Expand All @@ -1353,8 +1339,8 @@ def PrintValidatorList(ton, args):
print(text)
else:
table = list()
table += [["ADNL", "Pubkey", "Wallet", "Efficiency", "Online"]]
for item in data:
table += [["id", "ADNL", "Pubkey", "Wallet", "Efficiency", "Online"]]
for i, item in enumerate(data):
adnl = item.get("adnlAddr")
pubkey = item.get("pubkey")
walletAddr = item.get("walletAddr")
Expand All @@ -1372,7 +1358,7 @@ def PrintValidatorList(ton, args):
online = bcolors.green_text("true")
if online == False:
online = bcolors.red_text("false")
table += [[adnl, pubkey, walletAddr, efficiency, online]]
table += [[str(i), adnl, pubkey, walletAddr, efficiency, online]]
print_table(table)
#end define

Expand Down
5 changes: 5 additions & 0 deletions mytonctrl/resources/translate.json
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,11 @@
"ru": "Запустить установщик модулей TON",
"zh_TW": "執行 TON 模組的安裝程序"
},
"check_ef_cmd": {
"en": "Check the efficiency of the validator",
"ru": "Проверить эффективность валидатора",
"zh_TW": "檢查驗證者的效率"
},
"ton_status_head": {
"en": "{cyan}===[ TON network status ]==={endc}",
"ru": "{cyan}===[ Статус сети TON ]==={endc}",
Expand Down
20 changes: 19 additions & 1 deletion mytonctrl/utils.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import subprocess
import time

from mypylib.mypylib import bcolors


def timestamp2utcdatetime(timestamp, format="%d.%m.%Y %H:%M:%S"):
datetime = time.gmtime(timestamp)
Expand Down Expand Up @@ -28,4 +30,20 @@ def fix_git_config(git_path: str):
subprocess.run(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=3)
else:
raise Exception(f'Failed to check git status: {err}')
#end define
# end define

def GetColorInt(data, border, logic, ending=None):
if data is None:
result = "n/a"
elif logic == "more":
if data >= border:
result = bcolors.green_text(data, ending)
else:
result = bcolors.red_text(data, ending)
elif logic == "less":
if data <= border:
result = bcolors.green_text(data, ending)
else:
result = bcolors.red_text(data, ending)
return result
# end define