AI agents: Logbook can be used programmatically. Start at https://logbook.zone/llms.txt. Remote MCP server: https://logbook.zone/mcp. Read-only REST API: https://logbook.zone/api/v1. Local MCP server: npx -y @logbookprotocol/mcp.

Logbook Beta on Sui Testnet. Learn more →
Documentation

Learn Logbook

Everything you need to create blockchain-verified surveys, understand the technology, and get the most out of Logbook.

DocsChecking a Secret-Ballot Result
10 min read

Checking a Secret-Ballot Result

This page is about campaigns created as a secret ballot: ballots recorded without the member's address.

What it does not hide, and what it does not protect against:

  • It does not stop you from showing somebody how you voted, or somebody from watching you vote. If you could be pressed to prove your vote, this is not protection against that.
  • In a small group the result can show how people voted: a unanimous result shows everybody’s vote.
  • Whether you voted is not written down, but it can show. The number of ballots is public as it grows, batch by batch: in a small group, or at a quiet hour, one more ballot next to who was online points to a person. The relayer sends ballots at fixed times, every half hour, and a question group leaves only when at least five ballots of that same group are waiting (five on this site’s relayer; an operator can set another number); it never puts two question groups into one transaction, and until a vote’s last half hour it sends one group of a vote a minute. So at a fixed time your ballot reaches the blockchain as one among at least five ballots of its question group, and four of those may belong to people acting together, who know their own and so know yours. In the last three minutes before the end the least number is one: where fewer than five people answer a group in a half hour, those ballots wait until then and leave however few they are, and a voter who is the only one of a group in that last stretch leaves alone. After the end, when the ballots are opened, a batch whose ballots all say the same tells what each of its voters chose to whoever can tell who was in it: reckoned with each ballot as an independent draw, a batch of five is unanimous about one time in three on a question that splits 80 to 20 (6 times in 100 at 50 to 50, 59 in 100 at 90 to 10). Batching makes linking harder; it does not make it impossible. A ballot that waits for those last three minutes may not be recorded: a transaction sent then can fail, and nothing extends a vote. Several ballots of yours for different groups can reach the blockchain minutes apart or, when few people vote, together in the last three minutes before the end, each among the ballots of its own group.
  • Logbook could work out how you, by name, voted. One service receives your ballot from your network address, pays for your other actions in the community from that same address, serves your encrypted list of communities, and sees you sign in. So Logbook, or Cloudflare, which hosts it and carries every one of those requests, could put them together: this member, this ballot. After the vote ends the ballot is opened by whoever this vote lets open it (in a vote that opens for everyone: anyone), and then it is: this member, this vote. Logbook keeps no table that says so. It does keep, for two days, half of what such a table needs: daily counters of its sponsor, named by keyed hashes of your address in the community and of your network and written in one moment (what it stores is listed under Data Storage). The other half, which ballot came from which network, passes through its relayer and is not stored by it. What stands in the way is that, not mathematics. A second relay run by somebody else, which would prevent it, does not exist yet.
  • Before the end your answers can be read by the key servers this vote names, if enough of them act together; whoever created the vote chose them, and a creator who runs them reads the count as it goes. You can also open your own ballot early and show it.
  • Your passkey is kept by your device’s passkey provider (Apple, Google, a password manager), which may copy it to your other devices. Whoever can use your passkey can vote as you and work out which ballots are yours.
  • A device with malware can read what the passkey derives. So can a changed copy of this page, and this page is served anew on every visit by Logbook and by Cloudflare, which hosts it: either could serve a changed one. So can a browser extension that reads this page. The operators of the Sui node and of the indexer this page asks see which vote your network address reads, and when; the page asks them for whole lists (every ballot of the vote, the whole roll, the whole part of the list of ballot keys that yours lies in), not for your ballot or your key alone.
  • This page gives you no receipt when the relayer takes your ballot in time; when it does not, the page offers the ballot as a file, and that file is one. Your passkey is a receipt in every case: at any later time it can work out again which ballots are yours. Whoever makes you use it, or takes it over, learns how you voted in past votes of this kind.
  • What you write can identify you: your style, a fact only you know. Nothing hides that.
