Commit 31939bc9 authored by THAKARE AKSHAY HARIBHAU's avatar THAKARE AKSHAY HARIBHAU

Merge branch 'algorand' into 'master'

Fianlly submitted the project but not the complete

See merge request !10
parents 9b7da117 9098140d
lambda_proposer = 30# wait time for priority messages to be received
tou_proposer = 26 # proposer rolecount
ROLE_BLOCK_PROPOSER = 'BLOCK_PROPOSER'
tou_step = 28 # tou is expected number of users that sortition selects for committee
ROLE_COMMITEE_FOR_VOTE = 'committee'
lambda_block = 300 #seconds
lambda_step = 30
BLOCK_PROPOSAL_MSG_type = 'BLOCK_PROPOSAL_MSGs'
PRIORITY_MSG_type = 'PRIORITY_MSG'
COMMITTEE_VOTE_MSG_type = "COMMITTEE_VOTE"
TIMEOUT = "TIMEOUT"
T = 0.001 # 2/3 # T isa a fraction of expected committee size that defines BA*`s voting thershold
T_FINAL = 0.001
tou_FINAL = 28
FINALIZED_BLOCK_msg_type = "FINALIZED_BLOCK"
TENTATIVE_BLOCK_msg_type = "TENTATIVE_BLOCK"
NUMBER_OF_NODES_IN_NETWORK = 50
MAXSTEP = 15
FINAL_STEP = 9999999999
'''------------------------------------------------------------------------------'''
Experiment_1_OBS = {} #KEY : (subusercount,sortitionCount)
\ No newline at end of file
......@@ -78,8 +78,9 @@ class Link(SystemEntity):
'''
#todo process messages in queue
# generate tasks for todolist based on messges
for message in self.messageQueue:
for message in list(self.messageQueue):
self.scheduleMessageDelievery(message[0],message[1])
self.dequeMessage()
# TODO : perform task from todolist which are relevant for current tick
......
......@@ -2,3 +2,7 @@
2 3
3 4
4 1
3 5
2 6
3 7
7 4
\ No newline at end of file
0 57
0 62
0 58
1 23
1 65
1 10
2 84
2 58
2 90
2 99
3 22
3 56
4 72
4 62
4 38
5 52
5 57
5 42
6 10
6 90
7 21
7 45
8 76
8 71
9 32
9 97
9 46
10 59
10 79
11 83
11 81
11 23
12 27
12 75
12 59
13 66
13 44
13 41
14 99
14 65
15 16
15 71
15 95
16 40
17 95
17 74
17 34
17 29
18 39
18 52
19 96
19 82
20 81
20 90
21 26
21 91
22 26
22 92
23 97
23 44
24 27
24 94
25 80
25 77
25 46
26 48
26 30
27 83
27 80
28 40
28 44
28 98
29 78
30 74
30 48
30 50
31 52
31 55
31 49
32 91
32 93
33 47
33 51
34 37
35 85
35 61
35 48
36 98
36 93
37 57
37 51
37 55
38 73
38 67
38 81
39 40
39 94
40 59
41 48
42 85
42 68
42 78
43 53
43 98
44 65
45 80
46 88
46 56
47 74
49 82
49 68
49 53
50 89
51 93
51 68
54 99
54 63
55 96
55 87
56 71
56 91
58 83
60 78
60 97
61 63
62 68
62 98
63 74
64 70
64 88
66 87
67 90
67 99
69 89
69 81
70 86
72 93
72 73
75 82
76 77
78 84
79 97
83 85
85 86
92 94
0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
10 11
11 12
12 13
13 14
14 15
15 16
16 17
17 18
18 19
19 20
20 21
21 22
22 23
23 24
24 25
25 26
26 27
27 28
28 29
29 30
30 31
31 32
32 33
33 34
34 35
35 36
36 37
37 38
38 39
39 40
40 41
41 42
42 43
43 44
44 45
45 46
46 47
47 48
48 49
......@@ -4,16 +4,22 @@ import csv
from Node import Node
from OverlayNode import OverlayNode
import logging
logger = logging.getLogger(__name__)
import random
from numpy.random import randint
import numpy as np
import Config
class Network():
def __init__(self):
self.logger = logging.getLogger(__name__)
self.nodes = {}#{1 : Node(1),2:Node(2)}
self.links = {} #{(1,2):Link(1-2),(2,1):Link(2,1),(3,2):Link(3*2)} linkID = tuple(1,2)
self.networkClockTime = 0
self.pk_weight_map = {}
self.time = 0
self.BlocksHashTOBLOCK_MAP = {}
def setupNetwork(self):
'''
......@@ -27,19 +33,34 @@ class Network():
:return:
'''
with open('Nodes.dat', 'r') as f:
w = randint(1, 51, Config.NUMBER_OF_NODES_IN_NETWORK) # 51 is excluded - range (1,50)
print('Stakes that are given to the nodes are : \n')
print(w)
print('\n')
self.badaW = np.sum(w)
print(self.badaW)
i = 0
with open('Nodes1.dat', 'r') as f:
reader = csv.reader(f)
for row in reader:
node = row[0] # tuple of a link
self.nodes.update({node:OverlayNode(node,self)})
node = row[0] # Node id
xnode = {node:OverlayNode(node,self,w[i])}
self.pk_weight_map.update({xnode[node].pk:w[i]})
self.nodes.update(xnode)#added node to network
# print(self.nodes.get('1')) #keys are strings
i = i+1
with open('Links.dat', 'r') as f:
with open('Links1.dat', 'r') as f:
reader = csv.reader(f)
for row in reader:
link = tuple(row[0].split()) # tuple of a link
tup = row[0].split()
link = None # tuple of a link
if int(tup[0]) < int(tup[1]):
link = (tup[0],tup[1])
else:
link = (tup[1],tup[0])
linkDelay = 1
self.links.update({link:Link(link,self,linkDelay)})
......@@ -47,15 +68,23 @@ class Network():
self.nodes.get(link[0]).adjacentNodes.append(link[1])
self.nodes.get(link[1]).adjacentNodes.append(link[0])
# print(self.links.get(('1', '2'))) #keys are strings
for node in self.nodes.values():
self.logger.info("node {}".format((node.id,node.adjacentNodes)))
pass
def getLink(self,tup):
if int(tup[0]) < int(tup[1]) :
return self.links.get(tup)
else:
return self.links.get((tup[1],tup[0]))
def simulate(self,time):
self.time = time
# logger.info("simulating .. ")
self.networkClockTime = time
# Note links should be simulated before nodes
# Note links should be simulated before nodeself.ResumeTasks.append(("nextOn", self.startNodeLifeCycleGenerator,))s
# in order to receive the messge which is supposed to be received in this tick
for link in self.links.values():
link.simulate(time)
......@@ -63,6 +92,14 @@ class Network():
for node in self.nodes.values():
node.simulate(time)
if time == str(99999):
for link in self.links.values():
self.logger.info("remaining tasks : {}".format((link.link,link.todoList)))
for node in self.nodes.values():
self.logger.info("reamaining tasks : {}".format((node.id,node.todoList)))
self.logger.info("reamaining tasks : {}".format(node.ResumeTasks))
pass
if __name__ == '__main__':
......
from SystemEntity import SystemEntity
import logging
import Utility
import hashlib
from collections import defaultdict
class Node(SystemEntity):
def __init__(self,id,network):
def __init__(self,id,network,weight):
SystemEntity.__init__(self,network)
self.logger = logging.getLogger(__name__ + "-" + str(id))
self.id = id
self.weight = weight
self.adjacentNodes = []
self.messageQueue = []
self.sk,self.pk = Utility.genratePublicPrivateKey()
self.ResumeTasks = defaultdict(list)
'''make sure methods included here are not overriddenn'''
self.commands={"sendMessage":self.sendMessage,
"nextOn":self.nextOn
}
self.messagesTillNow = [] # list of messages forwarded
self.uniqueReceivedMessages = defaultdict(list) #this is a list of messages in buffer which were not processed, expecting two list of 'BLOCK_PROPOSAL_MSG','PRIORITY_MSG'
def enqueMessage(self,message):
......@@ -37,23 +47,45 @@ class Node(SystemEntity):
:param params: ('1','2','hello2')
:return:
'''
link = self.network.links.get((params[0],params[1]))
link = self.network.getLink((params[0],params[1]))
link.enqueMessage((time,params))
self.logger.info("Sending : " + str((time,params)))
# any message going out is recorded as sent and will be checked for duplicates
self.messagesTillNow.append(hashlib.sha256((str(params[2])).encode('utf-8')).hexdigest())
###### self.logger.info("Sending : " + str((time,params)))#(time,(sender,receiver,payload))
pass
def broadcast(self,time,gossipPayload):
for node in self.adjacentNodes:
link = self.network.links.get((self.id, node.id))
'''
:param time:
:param gossipPayload:
:return:
broadcast and processMessage together makes it gossip protocol
'''
self.messagesTillNow.append(hashlib.sha256((str(gossipPayload)).encode('utf-8')).hexdigest())
for nodeid in self.adjacentNodes:
node = self.network.nodes.get(nodeid)
link = self.network.getLink((self.id, node.id))
link.enqueMessage((time, (self.id, node.id,gossipPayload)))
self.logger.info("Sending : " + str((time, (self.id, node.id,gossipPayload))))
###### self.logger.info("Sending : " + str((time, (self.id, node.id,gossipPayload))))#(time,(sender,receiver,payload))
def processMessage(self,time,payload):
print("fianlly reached : " + str(payload))
'''remove any extra headers like source and destination here '''
payload.pop(0) # removed source header
payload.pop(0) #removed destination header
# TODO check messages for duplicates and brodacast them : Done
if not (hashlib.sha256((str(payload[0])).encode('utf-8')).hexdigest() in self.messagesTillNow) :
self.broadcast(time,payload[0])
self.uniqueReceivedMessages[payload[0][0]].append(payload[0])
def nextOn(self,time,generator):
return next(generator[0])
def startNodeLifeCycle(self):
pass
def simulate(self,time):
# self.logger.info("simulating .. ")
......@@ -69,9 +101,31 @@ class Node(SystemEntity):
# generate tasks for todolist based on messges
for message in list(self.messageQueue): #this creates adupliacte list and iterate over it while making changes to original queue
self.processMessage(message[0],list(message[1])) # message : (time,(payload))
self.logger.info("received : "+str(message))
# self.logger.info("received : "+str(message))
self.dequeMessage()
# check if main ba* has to be resumed or not
try:
ResumeTasks = self.ResumeTasks.pop(time)
for ResumeTask in ResumeTasks:
command = self.commands.get(ResumeTask[0])
ResumeOut = command(time,ResumeTask[1:])
'''
synatx for proper return commands
yield "resume",timeafter_which_to_resume
'''
if ResumeOut and ResumeOut[0] == "resume":
# self.logger.info("resume has been called")
self.ResumeTasks[str(int(time)+int(ResumeOut[1]))].append(("nextOn", self.startNodeLifeCycleGenerator,))
except KeyError as ke:
# not task pending at this time
pass
except StopIteration as si:
pass
except IndexError as Ie:
self.logger.info("No resume task from ba*")
# TODO : perform task from todolist which are relevant for current tick
......@@ -79,12 +133,12 @@ class Node(SystemEntity):
tasks = self.todoList.pop(time)
for task in tasks:
command = self.commands.get(task[0])
command(time,task[1:])
out = command(time,task[1:])
except KeyError as ke:
# not task pending at this time
pass
pass
if __name__ == '__main__':
# node = Node('1')
......@@ -100,4 +154,3 @@ if __name__ == '__main__':
......@@ -2,3 +2,6 @@
2
3
4
5
6
7
\ No newline at end of file
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
This diff is collapsed.
import matplotlib.pyplot as plt
stats= {49: [5, 3], 41: [14, 12], 23: [7, 5], 40: [5, 4], 19: [3, 3], 31: [7, 6], 28: [1, 1], 33: [7, 5], 38: [10, 8], 16: [2, 2], 48: [3, 3], 50: [4, 2], 12: [1, 1], 17: [3, 1], 42: [2, 2], 35: [1, 1], 45: [2, 2], 37: [7, 6], 36: [4, 2], 7: [1, 1], 29: [1, 1], 26: [4, 3], 32: [1, 1], 34: [1, 1], 39: [1, 1], 25: [5, 3], 46: [1, 1], 8: [1, 1], 30: [1, 1]}
stats2 ={38: [2, 2], 20: [2, 2], 37: [2, 2], 47: [2, 2], 41: [11, 8], 46: [1, 1], 49: [4, 3], 40: [2, 2], 32: [1, 1], 45: [4, 3], 24: [2, 2], 30: [1, 1], 31: [2, 2], 28: [2, 2], 35: [2, 2], 22: [1, 1], 43: [3, 3], 23: [1, 1], 39: [1, 1], 27: [2, 2], 7: [1, 1], 29: [3, 2]}
stats3 = {41: [2, 2], 16: [2, 2], 48: [1, 1], 5: [1, 1], 21: [2, 2], 39: [1, 1], 47: [2, 2], 46: [1, 1], 38: [1, 1], 45: [1, 1], 42: [1, 1], 40: [1, 1]}
dict = {}
for key, val in stats.items():
# print(key)
# print(val)
dict[key] = (val[0]/val[1])
# print(sorted(dict))
lists = sorted(dict.items()) # sorted by key, return a list of tuples
x, y = zip(*lists)
plt.xlabel('Stake')
plt.ylabel('Sub User')
plt.plot(x, y)
plt.savefig('stats.png')
plt.show()
#Algorand
* Basic requirements
* Dsicrete Event Simulator
* Gossip Protocol
* Installation
`pip3 install -r requirements.txt `
`pip3 install -r requirements.txt`
* Setup
* Requirements
* Configure Nodes and Links using Nodes.dat and Links.dat
* Stakes are randomly assigned to nodes between 1 and 50
* How to run
`$ ./start.sh`
### Nilesh doubts:
......@@ -4,7 +4,9 @@ from TestCases import populateTodolist
import logging
logging.basicConfig(filename='ASim.log', level=logging.INFO)
# logging.basicConfig(filename='ASim.log', level=logging.INFO)
# logging.basicConfig(filename='ASim.log', format="%(funcName)s():%(lineno)i: %(message)s")
logging.basicConfig(filename='ASim.log',level=logging.INFO, format="%(levelname)s [%(name)s.%(funcName)s:%(lineno)d] %(message)s")
logger = logging.getLogger(__name__)
......@@ -12,6 +14,6 @@ if __name__ == '__main__':
metronome = TimeSimulator()
network = Network()
network.setupNetwork()
populateTodolist(network)
# populateTodolist(network)
metronome.startTicking(network.simulate)
pass
\ No newline at end of file
......@@ -22,3 +22,4 @@ class SystemEntity(object):
'''
pass
......@@ -18,9 +18,12 @@ def populateTodolist(net):
instruction = row[0].split() # tuple of a link
node = network.nodes.get(instruction[0])
node.todoList[instruction[1]].append(tuple(instruction[2:]))
# for id, node in network.nodes.items():
# node.todoList['0'].append(("nextOn",node.startNodeLifeCycleGenerator,))
for id,node in network.nodes.items():
logger.info(id +" : "+str(node.todoList))
# logger.info(id +" : "+str(node.todoList))
pass
def simulateNetwork(net):
if not net:
......@@ -38,7 +41,12 @@ def simulateNetwork(net):
if __name__ == '__main__':
logging.basicConfig(filename='TestCases.log', level=logging.INFO)
# populateTodolist()
simulateNetwork(None)
# populateTodolist(None)
# simulateNetwork(None)
ak = ['hello','ramesh']
ak.append('rao')
if 'hello' in ak:
print("yay")
print(ak.pop())
pass
class Generator:
def __init__(self):
# self.todoList = [self.gen]
self.todoList = [(0, 0)]
#LIST OF GENERATOR OBJECTS OF METHODS
#generator object of self task creating method genrefer
self.refGen = self.genRefer("+")
def gen(self):
x = 0
count = 0
while True:
# print("generator : ", todoList)
self.todoList.insert(0, (count, x))
count += 1
self.todoList.insert(0, (count, x))
count += 1
self.todoList.insert(0, (count, x))
count += 1
yield x
x += 1
def genRefer(self,dot):
'''
THis method adds itself to to-do list by use of its own generator object which will be unique for different instances of generator class
:return:
'''
print("Gen refer Started",dot)
x = 0
count = 0
# while True:
while x<5:
# print("generator : ", todoList)
self.todoList.insert(0, (count, self.refGen))
count += 1
self.todoList.insert(0, (count, self.refGen))
count += 1
yield x
print("------",x)
x += 1
# return
def callgenRefer(self,dot):
'''this adapter method wil ensure that gen refer stats executing as soon as it is called by user, so only call this method not to genRefer from outside of this class'''
self.refGen = self.genRefer(dot)