Skip to content

Commit 2c127c4

Browse files
committed
Merge branch 'master' into dev
# Conflicts: # mytonctrl/mytonctrl.py # mytonctrl/scripts/upgrade.sh
2 parents 2bbcb34 + 6cc6705 commit 2c127c4

File tree

7 files changed

+149
-41
lines changed

7 files changed

+149
-41
lines changed

modules/validator.py

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
from mypylib.mypylib import color_print
1+
import time
2+
3+
from mypylib.mypylib import color_print, get_timestamp
24
from modules.module import MtcModule
5+
from mytonctrl.utils import timestamp2utcdatetime, GetColorInt
36

47

58
class ValidatorModule(MtcModule):
@@ -32,7 +35,61 @@ def vote_complaint(self, args):
3235
self.ton.VoteComplaint(election_id, complaint_hash)
3336
color_print("VoteComplaint - {green}OK{endc}")
3437

38+
def find_myself(self, validators: list) -> dict:
39+
adnl_addr = self.ton.GetAdnlAddr()
40+
for validator in validators:
41+
if validator.get("adnlAddr") == adnl_addr:
42+
return validator
43+
return None
44+
45+
def check_efficiency(self, args):
46+
self.local.add_log("start GetValidatorEfficiency function", "debug")
47+
previous_validators = self.ton.GetValidatorsList(past=True)
48+
validators = self.ton.GetValidatorsList()
49+
validator = self.find_myself(previous_validators)
50+
config32 = self.ton.GetConfig32()
51+
config34 = self.ton.GetConfig34()
52+
color_print("{cyan}===[ Validator efficiency ]==={endc}")
53+
start_time = timestamp2utcdatetime(config32.startWorkTime)
54+
end_time = timestamp2utcdatetime(config32.endWorkTime)
55+
color_print(f"Previous round time: {{yellow}}from {start_time} to {end_time}{{endc}}")
56+
if validator:
57+
if validator.is_masterchain == False:
58+
print("Validator index is greater than 100 in the previous round - no efficiency data.")
59+
elif validator.get('efficiency') is None:
60+
print('Failed to get efficiency for the previous round')
61+
else:
62+
efficiency = 100 if validator.efficiency > 100 else validator.efficiency
63+
color_efficiency = GetColorInt(efficiency, 90, logic="more", ending="%")
64+
created = validator.blocks_created
65+
expected = validator.blocks_expected
66+
color_print(f"Previous round efficiency: {color_efficiency} {{yellow}}({created} blocks created / {round(expected, 1)} blocks expected){{endc}}")
67+
else:
68+
print("Couldn't find this validator in the previous round")
69+
validator = self.find_myself(validators)
70+
start_time = timestamp2utcdatetime(config34.startWorkTime)
71+
end_time = timestamp2utcdatetime(int(get_timestamp()))
72+
color_print(f"Current round time: {{green}}from {start_time} to {end_time}{{endc}}")
73+
if validator:
74+
if validator.is_masterchain == False:
75+
print("Validator index is greater than 100 in the current round - no efficiency data.")
76+
elif (time.time() - config34.startWorkTime) / (config34.endWorkTime - config34.startWorkTime) < 0.8:
77+
print("The validation round has started recently, there is not enough data yet. "
78+
"The efficiency evaluation will become more accurate towards the end of the round.")
79+
elif validator.get('efficiency') is None:
80+
print('Failed to get efficiency for the current round')
81+
else:
82+
efficiency = 100 if validator.efficiency > 100 else validator.efficiency
83+
color_efficiency = GetColorInt(efficiency, 90, logic="more", ending="%")
84+
created = validator.blocks_created
85+
expected = validator.blocks_expected
86+
color_print(f"Current round efficiency: {color_efficiency} {{yellow}}({created} blocks created / {round(expected, 1)} blocks expected){{endc}}")
87+
else:
88+
print("Couldn't find this validator in the current round")
89+
# end define
90+
3591
def add_console_commands(self, console):
3692
console.AddItem("vo", self.vote_offer, self.local.translate("vo_cmd"))
3793
console.AddItem("ve", self.vote_election_entry, self.local.translate("ve_cmd"))
3894
console.AddItem("vc", self.vote_complaint, self.local.translate("vc_cmd"))
95+
console.AddItem("check_ef", self.check_efficiency, self.local.translate("check_ef_cmd"))

mytoncore/functions.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,7 @@ def Slashing(local, ton):
515515
def save_past_events(local, ton):
516516
local.try_function(ton.GetElectionEntries)
517517
local.try_function(ton.GetComplaints)
518+
local.try_function(ton.GetValidatorsList, args=[True]) # cache past vl
518519

519520

520521
def ScanLiteServers(local, ton):

mytoncore/mytoncore.py

