Merge pull request #1 from logos-co/refactor

Refactor
This commit is contained in:
Alberto Soutullo 2022-11-27 16:47:34 +01:00 committed by GitHub
commit 48da9c5730
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
36 changed files with 259 additions and 103 deletions

2
.dockerignore Normal file
View File

@ -0,0 +1,2 @@
*.md
.venv

2
.gitignore vendored
View File

@ -1 +1,3 @@
.idea/
.venv/
*__pycache__*

34
Dockerfile Normal file
View File

@ -0,0 +1,34 @@
# BUILD IMAGE --------------------------------------------------------
FROM rust as builder
# Update default packages
RUN apt-get update
# Get tools needed
RUN apt-get install -y git
# Get the simulation code
WORKDIR /rust-app
RUN git clone https://github.com/logos-co/consensus-research.git
# Compile it
WORKDIR /rust-app/consensus-research
RUN cargo build --profile release-opt --bin snow-family
# ACTUAL IMAGE ------------------------------------------------------
FROM python
COPY --from=builder /rust-app/consensus-research/target/release-opt/snow-family /usr/local/bin/snow-family
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
ENV PYTHONPATH "${PYTHONPATH}:src"
ENTRYPOINT ["python", "src/main.py"]

57
README.md Executable file
View File

@ -0,0 +1,57 @@
# Simulations Framework
This framework is to run simulations, as well as being able to obtain plots from the results in an easy-one command manner.
Simulations supported:
- Snow family: https://github.com/logos-co/consensus-research (default)
## How to use
In order to build the image, simply run:
`docker build -t desired_name_of_docker_image .`
In order to tell the container what to do, you need to specify the options in a configuration file, as json.
More information in:
Supported parameters:
- Run parameters `--run` or `-r`
- `both` (default) (to-do)
- `simulation`
- `plotter` (to-do)
- Simulation type `--protocol` or `-p` (to-do)
- `snow-family` (default, not changeable)
- Configuration file `--configuration-file` or `-cf`
- <configuration_file_name.json>
In order to receive the information, plots, and whatever is done inside the container, a shared folder is
provided inside this repository. Before running the container,
### Example of execution:
`docker run --rm -v </your/path/to/SimulationsFramework/shared>:/app/shared <desired_name_of_docker_image>
-r <simulation> -cf <configuration_file_name.json>`
The parameters inside `< >` can be changed. Where:
- `docker run --rm` will launch a docker container, and after it finishes, it will automatically destroy itself.
- `-v </your/path/to/SimulationsFramework/shared>:/app/shared` is the mount folder that will be used to share data
between the container and the host. In order to make things easier, the folder inside this repo can be used for that.
Still, any desired folder can be put here, as long as it is in absolute path. `/app/shared` is a internal framework
location, so this needs to remain unchanged.
- `<desired_name_of_docker_image>` is the docker image name previously created.
- `-r <simulation>` is the type of execution we want. It can be only simulation `simulation`, only plotting `plotter`,
or simulation and plot `both`. This last option is as default, so if this is the case, it is something that needs to
be specified.
- `-cf <configuration_file_name.json>` is the configuration file where we set up what we want to do in the execution.
This file needs to be in our shared host folder.
So, an example of a command would be:
`docker run --rm -v /mnt/d/Projects/SimulationsFramework/shared:/app/shared simulation-framework
-r simulation -cf config_example.json`
## Project structure
(to-do)

View File

@ -1,38 +0,0 @@
{
"consensus_settings": {
"snow_ball": {
"quorum_size": 14,
"sample_size": 20,
"decision_threshold": 20
}
},
"distribution": {
"yes": 0.6,
"no": 0.4,
"none": 0.0
},
"byzantine_settings": {
"total_size": 10000,
"distribution": {
"honest": 1.0,
"infantile": 0.0,
"random": 0.0,
"omniscient": 0.0
}
},
"wards": [
{
"time_to_finality": {
"ttf_threshold" : 1
}
}
],
"network_modifiers": [
{
"random_drop": {
"drop_rate": 0.01
}
}
],
"seed" : 18042022
}

View File

