mirror of
https://github.com/pezkuwichain/consensus.git
synced 2026-06-20 03:31:00 +00:00
Remote test and other stuff
This commit is contained in:
@@ -0,0 +1,2 @@
|
|||||||
|
.vscode
|
||||||
|
__pycache__
|
||||||
+40
-40
@@ -7,7 +7,7 @@ class edge:
|
|||||||
#self.index
|
#self.index
|
||||||
#self.voterindex
|
#self.voterindex
|
||||||
#self.canindex
|
#self.canindex
|
||||||
|
|
||||||
|
|
||||||
class voter:
|
class voter:
|
||||||
def __init__(self,votetuple):
|
def __init__(self,votetuple):
|
||||||
@@ -83,7 +83,7 @@ class assignment:
|
|||||||
def unelect(self,candidate):
|
def unelect(self,candidate):
|
||||||
self.canelected[candidate.index]=False
|
self.canelected[candidate.index]=False
|
||||||
self.electedcandidates.remove(candidate)
|
self.electedcandidates.remove(candidate)
|
||||||
|
|
||||||
def setuplists(votelist):
|
def setuplists(votelist):
|
||||||
#Instead of Python's dict here, you can use anything with O(log n) addition and lookup.
|
#Instead of Python's dict here, you can use anything with O(log n) addition and lookup.
|
||||||
#We can also use a hashmap, by generating a random constant r and useing H(canid+r)
|
#We can also use a hashmap, by generating a random constant r and useing H(canid+r)
|
||||||
@@ -94,7 +94,7 @@ def setuplists(votelist):
|
|||||||
numcandidates=0
|
numcandidates=0
|
||||||
numvoters=0
|
numvoters=0
|
||||||
numedges=0
|
numedges=0
|
||||||
|
|
||||||
#Get an array of candidates that we can reference these by index
|
#Get an array of candidates that we can reference these by index
|
||||||
for nom in voterlist:
|
for nom in voterlist:
|
||||||
nom.index=numvoters
|
nom.index=numvoters
|
||||||
@@ -115,13 +115,13 @@ def setuplists(votelist):
|
|||||||
edge.canindex=numcandidates
|
edge.canindex=numcandidates
|
||||||
numcandidates += 1
|
numcandidates += 1
|
||||||
return(voterlist,candidatearray)
|
return(voterlist,candidatearray)
|
||||||
|
|
||||||
|
|
||||||
def seqPhragmén(votelist,numtoelect):
|
def seqPhragmén(votelist,numtoelect):
|
||||||
nomlist,candidates=setuplists(votelist)
|
nomlist,candidates=setuplists(votelist)
|
||||||
#creating an assignment now also computes the total possible stake for each candidate
|
#creating an assignment now also computes the total possible stake for each candidate
|
||||||
a=assignment(nomlist,candidates)
|
a=assignment(nomlist,candidates)
|
||||||
|
|
||||||
for round in range(numtoelect):
|
for round in range(numtoelect):
|
||||||
for canindex in range(len(candidates)):
|
for canindex in range(len(candidates)):
|
||||||
if not a.canelected[canindex]:
|
if not a.canelected[canindex]:
|
||||||
@@ -172,8 +172,8 @@ def calculateScores(a,cutoff):
|
|||||||
#if not a.canelected[canindex]:
|
#if not a.canelected[canindex]:
|
||||||
#print(a.candidates[canindex].canid," has score ", a.canscore[canindex]," with cutoff ",cutoff)
|
#print(a.candidates[canindex].canid," has score ", a.canscore[canindex]," with cutoff ",cutoff)
|
||||||
#print("Approval stake: ", a.canapproval[canindex]," support: ",a.cansupport[canindex]," denominator: ",a.canscoredenominator[canindex], " numerator: ",a.canscorenumerator[canindex])
|
#print("Approval stake: ", a.canapproval[canindex]," support: ",a.cansupport[canindex]," denominator: ",a.canscoredenominator[canindex], " numerator: ",a.canscorenumerator[canindex])
|
||||||
|
|
||||||
|
|
||||||
def calculateMaxScore(a):
|
def calculateMaxScore(a):
|
||||||
supportList=[a.cansupport[can.index] for can in a.electedcandidates]
|
supportList=[a.cansupport[can.index] for can in a.electedcandidates]
|
||||||
supportList.append(0.0)
|
supportList.append(0.0)
|
||||||
@@ -249,7 +249,7 @@ def equalise(a, nom, tolerance):
|
|||||||
# Attempts to redistribute the nominators budget between elected validators
|
# Attempts to redistribute the nominators budget between elected validators
|
||||||
# Assumes that all elected validators have backedstake set correctly
|
# Assumes that all elected validators have backedstake set correctly
|
||||||
# returns the max difference in stakes between sup
|
# returns the max difference in stakes between sup
|
||||||
|
|
||||||
electededges=[edge for edge in nom.edges if a.canelected[edge.canindex]]
|
electededges=[edge for edge in nom.edges if a.canelected[edge.canindex]]
|
||||||
if len(electededges)==0:
|
if len(electededges)==0:
|
||||||
return 0.0
|
return 0.0
|
||||||
@@ -310,7 +310,7 @@ def seqPhragménwithpostprocessing(votelist,numtoelect, ratio=1):
|
|||||||
def factor3point15(votelist, numtoelect,tolerance=0.1):
|
def factor3point15(votelist, numtoelect,tolerance=0.1):
|
||||||
nomlist,candidates=setuplists(votelist)
|
nomlist,candidates=setuplists(votelist)
|
||||||
a=assignment(nomlist,candidates)
|
a=assignment(nomlist,candidates)
|
||||||
|
|
||||||
for round in range(numtoelect):
|
for round in range(numtoelect):
|
||||||
bestcandidate,score=calculateMaxScore(a)
|
bestcandidate,score=calculateMaxScore(a)
|
||||||
insertWithScore(a,bestcandidate, score)
|
insertWithScore(a,bestcandidate, score)
|
||||||
@@ -325,7 +325,7 @@ def maybecandidate(a,newcandidate,shouldremoveworst, tolerance):
|
|||||||
if shouldremoveworst:
|
if shouldremoveworst:
|
||||||
worstcanidate =min(electedcandidates, key = lambda x: b.cansupport[x.index])
|
worstcanidate =min(electedcandidates, key = lambda x: b.cansupport[x.index])
|
||||||
b.unelect(worstcandidate)
|
b.unelect(worstcandidate)
|
||||||
b.elect(newcandidate)
|
b.elect(newcandidate)
|
||||||
equaliseall(b,100000000,tolerance)
|
equaliseall(b,100000000,tolerance)
|
||||||
newvalue=min([b.cansupport[candidate.index] for candidate in b.electedcandidates])
|
newvalue=min([b.cansupport[candidate.index] for candidate in b.electedcandidates])
|
||||||
return b, newvalue
|
return b, newvalue
|
||||||
@@ -395,7 +395,7 @@ def binarysearchfeasible(votelist,numtoelect,tolerance=0.1):
|
|||||||
else:
|
else:
|
||||||
targetvalue=currentvalue
|
targetvalue=currentvalue
|
||||||
#print(targetvalue,lastgoodindex, maxvalue,bestknownvalue,currentvalue)
|
#print(targetvalue,lastgoodindex, maxvalue,bestknownvalue,currentvalue)
|
||||||
|
|
||||||
|
|
||||||
for round in range(lastgoodindex+1,numtoelect):
|
for round in range(lastgoodindex+1,numtoelect):
|
||||||
# First try maxscore candidate, which will help with PJR
|
# First try maxscore candidate, which will help with PJR
|
||||||
@@ -460,22 +460,22 @@ def doall(votelist, numtoelect, listvoters=True, listcans=True):
|
|||||||
if listvoters:
|
if listvoters:
|
||||||
print("Votes ",votelist)
|
print("Votes ",votelist)
|
||||||
alglist=[(approvalvoting,"Approval voting"), (seqPhragmén, "Sequential Phragmén"),
|
alglist=[(approvalvoting,"Approval voting"), (seqPhragmén, "Sequential Phragmén"),
|
||||||
(seqPhragménwithpostprocessing, "Sequential Phragmén with post processing"),
|
(seqPhragménwithpostprocessing, "Sequential Phragmén with post processing"),
|
||||||
(factor3point15, "The factor 3.15 thing"), (binarysearchfeasible,"Factor 2 by binary search"), (SFFB18, "SFFB18")]
|
(factor3point15, "The factor 3.15 thing"), (binarysearchfeasible,"Factor 2 by binary search"), (SFFB18, "SFFB18")]
|
||||||
for alg,name in alglist:
|
for alg,name in alglist:
|
||||||
st=time.perf_counter()
|
st=time.perf_counter()
|
||||||
a = alg(votelist,numtoelect)
|
a = alg(votelist,numtoelect)
|
||||||
et=time.perf_counter()
|
et=time.perf_counter()
|
||||||
print(name, " gives")
|
print(name, " gives")
|
||||||
printresult(a,listvoters,listcans)
|
printresult(a,listvoters,listcans)
|
||||||
print(" in ",et-st," seconds.")
|
print(" in ",et-st," seconds.")
|
||||||
print()
|
print()
|
||||||
|
|
||||||
|
|
||||||
def example1():
|
def example1():
|
||||||
votelist=[("A",10.0,["X","Y"]),("B",20.0,["X","Z"]),("C",30.0,["Y","Z"])]
|
votelist=[("A",10.0,["X","Y"]),("B",20.0,["X","Z"]),("C",30.0,["Y","Z"])]
|
||||||
doall(votelist,2)
|
doall(votelist,2)
|
||||||
|
|
||||||
|
|
||||||
def example2():
|
def example2():
|
||||||
# Approval voting does not do so well for this kind of thing.
|
# Approval voting does not do so well for this kind of thing.
|
||||||
@@ -491,7 +491,7 @@ def example3():
|
|||||||
bluevoters = [("BlueV"+str(i),20.0,blueparty) for i in range(20)]
|
bluevoters = [("BlueV"+str(i),20.0,blueparty) for i in range(20)]
|
||||||
votelist= redvoters+bluevoters
|
votelist= redvoters+bluevoters
|
||||||
doall(votelist, 20, False)
|
doall(votelist, 20, False)
|
||||||
|
|
||||||
|
|
||||||
def example4():
|
def example4():
|
||||||
#Now we want an example where seq Phragmén is not so good.
|
#Now we want an example where seq Phragmén is not so good.
|
||||||
@@ -518,7 +518,7 @@ def example6():
|
|||||||
("M",50.0, ["M"])]
|
("M",50.0, ["M"])]
|
||||||
print("Votes ",votelist)
|
print("Votes ",votelist)
|
||||||
doall(votelist,5)
|
doall(votelist,5)
|
||||||
|
|
||||||
def exampleLine():
|
def exampleLine():
|
||||||
votelist = [
|
votelist = [
|
||||||
("a", 2000, ["A"]),
|
("a", 2000, ["A"]),
|
||||||
@@ -530,7 +530,7 @@ def exampleLine():
|
|||||||
("g", 1000, ["F","G"])
|
("g", 1000, ["F","G"])
|
||||||
]
|
]
|
||||||
doall(votelist,7)
|
doall(votelist,7)
|
||||||
|
|
||||||
def ri(vals=20,noms=2000, votesize=10):
|
def ri(vals=20,noms=2000, votesize=10):
|
||||||
#Let's try a random instance
|
#Let's try a random instance
|
||||||
candidates=["Val"+str(i) for i in range(vals)]
|
candidates=["Val"+str(i) for i in range(vals)]
|
||||||
@@ -560,28 +560,28 @@ def riparty(vals=200,noms=2000, votesize=10,seed=1):
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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()
|
|
||||||
@@ -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])))
|
||||||
Reference in New Issue
Block a user