nexaroa 0.0.111__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- neuroshard/__init__.py +93 -0
- neuroshard/__main__.py +4 -0
- neuroshard/cli.py +466 -0
- neuroshard/core/__init__.py +92 -0
- neuroshard/core/consensus/verifier.py +252 -0
- neuroshard/core/crypto/__init__.py +20 -0
- neuroshard/core/crypto/ecdsa.py +392 -0
- neuroshard/core/economics/__init__.py +52 -0
- neuroshard/core/economics/constants.py +387 -0
- neuroshard/core/economics/ledger.py +2111 -0
- neuroshard/core/economics/market.py +975 -0
- neuroshard/core/economics/wallet.py +168 -0
- neuroshard/core/governance/__init__.py +74 -0
- neuroshard/core/governance/proposal.py +561 -0
- neuroshard/core/governance/registry.py +545 -0
- neuroshard/core/governance/versioning.py +332 -0
- neuroshard/core/governance/voting.py +453 -0
- neuroshard/core/model/__init__.py +30 -0
- neuroshard/core/model/dynamic.py +4186 -0
- neuroshard/core/model/llm.py +905 -0
- neuroshard/core/model/registry.py +164 -0
- neuroshard/core/model/scaler.py +387 -0
- neuroshard/core/model/tokenizer.py +568 -0
- neuroshard/core/network/__init__.py +56 -0
- neuroshard/core/network/connection_pool.py +72 -0
- neuroshard/core/network/dht.py +130 -0
- neuroshard/core/network/dht_plan.py +55 -0
- neuroshard/core/network/dht_proof_store.py +516 -0
- neuroshard/core/network/dht_protocol.py +261 -0
- neuroshard/core/network/dht_service.py +506 -0
- neuroshard/core/network/encrypted_channel.py +141 -0
- neuroshard/core/network/nat.py +201 -0
- neuroshard/core/network/nat_traversal.py +695 -0
- neuroshard/core/network/p2p.py +929 -0
- neuroshard/core/network/p2p_data.py +150 -0
- neuroshard/core/swarm/__init__.py +106 -0
- neuroshard/core/swarm/aggregation.py +729 -0
- neuroshard/core/swarm/buffers.py +643 -0
- neuroshard/core/swarm/checkpoint.py +709 -0
- neuroshard/core/swarm/compute.py +624 -0
- neuroshard/core/swarm/diloco.py +844 -0
- neuroshard/core/swarm/factory.py +1288 -0
- neuroshard/core/swarm/heartbeat.py +669 -0
- neuroshard/core/swarm/logger.py +487 -0
- neuroshard/core/swarm/router.py +658 -0
- neuroshard/core/swarm/service.py +640 -0
- neuroshard/core/training/__init__.py +29 -0
- neuroshard/core/training/checkpoint.py +600 -0
- neuroshard/core/training/distributed.py +1602 -0
- neuroshard/core/training/global_tracker.py +617 -0
- neuroshard/core/training/production.py +276 -0
- neuroshard/governance_cli.py +729 -0
- neuroshard/grpc_server.py +895 -0
- neuroshard/runner.py +3223 -0
- neuroshard/sdk/__init__.py +92 -0
- neuroshard/sdk/client.py +990 -0
- neuroshard/sdk/errors.py +101 -0
- neuroshard/sdk/types.py +282 -0
- neuroshard/tracker/__init__.py +0 -0
- neuroshard/tracker/server.py +864 -0
- neuroshard/ui/__init__.py +0 -0
- neuroshard/ui/app.py +102 -0
- neuroshard/ui/templates/index.html +1052 -0
- neuroshard/utils/__init__.py +0 -0
- neuroshard/utils/autostart.py +81 -0
- neuroshard/utils/hardware.py +121 -0
- neuroshard/utils/serialization.py +90 -0
- neuroshard/version.py +1 -0
- nexaroa-0.0.111.dist-info/METADATA +283 -0
- nexaroa-0.0.111.dist-info/RECORD +78 -0
- nexaroa-0.0.111.dist-info/WHEEL +5 -0
- nexaroa-0.0.111.dist-info/entry_points.txt +4 -0
- nexaroa-0.0.111.dist-info/licenses/LICENSE +190 -0
- nexaroa-0.0.111.dist-info/top_level.txt +2 -0
- protos/__init__.py +0 -0
- protos/neuroshard.proto +651 -0
- protos/neuroshard_pb2.py +160 -0
- protos/neuroshard_pb2_grpc.py +1298 -0
|
@@ -0,0 +1,453 @@
|
|
|
1
|
+
"""
|
|
2
|
+
NEP Voting - Stake-Weighted Governance
|
|
3
|
+
|
|
4
|
+
Voting power is proportional to staked NEURO. This ensures that
|
|
5
|
+
participants with skin in the game make decisions about protocol changes.
|
|
6
|
+
|
|
7
|
+
Voting Rules:
|
|
8
|
+
- 1 NEURO staked = 1 vote
|
|
9
|
+
- Voting period: 7 days (configurable per NEP)
|
|
10
|
+
- Approval threshold: 66% of votes (stake-weighted)
|
|
11
|
+
- Quorum: 20% of total staked NEURO must vote
|
|
12
|
+
"""
|
|
13
|
+
|
|
14
|
+
import sqlite3
|
|
15
|
+
import time
|
|
16
|
+
import hashlib
|
|
17
|
+
import json
|
|
18
|
+
import logging
|
|
19
|
+
import threading
|
|
20
|
+
from dataclasses import dataclass, asdict
|
|
21
|
+
from enum import Enum
|
|
22
|
+
from typing import Dict, List, Optional, Tuple
|
|
23
|
+
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class VoteChoice(Enum):
|
|
28
|
+
"""Voting options."""
|
|
29
|
+
YES = "yes" # Approve the proposal
|
|
30
|
+
NO = "no" # Reject the proposal
|
|
31
|
+
ABSTAIN = "abstain" # Participate without opinion (counts for quorum)
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@dataclass
|
|
35
|
+
class Vote:
|
|
36
|
+
"""A single vote on a NEP."""
|
|
37
|
+
vote_id: str
|
|
38
|
+
nep_id: str
|
|
39
|
+
voter_node_id: str
|
|
40
|
+
choice: VoteChoice
|
|
41
|
+
stake_at_vote: float # Stake when vote was cast (locked)
|
|
42
|
+
timestamp: float
|
|
43
|
+
signature: str # ECDSA signature
|
|
44
|
+
reason: str = "" # Optional reason for vote
|
|
45
|
+
|
|
46
|
+
def to_dict(self) -> Dict:
|
|
47
|
+
return {
|
|
48
|
+
"vote_id": self.vote_id,
|
|
49
|
+
"nep_id": self.nep_id,
|
|
50
|
+
"voter_node_id": self.voter_node_id,
|
|
51
|
+
"choice": self.choice.value,
|
|
52
|
+
"stake_at_vote": self.stake_at_vote,
|
|
53
|
+
"timestamp": self.timestamp,
|
|
54
|
+
"signature": self.signature,
|
|
55
|
+
"reason": self.reason,
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@classmethod
|
|
59
|
+
def from_dict(cls, data: Dict) -> 'Vote':
|
|
60
|
+
return cls(
|
|
61
|
+
vote_id=data["vote_id"],
|
|
62
|
+
nep_id=data["nep_id"],
|
|
63
|
+
voter_node_id=data["voter_node_id"],
|
|
64
|
+
choice=VoteChoice(data["choice"]),
|
|
65
|
+
stake_at_vote=data["stake_at_vote"],
|
|
66
|
+
timestamp=data["timestamp"],
|
|
67
|
+
signature=data["signature"],
|
|
68
|
+
reason=data.get("reason", ""),
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@dataclass
|
|
73
|
+
class VoteResult:
|
|
74
|
+
"""Aggregated voting results for a NEP."""
|
|
75
|
+
nep_id: str
|
|
76
|
+
|
|
77
|
+
# Vote counts (number of voters)
|
|
78
|
+
yes_count: int = 0
|
|
79
|
+
no_count: int = 0
|
|
80
|
+
abstain_count: int = 0
|
|
81
|
+
|
|
82
|
+
# Stake-weighted votes
|
|
83
|
+
yes_stake: float = 0.0
|
|
84
|
+
no_stake: float = 0.0
|
|
85
|
+
abstain_stake: float = 0.0
|
|
86
|
+
|
|
87
|
+
# Thresholds
|
|
88
|
+
total_stake_voted: float = 0.0
|
|
89
|
+
total_network_stake: float = 0.0
|
|
90
|
+
approval_threshold: float = 0.66
|
|
91
|
+
quorum_threshold: float = 0.20
|
|
92
|
+
|
|
93
|
+
# Status
|
|
94
|
+
quorum_reached: bool = False
|
|
95
|
+
approved: bool = False
|
|
96
|
+
|
|
97
|
+
@property
|
|
98
|
+
def participation_rate(self) -> float:
|
|
99
|
+
"""Percentage of network stake that voted."""
|
|
100
|
+
if self.total_network_stake == 0:
|
|
101
|
+
return 0.0
|
|
102
|
+
return self.total_stake_voted / self.total_network_stake
|
|
103
|
+
|
|
104
|
+
@property
|
|
105
|
+
def approval_rate(self) -> float:
|
|
106
|
+
"""Percentage of voting stake that approved."""
|
|
107
|
+
yes_no_total = self.yes_stake + self.no_stake
|
|
108
|
+
if yes_no_total == 0:
|
|
109
|
+
return 0.0
|
|
110
|
+
return self.yes_stake / yes_no_total
|
|
111
|
+
|
|
112
|
+
def to_dict(self) -> Dict:
|
|
113
|
+
return {
|
|
114
|
+
"nep_id": self.nep_id,
|
|
115
|
+
"yes_count": self.yes_count,
|
|
116
|
+
"no_count": self.no_count,
|
|
117
|
+
"abstain_count": self.abstain_count,
|
|
118
|
+
"yes_stake": self.yes_stake,
|
|
119
|
+
"no_stake": self.no_stake,
|
|
120
|
+
"abstain_stake": self.abstain_stake,
|
|
121
|
+
"total_stake_voted": self.total_stake_voted,
|
|
122
|
+
"total_network_stake": self.total_network_stake,
|
|
123
|
+
"participation_rate": self.participation_rate,
|
|
124
|
+
"approval_rate": self.approval_rate,
|
|
125
|
+
"quorum_reached": self.quorum_reached,
|
|
126
|
+
"approved": self.approved,
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
class VotingSystem:
|
|
131
|
+
"""
|
|
132
|
+
Manages NEP voting with stake-weighted governance.
|
|
133
|
+
"""
|
|
134
|
+
|
|
135
|
+
def __init__(
|
|
136
|
+
self,
|
|
137
|
+
db_path: str = "nep_votes.db",
|
|
138
|
+
ledger=None, # NEUROLedger for stake lookups
|
|
139
|
+
):
|
|
140
|
+
self.db_path = db_path
|
|
141
|
+
self.ledger = ledger
|
|
142
|
+
self.lock = threading.Lock()
|
|
143
|
+
|
|
144
|
+
self._init_db()
|
|
145
|
+
|
|
146
|
+
def _init_db(self):
|
|
147
|
+
"""Initialize voting database."""
|
|
148
|
+
with self.lock:
|
|
149
|
+
with sqlite3.connect(self.db_path, timeout=60.0) as conn:
|
|
150
|
+
conn.execute("""
|
|
151
|
+
CREATE TABLE IF NOT EXISTS votes (
|
|
152
|
+
vote_id TEXT PRIMARY KEY,
|
|
153
|
+
nep_id TEXT NOT NULL,
|
|
154
|
+
voter_node_id TEXT NOT NULL,
|
|
155
|
+
choice TEXT NOT NULL,
|
|
156
|
+
stake_at_vote REAL NOT NULL,
|
|
157
|
+
timestamp REAL NOT NULL,
|
|
158
|
+
signature TEXT NOT NULL,
|
|
159
|
+
reason TEXT DEFAULT '',
|
|
160
|
+
UNIQUE(nep_id, voter_node_id)
|
|
161
|
+
)
|
|
162
|
+
""")
|
|
163
|
+
|
|
164
|
+
conn.execute("""
|
|
165
|
+
CREATE INDEX IF NOT EXISTS idx_votes_nep
|
|
166
|
+
ON votes(nep_id)
|
|
167
|
+
""")
|
|
168
|
+
|
|
169
|
+
def cast_vote(
|
|
170
|
+
self,
|
|
171
|
+
nep_id: str,
|
|
172
|
+
voter_node_id: str,
|
|
173
|
+
choice: VoteChoice,
|
|
174
|
+
signature: str,
|
|
175
|
+
reason: str = "",
|
|
176
|
+
nep_registry=None,
|
|
177
|
+
) -> Tuple[bool, str]:
|
|
178
|
+
"""
|
|
179
|
+
Cast a vote on a NEP.
|
|
180
|
+
|
|
181
|
+
Requirements:
|
|
182
|
+
1. NEP must be in VOTING status
|
|
183
|
+
2. Voting period must be active
|
|
184
|
+
3. Voter must have stake > 0
|
|
185
|
+
4. Vote must be signed
|
|
186
|
+
|
|
187
|
+
Returns: (success, message)
|
|
188
|
+
"""
|
|
189
|
+
# Check NEP status
|
|
190
|
+
if nep_registry:
|
|
191
|
+
nep = nep_registry.get_proposal(nep_id)
|
|
192
|
+
if not nep:
|
|
193
|
+
return False, "NEP not found"
|
|
194
|
+
if not nep.is_voting_active():
|
|
195
|
+
return False, f"Voting not active for {nep_id}"
|
|
196
|
+
|
|
197
|
+
# Get voter's stake
|
|
198
|
+
stake = 0.0
|
|
199
|
+
if self.ledger:
|
|
200
|
+
stake = self.ledger.get_local_stake(voter_node_id)
|
|
201
|
+
if stake <= 0:
|
|
202
|
+
return False, "Must have staked NEURO to vote"
|
|
203
|
+
else:
|
|
204
|
+
# Test mode - assume 100 stake
|
|
205
|
+
stake = 100.0
|
|
206
|
+
|
|
207
|
+
# Check if already voted
|
|
208
|
+
with sqlite3.connect(self.db_path, timeout=60.0) as conn:
|
|
209
|
+
existing = conn.execute(
|
|
210
|
+
"SELECT vote_id FROM votes WHERE nep_id = ? AND voter_node_id = ?",
|
|
211
|
+
(nep_id, voter_node_id)
|
|
212
|
+
).fetchone()
|
|
213
|
+
|
|
214
|
+
if existing:
|
|
215
|
+
return False, "Already voted on this NEP"
|
|
216
|
+
|
|
217
|
+
# Create vote
|
|
218
|
+
vote_id = hashlib.sha256(
|
|
219
|
+
f"{nep_id}:{voter_node_id}:{time.time()}".encode()
|
|
220
|
+
).hexdigest()[:32]
|
|
221
|
+
|
|
222
|
+
vote = Vote(
|
|
223
|
+
vote_id=vote_id,
|
|
224
|
+
nep_id=nep_id,
|
|
225
|
+
voter_node_id=voter_node_id,
|
|
226
|
+
choice=choice,
|
|
227
|
+
stake_at_vote=stake,
|
|
228
|
+
timestamp=time.time(),
|
|
229
|
+
signature=signature,
|
|
230
|
+
reason=reason,
|
|
231
|
+
)
|
|
232
|
+
|
|
233
|
+
# Store vote
|
|
234
|
+
with self.lock:
|
|
235
|
+
with sqlite3.connect(self.db_path, timeout=60.0) as conn:
|
|
236
|
+
conn.execute("""
|
|
237
|
+
INSERT INTO votes
|
|
238
|
+
(vote_id, nep_id, voter_node_id, choice, stake_at_vote,
|
|
239
|
+
timestamp, signature, reason)
|
|
240
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
241
|
+
""", (
|
|
242
|
+
vote.vote_id,
|
|
243
|
+
vote.nep_id,
|
|
244
|
+
vote.voter_node_id,
|
|
245
|
+
vote.choice.value,
|
|
246
|
+
vote.stake_at_vote,
|
|
247
|
+
vote.timestamp,
|
|
248
|
+
vote.signature,
|
|
249
|
+
vote.reason,
|
|
250
|
+
))
|
|
251
|
+
|
|
252
|
+
logger.info(
|
|
253
|
+
f"Vote cast: {voter_node_id[:16]}... voted {choice.value} "
|
|
254
|
+
f"on {nep_id} with {stake:.2f} stake"
|
|
255
|
+
)
|
|
256
|
+
|
|
257
|
+
return True, f"Vote recorded: {choice.value} with {stake:.2f} stake"
|
|
258
|
+
|
|
259
|
+
def get_vote_tally(
|
|
260
|
+
self,
|
|
261
|
+
nep_id: str,
|
|
262
|
+
approval_threshold: float = 0.66,
|
|
263
|
+
quorum_threshold: float = 0.20,
|
|
264
|
+
) -> VoteResult:
|
|
265
|
+
"""
|
|
266
|
+
Get the current vote tally for a NEP.
|
|
267
|
+
"""
|
|
268
|
+
result = VoteResult(
|
|
269
|
+
nep_id=nep_id,
|
|
270
|
+
approval_threshold=approval_threshold,
|
|
271
|
+
quorum_threshold=quorum_threshold,
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
with sqlite3.connect(self.db_path, timeout=60.0) as conn:
|
|
275
|
+
votes = conn.execute(
|
|
276
|
+
"SELECT choice, stake_at_vote FROM votes WHERE nep_id = ?",
|
|
277
|
+
(nep_id,)
|
|
278
|
+
).fetchall()
|
|
279
|
+
|
|
280
|
+
for choice_str, stake in votes:
|
|
281
|
+
choice = VoteChoice(choice_str)
|
|
282
|
+
|
|
283
|
+
if choice == VoteChoice.YES:
|
|
284
|
+
result.yes_count += 1
|
|
285
|
+
result.yes_stake += stake
|
|
286
|
+
elif choice == VoteChoice.NO:
|
|
287
|
+
result.no_count += 1
|
|
288
|
+
result.no_stake += stake
|
|
289
|
+
else:
|
|
290
|
+
result.abstain_count += 1
|
|
291
|
+
result.abstain_stake += stake
|
|
292
|
+
|
|
293
|
+
result.total_stake_voted = (
|
|
294
|
+
result.yes_stake + result.no_stake + result.abstain_stake
|
|
295
|
+
)
|
|
296
|
+
|
|
297
|
+
# Get total network stake
|
|
298
|
+
if self.ledger:
|
|
299
|
+
# Query total staked from ledger
|
|
300
|
+
result.total_network_stake = self._get_total_network_stake()
|
|
301
|
+
else:
|
|
302
|
+
# Test mode - assume voted stake is 50% of network
|
|
303
|
+
result.total_network_stake = result.total_stake_voted * 2
|
|
304
|
+
|
|
305
|
+
# Check quorum
|
|
306
|
+
if result.total_network_stake > 0:
|
|
307
|
+
result.quorum_reached = (
|
|
308
|
+
result.participation_rate >= quorum_threshold
|
|
309
|
+
)
|
|
310
|
+
|
|
311
|
+
# Check approval (only if quorum reached)
|
|
312
|
+
if result.quorum_reached:
|
|
313
|
+
result.approved = result.approval_rate >= approval_threshold
|
|
314
|
+
|
|
315
|
+
return result
|
|
316
|
+
|
|
317
|
+
def _get_total_network_stake(self) -> float:
|
|
318
|
+
"""Get total staked NEURO in the network."""
|
|
319
|
+
if not self.ledger:
|
|
320
|
+
return 0.0
|
|
321
|
+
|
|
322
|
+
try:
|
|
323
|
+
with sqlite3.connect(self.ledger.db_path, timeout=60.0) as conn:
|
|
324
|
+
row = conn.execute(
|
|
325
|
+
"SELECT SUM(amount) FROM stakes WHERE locked_until > ?",
|
|
326
|
+
(time.time(),)
|
|
327
|
+
).fetchone()
|
|
328
|
+
return row[0] if row and row[0] else 0.0
|
|
329
|
+
except Exception as e:
|
|
330
|
+
logger.error(f"Failed to get network stake: {e}")
|
|
331
|
+
return 0.0
|
|
332
|
+
|
|
333
|
+
def get_voter_history(self, voter_node_id: str) -> List[Vote]:
|
|
334
|
+
"""Get all votes by a node."""
|
|
335
|
+
with sqlite3.connect(self.db_path, timeout=60.0) as conn:
|
|
336
|
+
rows = conn.execute(
|
|
337
|
+
"SELECT vote_id, nep_id, voter_node_id, choice, "
|
|
338
|
+
"stake_at_vote, timestamp, signature, reason "
|
|
339
|
+
"FROM votes WHERE voter_node_id = ? ORDER BY timestamp DESC",
|
|
340
|
+
(voter_node_id,)
|
|
341
|
+
).fetchall()
|
|
342
|
+
|
|
343
|
+
return [
|
|
344
|
+
Vote(
|
|
345
|
+
vote_id=row[0],
|
|
346
|
+
nep_id=row[1],
|
|
347
|
+
voter_node_id=row[2],
|
|
348
|
+
choice=VoteChoice(row[3]),
|
|
349
|
+
stake_at_vote=row[4],
|
|
350
|
+
timestamp=row[5],
|
|
351
|
+
signature=row[6],
|
|
352
|
+
reason=row[7],
|
|
353
|
+
)
|
|
354
|
+
for row in rows
|
|
355
|
+
]
|
|
356
|
+
|
|
357
|
+
def finalize_voting(
|
|
358
|
+
self,
|
|
359
|
+
nep_id: str,
|
|
360
|
+
nep_registry,
|
|
361
|
+
) -> Tuple[bool, str, VoteResult]:
|
|
362
|
+
"""
|
|
363
|
+
Finalize voting and update NEP status.
|
|
364
|
+
|
|
365
|
+
Called when voting period ends.
|
|
366
|
+
Returns: (success, message, final_result)
|
|
367
|
+
"""
|
|
368
|
+
nep = nep_registry.get_proposal(nep_id)
|
|
369
|
+
if not nep:
|
|
370
|
+
return False, "NEP not found", None
|
|
371
|
+
|
|
372
|
+
# Get final tally
|
|
373
|
+
result = self.get_vote_tally(
|
|
374
|
+
nep_id,
|
|
375
|
+
approval_threshold=nep.approval_threshold,
|
|
376
|
+
quorum_threshold=nep.quorum_threshold,
|
|
377
|
+
)
|
|
378
|
+
|
|
379
|
+
if result.approved:
|
|
380
|
+
# Calculate activation block (e.g., 10000 blocks from now)
|
|
381
|
+
activation_block = self._get_current_block() + nep.upgrade_path.activation_delay_blocks
|
|
382
|
+
|
|
383
|
+
nep_registry.update_status(
|
|
384
|
+
nep_id,
|
|
385
|
+
NEPStatus.SCHEDULED,
|
|
386
|
+
activation_block=activation_block,
|
|
387
|
+
)
|
|
388
|
+
|
|
389
|
+
message = (
|
|
390
|
+
f"Approved! Activation scheduled at block {activation_block}. "
|
|
391
|
+
f"Approval: {result.approval_rate:.1%}, "
|
|
392
|
+
f"Participation: {result.participation_rate:.1%}"
|
|
393
|
+
)
|
|
394
|
+
|
|
395
|
+
elif result.quorum_reached:
|
|
396
|
+
nep_registry.update_status(nep_id, NEPStatus.REJECTED)
|
|
397
|
+
message = (
|
|
398
|
+
f"Rejected. Approval: {result.approval_rate:.1%} "
|
|
399
|
+
f"(needed {nep.approval_threshold:.1%})"
|
|
400
|
+
)
|
|
401
|
+
|
|
402
|
+
else:
|
|
403
|
+
nep_registry.update_status(nep_id, NEPStatus.REJECTED)
|
|
404
|
+
message = (
|
|
405
|
+
f"Failed to reach quorum. Participation: {result.participation_rate:.1%} "
|
|
406
|
+
f"(needed {nep.quorum_threshold:.1%})"
|
|
407
|
+
)
|
|
408
|
+
|
|
409
|
+
logger.info(f"Voting finalized for {nep_id}: {message}")
|
|
410
|
+
|
|
411
|
+
return True, message, result
|
|
412
|
+
|
|
413
|
+
def _get_current_block(self) -> int:
|
|
414
|
+
"""
|
|
415
|
+
Get current block number.
|
|
416
|
+
|
|
417
|
+
In a true blockchain, this would query the chain.
|
|
418
|
+
For NeuroShard, we use a logical block based on proof count.
|
|
419
|
+
"""
|
|
420
|
+
if self.ledger:
|
|
421
|
+
try:
|
|
422
|
+
stats = self.ledger.get_global_stats()
|
|
423
|
+
# Use proof count as "block height"
|
|
424
|
+
return stats.total_proofs_processed
|
|
425
|
+
except:
|
|
426
|
+
pass
|
|
427
|
+
return int(time.time() / 60) # Fallback: 1 "block" per minute
|
|
428
|
+
|
|
429
|
+
|
|
430
|
+
# Module-level convenience functions
|
|
431
|
+
from .proposal import NEPStatus
|
|
432
|
+
|
|
433
|
+
def cast_vote(
|
|
434
|
+
voting_system: VotingSystem,
|
|
435
|
+
nep_id: str,
|
|
436
|
+
voter_node_id: str,
|
|
437
|
+
choice: VoteChoice,
|
|
438
|
+
signature: str,
|
|
439
|
+
reason: str = "",
|
|
440
|
+
nep_registry=None,
|
|
441
|
+
) -> Tuple[bool, str]:
|
|
442
|
+
"""Cast a vote on a NEP."""
|
|
443
|
+
return voting_system.cast_vote(
|
|
444
|
+
nep_id, voter_node_id, choice, signature, reason, nep_registry
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
|
|
448
|
+
def get_vote_tally(
|
|
449
|
+
voting_system: VotingSystem,
|
|
450
|
+
nep_id: str,
|
|
451
|
+
) -> VoteResult:
|
|
452
|
+
"""Get current vote tally for a NEP."""
|
|
453
|
+
return voting_system.get_vote_tally(nep_id)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# neuroshard/core/model/__init__.py
|
|
2
|
+
"""
|
|
3
|
+
Model components for NeuroShard.
|
|
4
|
+
|
|
5
|
+
- dynamic: DynamicNeuroNode, DynamicLayerPool, DynamicNeuroLLM
|
|
6
|
+
- llm: NeuroLLMModel, NeuroDecoderLayer
|
|
7
|
+
- tokenizer: NeuroTokenizer, get_neuro_tokenizer
|
|
8
|
+
- registry: TokenizerConfig
|
|
9
|
+
- scaler: ArchitectureScaler
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from neuroshard.core.model.dynamic import (
|
|
13
|
+
DynamicNeuroNode,
|
|
14
|
+
DynamicLayerPool,
|
|
15
|
+
DynamicNeuroLLM,
|
|
16
|
+
create_dynamic_node,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
# Lazy imports to avoid circular dependencies
|
|
20
|
+
def get_tokenizer(*args, **kwargs):
|
|
21
|
+
from neuroshard.core.model.tokenizer import get_neuro_tokenizer
|
|
22
|
+
return get_neuro_tokenizer(*args, **kwargs)
|
|
23
|
+
|
|
24
|
+
__all__ = [
|
|
25
|
+
'DynamicNeuroNode',
|
|
26
|
+
'DynamicLayerPool',
|
|
27
|
+
'DynamicNeuroLLM',
|
|
28
|
+
'create_dynamic_node',
|
|
29
|
+
'get_tokenizer',
|
|
30
|
+
]
|