Преглед изворни кода

[research/ouroboros] finished basic simulation

mohab пре 4 година
родитељ
комит
4545cf2a1c

+ 6 - 6
script/research/dpos/ouroboros/beacon.py

@@ -14,7 +14,7 @@ proof, and base to the genesis block.
 #TODO implement trustedbeacon as a node
 #TODO implement trustedbeacon as a node
 '''
 '''
 class TrustedBeacon(SynchedNTPClock, threading.Thread):
 class TrustedBeacon(SynchedNTPClock, threading.Thread):
-    def __init__(self, node, vrf_sk, epoch_length):
+    def __init__(self, node, vrf_sk, epoch_length, genesis_time):
         self.epoch_length=epoch_length # how many slots in a a block
         self.epoch_length=epoch_length # how many slots in a a block
         SynchedNTPClock.__init__(self)
         SynchedNTPClock.__init__(self)
         threading.Thread.__init__(self)
         threading.Thread.__init__(self)
@@ -22,11 +22,11 @@ class TrustedBeacon(SynchedNTPClock, threading.Thread):
         self.node = node #stakeholder
         self.node = node #stakeholder
         self.vrf = VRF(self.node.vrf_pk, vrf_sk, self.node.vrf_base)
         self.vrf = VRF(self.node.vrf_pk, vrf_sk, self.node.vrf_base)
         self.current_slot = self.slot
         self.current_slot = self.slot
-        self.log = Logger(self)
-        self.log.info("[TrustedBeacon]")
+        self.log = Logger(self, genesis_time)
+        self.log.info(f"[TrustedBeacon] constructed for node {str(node)}")
 
 
     def __repr__(self):
     def __repr__(self):
-        return f"trustedbeadon\n"
+        return f"trustedbeacon"
 
 
     def run(self):
     def run(self):
         self.log.info("[TrustedBeacon] thread [start]")
         self.log.info("[TrustedBeacon] thread [start]")
@@ -44,9 +44,10 @@ class TrustedBeacon(SynchedNTPClock, threading.Thread):
         self.current_slot = self.slot
         self.current_slot = self.slot
         sigmas = []
         sigmas = []
         proofs = []
         proofs = []
-        self.log.info(f"[TrustedBeacon] new slot of idx: {self.current_slot}")
         for i in range(self.epoch_length):
         for i in range(self.epoch_length):
+            self.log.info(f"[TrustedBeacon] callback: new slot of idx: {self.current_slot}, epoch slot {i}")
             y, pi = self.vrf.sign(self.current_slot)
             y, pi = self.vrf.sign(self.current_slot)
+            self.log.info(f"[TrustedBeacon] callback: signature calculated for {str(self.node)}")
             sigmas.append(y)
             sigmas.append(y)
             proofs.append(pi)
             proofs.append(pi)
         if self.current_slot%self.epoch_length==0:
         if self.current_slot%self.epoch_length==0:
@@ -58,4 +59,3 @@ class TrustedBeacon(SynchedNTPClock, threading.Thread):
 
 
     def verify(self, y, pi, pk_raw, g):
     def verify(self, y, pi, pk_raw, g):
         return VRF.verify(self.current_slot, y, pi, pk_raw, g)
         return VRF.verify(self.current_slot, y, pi, pk_raw, g)
-    

+ 3 - 2
script/research/dpos/ouroboros/blockchain.py

@@ -1,12 +1,13 @@
 from ouroboros.logger import Logger
 from ouroboros.logger import Logger
+import time
 '''
 '''
 Non-forkable Blockchain for simplicity
 Non-forkable Blockchain for simplicity
 #TODO consider forkable property
 #TODO consider forkable property
 '''
 '''
 class Blockchain(object):
 class Blockchain(object):
-    def __init__(self, R):
+    def __init__(self, R, genesis_time):
         self.blocks = []
         self.blocks = []
-        self.log = Logger(self)
+        self.log = Logger(self, genesis_time)
         self.R = R # how many slots in single epoch
         self.R = R # how many slots in single epoch
     
     
     @property
     @property

+ 9 - 7
script/research/dpos/ouroboros/environment.py

@@ -2,12 +2,14 @@ import numpy as np
 import math
 import math
 import random
 import random
 from ouroboros.logger import Logger
 from ouroboros.logger import Logger
+import time
 '''
 '''
 \class Z is the environment
 \class Z is the environment
 '''
 '''
 class Z(object):
 class Z(object):