Lines changed: 49 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -870,9 +870,10 @@ def GetConfig32(self):
870870
#end if
871871

872872
self.local.add_log("start GetConfig32 function", "debug")
873-
config32 = dict()
873+
config32 = Dict()
874874
result = self.liteClient.Run("getconfig 32")
875875
config32["totalValidators"] = int(parse(result, "total:", ' '))
876+
config32["mainValidators"] = int(parse(result, "main:", ' '))
876877
config32["startWorkTime"] = int(parse(result, "utime_since:", ' '))
877878
config32["endWorkTime"] = int(parse(result, "utime_until:", ' '))
878879
lines = result.split('\n')
@@ -885,7 +886,7 @@ def GetConfig32(self):
885886
validatorWeight = int(parse(line, "weight:", ' '))
886887
except ValueError:
887888
validatorWeight = int(parse(line, "weight:", ')'))
888-
buff = dict()
889+
buff = Dict()
889890
buff["adnlAddr"] = validatorAdnlAddr
890891
buff["pubkey"] = pubkey
891892
buff["weight"] = validatorWeight
@@ -906,9 +907,10 @@ def GetConfig34(self):
906907
#end if
907908

908909
self.local.add_log("start GetConfig34 function", "debug")
909-
config34 = dict()
910+
config34 = Dict()
910911
result = self.liteClient.Run("getconfig 34")
911912
config34["totalValidators"] = int(parse(result, "total:", ' '))
913+
config34["mainValidators"] = int(parse(result, "main:", ' '))
912914
config34["startWorkTime"] = int(parse(result, "utime_since:", ' '))
913915
config34["endWorkTime"] = int(parse(result, "utime_until:", ' '))
914916
config34["totalWeight"] = int(parse(result, "total_weight:", ' '))
@@ -922,7 +924,7 @@ def GetConfig34(self):
922924
validatorWeight = int(parse(line, "weight:", ' '))
923925
except ValueError:
924926
validatorWeight = int(parse(line, "weight:", ')'))
925-
buff = dict()
927+
buff = Dict()
926928
buff["adnlAddr"] = validatorAdnlAddr
927929
buff["pubkey"] = pubkey
928930
buff["weight"] = validatorWeight
@@ -2152,6 +2154,19 @@ def GetSaveComplaints(self):
21522154
return saveComplaints
21532155
#end define
21542156

2157+
def GetSaveVl(self):
2158+
timestamp = get_timestamp()
2159+
save_vl = self.local.db.get("saveValidatorsLoad")
2160+
if save_vl is None:
2161+
save_vl = dict()
2162+
self.local.db["saveValidatorsLoad"] = save_vl
2163+
for key, item in list(save_vl.items()):
2164+
diff_time = timestamp - int(key)
2165+
if diff_time > 172800: # 48 hours
2166+
save_vl.pop(key)
2167+
return save_vl
2168+
#end define
2169+
21552170
def GetAdnlFromPubkey(self, inputPubkey):
21562171
config32 = self.GetConfig32()
21572172
validators = config32["validators"]
@@ -2299,12 +2314,17 @@ def get_valid_complaints(self, complaints: dict, election_id: int):
22992314
pseudohash = pubkey + str(election_id)
23002315
if pseudohash == complaint['pseudohash']:
23012316
exists = True
2317+
vid = item['id']
23022318
break
23032319

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

2324+
if vid >= config32['mainValidators']:
2325+
self.local.add_log(f"complaint {complaint['hash_hex']} declined: complaint created for non masterchain validator", "info")
2326+
continue
2327+
23082328
# check complaint fine value
23092329
if complaint['suggestedFine'] != 101: # https://github.com/ton-blockchain/ton/blob/5847897b3758bc9ea85af38e7be8fc867e4c133a/lite-client/lite-client.cpp#L3708
23102330
self.local.add_log(f"complaint {complaint['hash_hex']} declined: complaint fine value is {complaint['suggestedFine']} ton", "info")
@@ -2318,7 +2338,7 @@ def get_valid_complaints(self, complaints: dict, election_id: int):
23182338

23192339
def GetOnlineValidators(self):
23202340
onlineValidators = list()
2321-
validators = self.GetValidatorsList()
2341+
validators = self.GetValidatorsList(fast=True)
23222342
for validator in validators:
23232343
online = validator.get("online")
23242344
if online is True:
@@ -2335,7 +2355,6 @@ def GetValidatorsLoad(self, start, end, saveCompFiles=False) -> dict:
23352355
if buff:
23362356
return buff
23372357
#end if
2338-
23392358
text = "start GetValidatorsLoad function ({}, {})".format(start, end)
23402359
self.local.add_log(text, "debug")
23412360
if saveCompFiles is True:
@@ -2411,7 +2430,7 @@ def GetValidatorsLoad(self, start, end, saveCompFiles=False) -> dict:
24112430
return data
24122431
#end define
24132432