@ -1,23 +0,0 @@
# Python Imports
import typer
# Project Imports
from Utilities.Files.Json.simulation_config_parser import SimulationConfigParser
from runner import run_simulation
def main(
# todo put in output format possible names (-f --output-format)
output_format: str = typer.Option(..., "--output-format", "-f"),
input_settings: str = typer.Option(..., "--input-settings", "-i"),
output_file: str = typer.Option(..., "--output-file", "-o")
):
# Check config file
parser = SimulationConfigParser(input_settings)
parser.read_content()
# Calls simulation with configuration
run_simulation(output_format, input_settings, output_file)
if __name__ == '__main__':
typer.run(main)

View File

@ -1,9 +0,0 @@
# Python Imports
import os
# Project Imports
from Utilities.env_variables import binary_path
def run_simulation(output_format, input_settings, output_file):
os.system(binary_path + " -f " + output_format + " -i " + input_settings + " -o " + output_file)

View File

@ -1,20 +0,0 @@
from Utilities import env_variables
from Utilities.Files.Json.json_utils import read_json, validate_json
class SimulationConfigParser:
def __init__(self, file_path):
self._file_path = file_path
self._configuration = None
def read_content(self):
# Retrieve raw info
json_configuration = read_json(self._file_path)
# Retrieve valid schema
json_schema = read_json(env_variables.schema_path)
# Validate
validate_json(json_configuration, json_schema)
self._configuration = json_configuration

View File

@ -1,4 +0,0 @@
# Workaround while docker is not set up
binary_path = "C:/Users/Alberto/Desktop/Status/consensus-prototypes/target/release-opt/consensus-simulations.exe"
schema_path = "../Utilities/Files/Schemas/configuration_schema.json"

BIN
requirements.txt Executable file

Binary file not shown.

View File

@ -0,0 +1,44 @@
{
"arguments": {"output-format": "csv", "output-file": "test"},
"simulation": {
"consensus_settings": {
"snow_ball": {
"quorum_size": 14,
"sample_size": 20,
"decision_threshold": 20
}
},
"distribution": {
"yes": 0.6,
"no": 0.4,
"none": 0.0
},
"byzantine_settings": {
"total_size": 10000,
"distribution": {
"honest": 1.0,
"infantile": 0.0,
"random": 0.0,
"omniscient": 0.0
}
},
"wards": [
{
"time_to_finality": {
"ttf_threshold": 1
}
}
],
"network_modifiers": [
{
"random_drop": {
"drop_rate": 0.01
}
}
],
"seed": 18042022
},
"plotting": {
"test": "test"
}
}

0
Plotter/__init__.py → src/__init__.py Normal file → Executable file
View File

View File

@ -0,0 +1 @@
{"consensus_settings": {"snow_ball": {"quorum_size": 14, "sample_size": 20, "decision_threshold": 20}}, "distribution": {"yes": 0.6, "no": 0.4, "none": 0.0}, "byzantine_settings": {"total_size": 10000, "distribution": {"honest": 1.0, "infantile": 0.0, "random": 0.0, "omniscient": 0.0}}, "wards": [{"time_to_finality": {"ttf_threshold": 1}}], "network_modifiers": [{"random_drop": {"drop_rate": 0.01}}], "seed": 18042022}

27
src/main.py Executable file
View File

@ -0,0 +1,27 @@
# Python Imports
import typer
# Project Imports
from src.simulation_runner.runner import run_simulation
from src.utilities.files.json.simulation_config_parser import SimulationConfigParser
def main(
run_type: str = typer.Option(..., "--run", "-r"),
configuration_file: str = typer.Option(..., "--configuration-file", "-cf")
):
parser = SimulationConfigParser(configuration_file)
arguments_config, simulation_config, plotter_config = parser.read_content()
# Calls depending on json config
if run_type == "simulation":
run_simulation(arguments_config, simulation_config)
elif run_type == "plotter":
# run_plotter()
pass
else:
run_simulation()
# run_plotter()
if __name__ == '__main__':
typer.run(main)

View File

@ -0,0 +1,18 @@
# Python Imports
import os
# Project Imports
from src.utilities.env_variables import BINARY_PATH, CONFIGURATION_SETTINGS, SHARED_FOLDER
from src.utilities.files.json.json_utils import write_json
def run_simulation(arguments_config: dict, simulation_config: dict):
write_json(simulation_config, CONFIGURATION_SETTINGS)
os.system(BINARY_PATH
+ " -f " + arguments_config["output-format"]
+ " -i " + CONFIGURATION_SETTINGS + " -o "
+ arguments_config["output-file"])
os.system("mv " + arguments_config["output-file"] + "." + arguments_config["output-format"] + " " + SHARED_FOLDER)

View File

