Remote test and other stuff

This commit is contained in:
kianenigma
2020-08-06 16:35:59 +02:00
parent 2c908f3493
commit 115074225a
4 changed files with 148 additions and 67 deletions
+2
View File
@@ -0,0 +1,2 @@
.vscode
__pycache__
+14 -27
View File
@@ -1,5 +1,4 @@
import unittest import unittest
import sys
def print_list(ll): def print_list(ll):
@@ -16,7 +15,7 @@ class edge:
self.candidate = None self.candidate = None
def __str__(self): def __str__(self):
return "Edge({}, weight = {})".format( return "Edge({}, weight = {:,})".format(
self.validator_id, self.validator_id,
self.weight, self.weight,
) )
@@ -30,7 +29,7 @@ class nominator:
self.load = 0 self.load = 0
def __str__(self): def __str__(self):
return "Nominator({}, budget = {}, load = {}, edges = {})".format( return "Nominator({}, budget = {:,}, load = {}, edges = {})".format(
self.nominator_id, self.nominator_id,
self.budget, self.budget,
self.load, self.load,
@@ -49,12 +48,10 @@ class candidate:
self.scoredenom = 0 self.scoredenom = 0
def __str__(self): def __str__(self):
return "Candidate({}, approval = {}, backed = {}, score = {}, scoredenom = {})".format( return "Candidate({}, approval = {:,}, backed_stake = {:,})".format(
self.validator_id, self.validator_id,
self.approval_stake, self.approval_stake,
self.backed_stake, int(self.backed_stake),
self.score,
self.scoredenom,
) )
@@ -194,7 +191,6 @@ def calculateMaxScoreNoCutoff(nomlist, candidates):
for candidate in candidates: for candidate in candidates:
if candidate.approval_stake > 0.0: if candidate.approval_stake > 0.0:
candidate.score = candidate.approval_stake / candidate.scoredenom candidate.score = candidate.approval_stake / candidate.scoredenom
print("score of {} in this round is {}".format(candidate.validator_id, candidate.score))
if not candidate.elected and candidate.score > best_score: if not candidate.elected and candidate.score > best_score:
best_score = candidate.score best_score = candidate.score
best_candidate = candidate best_candidate = candidate
@@ -209,19 +205,23 @@ def electWithScore(nomlist, elected_candidate, cutoff):
for new_edge in nom.edges: for new_edge in nom.edges:
if new_edge.validator_id == elected_candidate.validator_id: if new_edge.validator_id == elected_candidate.validator_id:
used_budget = sum([edge.weight for edge in nom.edges]) used_budget = sum([edge.weight for edge in nom.edges])
new_edge.weight = nom.budget - used_budget new_edge.weight = nom.budget - used_budget
elected_candidate.backed_stake += nom.budget - used_budget elected_candidate.backed_stake += nom.budget - used_budget
for edge in nom.edges: for edge in nom.edges:
if edge.validator_id != elected_candidate.validator_id and edge.weight > 0.0: if edge.validator_id != elected_candidate.validator_id and edge.weight > 0.0:
if edge.candidate.backed_stake > cutoff: if edge.candidate.backed_stake > cutoff:
stake_to_take = edge.weight * cutoff / edge.candidate.backed_stake stake_to_take = edge.weight * cutoff / edge.candidate.backed_stake
new_edge.weight += stake_to_take new_edge.weight += stake_to_take
edge.weight -= stake_to_take
edge.candidate.backed_stake -= stake_to_take
elected_candidate.backed_stake += stake_to_take elected_candidate.backed_stake += stake_to_take
edge.weight -= stake_to_take
edge.candidate.backed_stake -= stake_to_take
def balanced_heuristic(votelist, num_to_elect, tolerance=0.1):
def phragmms(votelist, num_to_elect, tolerance=0.1):
nomlist, candidates = setuplists(votelist) nomlist, candidates = setuplists(votelist)
calculate_approval(nomlist) calculate_approval(nomlist)
@@ -229,16 +229,12 @@ def balanced_heuristic(votelist, num_to_elect, tolerance=0.1):
for round in range(num_to_elect): for round in range(num_to_elect):
(elected_candidate, score) = calculateMaxScoreNoCutoff(nomlist, candidates) (elected_candidate, score) = calculateMaxScoreNoCutoff(nomlist, candidates)
electWithScore(nomlist, elected_candidate, score) electWithScore(nomlist, elected_candidate, score)
print("####\nRound {} max candidate {} with score {}".format(round, elected_candidate.validator_id, score))
print_list(nomlist)
elected_candidate.elected = True elected_candidate.elected = True
elected_candidates.append(elected_candidate) elected_candidates.append(elected_candidate)
elected_candidate.electedpos = round elected_candidate.electedpos = round
equalise_all(nomlist, 10, tolerance) equalise_all(nomlist, 10, tolerance)
print("After balancing")
print_list(nomlist)
return nomlist, elected_candidates return nomlist, elected_candidates
@@ -309,7 +305,7 @@ def run_and_print_all(votelist, to_elect):
printresult(nomlist, elected_candidates) printresult(nomlist, elected_candidates)
print("\nBalanced Heuristic (3.15 factor) gives") print("\nBalanced Heuristic (3.15 factor) gives")
nomlist, elected_candidates = balanced_heuristic(votelist, to_elect) nomlist, elected_candidates = phragmms(votelist, to_elect)
printresult(nomlist, elected_candidates) printresult(nomlist, elected_candidates)
@@ -367,7 +363,7 @@ class MaxScoreTest(unittest.TestCase):
(20, 20.0, [1, 3]), (20, 20.0, [1, 3]),
(30, 30.0, [2, 3]), (30, 30.0, [2, 3]),
] ]
nomlist, winners = balanced_heuristic(votelist, 2, 0) nomlist, winners = phragmms(votelist, 2, 0)
self.assertEqual(winners[0].validator_id, 3) self.assertEqual(winners[0].validator_id, 3)
self.assertEqual(winners[1].validator_id, 2) self.assertEqual(winners[1].validator_id, 2)
@@ -385,7 +381,7 @@ class MaxScoreTest(unittest.TestCase):
(130, 1000, [61, 71]), (130, 1000, [61, 71]),
] ]
nomlist, winners = balanced_heuristic(votelist, 4, 0) nomlist, winners = phragmms(votelist, 4, 0)
self.assertEqual(winners[0].validator_id, 11) self.assertEqual(winners[0].validator_id, 11)
self.assertEqual(winners[0].backed_stake, 3000) self.assertEqual(winners[0].backed_stake, 3000)
@@ -430,12 +426,3 @@ def main():
# example1() # example1()
example2() example2()
# example3() # example3()
if len(sys.argv) >= 2:
if sys.argv[1] == "run":
main()
else:
unittest.main()
else:
unittest.main()
+92
View File
@@ -0,0 +1,92 @@
import npos
import pprint
from substrateinterface import SubstrateInterface
from substrateinterface.utils.ss58 import ss58_decode, ss58_encode
pp = pprint.PrettyPrinter(indent=4)
substrate = SubstrateInterface(
url="ws://localhost:9944",
address_type=0,
type_registry={'types': {
"StakingLedger<AccountId, BalanceOf>": {
"type": "struct",
"type_mapping": [
["stash", "AccountId"],
["total", "Compact<Balance>"],
["active", "Compact<Balance>"],
["unlocking", "Vec<UnlockChunk<Balance>>"],
["claimedReward", "Vec<EraIndex>"]
]
},
}
},
type_registry_preset='polkadot',
)
head = substrate.get_chain_finalised_head()
def get_candidates():
prefix = substrate.generate_storage_hash("Staking", "Validators")
pairs = substrate.rpc_request(method="state_getPairs", params=[prefix, head])['result']
last_32_bytes = list(map(lambda p: "0x" + p[0][-64:], pairs))
return list(map(lambda k: ss58_encode(k), last_32_bytes))
def get_nominators():
prefix = substrate.generate_storage_hash("Staking", "Nominators")
pairs = substrate.rpc_request(method="state_getPairs", params=[prefix, head])['result']
nominators = list(
map(lambda p: ("0x" + p[0][-64:], substrate.decode_scale("Nominations<AccountId>", p[1])['targets']), pairs)
)
nominators = list(map(lambda x: (
ss58_encode(x[0], substrate.address_type),
x[1],
), nominators))
return list(map(lambda x: (
x[0],
get_backing_stake_of(x[0]),
[ss58_encode(acc, substrate.address_type) for acc in x[1]],
), nominators))
def get_backing_stake_of(who):
ctrl = substrate.get_runtime_state(
module="Staking",
storage_function="Bonded",
params=[who],
block_hash=head,
)['result']
ctrl = ss58_encode(ctrl, substrate.address_type)
ledger = substrate.get_runtime_state(
module="Staking",
storage_function="Ledger",
params=[ctrl],
block_hash=head,
)['result']
return ledger['active']
def validator_count():
return substrate.get_runtime_state("Staking", "ValidatorCount", [], head)['result']
candidates = get_candidates()
nominators = get_nominators()
to_elect = validator_count()
print("{} validators, {} nominators, electing {}".format(len(candidates), len(nominators), to_elect))
distribution, winners = npos.phragmms(nominators, to_elect)
npos.print_list(winners)
print(sum([c.backed_stake for c in winners]))
print(min([c.backed_stake for c in winners]))
score = [min([c.backed_stake for c in winners]), sum([c.backed_stake for c in winners])]
print("score = [{:,}, {:,}]".format(int(score[0]), int(score[1])))