|
@@ -25,6 +25,15 @@ class DarkfiTable:
|
|
|
def add_darkie(self, darkie):
|
|
def add_darkie(self, darkie):
|
|
|
self.darkies+=[darkie]
|
|
self.darkies+=[darkie]
|
|
|
|
|
|
|
|
|
|
+ """
|
|
|
|
|
+ for every slot under given running time, set f based off prior on-chain public \
|
|
|
|
|
+ values, set sigmas, f, update vesting, stake for every stakeholder, resolve \
|
|
|
|
|
+ forks.
|
|
|
|
|
+ @param rand_running_time: randomization running time state
|
|
|
|
|
+ @param debug: debug option
|
|
|
|
|
+ @param hp: high precision option
|
|
|
|
|
+ @returns: acc, avg_apy, avg_reward, stake_ratio, avg_apr
|
|
|
|
|
+ """
|
|
|
def background(self, rand_running_time=True, debug=False, hp=True):
|
|
def background(self, rand_running_time=True, debug=False, hp=True):
|
|
|
self.debug=debug
|
|
self.debug=debug
|
|
|
self.start_time=time.time()
|
|
self.start_time=time.time()
|
|
@@ -34,17 +43,16 @@ class DarkfiTable:
|
|
|
self.running_time = rand_running_time
|
|
self.running_time = rand_running_time
|
|
|
rt_range = tqdm(np.arange(0,self.running_time, 1))
|
|
rt_range = tqdm(np.arange(0,self.running_time, 1))
|
|
|
merge_length = 0
|
|
merge_length = 0
|
|
|
|
|
+ # loop through slots
|
|
|
for count in rt_range:
|
|
for count in rt_range:
|
|
|
merge_length = 0
|
|
merge_length = 0
|
|
|
- winners=0
|
|
|
|
|
|
|
+ # calculate probability of winning owning 100% of stake
|
|
|
f = self.secondary_pid.pid_clipped(float(feedback), debug)
|
|
f = self.secondary_pid.pid_clipped(float(feedback), debug)
|
|
|
-
|
|
|
|
|
|
|
+ # calculate reward value every epoch
|
|
|
if count%EPOCH_LENGTH == 0:
|
|
if count%EPOCH_LENGTH == 0:
|
|
|
acc = self.secondary_pid.acc()
|
|
acc = self.secondary_pid.acc()
|
|
|
reward = self.primary_pid.pid_clipped(acc, debug)
|
|
reward = self.primary_pid.pid_clipped(acc, debug)
|
|
|
self.rewards += [reward]
|
|
self.rewards += [reward]
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
#note! thread overhead is 10X slower than sequential node execution!
|
|
#note! thread overhead is 10X slower than sequential node execution!
|
|
|
total_stake = 0
|
|
total_stake = 0
|
|
|
for i in range(len(self.darkies)):
|
|
for i in range(len(self.darkies)):
|
|
@@ -52,16 +60,20 @@ class DarkfiTable:
|
|
|
self.darkies[i].update_vesting()
|
|
self.darkies[i].update_vesting()
|
|
|
self.darkies[i].run(hp)
|
|
self.darkies[i].run(hp)
|
|
|
total_stake += self.darkies[i].stake
|
|
total_stake += self.darkies[i].stake
|
|
|
-
|
|
|
|
|
|
|
+ # count number of leads per slot
|
|
|
|
|
+ winners=0
|
|
|
|
|
+ # count secondary controller feedback
|
|
|
for i in range(len(self.darkies)):
|
|
for i in range(len(self.darkies)):
|
|
|
winners += self.darkies[i].won_hist[-1]
|
|
winners += self.darkies[i].won_hist[-1]
|
|
|
-
|
|
|
|
|
self.winners +=[winners]
|
|
self.winners +=[winners]
|
|
|
feedback = winners
|
|
feedback = winners
|
|
|
|
|
+ ################
|
|
|
|
|
+ # resolve fork #
|
|
|
|
|
+ ################
|
|
|
if self.winners[-1]==1:
|
|
if self.winners[-1]==1:
|
|
|
for i in range(len(self.darkies)):
|
|
for i in range(len(self.darkies)):
|
|
|
if self.darkies[i].won_hist[-1]:
|
|
if self.darkies[i].won_hist[-1]:
|
|
|
- if random.random() < SLASHING_RATIO:
|
|
|
|
|
|
|
+ if random.random() < len(self.darkies)**-1:
|
|
|
self.darkies.remove(self.darkies[i])
|
|
self.darkies.remove(self.darkies[i])
|
|
|
print('stakeholder {} slashed'.format(i))
|
|
print('stakeholder {} slashed'.format(i))
|
|
|
else:
|
|
else:
|
|
@@ -90,27 +102,43 @@ class DarkfiTable:
|
|
|
break
|
|
break
|
|
|
self.darkies[darkie_winning_idx].resync_stake(resync_reward)
|
|
self.darkies[darkie_winning_idx].resync_stake(resync_reward)
|
|
|
self.Sigma += resync_reward
|
|
self.Sigma += resync_reward
|
|
|
|
|
+ #################
|
|
|
|
|
+ # fork resolved #
|
|
|
|
|
+ #################
|
|
|
rt_range.set_description('epoch: {}, fork: {} issuance {} DRK, acc: {}%, stake = {}%, sr: {}%, reward:{}, apr: {}%'.format(int(count/EPOCH_LENGTH), merge_length, round(self.Sigma,2), round(acc*100, 2), round(total_stake/self.Sigma*100 if self.Sigma>0 else 0,2), round(self.avg_stake_ratio()*100,2) , round(self.rewards[-1],2), round(self.avg_apr()*100,2)))
|
|
rt_range.set_description('epoch: {}, fork: {} issuance {} DRK, acc: {}%, stake = {}%, sr: {}%, reward:{}, apr: {}%'.format(int(count/EPOCH_LENGTH), merge_length, round(self.Sigma,2), round(acc*100, 2), round(total_stake/self.Sigma*100 if self.Sigma>0 else 0,2), round(self.avg_stake_ratio()*100,2) , round(self.rewards[-1],2), round(self.avg_apr()*100,2)))
|
|
|
- #print('[2]stake: {}, sigma: {}, reward: {}'.format(total_stake, self.Sigma, self.rewards[-1]))
|
|
|
|
|
- #assert(round(total_stake,1) <= round(self.Sigma,1))
|
|
|
|
|
|
|
+ assert round(total_stake,1) <= round(self.Sigma,1), 'stake: {}, sigma: {}'.format(total_stake, self.Sigma)
|
|
|
count+=1
|
|
count+=1
|
|
|
self.end_time=time.time()
|
|
self.end_time=time.time()
|
|
|
avg_reward = sum(self.rewards)/len(self.rewards)
|
|
avg_reward = sum(self.rewards)/len(self.rewards)
|
|
|
stake_ratio = self.avg_stake_ratio()
|
|
stake_ratio = self.avg_stake_ratio()
|
|
|
avg_apy = self.avg_apy()
|
|
avg_apy = self.avg_apy()
|
|
|
avg_apr = self.avg_apr()
|
|
avg_apr = self.avg_apr()
|
|
|
- #print('apy: {}, staked_ratio: {}'.format(avg_apy, stake_ratio))
|
|
|
|
|
return self.secondary_pid.acc_percentage(), avg_apy, avg_reward, stake_ratio, avg_apr
|
|
return self.secondary_pid.acc_percentage(), avg_apy, avg_reward, stake_ratio, avg_apr
|
|
|
|
|
|
|
|
|
|
+ """
|
|
|
|
|
+ average APY (with compound interest added every epoch) ,
|
|
|
|
|
+ scaled to running time for all nodes
|
|
|
|
|
+ @returns: average APY for all nodes
|
|
|
|
|
+ """
|
|
|
def avg_apy(self):
|
|
def avg_apy(self):
|
|
|
return Num(sum([darkie.apy_scaled_to_runningtime(self.rewards) for darkie in self.darkies])/len(self.darkies))
|
|
return Num(sum([darkie.apy_scaled_to_runningtime(self.rewards) for darkie in self.darkies])/len(self.darkies))
|
|
|
|
|
|
|
|
|
|
+ """
|
|
|
|
|
+ average APR scaled to running time for all nodes
|
|
|
|
|
+ @returns: average APR for all nodes
|
|
|
|
|
+ """
|
|
|
def avg_apr(self):
|
|
def avg_apr(self):
|
|
|
return Num(sum([darkie.apr_scaled_to_runningtime() for darkie in self.darkies])/len(self.darkies))
|
|
return Num(sum([darkie.apr_scaled_to_runningtime() for darkie in self.darkies])/len(self.darkies))
|
|
|
|
|
|
|
|
|
|
+ """
|
|
|
|
|
+ returns: average stake ratio for all nodes
|
|
|
|
|
+ """
|
|
|
def avg_stake_ratio(self):
|
|
def avg_stake_ratio(self):
|
|
|
return sum([darkie.staked_tokens_ratio() for darkie in self.darkies]) / len(self.darkies)
|
|
return sum([darkie.staked_tokens_ratio() for darkie in self.darkies]) / len(self.darkies)
|
|
|
|
|
|
|
|
|
|
+ """
|
|
|
|
|
+ write lottery reward log
|
|
|
|
|
+ """
|
|
|
def write(self):
|
|
def write(self):
|
|
|
elapsed=self.end_time-self.start_time
|
|
elapsed=self.end_time-self.start_time
|
|
|
for id, darkie in enumerate(self.darkies):
|
|
for id, darkie in enumerate(self.darkies):
|