forked from mit-ll/blockchain-simulation-framework
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsimulation_settings.py
123 lines (92 loc) · 4.36 KB
/
simulation_settings.py
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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
from enum import Enum
import json
import logging
from pprint import pformat
from distribution import Distribution
from protocol_settings import ProtocolSettings
from topology_settings import TopologySettings
class TopologySelection(Enum):
"""Enumeration of the possible topology selection.
"""
GENERATE_ONCE = 1
GENERATE_EACH_TIME = 2
class TerminationCondition(Enum):
"""Enumeration tracking when an individual simulation terminates.
"""
NUMBER_OF_GENERATED_TRANSACTIONS = 1
NUMBER_OF_TIME_TICKS = 2
class SimulationSettings:
"""Handles loading simulation settings information from a file.
"""
def __init__(self, fname):
"""
Arguments:
fname {str} -- Filename to load settings from.
"""
with open(fname, 'r') as settingsFile:
data = json.load(settingsFile)
# Load settings.
self.thread_workers = data['threadWorkers']
self.number_of_executions = data['numberOfExecutions']
self.topology_selection = TopologySelection[data['topologySelection']]
self.termination_condition = TerminationCondition[data['terminationCondition']]
self.termination_value = data['terminationValue']
self.miner_power_distribution = Distribution(data['minerPower'])
self.top_miner_power = None
# Percent power share of the top N miners, currently drawn from https://btc.com/stats/pool?pool_mode=week on July 11, 2018.
# Each element of the list is an float between 0 and 100; the list must sum to < 100.
if 'topMinerPower' in data:
self.top_miner_power = data['topMinerPower']
self.target_termination_ticks = -1
# Parameterize in JSON later?
self.allow_termination_cooldown = True
self.hard_limit_ticks = 1000 # Should this be a function of the number of miners?
# Load the other settings objects.
self.topology = TopologySettings(data['topology'])
self.protocol = ProtocolSettings(data['protocol'])
def shouldMakeNewTx(self, simulation):
"""Returns True if the simulation should generate more transactions, False otherwise.
Arguments:
simulation {Simulation} -- The simulation in question.
"""
return not self.shouldFinish(simulation)
def shouldFinish(self, simulation):
"""Returns True if the simulation termination condition is met, False otherwise.
Arguments:
simulation {Simulation} -- The simulation in question.
"""
if self.termination_condition == TerminationCondition.NUMBER_OF_GENERATED_TRANSACTIONS:
return simulation.next_id > self.termination_value # Conditioned on next_id, not len(all_tx) so that reiusses don't count.
elif self.termination_condition == TerminationCondition.NUMBER_OF_TIME_TICKS:
return simulation.tick > self.termination_value
else:
raise NotImplementedError("Selected termination condition is not implemented.")
def shouldTerminate(self, simulation):
"""Returns True if the simulation should immediately terminate (termination condition is met and either allow_termination_cooldown is False, cooldown is finished, or hard_limit is reached), False otherwise.
Arguments:
simulation {Simulation} -- The simulation in question.
"""
should_finish = self.shouldFinish(simulation)
if not should_finish:
return False
elif not self.allow_termination_cooldown:
return True
if should_finish and self.target_termination_ticks < 0: # Set the target if it hasn't been set already.
self.target_termination_ticks = simulation.tick + self.hard_limit_ticks
if simulation.tick > self.target_termination_ticks:
logging.info("Terminating due to surpassed hard tick limit.")
return True
miners_have_msgs = bool([True for node_id in simulation.graph.nodes if simulation.graph.nodes[node_id]['miner'].queue])
return not miners_have_msgs
def __str__(self):
"""
Returns:
str -- String representation of object.
"""
return pformat(self.__dict__, indent=4)
def __repr__(self):
"""
Returns:
str -- String representation of object.
"""
return pformat(self.__dict__, indent=4)