The purpose of this report is to describe our 3 months work in the context of an implementation of a distributed system. This project outlines the objectives of a system ideally commissioned by the European Union. The system is designed to facilitate inter-nation communication, enabling consensus-building and the ex-change of locally collected data and public opinions. It aims to provide participating countries with essential resources for the accurate formulation of new referendums, subject to the vote of both national and European citizenship.
The document details the technical aspects, not the legal ones.
In the context of this system, referendums serve as a pivotal mechanism for citizen engagement anddecision-making. Here it is a breakdown of the referendum process:
- Submission to Citizens: a nation can initiate a referendum and present it to its citizens. Citizens have the option to participate in the referendum by casting their votes or choosing to abstain.
- Citizen-Proposed Referendums: any individual citizen has the opportunity to publicly propose a referendum idea via a dedicated portal. To move the idea forward, it must garner approvals from other citizens, reaching a threshold of 1% of the total number of citizens.
- Nation-Level Evaluation: the nation’s authorities assess the proposed referendum idea and decide whether to formulate it. A referendum can be designed to have either national or European scope, depending on its nature and relevance.
- Approval Criteria at the National Level: national referendums must meet uniform approval criteria across all nations. These criteria include achieving a majority vote in favor of the referendum and garnering participation from a number of voters exceeding 50% of the total number of citizens in that nation.
- Outcome of National Referendums: when the result of a national referendum aligns with the conditions set forth in step 4, it is considered approved at the national level. If the referendum does not meet these criteria, it is deemed null and void.
- European Referendums: European referendums are distinct in that they are shared with all participating nations. Each national representative assesses whether to present the referendum to their own citizens. If a majority of nations opt to proceed with the referendum, it is made available for voting by all EU citizens.
- Minimum Voting Threshold: once a referendum is approved for voting, if it fails to attract a sufficient number of voting citizens from a nation, that nation abstains from voting, and its votes are not considered in the final tally.
This standardized referendum process ensures that the voice of the citizens is central to decision-making, both at the national and European levels, while maintaining consistency and fairness in the evaluation and execution of referendums.
Main servicesThe system is build on Docker to allow an easy installation and usage for the users. Using this platform, we have implemented a distributed system in which every Nation has its own services. In particular every Nation has:
- Web: this is the web interface. The service uses the REST API to manipulate national data and ensure its persistence through the web interface. It also uses the Broadcast API to exchange messages with other nations.
- Broadcast APIserver: this servant is a programming interface that enables the simultaneous distribution of data, messages, or content to multiple recipients or channels, facilitating efficient and real-time communication across various platforms or devices.
- REST API server: this component is a web-based communication protocol that allows clientsto request and manipulate resources on a server using standard HTTP methods.
- PostgreSQL database: the database serves as a repository for national data, encompassingcitizen credentials, European referendums, and associated consensus data structures.Standalone services:
- RabbitMQ broker: this node is needed for making asynchronous communication possible be-tween the servers in charge of dispatching the messages between the organization workers. Eachnation establishes its own queue on this broker and designates a routing key. When a nationdesires to send a broadcast message, it selects a routing key that matches all the nations, allowing them to receive the message in their respective queues. Once the message has been read, it will be automatically removed from the queue.
For development purposes, all the system’s deployments were made accessible within the local network, allowing developers to test each component at the localhost address. This setup eliminated the need for multiple machines and simplified the testing process. To achieve this, various host entries were created under the same remote address, which were named in a way that reflected the functionality they exposed.
These components seamlessly communicated with each other through the network established by the Docker deployment, enabling efficient testing and development. The link for the different services are the following. We have divided into the different nation that we have implemented for the simulation (we have used 3 nations for the simulation).
For Italy:
- http://localhost:8080/ ← web-ita
- http://localhost:8081/ ← rest-ita
- http://localhost:8082/ ← broadcast-ita
For France:
- http://localhost:8084/ ←web-fra
- http://localhost:8085/ ← rest-fra
- http://localhost:8086/ ← broadcast-fra
For Germany:
- http://localhost:8088/ ← web-ger
- http://localhost:8089/ ← rest-ger
- http://localhost:8090/ ← broadcast-ger
Then, there is the address to manage RabbitMQ:
- http://localhost:15672/ ← RabbitMQ admin
Spring Boot is an open-source framework for building Java applications, designed to simplify development with minimal configuration. It provides an embedded web server, auto-configuration, and seamless integration with the Spring ecosystem. Spring Boot applications can be run as standalone Java applications and are suitable for various use cases, including web applications and microservices. It emphasizes Java-based configuration and properties files, reducing the need for XML configuration. Spring Boot is actively maintained and has a rich ecosystem of libraries and extensions, making it a popular choice for modern Java development.
All the services are Spring-Boot project.
To allow the correct implementation, we have imported different dependencies for the services. Inparticular:
- Web service: Thymeleaf, Spring Boot Starter Web, Spring DevTools, and Spring Boot Starter Test:
- Rest service: Spring Data JPA, Spring Boot Starter Web, Spring DevTools, Spring Boot Starter Test, and PostgreSQL.
- Broadcast service: Spring Boot Starter AMQP, Spring Boot Starter Web, Spring DevTools, Spring Boot Starter Test, Spring Rabbit Test, and Google Gson.
The plugins used for every service are:
- org.springframework.boot: used to package the Spring Boot application.
- org.apache.maven.plugins: used to configure Surefire to skip tests during the build.
For each service, in every nation, there is a docker file to allow the creation of the jarfile and the container. For example, we explain the docker file of the service ’rest’. It is a multi-stage build for a Java application using Maven and OpenJDK 17. We used to build and package a Java application into a Docker image.
#
# Build stage
#
FROM maven AS build
COPY src /home/app/src
COPY pom.xml /home/app
RUN mvn -f /home/app/pom.xml clean package
#
# Package stage
#
FROM openjdk:17-jdk-alpine
COPY --from=build /home/app/target/rest-0.0.1-SNAPSHOT.jar /usr/local/lib/app-1.0.0.jar
ENTRYPOINT ["java","-jar","/usr/local/lib/app-1.0.0.jar"]
There are two main parts.
Build Stage:
- It starts from the official Maven image.
- It copies the application source code and the ’pom.xml’ file into the ’/home/app’ directory inside the Docker container.
- It then runs ’mvn clean package’ to build the Java application using Maven.
Package Stage:
- It starts from the official OpenJDK 17 image (’openjdk:17-jdk-alpine’), which is a minimal image containing the Java Runtime Environment (JRE).
- It copies the JAR file generated in the build stage (’rest-0.0.1-SNAPSHOT.jar’) from the build stage’s ’/home/app/target’ directory to ’/usr/local/lib/app-1.0.0.jar’ in the current image.
- It sets the entry point for the Docker container to run the Java application using the JAR file (’app-1.0.0.jar’).
This Dockerfile separates the build process from the final runtime image, resulting in a smaller runtime image that only contains the necessary JRE and the application JAR file.
Docker Compose for RabbitMQ BrokerTo allow a correct use of Docker, we have implemented a docker-compose for each nation, plus a docker-compose for RabbitMQ.
#Docker-Compose RABBIT_MQ
version: '3.9'
name: epo-all
services:
rabbitmq:
container_name: rabbitmq
image: rabbitmq:3-management
ports:
- "5672:5672"
- "15672:15672"
networks:
- network-ita
- network-fra
- network-ger
networks:
network-ita:
name : rabbitmq-ita
network-fra:
name : rabbitmq-fra
network-ger:
name : rabbitmq-ger
The docker compose for the Rabbit MQ Broker is structured as follow:
- Version: Specifies the version of Docker Compose used for this configuration.
- Name (epo-all): Sets the name of the Docker Compose project. This is used to group and managerelated containers.
- Services: Defines the services to be run as containers (in this case, rabbitmq).
- Configuration for the rabbitmq service: container name (assigns a name to the RabbitMQ container), image (rabbitmq:3-management), ports (maps the container ports for RabbitMQ (5672 for AMQP and 15672 for the management interface) to the corresponding host ports), and networks (specifies the networks to which this service is connected. It is connected to 3networks: network-ita, network-fra, and network-ger).
- Networks: Defines three custom Docker networks: network-ita, network-fra, and network-ger.These networks are named and can be used to connect containers to specific network segments.In this case, they are used for RabbitMQ but could potentially be used for other services as well.
This Docker Compose configuration sets up a RabbitMQ container with the RabbitMQ Management Plugin enabled, allowing to manage RabbitMQ through a web interface. The container is connected to 3 custom networks, which we have used to facilitate communication between RabbitMQ and other containers in different networks.
Docker Compose for a Nation#Docker-Compose ITA
version: '3.9'
name: epo-ita
services:
web:
image: epo/web
build: ./web
container_name: web-ita
ports:
- 8080:8080
depends_on:
- rest
networks:
- network-ita
environment:
- REST_URL=http://rest:8080
- NATION=IT
rest:
image: epo/rest
build: ./rest
container_name: rest-ita
ports:
- 8081:8080
environment:
- DATABASE_URL=jdbc:postgresql://psql_db:5432/postgres
- DATABASE_USERNAME=postgres
- DATABASE_PASSWORD=postgres
depends_on:
- psql_db
networks:
- network-ita
psql_db:
image: postgres
container_name: psql_db-ita
ports:
- 5433:5432
environment:
POSTGRES_USER: postgres
POSTGRES_PASSWORD: postgres
POSTGRES_DB: postgres
#volumes:
# - pgdata:/var/lib/postgresql/data
networks:
- network-ita
broadcast:
image: epo/broadcast
build: ./broadcast
container_name: broadcast-ita
environment:
- spring_rabbitmq_host=rabbitmq
- QUEUE_NAME=ita
- REST_URL=http://rest:8080
- LIST_NATIONS=ita,fra,ger
- POPULATION=3
ports:
- "8082:8080"
depends_on:
- rest
networks:
- network-ita
networks:
network-ita:
name: rabbitmq-ita
external: true
volumes:
pgdata: {}
Meanwhile, the docker-compose for the different nations is the following one and it has a common pattern:
- Version: as before.
- Name (epo-ita, epo-ger or epo-fra): Specifies the name of the Docker Compose project. This can be used to group and manage related containers.
- Services: Defines all the containerized services required for the application. In this case, there are 4 services: web, rest, psqlDB, and broadcast.
- Configuration for the web service.
- Configuration for the rest service.
- Configuration for the psqlDB service.
- Configuration for the broadcast service.
- Networks: defines a network named network-ita (or network-fra, or network-ger), which appears to be connected to an external RabbitMQ service. This allows containers to communicate with each other through this network.
- Volumes: used to mount a volume for PostgreSQL database data.
Ports are mapped to allow access to the services from an external host.
Demo for Consensus PrimitiveThe main components of the distributed system are outlined through the example of a European Referendum. The consensus implementation used is the flooding consensus since we are simulating 3 correct nations. For simplicity, each Referendum has three possible outcomes: null if the majority of participants do not vote, true if the majority of the nation votes true, and false if the majority votes false:
- A national representative can propose a European Referendum by submitting the title and argument through a POST API at /europeanReferendumProposal to local Broadcast services. i.e. {"title": "This is a demo referendum", "argument": "Lorem ipsum dolor sit amet, consectetur adipiscing elit"}. Output:
- Each nation will receive the Referendum proposal and automatically enter it into the first consensus, storing the Referendum and initializing the data structures in the local database. Output:
- The national representative can respond to the Referendum proposal by broadcasting the proposed message in round one. To send this message another POST API is implemented in the local Broadcast service. The URL is /europeanReferendumFirstConsensus and the body requested includes the ID of the referendum (i.e. title, creation date) and the proposal value: { "title": "This is a demo referendum", "dateStartConsensusProposal": "14/09/2023 16:31:45", "answer": true}.
- When a nation receives a consensus message updates its local data structures e.g. proposals and received sets. If the local receivedFrom set contains all the correct processes, the nation can decide a value, broadcasting the decision. Output:
- Assuming the first consensus on the Referendum proposal is true, we can proceed with presenting the Referendum to each nation’s citizens individually. For the sake of simplicity, we will not include a voting component in this demonstration and assume that all nations will answer "yes" to the Referendum. This implies that the majority of citizens have also answered "yes" to the Referendum. If a nation does not respond to the Referendum by the end date, the system implements a timeout using a thread to make a decision. The agreement regarding uniforms is only met if the broadcast communication is of the URB type.
- When the vote ends, the date is defined during the creation of the Referendum, a second consensus starts and all the nations automatically send its result. Finally after the flooding of the messages a decision to the Referendum is taken. Output:
You can see the code on the GitHub page.
How to deploy the system for the first timeThe only requirement is Docker. All the data and programs will be installed downloading and launching the Github code:
- Clone the repository executing the following CLI command:
git clone git clone https://github.com/RicGobs/EPO-European-Parliament-Online.git
- Now, you have to launch the program. Launch in four different terminal the following commands:
sudo docker compose -f docker-compose-all.yaml up --build
# Wait until rabbitmq container ends the initialization
sudo docker compose -f docker-compose-ita.yaml up --build
sudo docker compose -f docker-compose-fra.yaml up --build
sudo docker compose -f docker-compose-ger.yaml up --build
It is possible to have some errors. We will give you some useful commands to solve the easiest issues:
- Sometimes, the port neeeded for the program are already used; so use the following commands:
# to check which ports are in use
sudo lsof -i -P -n | grep LISTEN
# to kill the process running in port 5672
sudo fuser -k 5672/tcp
# to kill the process running in port 5432
sudo fuser -k 5432/tcp
- Sometimes, docker gives some problems with old containers; so, to eliminate old containers that can create conflicts:
sudo docker container rm /rabbitmq
sudo docker container rm /sender
sudo docker container rm /receiver
sudo docker container rm /web
sudo docker container rm /rest
- In the end, to clean your system from all docker containers and volumes:
sudo docker system prune --all --force
Agile MethodologyUser StoriesWe have implemented several user stories at the start of the project, to know the future properties of our system. We have designed all these user stories in several mockup using Balsamiq.
The most important ones are:
- As a user, I want to select the citizen or the national representative role, so that I can enter and navigate in the page hosted by that nation.
- As a citizen, I want to register myself in the page hosted by the nation related to my legal citizenship, so that I can authenticate myself in the future.
- As a citizen, I want to authenticate myself in the the page hosted by the nation related to my legal citizenship, so that I can access the national service.
- As a citizen, I want to have a personal area displaying the possible services, so that I can choose a service (referendum and information).
- As a nation representative, I want to propose an idea for an European Referendum to other European nations, so that it can be proposed to all European citizens.
- As a nation representative, I want to authenticate myself in the context of my nation, so that I can manage the national service.
- As a nation representative, I want to declare a new national referendum, constituted by one question with "Yes" or "No" answer, so that I can obtain votes from citizens of my nation.
- As a citizen, I want to see the list of all referendums declared by my nation, so that I can vote.
- As a nation representative, I want to see the final result of the voting process related to an European referendum, so that I can apply it if it has been approved by European citizens.
- As a citizen, I want to see the results of a referendum declared by my nation, so that I can know the outcome.
- As a citizen, I want to vote in a referendum declared by my nation, so that I can express my opinion.
To work with an agile method, we have organized a Sprint Planning:
- Create a product backlog, which included a list of features and requirements.
- Prioritize the items in the backlog, based on their value to the end-users and the organization.
- Select a set of items from the product backlog and created a sprint backlog, which included a list of tasks and objectives for the sprint.
We have also drafted the product backlog.
The main purpose of this project is to experiment the consensus in a distributed voting system across nations. Despite the implementation of a distributed algorithm, which overcomes the limitation of the legacy centralized voting environment and make the system more secure by design, security is not the main focus of our system. But this is a crucial aspect in the real world.
In fact, the vast majority of recent e-voting systems are based on blockchain, which guarantees the confidentiality (absence of unauthorized disclosure of information), the integrity (absence of unauthorized system alterations) and the validity (respected logical constraints) of the voting process, as well as availability for authorized actions. In detail, a common used method to is the Proof-of-Voting (PoV), preferred over the common PoW for its lower cost and lower power consumption, by keeping security satisfied. An example of these systems is, where hierarchical voting roles are defined, each one associated to a smart contract. The method used to reach consensus is PoV, useful also to identify Byzantine processes in order to remove them from the blockchain. The main idea is to assure that only a specific voter could have cast his own vote. Other recent systems seem to be all different implementations of the same blockchain-based solution idea. So, it seems natural to think that a future improvement of our system can be to integrate some security measures in order to avoid attacks to the system functioning principle.
Comments
Please log in or sign up to comment.