Browse Source

[research/lotterysim] move from tipless fee mechanism to tip auction

ertosns 3 years ago
parent
commit
45746dbdd2

+ 1 - 1
script/research/lotterysim/core/constants.py

@@ -39,7 +39,7 @@ PRIMARY_REWARD_TARGET = 0.35 # staked ratio
 # secondary controller assumes certain frequency of leaders per slot
 SECONDARY_LEAD_TARGET = 1 #number of lead per slot
 # maximum transaction size
-MAX_BLOCK_SIZE = 1000
+MAX_BLOCK_SIZE = 100
 # maximum transaction computational cost
 MAX_BLOCK_CC = 10
 # fee controller computational capacity target

+ 16 - 5
script/research/lotterysim/core/darkie.py

@@ -14,6 +14,7 @@ class Darkie():
         self.slot = 0
         self.won_hist = [] # winning history boolean
         self.fees = []
+        self.tips = [0]
 
     def clone(self):
         return Darkie(self.stake)
@@ -170,8 +171,17 @@ class Darkie():
 
     @returns: transaction emulated as series of random floats between 0,1
     """
-    def tx(self):
-        return Tx(random.randint(0, MAX_BLOCK_SIZE))
+    def tx(self, last_reward):
+        tx_size = random.randint(0, MAX_BLOCK_SIZE)
+        tip = self.tx_tip(tx_size, last_reward)
+        if self.stake < tip:
+            return Tx(tx_size, 0)
+        return Tx(tx_size, tip)
+
+    def tx_tip(self, tx_size, last_reward):
+        tip = random_tip_strategy()
+        apr = self.apr_scaled_to_runningtime()
+        return tip.get_tip(float(last_reward), float(apr), tx_size, self.tips[-1])
 
     """
     deduct tip paid to miner plus burned base fee or computational cost.
@@ -185,20 +195,21 @@ class Darkie():
         return self.fees[-1] if len(self.fees)>0 else 0
 
 class Tx(object):
-    def __init__(self, size):
+    def __init__(self, size, tip):
         self.tx = [random.random() for _ in range(size)]
         self.len = size
+        self.tip = tip
 
     """
     anonymous contract assumed to be of random streams from uniform distribution,
     it's circuit execution cost it thus random.
-    naive emulation of transaction smart contract computational cost (aka tip) as a avg of txs sum,
+    naive emulation of transaction smart contract computational cost as a avg of txs sum,
     which is random function
 
     @returns: transaction computational cost
     """
     def cc(self):
-        return sum(self.tx) if len(self.tx)>0 else 0
+        return int(sum(self.tx) if len(self.tx)>0 else 0)
 
     def __len__(self):
         return len(self.tx)

+ 5 - 4
script/research/lotterysim/core/lottery.py

@@ -143,7 +143,8 @@ class DarkfiTable:
     def tx_fees(self, darkie_lead_idx, debug=False):
         txs = []
         for darkie in self.darkies:
-            txs += [darkie.tx()]
+            # make sure tip is covered by darkie stake
+            txs += [darkie.tx(self.rewards[-1])]
         ret, actual_cc = DarkfiTable.auction(txs)
         self.computational_cost += [actual_cc]
         self.cc_diff += [MAX_BLOCK_CC - actual_cc]
@@ -209,9 +210,9 @@ class DarkfiTable:
             for w in range(W + 1):
                 if i == 0 or w == 0:
                     K[i][w] = [0,[]]
-                elif len(txs[i-1]) <= w:
-                    if txs[i-1].cc() + K[i-1][w-len(txs[i-1])][0] > K[i-1][w][0]:
-                        K[i][w] = [txs[i-1].cc() + K[i-1][w-len(txs[i-1])][0], K[i-1][w-len(txs[i-1])][1] + [i-1]]
+                elif txs[i-1].cc() <= w:
+                    if txs[i-1].tip + K[i-1][w-txs[i-1].cc()][0] > K[i-1][w][0]:
+                        K[i][w] = [txs[i-1].tip + K[i-1][w-txs[i-1].cc()][0], K[i-1][w-txs[i-1].cc()][1] + [i-1]]
                     else:
                         K[i][w] = K[i-1][w]
                 else:

+ 105 - 0
script/research/lotterysim/core/strategy.py

@@ -72,6 +72,7 @@ class SigmoidStrategy(Strategy):
     def set_ratio(self, slot, apr):
         if slot%self.epoch_len==0:
                 apr_ratio = apr/self.target_apy
+                apr_ratio = max(apr_ratio, 0)
                 sr = Num(2/(1+math.pow(math.e, -4*apr_ratio))-1)
                 if sr>1:
                     sr = 1
@@ -90,3 +91,107 @@ def random_strategy(epoch_length=EPOCH_LENGTH):
         return LogarithmicStrategy(epoch_length)
     else:
         return SigmoidStrategy(epoch_length)
