Contract masternodes

Created On NaN secs ago - Invalid Date UTC+0

Contract Code


  
1 INTRODUCE_MOTION = 'introduce_motion'
2 VOTE_ON_MOTION = 'vote_on_motion'
3 NO_MOTION = 0
4 REMOVE_MEMBER = 1
5 ADD_SEAT = 2
6 REMOVE_SEAT = 3
7 VOTING_PERIOD = datetime.DAYS * 1
8 S = Hash(contract='masternodes', name='S')
9 minimum_nodes = Variable(contract='masternodes', name='minimum_nodes')
10 candidate_contract = Variable(contract='masternodes', name=
11 'candidate_contract')
12
13
14 def (initial_members: list, minimum: int=1, candidate: str='elect_members'
15 ):
16 S['members'] = initial_members
17 minimum_nodes.set(minimum)
18 candidate_contract.set(candidate)
19 S['yays'] = 0
20 S['nays'] = 0
21 S['current_motion'] = NO_MOTION
22 S['motion_opened'] = now
23
24
25 @export('masternodes')
26 def quorum_max():
27 return int(len(S['members']) * 2 / 3) + 1
28
29
30 @export('masternodes')
31 def quorum_min():
32 return min(quorum_max(), minimum_nodes.get())
33
34
35 @export('masternodes')
36 def current_value():
37 return S['members']
38
39
40 @export('masternodes')
41 def vote(vk: str, obj: list):
42 assert type(obj) == list, 'Pass a list!'
43 arg = None
44 try:
45 action, position, arg = obj
46 except ValueError:
47 action, position = obj
48 assert_vote_is_valid(vk, action, position, arg)
49 if action == INTRODUCE_MOTION:
50 introduce_motion(position, arg)
51 else:
52 assert S['current_motion'] != NO_MOTION, 'No motion proposed.'
53 assert S['positions', vk] is None, 'VK already voted.'
54 if position is True:
55 S['yays'] += 1
56 S['positions', vk] = position
57 else:
58 S['nays'] += 1
59 S['positions', vk] = position
60 if S['yays'] >= len(S['members']) // 2 + 1:
61 pass_current_motion()
62 reset()
63 elif S['nays'] >= len(S['members']) // 2 + 1:
64 reset()
65 elif now - S['motion_opened'] >= VOTING_PERIOD:
66 reset()
67
68
69 def assert_vote_is_valid(vk: str, action: str, position: bool, arg: Any=None
70 ):
71 assert vk in S['members'], 'Not a member.'
72 assert action in [INTRODUCE_MOTION, VOTE_ON_MOTION], 'Invalid action.'
73 if action == INTRODUCE_MOTION:
74 assert S['current_motion'] == NO_MOTION, 'Already in motion.'
75 assert 0 < position <= REMOVE_SEAT, 'Invalid motion.'
76 if position == REMOVE_MEMBER:
77 assert_vk_is_valid(arg)
78 elif action == VOTE_ON_MOTION:
79 assert type(position) == bool, 'Invalid position'
80
81
82 def assert_vk_is_valid(vk: str):
83 assert vk is not None, 'No VK provided.'
84 assert type(vk) == str, 'VK not a string.'
85 assert len(vk) == 64, 'VK is not 64 characters.'
86 int(vk, 16)
87
88
89 def introduce_motion(position: int, arg: Any):
90 assert position <= REMOVE_SEAT, 'Invalid position.'
91 if position == REMOVE_MEMBER:
92 assert arg in S['members'], 'Member does not exist.'
93 assert len(S['members']) > minimum_nodes.get(
94 ), 'Cannot drop below current quorum.'
95 S['member_in_question'] = arg
96 S['current_motion'] = position
97 S['motion_opened'] = now
98
99
100 def pass_current_motion():
101 current_motion = S['current_motion']
102 members = S['members']
103 if current_motion == REMOVE_MEMBER:
104 members.remove(S['member_in_question'])
105 elif current_motion == ADD_SEAT:
106 member_candidates = importlib.import_module(candidate_contract.get())
107 new_mem = member_candidates.top_member()
108 if new_mem is not None:
109 members.append(new_mem)
110 member_candidates.pop_top()
111 elif current_motion == REMOVE_SEAT:
112 member_candidates = importlib.import_module(candidate_contract.get())
113 old_mem = member_candidates.last_member()
114 if old_mem is not None:
115 members.remove(old_mem)
116 member_candidates.pop_last()
117 S['members'] = members
118
119
120 def reset():
121 S['current_motion'] = NO_MOTION
122 S['member_in_question'] = None
123 S['yays'] = 0
124 S['nays'] = 0
125 S.clear('positions')
126