2414-
def GetValidatorsList(self, past=False):
2433+
def GetValidatorsList(self, past=False, fast=False):
24152434
# Get buffer
24162435
bname = "validatorsList" + str(past)
24172436
buff = self.GetFunctionBuffer(bname, timeout=60)
@@ -2421,13 +2440,21 @@ def GetValidatorsList(self, past=False):
24212440

24222441
timestamp = get_timestamp()
24232442
end = timestamp - 60
2424-
start = end - 2000
24252443
config = self.GetConfig34()
2444+
if fast:
2445+
start = end - 1000
2446+
else:
2447+
start = config.get("startWorkTime")
24262448
if past:
24272449
config = self.GetConfig32()
24282450
start = config.get("startWorkTime")
24292451
end = config.get("endWorkTime") - 60
2452+
save_vl = self.GetSaveVl()
2453+
start_str = str(start)
2454+
if start_str in save_vl:
2455+
return save_vl[start_str]
24302456
#end if
2457+
24312458
validatorsLoad = self.GetValidatorsLoad(start, end)
24322459
validators = config["validators"]
24332460
electionId = config.get("startWorkTime")
@@ -2440,12 +2467,22 @@ def GetValidatorsList(self, past=False):
24402467
validator["wr"] = validatorsLoad[vid]["wr"]
24412468
validator["efficiency"] = validatorsLoad[vid]["efficiency"]
24422469
validator["online"] = validatorsLoad[vid]["online"]
2470+
validator["blocks_created"] = validatorsLoad[vid]["masterBlocksCreated"] + validatorsLoad[vid]["workBlocksCreated"]
2471+
validator["blocks_expected"] = validatorsLoad[vid]["masterBlocksExpected"] + validatorsLoad[vid]["workBlocksExpected"]
2472+
validator["is_masterchain"] = False
2473+
if vid < config["mainValidators"]:
2474+
validator["is_masterchain"] = True
2475+
if not validator["is_masterchain"]:
2476+
validator["efficiency"] = round(validator["wr"] * 100, 2)
24432477
if saveElectionEntries and adnlAddr in saveElectionEntries:
24442478
validator["walletAddr"] = saveElectionEntries[adnlAddr]["walletAddr"]
24452479
#end for
24462480

24472481
# Set buffer
24482482
self.SetFunctionBuffer(bname, validators)
2483+
if past:
2484+
save_vl = self.GetSaveVl()
2485+
save_vl[str(start)] = validators
24492486
return validators
24502487
#end define
24512488

@@ -2457,6 +2494,7 @@ def CheckValidators(self, start, end):
24572494
data = self.GetValidatorsLoad(start, end, saveCompFiles=True)
24582495
fullElectorAddr = self.GetFullElectorAddr()
24592496
wallet = self.GetValidatorWallet(mode="vote")
2497+
config = self.GetConfig32()
24602498

24612499
# Check wallet and balance
24622500
if wallet is None:
@@ -2474,6 +2512,8 @@ def CheckValidators(self, start, end):
24742512
pseudohash = pubkey + str(electionId)
24752513
if pseudohash in valid_complaints:
24762514
continue
2515+
if item['id'] >= config['mainValidators']: # do not create complaints for non-masterchain validators
2516+
continue
24772517
# Create complaint
24782518
fileName = self.remove_proofs_from_complaint(fileName)
24792519
fileName = self.PrepareComplaint(electionId, fileName)
@@ -3188,7 +3228,7 @@ def ImportCertificate(self, pubkey, fileName):
31883228

31893229
def GetValidatorsWalletsList(self):
31903230
result = list()
3191-
vl = self.GetValidatorsList()
3231+
vl = self.GetValidatorsList(fast=True)
31923232
for item in vl:
31933233
walletAddr = item["walletAddr"]
31943234
result.append(walletAddr)

mytonctrl/mytonctrl.py

Lines changed: 4 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
)
4343
from mytoncore.telemetry import is_host_virtual
4444
from mytonctrl.migrate import run_migrations
45-
from mytonctrl.utils import GetItemFromList, timestamp2utcdatetime, fix_git_config, is_hex
45+
from mytonctrl.utils import GetItemFromList, timestamp2utcdatetime, fix_git_config, is_hex, GetColorInt
4646

4747
import sys, getopt, os
4848

@@ -542,7 +542,7 @@ def PrintStatus(local, ton, args):
542542

543543
if opt != "fast":
544544
onlineValidators = ton.GetOnlineValidators()
545-
validator_efficiency = ton.GetValidatorEfficiency()
545+
# validator_efficiency = ton.GetValidatorEfficiency()
546546
if onlineValidators:
547547
onlineValidators = len(onlineValidators)
548548