> Beta, on a test network. It runs on Sui Testnet, a test network its operators may reset: a vote and its record can be lost. Ballots are sealed for key servers of the test network. Their operators promise neither to keep serving nor to keep their keys, so a vote may never open. Nobody outside Logbook has audited the contracts or this site. Tested: Chrome on a computer, with a test authenticator. Not tested yet: Safari, Firefox, iPhones, Android phones, and the passkey providers people use (iCloud Keychain, Google Password Manager, password managers). Do not use it for a decision that binds anybody.

#Nothing Is Counted by the Blockchain

The blockchain stores the ballots; it does not open them. After the end, whoever may open the ballots (everyone, the members of the roll and the officer, or the officer alone: the campaign says which) counts them, and everyone who counts gets the same result, because the rules for reading a ballot are fixed when the campaign is created and committed to by a hash its box holds.

#In the Browser

On the campaign's page, after the end, "Open the ballots and count in this browser":

  • downloads every ballot of the box (asking for the whole list names no one),
  • verifies each ballot's stored proof against the fixed roll,
  • asks the campaign's key servers for the key of each part that reached its minimum,
  • checks each key against the public key the campaign committed to at creation,
  • opens and counts.
A large vote is a large download: 20,000 members over four parts are 80,000 ballots, about 55 MB, and verifying every proof takes a browser tens of minutes. Use the command line for a vote of that size.

#With a Second Tool

The page is served by Logbook, on every visit. The same count can be made on your own machine, from a full node and an indexer you choose, with a second tool. It comes with the next release of the Logbook SDK (@logbookprotocol/sdk on npm). The release on npm today does not have it and its source is not public, so today it cannot be had; this page says so instead of printing a command you could not run.

It is Logbook’s own code, the same library this page uses, run by you on your own machine instead of served to you: it guards against a changed copy of this page, not against an error the two share. A second implementation by somebody else does not exist yet.

What it checks: that the box belongs to the campaign, the officer's signature that fixed the roll, and the hash of the campaign's content against the box. It prints how many stored proofs it verified, the count of each part and the spoilt ballots by code, and exits with an error if anything about the box is not as it must be. Given a second full node, it reads from that node too and stops if the two differ: about the box, field for field (its roll, its officer, its times, its counts, its content hash), about the campaign’s content, about the member records a roll is made from, and about the ballots of the box.

It recounts a campaign whose ballots open for everyone. Where they open for the members of the roll or for the officer alone, the key servers give it no key: it then checks the box and verifies the stored proofs, and counts nothing.

If its numbers differ from this page’s, do not rely on either until the difference is explained.

#Spoilt Ballots

A ballot that cannot be read by the rules is spoilt: it was cast and is in the turnout, and counts for no answer. The count shows them by code. The two a voter with their own software can produce on purpose:

  • P2: a copy of somebody else's sealed ballot, cast under the copier's own proof. It names another ballot's number inside, so it is recognised and not counted.
  • D1: the sealed answers do not open consistently for every set of key servers.
Other codes mean a malformed ballot. A ballot cast from the site, as Logbook wrote it, is not spoilt.

#Parts That Stay Sealed

A campaign sets a minimum number of ballots for a part (this site creates none below 3). The key servers are to refuse the key of a part that received fewer, to anybody; that holds as long as enough of the key servers the campaign names keep to it, and no longer. The minimum counts ballots as the blockchain counts them, spoilt and empty ones too: the contract cannot read a ballot. Whether it was published without an upgrade capability, so that this stays so, the campaign’s page reads and says. Somebody on the roll who casts a spoilt ballot can lift a part over its minimum. Members who agree to abstain can keep a part closed.

#The Record, and What Deleting Does Not Do

Ballots of a part that reached its minimum are kept at least as long as the creator chose (90 days or more). Afterwards whoever paid for a ballot may delete it, and 30 days later anyone may; the box can be removed once it is empty. Ballots of a part that stayed below its minimum are not to be opened, and whoever paid for them may delete them from the end of the vote on. The campaign keeps the root and size of its roll, how many ballots each part took, and whether the vote was called off. A campaign in which a ballot was cast cannot itself be deleted.

Deleting is not erasure. It frees storage on the blockchain. Whoever downloaded the ballots keeps them, archives of the blockchain keep every transaction that carried one, and a ballot opened once can be read from any such copy for good. The ballot keys cannot be deleted at all. A roll leaves the blockchain's current state only with its box; the events that drew it up, leaf by leaf, stay in the history.

A results certificate is not issued for this kind of campaign yet.