Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 21 additions & 0 deletions flockoff/validator/database.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ def _init_db(self):
"""CREATE TABLE IF NOT EXISTS dataset_revisions
(local_path TEXT PRIMARY KEY, namespace TEXT, revision TEXT)"""
)
c.execute("""
CREATE TABLE IF NOT EXISTS validator_state (
key TEXT PRIMARY KEY, value TEXT)"""
)
self.conn.commit()
except sqlite3.Error as e:
logger.error(f"Failed to initialize database tables: {str(e)}")
Expand Down Expand Up @@ -246,6 +250,23 @@ def get_competition_winner(self, competition_id: str) -> int:
logger.error(f"Failed to get get_competition_status: {str(e)}")
raise DatabaseError(f"Failed to get get_competition_status: {str(e)}") from e

def set_state(self, key: str, value):
cursor = self.conn.cursor()
cursor.execute(
"REPLACE INTO validator_state (key, value) VALUES (?, ?)",
(key, json.dumps(value)),
)
self.conn.commit()

def get_state(self, key: str):
cursor = self.conn.cursor()
cursor.execute(
"SELECT value FROM validator_state WHERE key = ?",
(key,),
)
row = cursor.fetchone()
return json.loads(row[0]) if row else None

def __del__(self):
"""Close the connection when the instance is destroyed."""
try:
Expand Down
45 changes: 38 additions & 7 deletions neurons/validator.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
from flockoff.utils.chain import assert_registered
from flockoff.utils.git import check_and_update_code
from enum import Enum
from datetime import datetime, timezone
from datetime import datetime, timezone, timedelta
from flockoff.validator.chain import (
retrieve_model_metadata,
set_weights_with_err_msg,
Expand Down Expand Up @@ -200,11 +200,8 @@ def __init__(self):
new_weights[winner] = 1
self.weights = new_weights
else:
self.weights = torch.zeros_like(torch.tensor(self.metagraph.S))
# Get the burn UID.
burn_uid = self.get_burn_uid()
self.weights[burn_uid] =1
bt.logging.info(f"Initial weight :{self.weights}")
self._comp_exists_in_db()


bt.logging.info("Validator ready to run")

Expand Down Expand Up @@ -280,6 +277,38 @@ def should_start_new_competition(self, main_commit_id: str) -> bool:
return False
return True

def persist_state(self):
try:
self.score_db.set_state("active_competition_id", self.active_competition_id)
self.score_db.set_state("reward_competition_id", self.reward_competition_id)
self.score_db.set_state("use_yesterday_reward", self.use_yesterday_reward)
self.score_db.set_state("weights", self.weights.tolist() if isinstance(self.weights, torch.Tensor) else self.weights)
except Exception as e:
bt.logging.error(f"Failed to persist validator state: {e}")

def _comp_exists_in_db(self):
now = datetime.now(timezone.utc)
competition_id_today = now.strftime("%Y%m%d")
competition_id_yesterday = (now - timedelta(days=1)).strftime("%Y%m%d")

stored_active = self.score_db.get_state("active_competition_id")
stored_reward = self.score_db.get_state("reward_competition_id")
stored_use_yesterday = self.score_db.get_state("use_yesterday_reward")
stored_weights = self.score_db.get_state("weights")

if stored_active and stored_active in (competition_id_today, competition_id_yesterday) and \
self.score_db.get_competition_info(stored_active):
self.active_competition_id = stored_active
self.reward_competition_id = stored_reward
self.use_yesterday_reward = stored_use_yesterday
self.weights = torch.tensor(stored_weights, dtype=torch.float32)
else:
self.weights = torch.zeros_like(torch.tensor(self.metagraph.S))
# Get the burn UID.
burn_uid = self.get_burn_uid()
self.weights[burn_uid] = 1
bt.logging.info(f"Initial weight :{self.weights}")

async def run_step(self):
bt.logging.info("Starting run step")
check_and_update_code()
Expand Down Expand Up @@ -387,14 +416,15 @@ async def run_step(self):
self.active_competition_id = competition_id_today
self.use_yesterday_reward = False
self.score_db.create_competition(self.active_competition_id, int(now.timestamp()), main_commit_id)

self.persist_state()
else:
bt.logging.info("COPY COMPETITION REWARD BEFORE")
bt.logging.info(f"weights set by reward_competition_id {self.reward_competition_id}")
self.use_yesterday_reward = True
self.score_db.copy_competition_id(competition_id_today, self.active_competition_id)
self.score_db.update_competition_status(self.active_competition_id, CompetitionState.COMPLETED.value)
self.active_competition_id = competition_id_today
self.persist_state()

# VALIDATION
elif constants.validate_start_utc_min <= minutes_today < 24 * 60 or \
Expand Down Expand Up @@ -684,6 +714,7 @@ async def run_step(self):
self.score_db.update_competition_status(self.active_competition_id, CompetitionState.REWARDING.value)
self.score_db.update_competition_score(self.active_competition_id, winner, winner_loss)
bt.logging.info(f"weights set by reward_competition_id {self.reward_competition_id}")
self.persist_state()

else:
bt.logging.error(f"There is no score for Competition_id {self.active_competition_id}")
Expand Down
25 changes: 25 additions & 0 deletions neurons/validator_write_db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
import torch
import bittensor as bt
from flockoff.validator.database import ScoreDB
from datetime import datetime, timezone, timedelta


score_db = ScoreDB("scores.db")

now = datetime.now(timezone.utc)
competition_id_today = now.strftime("%Y%m%d")
competition_id_yesterday = (now - timedelta(days=1)).strftime("%Y%m%d")

netuid = 96
subtensor = bt.subtensor()
metagraph = subtensor.metagraph(netuid)
new_weights = torch.zeros_like(torch.tensor(metagraph.S), dtype=torch.float32)
winner = score_db.get_competition_winner(competition_id_yesterday)
if winner:
new_weights[winner] = 1

score_db.set_state("active_competition_id", competition_id_today)
score_db.set_state("reward_competition_id", competition_id_yesterday)
score_db.set_state("use_yesterday_reward", True)
score_db.set_state("weights", new_weights.tolist())