This guide walks you through setting up Ubu-Block, initializing your first blockchain, submitting election results, and validating the chain. You’ll see firsthand how the immutable ledger prevents tampering.
Prerequisites
Before you begin, make sure you have:
Rust and Cargo installed (version 1.70 or later)
Git for cloning the repository
Basic familiarity with command-line tools
New to Rust? Install it from rustup.rs . It takes about 5 minutes.
Set up your environment
Clone the repository
Clone the Ubu-Block repository and navigate into it: git clone https://github.com/koleshjr/ubu-block
cd ubu-block
Create the data directory
Set up the directory structure for your blockchain databases: This creates a data/ folder where your blockchain and private key databases will be stored.
Copy database files
Initialize the SQLite database files from the empty templates: cp crates/database/sql/empty.db data/blockchain.db
cp crates/database/sql/empty.db data/private.db
These two databases serve different purposes:
blockchain.db stores the public blockchain data
private.db stores your node’s cryptographic keys
Initialize your blockchain
Now you’ll create the genesis block and set up the regional data structure:
cargo run --bin ubu-block-cli -- -c config.toml init --source apps/cli/init.sql
You should see:
INFO ubu_block] Blockchain was successfully initialized!
The init.sql file contains sample constituency, ward, and station data. You can customize this for your region.
Submit your first election results
Add blocks to the blockchain with sample election data:
cargo run --bin ubu-block-cli -- -c config.toml submit http://localhost:8080 022113056303301 1 66
cargo run --bin ubu-block-cli -- -c config.toml submit http://localhost:8080 022113056303301 2 21
These commands submit to a local node. Make sure you have a submission node running on port 8080, or the commands will fail.
Each successful submission returns:
Block submitted successfully
The command format is:
cargo run --bin ubu-block-cli -- submit < node-addres s > < station-i d > < candidate-i d > < vote s >
Validate the blockchain
Verify that your blockchain is cryptographically valid:
cargo run --bin ubu-block-cli -- -c config.toml validate
You should see:
INFO ubu_block] Blockchain is valid!
This command verifies:
All block hashes are correctly computed
The chain of hashes links properly
All signatures are valid
Merkle roots match the transaction data
Test tamper detection
Let’s verify that the blockchain actually prevents tampering:
Modify a vote count
Open data/blockchain.db with any SQLite editor and run: UPDATE "results" SET "votes" = 71 WHERE _rowid_ = 1
This changes one candidate’s vote count from 21 to 71.
Attempt validation
Try validating the blockchain again: cargo run --bin ubu-block-cli -- -c config.toml validate
The validation will fail with a panic showing the hash mismatch: thread 'main' panicked at 'Could not verify block, found 0e70cebe0ab3bd8c3606a08d26483d092534eea4ccdb7816fc2692aee5ed3109, block: Block {...
Restore the database
The blockchain detected the tampering! Restore your database: cp crates/database/sql/empty.db data/blockchain.db
cp crates/database/sql/empty.db data/private.db
This demonstrates Ubu-Block’s core promise: no “fungua server” shenanigans. Any tampering is immediately detectable.
Query election results
Run SQL queries directly on the blockchain:
cargo run --bin ubu-block-cli -- -c config.toml query -q "SELECT
c.name as candidate,
SUM(votes) as votes,
ward_name as ward,
constituency_name as constituency,
county_name as county,
parties.title as party
FROM results
INNER JOIN stations ON stations.id = results.station_id
INNER JOIN candidates c ON c.id = results.candidate_id
INNER JOIN wards on stations.ward_code = wards.ward_code
INNER JOIN parties ON parties.id = c.party_id
INNER JOIN constituencies ON wards.constituency_code = constituencies.constituency_code
INNER JOIN counties ON constituencies.county_code = counties.county_code
WHERE position_type = 'Mp' and constituency = 'Juja'
GROUP BY candidate;"
You’ll see formatted results:
+--------+--------------+----------+-----------+-------+-------+
| county | constituency | ward | candidate | party | votes |
+--------+--------------+----------+-----------+-------+-------+
| Kiambu | Juja | Kalimoni | Omosh | ODM | 21 |
| Kiambu | Juja | Kalimoni | Mwas | PNU | 66 |
+--------+--------------+----------+-----------+-------+-------+
Next steps
Node types Learn about Submission, Observer, and Verification nodes
Submit results Learn how to submit results to a live network
Run a node Set up your own Observer or Submission node
API reference Explore the REST API for programmatic access