+
+
+class Tip(object):
+    def __init__(self):
+        self.type = 'tip'
+
+    def get_tip(self, last_reward, apr, size, last_tip):
+        return 0
+
+class ZeroTip(Tip):
+
+    def __init__(self):
+        super().__init__()
+        self.type = 'zero'
+
+    def get_tip(self, last_reward, apr, size, last_tip):
+        return 0
+
+class TenthOfReward(Tip):
+    def __init__(self):
+        super().__init__()
+        self.type = '10th'
+
+    def get_tip(self, last_reward, apr, size, last_tip):
+        return last_reward/10
+
+class HundredthOfReward(Tip):
+    def __init__(self):
+        super().__init__()
+        self.type = '100th'
+
+    def get_tip(self, last_reward, apr, size, last_tip):
+        return last_reward/100
+
+class MilthOfReward(Tip):
+    def __init__(self):
+        super().__init__()
+        self.type = '1000th'
+
+    def get_tip(self, last_reward, apr, size, last_tip):
+        return last_reward/1000
+
+class RewardApr(Tip):
+    def __init__(self):
+        super().__init__()
+        self.type = 'reward_apr'
+
+    def get_tip(self, last_reward, apr, size, last_tip):
+        apr_relu = max(apr, 0)
+        return last_reward*apr_relu
+
+class TenthRewardApr(Tip):
+    def __init__(self):
+        super().__init__()
+        self.type = 'reward_apr'
+
+    def get_tip(self, last_reward, apr, size, last_tip):
+        apr_relu = max(apr, 0)
+        return last_reward*apr_relu/10
+
+
+class TenthCCApr(Tip):
+    def __init__(self):
+        super().__init__()
+        self.type = "cc_apr_10"
+
+    def get_tip(self, last_reward, apr, size, last_tip):
+        return size/MAX_BLOCK_SIZE/10
+
+class HundredthCCApr(Tip):
+    def __init__(self):
+        super().__init__()
+        self.type = "cc_apr_100"
+
+    def get_tip(self, last_reward, apr, size, last_tip):
+        return size/MAX_BLOCK_SIZE/100
+
+class MilthCCApr(Tip):
+    def __init__(self):
+        super().__init__()
+        self.type = "cc_apr_1000"
+
+    def get_tip(self, last_reward, apr, size, last_tip):
+        return size/MAX_BLOCK_SIZE/1000
+
+class Conservative(Tip):
+    def __init__(self):
+        super().__init__()
+        self.type = "cc_apr_1000"
+
+    def get_tip(self, last_reward, apr, size, last_tip):
+        return last_tip
+
+class Generous(Tip):
+    def __init__(self):
+        super().__init__()
+        self.type = "cc_apr_1000"
+
+    def get_tip(self, last_reward, apr, size, last_tip):
+        return last_tip*2
+
+
+def random_tip_strategy():
+    return random.choice([ZeroTip(), TenthOfReward(), HundredthOfReward(), MilthOfReward(), RewardApr(), TenthRewardApr(), TenthCCApr(), HundredthCCApr(), MilthCCApr(), Conservative(), Generous()])

+ 3 - 3
script/research/lotterysim/discrete_instance_pi_headstart.py

@@ -16,12 +16,12 @@ if __name__ == "__main__":
     mu = PREMINT/NODES
     darkies = [Darkie(random.gauss(mu, mu/10), strategy=random_strategy(EPOCH_LENGTH)) for _ in range(NODES)]
     #dt = DarkfiTable(0, RUNNING_TIME, CONTROLLER_TYPE_DISCRETE, kp=-0.010399999999938556, ki=-0.0365999996461878, kd=0.03840000000000491,  r_kp=-2.53, r_ki=29.5, r_kd=53.77)
-    dt = DarkfiTable(PREMINT, RUNNING_TIME, CONTROLLER_TYPE_DISCRETE, kp=-0.010399999999938556, ki=-0.0365999996461878, kd=0.03840000000000491,  r_kp=-0.719, r_ki=1.6, r_kd=0.1)
+    dt = DarkfiTable(PREMINT, RUNNING_TIME, CONTROLLER_TYPE_DISCRETE, kp=-0.010399999999938556, ki=-0.0365999996461878, kd=0.03840000000000491,  r_kp=-0.719, r_ki=1.6, r_kd=0.1, fee_kp=-0.068188, fee_ki=-0.000205)
     for darkie in darkies:
         dt.add_darkie(darkie)
-    acc, avg_apy, avg_reward, stake_ratio, avg_apr = dt.background(rand_running_time=False)
+    acc, cc_acc, avg_apy, avg_reward, stake_ratio, avg_apr = dt.background(rand_running_time=False)
     #sum_zero_stake = sum([darkie.stake for darkie in darkies[NODES:]])
-    print('acc: {}, avg(apr): {}%, avg(reward): {}, stake_ratio: {}'.format(acc, round(avg_apr*100,2), avg_reward, stake_ratio))
+    print('acc: {}, cc_acc: {}, avg(apr): {}%, avg(reward): {}, stake_ratio: {}'.format(round(acc,2), round(cc_acc, 2), round(avg_apr*100,2), avg_reward, stake_ratio))
     #print('total stake of 0mint: {}, ratio: {}'.format(sum_zero_stake, sum_zero_stake/ERC20DRK))
     dt.write()
     aprs = []