-    def __init__(self, stakeholdes, epoch_length):
-        self.log = Logger(self)
+    def __init__(self, stakeholdes, epoch_length, genesis_time=time.time()):
+        self.genesis_time=genesis_time
+        self.log = Logger(self, genesis_time)
         self.epoch_length=epoch_length
         self.epoch_length=epoch_length
         self.stakeholders = np.array(stakeholdes)
         self.stakeholders = np.array(stakeholdes)
         self.adversary_mask=np.array([True]*len(stakeholdes))
         self.adversary_mask=np.array([True]*len(stakeholdes))
@@ -72,12 +74,12 @@ class Z(object):
         return len(self.stakeholders[self.adversary_mask])
         return len(self.stakeholders[self.adversary_mask])
 
 
     def select_epoch_leaders(self, sigmas, proofs):
     def select_epoch_leaders(self, sigmas, proofs):
-        assert(len(sigmas)==self.epoch_length and len(proofs)==self.epoch_length, \
-            f"size mismatch between sigmas: {len(sigmas)}, proofs: {len(proofs)}, and epoch_length: {self.epoch_length}")
+        if len(sigmas)==self.epoch_length or len(proofs)==self.epoch_length:
+            self.log.error(f"size mismatch between sigmas: {len(sigmas)}, proofs: {len(proofs)}, and epoch_length: {self.epoch_length}")
         for i in range(self.epoch_length):
         for i in range(self.epoch_length):
             self.log.info(f"current sigma of index {i} of total {len(sigmas)}, epoch_length: {self.epoch_length}")
             self.log.info(f"current sigma of index {i} of total {len(sigmas)}, epoch_length: {self.epoch_length}")
             sigma = sigmas[i]
             sigma = sigmas[i]
-            assert (sigma!=None, 'proof cant be None')
+            assert sigma!=None, 'proof cant be None'
             def leader_selection_hash(sigma):
             def leader_selection_hash(sigma):
                 Y = np.array(sigma)
                 Y = np.array(sigma)
                 y_hypotenuse2 = math.ceil(np.sum(Y[1]**2+Y[2]**2))
                 y_hypotenuse2 = math.ceil(np.sum(Y[1]**2+Y[2]**2))
@@ -97,7 +99,7 @@ class Z(object):
         self.current_slot=slot
         self.current_slot=slot
         self.log.info(f"stakeholders: {self.stakeholders}")
         self.log.info(f"stakeholders: {self.stakeholders}")
         current_leader = self.stakeholders[self.current_leader_id]
         current_leader = self.stakeholders[self.current_leader_id]
-        assert(current_leader!=None, "current leader cant be None")
+        assert current_leader!=None, "current leader cant be None"
         if current_leader.is_leader:
         if current_leader.is_leader:
             #pass leadership to the current slot leader from the epoch leader
             #pass leadership to the current slot leader from the epoch leader
             self.stakeholders[self.current_epoch_leaders[slot%self.epoch_length]].set_leader()
             self.stakeholders[self.current_epoch_leaders[slot%self.epoch_length]].set_leader()
@@ -106,7 +108,7 @@ class Z(object):
         self.current_slot=slot
         self.current_slot=slot
         #self.log.info(f"stakeholders: {self.stakeholders}")
         #self.log.info(f"stakeholders: {self.stakeholders}")
         #current_leader = self.stakeholders[self.current_leader_id]
         #current_leader = self.stakeholders[self.current_leader_id]
-        #assert(current_leader!=None, 'current leader cant be none')
+        #assert current_leader!=None, 'current leader cant be none'
         #assert(current_leader.is_leader)
         #assert(current_leader.is_leader)
         self.select_epoch_leaders(sigmas, proofs)
         self.select_epoch_leaders(sigmas, proofs)
 
 

+ 15 - 4
script/research/dpos/ouroboros/logger.py

@@ -1,13 +1,24 @@
+import time
+import os
+os.system("color")
+
 class Logger(object):
 class Logger(object):
-    def __init__(self, obj):
+    def __init__(self, obj, genesis_time=time.time()):
         self.obj = obj
         self.obj = obj
+        self.genesis=genesis_time
+
+    @property
+    def diff(self):
+        cur = time.time()
+        d = cur - self.genesis
+        return round(d,1)
 
 
     def info(self, payload):
     def info(self, payload):
-        print(f"\t[{self.obj}]:\n{payload}\n")
+        print("\033[32m", f"[{self.diff}] - [{self.obj}]:\n\t{payload}\n", "\033[0m")
     
     
     def warn(self, payload):
     def warn(self, payload):
-        print(f"\t[{self.obj}]:\n{payload}\n")
+        print("\033[33m", f"[{self.diff}] - [{self.obj}]:\n\t{payload}\n", "\033[0m")
     
     
     def error(self, payload):
     def error(self, payload):
