Velvet
Velvet is the tallying and reporting engine for the Sequent Tech voting platform. The name comes from the type of woven tufted fabric, implying smoothness and luxury in processing election results.
Overview
Velvet is a Rust cargo crate that provides both a library and a binary executable for processing election results. It handles the entire post-voting workflow including:
- Decoding encrypted ballots
- Executing tally algorithms
- Generating reports and receipts
- Producing verifiable results
While Velvet includes a CLI tool for testing and development, its primary use is as a library integrated into the platform's backend services. The main functionality is triggered from the Admin Portal when an election administrator executes a tally.
Architecture
Velvet is organized around several key components:
Pipes
Pipes are the core processing units in Velvet. Each pipe performs a specific task in the tallying workflow:
- decode_ballots - Decodes encrypted ballots into plaintext votes
- do_tally - Executes the counting algorithm on decoded ballots
- generate_db - Creates a SQLite database with tally results
- generate_reports - Produces PDF and CSV reports
- mark_winners - Determines winning candidates based on tally results
- vote_receipts - Generates individual vote receipts for voters
Pipes can be chained together in a processing pipeline defined by configuration.
Tally Engine
The tally engine (do_tally) is responsible for executing counting algorithms on ballots. It supports multiple electoral systems through a pluggable algorithm architecture.
Counting Algorithms
Velvet supports various counting algorithms for different electoral systems:
- Plurality at Large - Simple majority voting where candidates with the most votes win
- Instant Runoff Voting (IRV) - Ranked-choice voting with elimination rounds
Each algorithm implements the CountingAlgorithm trait, making it easy to add new electoral systems.
CLI
The command-line interface provides a way to run Velvet pipelines directly:
velvet run {stage} {optional-pipe} \
--config ./path/to/velvet-config.json \
--input-dir ./path/to/input-dir \
--output-dir ./path/to/output-dir
The CLI is primarily used for development, testing, and debugging. In production, Velvet is invoked programmatically from the backend services.
Tests
Velvet includes comprehensive test coverage:
- Unit tests - Test individual functions and components (e.g.,
irv_unit_tests.rs) - Integration tests - Test complete tallying workflows (e.g.,
irv_integration_tests.rs) - Pipe tests - Test individual pipes in isolation
Tests can be run with:
cargo test
Benchmarks
Performance benchmarks are included to measure and optimize critical operations like PDF generation. Benchmarks use the Criterion framework and can be run with:
cargo bench
Workflow
A typical Velvet execution flow:
- Input - Election configuration and encrypted ballots are provided
- Decode - Ballots are decrypted and decoded
- Tally - The counting algorithm processes the ballots
- Aggregate - Results from different areas/districts are combined
- Mark Winners - Winning candidates are determined
- Generate Reports - PDF and CSV reports are created
- Output - Results are stored and made available
Integration with Admin Portal
When an election administrator clicks "Execute Tally" in the Admin Portal:
- The Admin Portal sends a request to the backend service (Windmill)
- Windmill prepares the input data and configuration
- Velvet is invoked as a library to process the tally
- Results are stored in the database
- Reports and receipts are generated
- The Admin Portal displays the results
This integration allows for secure, auditable, and verifiable election tallying within the platform.
Design Documentation
For more detailed design information, see the Velvet design document.
Package Location
Velvet is located at: /packages/velvet/