The control flow for executing test harnesses and delaying messages can be found in scheduler.rs.
The start
function spawns several threads. The listen_to_peers
function listens to messages sent by peers and
relays the message, based on the current schedule, to their destination. The listen_to_ga
function continually listens
to the genetic algorithm for a new individual. The update_current_round
and update_latest_validated_ledger
functions
keep track of when all nodes have started on a new round or validated a new ledger. The harness_controller
is responsible for
checking and updating the stability of the network, starting the test harness and sending the found fitness to the ga component.
Priority-based scheduling and delay-based scheduling can be found in priority_scheduler.rs
and delay_scheduler.rs respectively. These schedulers implement the scheduler trait and
define their own logic for how to schedule messages.
The consensus properties of RCA are checked after and during each test run.
consensus_properties.rs contains integrity, agreement and validity checks.
scheduler.rs contains the bounded liveness check in update_latest_validated_ledger
.
Most of the properties are violated during temporary disconnects and long delays in messages.
When Agreement2 (A2) or DoubleSpend are violated, two different ledgers are validated and the consensus algorithm has truly failed.
The genetic algorithm uses genevo as a base implementation.
In genetic_algorithm.rs the run_ga
and run_permutation_ga
function
starts the ga for delay scheduling and priority scheduling. This function also starts the scheduler handler.
The scheduler handler is responsible for communicating new individuals to the scheduler. Fitness functions request evaluations from this handler.
The guassian mutation operator is implemented in mutation.rs. The logic can be found here. The swap mutation operator and PMX are from genevo. The SBX implementation can be found in crossover.rs.
The different ecndoings can be foun in encoding
The different fitness functions are found in the fitness folder. All fitness functions implement the trait
ExtendedFitness
which contains the run_harness
function. In this function, the test harness is run and the fitness function can check the state before
and after the test harness to determine the fitness of the chromosome.
Genevo uses a struct implementing the trait FitnessFunction. Every time the fitness of an individual needs to evaluated,
it calls the fitness_of
function. In the code this trait is implemented by FitnessCalculation<T>
Where T is any fitness function as defined above. This struct then tells the scheduler handler to run a particular individual and returns the fitness.
To use a different fitness function, change the CurrentFitness type in genetic_algorithm.rs to the desired fitness functions.
In node_state.rs the state of the different nodes is tracked. This struct is a mutex which allows it to be shared and edited by many different threads. Almost all components of the system use the node state in some way. It is used by the fitness functions to poll state before and after a test harness. The scheduler informs the node state of message sends and receives to build the trace graphs.
In container_manager.rs, the docker containers are removed and started programmatically.
The client.rs file contains code for sending client commands to the nodes and receiving their responses. For every node, a client is started in app.rs. Several client commands are used.
- Subscriptions: The nodes send updates with regard to consensus phase, ledgers, validations, etc. This information is sent to collector.rs and stored in the node_state.rs.
- Transactions: The test harness submits transactions at scheduled times during the test harness.
- State Accounting: The state accounting fitness function polls the state accounting info through the server_state command before and after the test harness to determine fitness.
The collector is responsible for collecting data from the nodes, writing this data to files and updating the node states.
Test_harness.rs is used for running a test case. It reads what transactions to apply and at what time from harness.txt
.
The fitness functions use this test harness in run_harness
to schedule the transactions. In the schedule_transactions
function the transactions are scheduled
and the function waits for all transactions to appear in a validated ledger, after which it will return to the run_harness
function in the fitness function.
The trace_comparisons.rs file contains code for collecting the data used in the trace graph and fitness function comparison experiment.
Instead of running the genetic algorithm scheduler handler and starting the GA, a custom SchedulerHandler is used which supplies predetermined delays and writes their fitness to disk.
For the fitness comparison experiment, use the compared_fitness_functions.rs as the CurrentFitness type. This combines different fitness functions. See the run_harness
function.
The experiments are conducted in the trace_comparisons folder.
The scaling.rs file contains code for collecting and executing the scaling experiment. The locality.rs file contains code collecting and executing the locality experiments.