-        print(f"\t[{self.obj}]:\n{payload}\n")
+        print("\033[31m", f"[{self.diff}] - [{self.obj}]:\n\t{payload}\n", "\033[0m")
         exit()
         exit()

+ 10 - 6
script/research/dpos/ouroboros/stakeholder.py

@@ -6,7 +6,7 @@ from ouroboros.beacon import TrustedBeacon
 from ouroboros.vrf import generate_vrf_keys, VRF
 from ouroboros.vrf import generate_vrf_keys, VRF
 from ouroboros.utils import *
 from ouroboros.utils import *
 from ouroboros.logger import Logger
 from ouroboros.logger import Logger
-
+import time
 '''
 '''
 \class Stakeholder
 \class Stakeholder
 '''
 '''
@@ -17,24 +17,23 @@ class Stakeholder(object):
         self.stake=0
         self.stake=0
         self.epoch_length=epoch_length
         self.epoch_length=epoch_length
         pk, sk, g = generate_vrf_keys(self.passwd)
         pk, sk, g = generate_vrf_keys(self.passwd)
+        #verification keys
         self.__vrf_pk = pk
         self.__vrf_pk = pk
         self.__vrf_sk = sk
         self.__vrf_sk = sk
         self.__vrf_base = g
         self.__vrf_base = g
-
-        self.blockchain = Blockchain(self.epoch_length)
-        self.beacon = TrustedBeacon(self, self.epoch_length, self.__vrf_sk)
+        #signature keys
         sig_sk, sig_pk = generate_sig_keys(self.passwd)
         sig_sk, sig_pk = generate_sig_keys(self.passwd)
         self.sig_sk = sig_sk
         self.sig_sk = sig_sk
         self.sig_pk = sig_pk
         self.sig_pk = sig_pk
+        #
         self.current_block = None
         self.current_block = None
         self.uncommited_tx=''
         self.uncommited_tx=''
         self.tx=''
         self.tx=''
-        self.current_slot_uid = self.beacon.slot
         self.current_epoch = None
         self.current_epoch = None
         self.am_current_leader=False
         self.am_current_leader=False
         self.am_current_endorder=False
         self.am_current_endorder=False
         self.am_corrupt=False
         self.am_corrupt=False
-        self.log = Logger(self)
+        #
 
 
     @property
     @property
     def is_leader(self):
     def is_leader(self):
@@ -55,6 +54,11 @@ class Stakeholder(object):
 
 
     def __call__(self, env):
     def __call__(self, env):
         self.env=env
         self.env=env
+        self.log = Logger(self, self.env.genesis_time)
+        self.blockchain = Blockchain(self.epoch_length, self.env.genesis_time)
+        self.beacon = TrustedBeacon(self,  self.__vrf_sk, self.epoch_length, self.env.genesis_time)
+        self.current_slot_uid = self.beacon.slot
+
 
 
     def start(self):
     def start(self):
         self.log.info("Stakeholder.start [started]")
         self.log.info("Stakeholder.start [started]")

+ 1 - 2
script/research/dpos/ouroboros/vrf.py

@@ -14,8 +14,7 @@ def generate_vrf_keys(sk_seed):
         generate pk/sk
         generate pk/sk
     return: list of pk (public key), sk(secret key), base(field base)
     return: list of pk (public key), sk(secret key), base(field base)
     '''
     '''
-    #sk = vrf_hash(sk_seed)
-    sk=2
+    sk = vrf_hash(sk_seed)
     base = ecc.gen()
     base = ecc.gen()
     pk = ecc.scalar_mult(sk, base)
     pk = ecc.scalar_mult(sk, base)
     return (pk, sk, base)
     return (pk, sk, base)

+ 2 - 2
script/research/dpos/simulation.py

@@ -1,13 +1,13 @@
 from ouroboros import Stakeholder
 from ouroboros import Stakeholder
 from ouroboros import Z
 from ouroboros import Z
-import random
+import time
 
 
 EPOCH_LENGTH = 3
 EPOCH_LENGTH = 3
 stakeholders = []
 stakeholders = []
 for i in range(3):
 for i in range(3):
     stakeholders.append(Stakeholder(EPOCH_LENGTH))
     stakeholders.append(Stakeholder(EPOCH_LENGTH))
 
 
-environment = Z(stakeholders, EPOCH_LENGTH)
+environment = Z(stakeholders, EPOCH_LENGTH, genesis_time=time.time())
 
 
 environment.start()
 environment.start()