@@ -726,7 +726,7 @@ def PrintLocalStatus(local, ton, adnlAddr, validatorIndex, validatorEfficiency,
726726
color_print(local.translate("local_status_head"))
727727
if ton.using_validator():
728728
print(validatorIndex_text)
729-
print(validatorEfficiency_text)
729+
# print(validatorEfficiency_text)
730730
print(adnlAddr_text)
731731
print(fullnode_adnl_text)
732732
if ton.using_validator():
@@ -747,22 +747,6 @@ def PrintLocalStatus(local, ton, adnlAddr, validatorIndex, validatorEfficiency,
747747
print()
748748
#end define
749749

750-
def GetColorInt(data, border, logic, ending=None):
751-
if data is None:
752-
result = "n/a"
753-
elif logic == "more":
754-
if data >= border:
755-
result = bcolors.green_text(data, ending)
756-
else:
757-
result = bcolors.red_text(data, ending)
758-
elif logic == "less":
759-
if data <= border:
760-
result = bcolors.green_text(data, ending)
761-
else:
762-
result = bcolors.red_text(data, ending)
763-
return result
764-
#end define
765-
766750
def GetColorStatus(input):
767751
if input == True:
768752
result = bcolors.green_text("working")
@@ -839,6 +823,7 @@ def PrintTimes(local, rootWorkchainEnabledTime_int, startWorkTime, oldStartWorkT
839823
print(startNextElectionTime_text)
840824
#end define
841825

826+
842827
def GetColorTime(datetime, timestamp):
843828
newTimestamp = get_timestamp()
844829
if timestamp > newTimestamp:

mytonctrl/resources/translate.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,6 +199,11 @@
199199
"ru": "Запустить установщик модулей TON",
200200
"zh_TW": "執行 TON 模組的安裝程序"
201201
},
202+
"check_ef_cmd": {
203+
"en": "Check the efficiency of the validator",
204+
"ru": "Проверить эффективность валидатора",
205+
"zh_TW": "檢查驗證者的效率"
206+
},
202207
"ton_status_head": {
203208
"en": "{cyan}===[ TON network status ]==={endc}",
204209
"ru": "{cyan}===[ Статус сети TON ]==={endc}",

mytonctrl/scripts/upgrade.sh

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -48,22 +48,24 @@ else
4848
systemctl daemon-reload
4949
fi
5050

51-
# compile openssl_3
52-
rm -rf ${bindir}/openssl_3
53-
git clone https://github.com/openssl/openssl ${bindir}/openssl_3
54-
cd ${bindir}/openssl_3
55-
git checkout openssl-3.1.4
56-
./config
57-
make build_libs -j$(nproc)
58-
opensslPath=`pwd`
51+
if [ ! -d "${bindir}/openssl_3" ]; then
52+
git clone https://github.com/openssl/openssl ${bindir}/openssl_3
53+
cd ${bindir}/openssl_3
54+
git checkout openssl-3.1.4
55+
./config
56+
make build_libs -j$(nproc)
57+
opensslPath=`pwd`
58+
else
59+
opensslPath=${bindir}/openssl_3
60+
fi
5961

6062
# Go to work dir
61-
cd ${srcdir}
62-
rm -rf ${srcdir}/${repo}
63+
cd ${srcdir}/${repo}
64+
ls -A1 | xargs rm -rf
6365

6466
# Update code
6567
echo "https://github.com/${author}/${repo}.git -> ${branch}"
66-
git clone --recursive https://github.com/${author}/${repo}.git
68+
git clone --recursive https://github.com/${author}/${repo}.git .
6769
cd ${repo} && git checkout ${branch}
6870
export CC=/usr/bin/clang
6971
export CXX=/usr/bin/clang++

mytonctrl/utils.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import subprocess
22
import time
33

4+
from mypylib.mypylib import bcolors
5+
46

57
def timestamp2utcdatetime(timestamp, format="%d.%m.%Y %H:%M:%S"):
68
datetime = time.gmtime(timestamp)
@@ -36,4 +38,20 @@ def fix_git_config(git_path: str):
3638
subprocess.run(args, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=3)
3739
else:
3840
raise Exception(f'Failed to check git status: {err}')
39-
#end define
41+
# end define
42+
43+
def GetColorInt(data, border, logic, ending=None):
44+
if data is None:
45+
result = "n/a"
46+
elif logic == "more":
47+
if data >= border:
48+
result = bcolors.green_text(data, ending)
49+
else:
50+
result = bcolors.red_text(data, ending)
51+
elif logic == "less":
52+
if data <= border:
53+
result = bcolors.green_text(data, ending)
54+
else:
55+
result = bcolors.red_text(data, ending)
56+
return result
57+
# end define

0 commit comments

Comments
 (0)