Skip to main content

Overview

The submit command creates a new block containing election results from a polling station and submits it to a submission node via HTTP. The block is cryptographically signed and includes a Merkle tree root for result verification.

Syntax

ubu-block --config <CONFIG_FILE> submit <NODE_ADDR> <STATION_ID> <CANDIDATE_ID> <VOTES>

Parameters

node_addr
string
required
The HTTP address of the submission node to send the block to. Include the protocol and port.Example: http://localhost:3000 or https://node.example.com
station_id
integer
required
The unique identifier of the polling station where votes were cast. This should match a station ID in your database.Example: 022113056303301
candidate_id
integer
required
The unique identifier of the candidate receiving votes. This should match a candidate ID in your database.Example: 1
votes
integer
required
The number of votes the candidate received at this station. Must be a positive integer.Example: 66

How It Works

1

Retrieve Chain State

The command connects to your local blockchain database and retrieves:
  • Current blockchain height
  • Hash of the most recent block
  • Your private signing key
2

Create Result Data

Packages the submission into a CandidateResult structure:
CandidateResult {
  station_id: 022113056303301,
  candidate_id: 1,
  votes: 66
}
3

Build Merkle Tree

Constructs a Merkle tree from the election results to enable efficient verification:
  • Each result is hashed
  • Hashes are combined into a tree structure
  • Root hash is calculated
4

Create Block

Generates a new block with:
  • Previous block hash (chain linkage)
  • Height (current height + 1)
  • Election results
  • Merkle root hash
  • Cryptographic signature
5

Submit to Node

Sends the block via HTTP POST to <node_addr>/submit as JSON
6

Receive Confirmation

The submission node validates and responds with success or error status

Examples

Submit Single Result

ubu-block --config config.toml submit http://localhost:3000 022113056303301 1 66
Expected Output:
Block submitted successfully

Submit to Remote Node

ubu-block --config config.toml submit https://submission.ubu-block.org 022113056303302 2 85

Submit Multiple Results

To submit results for multiple candidates at the same station, run the command multiple times:
# Candidate 1 results
ubu-block --config config.toml submit http://localhost:3000 022113056303301 1 66

# Candidate 2 results  
ubu-block --config config.toml submit http://localhost:3000 022113056303301 2 21
Each submission creates a separate block. Currently, the CLI submits one result per block. For batch submissions, consider using the REST API directly.

Block Structure

Each submitted block contains:
{
  "height": 42,
  "prev_hash": "0e70cebe0ab3bd8c3606a08d26483d092534eea4ccdb7816fc2692aee5ed3109",
  "timestamp": 1678901234,
  "results": [
    {
      "station_id": 22113056303301,
      "candidate_id": 1,
      "votes": 66
    }
  ],
  "merkle_root": "a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a",
  "signature": "...",
  "public_key": "..."
}

Submission Node Validation

When the submission node receives your block, it validates:
  1. Signature: Verifies the block is signed by an authorized key
  2. Chain Continuity: Ensures prev_hash matches the latest block
  3. Height: Confirms height is current height + 1
  4. Merkle Root: Validates the Merkle tree root matches the results
  5. Result Format: Checks that station_id, candidate_id exist and votes are valid
  6. Consensus: May require consensus from other nodes depending on configuration

Error Responses

Failed to Submit Block

Failed to submit block: 400 Bad Request
Possible causes:
  • Invalid station_id or candidate_id
  • Malformed block data
  • Block already exists at this height

Connection Error

Error submitting block: Connection refused (os error 111)
Possible causes:
  • Submission node is not running
  • Incorrect node address
  • Network connectivity issues
  • Firewall blocking connection

Unauthorized

Failed to submit block: 401 Unauthorized
Possible causes:
  • Your public key is not registered with the submission node
  • Signature validation failed
  • You don’t have permission to submit to this node

Prerequisites

You must have a blockchain initialized with ubu-block init before submitting results.
The station_id and candidate_id must exist in your local database schema.
A submission node must be running and accessible at the specified address.
Your machine must have network access to reach the submission node.

Security Considerations

Private Key Security: The submit command uses your private key to sign blocks. Keep your private database secure and never share it.
  • Authentication: Only nodes with registered public keys can submit blocks
  • Non-repudiation: Each block is cryptographically signed and cannot be forged
  • Audit Trail: All submissions (accepted and rejected) are logged by submission nodes
  • Tamper Evidence: Any modification to block data invalidates the signature

Best Practices

  1. Verify Before Submitting: Ensure data accuracy before submission
  2. Check Node Status: Confirm the submission node is operational
  3. Monitor Responses: Watch for error messages and handle them appropriately
  4. Batch Operations: For multiple results, consider scripting submissions
  5. Backup Keys: Always maintain secure backups of your private database
  6. Test Locally: Test submissions on a local node before using production nodes

Troubleshooting

Can’t Find Private Key

Error: Failed to get private key
Solution: Ensure you’ve run init to generate keys, and the private database path in your config is correct.

Invalid Block Height

Failed to submit block: Invalid height
Solution: Sync your local chain with the submission node, or check if another block was added since you last synced.

Station/Candidate Not Found

If the submission succeeds but node validation fails:
  • Verify station_id exists in the stations table
  • Verify candidate_id exists in the candidates table
  • Check that IDs match the format expected by the node

Implementation Details

The submit command is implemented in apps/cli/src/main.rs:74-131 and:
  • Uses Ed25519 signatures for block signing
  • Constructs Merkle trees with SHA-256 hashing
  • Sends blocks via HTTP POST with JSON encoding
  • Retrieves chain state from local SQLite databases
  • Validates result format before creating blocks

Next Steps

Query Results

Query submitted results from the blockchain

Validate Chain

Verify blockchain integrity after submission

Submission Nodes

Learn more about running submission nodes

REST API

Submit via the REST API for batch operations

Build docs developers (and LLMs) love