@ -0,0 +1,11 @@
# Binary
BINARY_PATH = "snow-family"
CONFIGURATION_SETTINGS = "shared/configuration_settings.json"
# Schemas
ARGUMENTS_SCHEMA_PATH = "src/utilities/files/schemas/arguments_schema.json"
CONFIGURATION_SCHEMA_PATH = "src/utilities/files/schemas/snow_family_configuration_schema.json"
# Shared folder
SHARED_FOLDER = "shared/"

View File

@ -3,13 +3,18 @@ import json
import jsonschema
def read_json(file_path):
def read_json(file_path: str) -> dict:
with open(file_path, "r") as file:
json_content = json.load(file)
return json_content
def validate_json(json_content, json_schema):
def write_json(info: dict, file_path: str):
with open(file_path, "w") as file:
json.dump(info, file)
def validate_json(json_content: dict, json_schema: dict):
jsonschema.validate(instance=json_content, schema=json_schema)

View File

@ -0,0 +1,32 @@
# Project Imports
from src.utilities import env_variables
from src.utilities.files.json.json_utils import read_json, validate_json
class SimulationConfigParser:
_file_path: str
def __init__(self, file_path: str):
self._file_path = file_path
def read_content(self) -> tuple[dict, dict, dict]:
# Retrieve raw info
json_configuration = read_json(env_variables.SHARED_FOLDER + self._file_path)
# Split two parts
arguments_config = json_configuration["arguments"]
simulation_config = json_configuration["simulation"]
# plotter_config = json_configuration["plotter"]
# Retrieve valid schemas
arguments_json_schema = read_json(env_variables.ARGUMENTS_SCHEMA_PATH)
config_json_schema = read_json(env_variables.CONFIGURATION_SCHEMA_PATH)
# plotter_json_schema = read_json(env_variables.plotter_schema_path)
# Validate
validate_json(arguments_config, arguments_json_schema)
validate_json(simulation_config, config_json_schema)
# validate_json(plotter_config, plotter_json_schema)
# return simulation_config, plotter_config
return arguments_config, simulation_config, {}

View File

@ -0,0 +1,17 @@
{
"type": "object",
"properties": {
"output-format": {
"type": "string",
"enum": [
"parquet",
"csv",
"json"
],
"default": "parquet"
},
"output-file": {
"type": "string"
}
}
}

View File

@ -19,7 +19,7 @@
},
"required": ["quorum_size", "sample_size", "decision_threshold"]
},
"glacier": {
"claro": {
"type": "object",
"properties": {
"evidence_alpha": {"type": "number"},

View File

@ -2,9 +2,9 @@
import os.path
# Project Imports
from Utilities.Files.SimulationDataTypes.JsonDataSimulationHandler import JsonDataSimulationHandler
from Utilities.Files.SimulationDataTypes.CsvDataSimulationHandler import CsvDataSimulationHandler
from Utilities.Files.SimulationDataTypes.ParquetSimulationDataHandler import ParquetDataSimulationHandler
from src.utilities.files.simulation_data_types.json_data_simulation_handler import JsonDataSimulationHandler
from src.utilities.files.simulation_data_types.csv_data_simulation_handler import CsvDataSimulationHandler
from src.utilities.files.simulation_data_types.parquet_simulation_data_handler import ParquetDataSimulationHandler
handlers = {'.csv': CsvDataSimulationHandler,
'.json': JsonDataSimulationHandler,

View File

@ -1,4 +1,4 @@
from Utilities.Files.SimulationDataTypes.BaseDataSimulationHandler import BaseDataSimulationHandler
from src.utilities.files.simulation_data_types.base_data_simulation_handler import BaseDataSimulationHandler
class CsvDataSimulationHandler(BaseDataSimulationHandler):

View File

@ -1,4 +1,4 @@
from Utilities.Files.SimulationDataTypes.BaseDataSimulationHandler import BaseDataSimulationHandler
from src.utilities.files.simulation_data_types.base_data_simulation_handler import BaseDataSimulationHandler
class JsonDataSimulationHandler(BaseDataSimulationHandler):

View File

@ -1,4 +1,4 @@
from Utilities.Files.SimulationDataTypes.BaseDataSimulationHandler import BaseDataSimulationHandler
from src.utilities.files.simulation_data_types.base_data_simulation_handler import BaseDataSimulationHandler
class ParquetDataSimulationHandler(BaseDataSimulationHandler):