jmlx42 / cocorico Goto Github PK
View Code? Open in Web Editor NEWCocorico is an open online voting platform powered by the blockchain.
Home Page: https://cocorico.cc
License: MIT License
Cocorico is an open online voting platform powered by the blockchain.
Home Page: https://cocorico.cc
License: MIT License
Today voters need to wait until the vote is closed to access the result page and verify their vote. It would be great if voters could verify their vote through a dedicated page even if the voting process is not over yet.
During the ODN4 hackathon, we've added an API endpoint and the corresponding page to list all the ballot blockchain transactions for a specific vote.
The goal of this page if to provide an easy way for anyone to explorer the content of the "digital ballot box" that is our smart contract.
First, we should add a "search by address" field. By entering (part of) its address (/public key), the user should be able to filter the transaction list to get only the matching ones. The existing /vote/transactions/:voteId
API endpoint should be updated to support an optional "address" POST parameter and filter the transaction list to return only the one with an address that starts with the specified one.
Then, because typing an address is cumbersome and it is supposed to be embedded in the downloadable SVG vote card, we should provide a way for the user to provide his vote card instead of filling up the address form manually.
ATTENTION! For privacy reasons, the vote card must NOT be sent to the server at any time. We already have existing Web app code to ask the user to provide his vote card without sending anything to the server and this code should be re-used.
Thanks to #64 the app should now work on Safari.
If that's the case, Safari (macOS and iOS) should be added to the Web browser whitelist.
There is a typo in one of the vote labels which is written "tres bien" instead of "très bien".
Edit : translated from French from the original message below
Il manque un accent grave au vote "tres bien", qui devrait être écrit "très bien".
The blockchain (vote & ballot) workers run as single processes.
We should use NodeJS cluster feature to fork them and handle each queue with multiple consumers.
I1105 16:25:30.644935 server.go:1934] http: Accept error: accept tcp 127.0.0.1:8545: accept4: too many open files; retrying in 1s
I1105 16:25:31.660103 server.go:1934] http: Accept error: accept tcp 127.0.0.1:8545: accept4: too many open files; retrying in 1s
I1105 16:25:32.694325 server.go:1934] http: Accept error: accept tcp 127.0.0.1:8545: accept4: too many open files; retrying in 1s
I1105 16:25:33.697415 server.go:1934] http: Accept error: accept tcp 127.0.0.1:8545: accept4: too many open files; retrying in 1s
I1105 16:25:34.708284 server.go:1934] http: Accept error: accept tcp 127.0.0.1:8545: accept4: too many open files; retrying in 1s
I1105 16:25:35.766081 server.go:1934] http: Accept error: accept tcp 127.0.0.1:8545: accept4: too many open files; retrying in 1s
I1105 16:25:36.767862 server.go:1934] http: Accept error: accept tcp 127.0.0.1:8545: accept4: too many open files; retrying in 1s
I1105 16:25:37.779899 server.go:1934] http: Accept error: accept tcp 127.0.0.1:8545: accept4: too many open files; retrying in 1s
I1105 16:25:38.819855 server.go:1934] http: Accept error: accept tcp 127.0.0.1:8545: accept4: too many open files; retrying in 1s
It might be related to the ballot consumer not properly removing filters.
It would be better to create a separate new web3
instance in each relevant ballot step and to reset()
it when the step is done.
Continuous integration using Travis CI:
We're using react-intl for the locale management.
The corresponding Web app locale messages are located here:
https://github.com/promethe42/cocorico/blob/master/app/src/script/intl/intl.js
We must:
Currently, webhook messages whose HTTP call fails are consumed and requeued from/to RabbitMQ continuously. Doing so wastes a full CPU core for nothing. A less costly approach would be to use the dead-letter mechanism RabbitMQ provides.
Here is the general idea:
This mechanism requires subtle configuration that I will describe here once I manage to have working POC.
3rd party Apps - especially if they provide there own user database - are more than likely to need to know what voter participated to what vote. For example, LaPrimaire.org must be able to send reminders to the people who did not complete the voting process.
One could use blockchain events or we could provide a way for our smart contract to call a specified sub-contract. But the blockchain stores only the ballot values and has no information about the "real" user. This method cannot apply here but could be used for monitoring the voting process itself instead of the state of the users.
Thus, 3rd party Apps integrating Cocorico should be made aware of vote/ballot events using webhooks.
When registering an App, the developer should be able to provide web hooks for the following events (at least):
Those webhooks must guarantee the privacy of the user and avoid sending private data. For example, the webhook can tell you that the user has successfully voted, but will not give you the value on the ballot.
Still, even if the webhooks does not tell the 3rd party App what the user voted, it still weakens the privacy model of Cocorico since even the information about who did (not) vote is not kept/made available in the platform itself as of today.
Another concern with webhooks is how unpredictable they are:
Webhooks best practices:
Implementation ideas:
We're not storing "ballots". We're storing the equivalent of a digital signing sheet.
Thus, the "Ballot" model should now be called "VoterSignature".
Hi there!
We can buy *.vote domains and they are not too expensive (<70€/year)!
We could buy the cocorico.vote domain for example.
But we could also see this as an opportunity to find a better brand.
Any suggestions?
I use several cocorico iframe on one page. Each of these iframe emit messages with postMessage but I am unable to trace back which iFrame emitted which message if the message does not include the id of the vote (1 vote <-> 1 iframe). Unless I am mistaken, I did not see the id of the vote in the voteComplete nor voteSuccess MessageEvents.
My first idea would be to pass voteComplete_[voteId] as data but I am definitely not a JS expert :)
The voting machine is composed of many software parts. Some of them listen to one or many ports on both the loopback network interface and other public-facing interfaces. Although the security of the voting mecanism shouldn't rely on preventing access to the machine itself, it is still a good idea to lower the attack surface.
Here is a list of all processes listening to TCP or UDP ports.
root@local:~# netstat -pluton
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name Timer
tcp 0 0 0.0.0.0:111 0.0.0.0:* LISTEN 706/rpcbind off (0.00/0/0)
tcp 0 0 0.0.0.0:28017 0.0.0.0:* LISTEN 1128/mongod off (0.00/0/0)
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1764/sshd off (0.00/0/0)
tcp 0 0 0.0.0.0:15672 0.0.0.0:* LISTEN 1041/beam.smp off (0.00/0/0)
tcp 0 0 0.0.0.0:55672 0.0.0.0:* LISTEN 1041/beam.smp off (0.00/0/0)
tcp 0 0 127.0.0.1:8545 0.0.0.0:* LISTEN 1834/geth off (0.00/0/0)
tcp 0 0 0.0.0.0:46307 0.0.0.0:* LISTEN 754/rpc.statd off (0.00/0/0)
tcp 0 0 0.0.0.0:49414 0.0.0.0:* LISTEN 1041/beam.smp off (0.00/0/0)
tcp 0 0 0.0.0.0:27017 0.0.0.0:* LISTEN 1128/mongod off (0.00/0/0)
tcp 0 0 127.0.0.1:6379 0.0.0.0:* LISTEN 1243/redis-server 1 off (0.00/0/0)
tcp6 0 0 :::111 :::* LISTEN 706/rpcbind off (0.00/0/0)
tcp6 0 0 :::80 :::* LISTEN 1378/apache2 off (0.00/0/0)
tcp6 0 0 :::4369 :::* LISTEN 1077/epmd off (0.00/0/0)
tcp6 0 0 :::22 :::* LISTEN 1764/sshd off (0.00/0/0)
tcp6 0 0 :::40886 :::* LISTEN 754/rpc.statd off (0.00/0/0)
tcp6 0 0 :::3000 :::* LISTEN 2286/nodejs off (0.00/0/0)
tcp6 0 0 :::443 :::* LISTEN 1378/apache2 off (0.00/0/0)
tcp6 0 0 :::30303 :::* LISTEN 1834/geth off (0.00/0/0)
tcp6 0 0 :::5672 :::* LISTEN 1041/beam.smp off (0.00/0/0)
udp 0 0 0.0.0.0:10841 0.0.0.0:* 635/dhclient off (0.00/0/0)
udp 0 0 0.0.0.0:873 0.0.0.0:* 706/rpcbind off (0.00/0/0)
udp 0 0 127.0.0.1:930 0.0.0.0:* 754/rpc.statd off (0.00/0/0)
udp 0 0 0.0.0.0:40331 0.0.0.0:* 754/rpc.statd off (0.00/0/0)
udp 0 0 0.0.0.0:68 0.0.0.0:* 635/dhclient off (0.00/0/0)
udp 0 0 0.0.0.0:111 0.0.0.0:* 706/rpcbind off (0.00/0/0)
udp6 0 0 :::873 :::* 706/rpcbind off (0.00/0/0)
udp6 0 0 :::50384 :::* 754/rpc.statd off (0.00/0/0)
udp6 0 0 :::26304 :::* 635/dhclient off (0.00/0/0)
udp6 0 0 :::111 :::* 706/rpcbind off (0.00/0/0)
Here is a list of TCP ports open to connection from outside the voting machine.
$ nmap 192.168.50.42 -p-
Starting Nmap 7.12 ( https://nmap.org ) at 2016-10-15 17:58 CEST
Nmap scan report for local.cocorico.cc (192.168.50.42)
Host is up (0.00036s latency).
Not shown: 65521 closed ports
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
111/tcp open rpcbind
443/tcp open https
3000/tcp open ppp
4369/tcp open epmd
5672/tcp open amqp
15672/tcp open unknown
27017/tcp open mongod
28017/tcp open mongod
30303/tcp open unknown
46307/tcp open unknown
49414/tcp open unknown
55672/tcp open unknown
Nmap done: 1 IP address (1 host up) scanned in 2.65 seconds
In order to lower the number of ports exposed to the public, we should:
The vote, ballot and webhook workers all connect to RabbitMQ at startup. However, when RabbitMQ is restarted, they do not reconnect by themselves. To have them continue consuming messages from the broker, they have to be restarted intentionally.
I can think of at least two potential solutions to this problem:
The "Privacy Policy" page is just a placeholder:
https://github.com/promethe42/cocorico/blob/master/api/db/pages/privacy-policy.html
We need to fix it by translating/adapting the content of:
https://github.com/promethe42/cocorico/blob/master/api/db/pages/politique-de-confidentialite.md
Documentation about how to translate pages is here:
https://github.com/promethe42/cocorico/blob/master/doc/Localization.md#translating-pages
Does it make sense to keep the FranceConnect stuff in the English version?
Should we go for a more generic "digital ID" thing?
We use '*' instead of a propre URL.
Thus, any host frame will be able to listen to the embedded VoteWidget events.
The "Política de privacidad" page is just a placeholder:
https://github.com/promethe42/cocorico/blob/master/api/db/pages/privacy-policy.html
We need to fix it by translating/adapting the content of:
https://github.com/promethe42/cocorico/blob/master/api/db/pages/politica-de-privacidad.md
Documentation about how to translate pages is here:
https://github.com/promethe42/cocorico/blob/master/doc/Localization.md#translating-pages
Does it make sense to keep the FranceConnect stuff in the Spanish version?
Should we go for a more generic "digital ID" thing?
to avoid XSS/CSRF attacks
Currently, webhooks are called synchronously. This is because we process webhook messages from RabbitMQ one by one through a single channel (a RabbitMQ channel is synchronous by nature).
Potential solutions are:
pm2
might be helpful here).positive => blue
negative => red
0 => grey
The current voting process is cumbersome: we generate a complicated "vote card" which the user don't actually need. 99% of the data in that vote card is useless: the public key (or the address) alone would be enough as of now.
Yet, we offer no simple way to audit a ballot using the "vote card": we have the address of the account, but we have no idea about what the user actually voted. So it would be up to him to remember what he voted when he's going to audit his ballot in the ballot box.
We must keep generating the "vote card" since it's mandatory (it's basically the blockchain account used to create and sign the ballot transaction). Yet we could do all of it in the background and never tell the user about it.
Instead, we should create a new kind of token that can be used to assess/audit the ballot and its value in the ballot box. This would be a "proof of vote". This proof of vote would be a JWT containing:
This JWT would be created and signed by the server as a response to the POST /api/ballot API endpoint. This JWT signing key should be unique per-vote and never made available by the API.
Lots of messages are stored as pages in the database instead of a locale message. For example, the vote widget wording is mostly loaded from pages.
This is not cool because someone who wants to translate the app will have a hard time figuring what is where.
I did this originally because I wasn't sure I could properly format this kind of content in the locale file. But it turns out it's possible using <FormattedHTMLMessage>
instead of the simpler <FormattedMessage>
.
We should:
When we have #43, the /vote/ballot-box
page should provide a way to "audit" one's ballot.
To audit its ballot, the user will have to provide (scan or select the file) his "proof of vote". From this proof of vote, we can read:
We can then make sure that triplet matches with an actual ballot transaction/event on the blockchain and show a side-by-side comparison of the proof of vote and the blockchain data.
Every time a user audits his ballot, we should increment a counter to know how many audits have succeeded/failed. On the ballot box page, we could then show:
Today, to verify your vote, you have to go to the ballot box page and upload your voting proof, a QR code that hides a JWT. It would be neat if the QR code would be a url with the JWT already appended to it so that, by scanning the QR code, the user would automatically come to a page that verifies its vote. This page would be different than the ballot box page so that one could verify his vote even if the voting process is not over yet.
The "Acerca de esto" page is just a placeholder:
https://github.com/promethe42/cocorico/blob/master/api/db/pages/acerca-de-esto.html
We need to fix it by translating/adapting the content of:
https://github.com/promethe42/cocorico/blob/master/api/db/pages/a-propos.md
Documentation about how to translate pages is here:
https://github.com/promethe42/cocorico/blob/master/doc/Localization.md#translating-pages
The "About" page is just a placeholder:
https://github.com/promethe42/cocorico/blob/master/api/db/pages/about.html
We need to fix it by translating/adapting the content of:
https://github.com/promethe42/cocorico/blob/master/api/db/pages/a-propos.md
Documentation about how to translate pages is here:
https://github.com/promethe42/cocorico/blob/master/doc/Localization.md#translating-pages
This should be done AFTER #27.
Pages are stored in the database and can be edited through the CMS admin.
For now, pages are 100% French content, including their content but also their slug.
Pages are loaded by the Web app by the Page
component using the page slug. Example:
<Page slug="accueil"/>
The easiest way to proceed would be to rely on react-intl to localize the page slugs.
First, we create a copy of each page and translate it into another locale (English?).
Second, we add a "page" section to the intl.js file:
page : {
HOME: "accueil",
HELP: "aide",
// all the other slugs...
}
Third, we change all references to the Page
component to read the slug from the locale using getIntlMessage()
. Example :
<Page slug="accueil"/>
becomes:
<Page slug={this.getIntlMessage('page.HOME'}/>
Here is the todo list:
getIntlMessage()
when using the Page
componentHey,
As discussed during the hackathon last week-end :
It'd be great to make cocorico available in other languages. How do you suggest we do that? Could you provide the link to the files that need translations?
Thanks!
Currently, we use some URLs coming from meetup.com to run the API tests.
As a result, some tests will fail when there is no internet connectivity.
We should solve this by running a test-dedicated Web server with static content.
Web browser cache has to be manually emptied to get the latest version of /public/app.js
.
Today the locale in which the text is displayed is being automatically selected depending on the user's browser locale configuration. Given that (i) labels and messages are not localized and (ii) multi-language voting is very likely a rare case (by default english will be used), it would be good to be able to force the use of a specific locale at vote creation time (/api/vote). I would add 'locale' as an optional parameter.
Today, the root "authority" blockchain accounts credits the user browser-side generated account with more than enough ETH to perform the smart contract method call.
We should credit only the minimum amount of ETH necessary to handle the call transaction.
With this modification, the balance of the user account should be 0.
If it's not zero, the balance should be sent back to the root account.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.