In-progress minimal voting app.

This commit is contained in:
Elliot Glaysher 2019-06-04 16:46:34 -07:00
parent b4cdc7f978
commit 821678fdcf
4 changed files with 227 additions and 0 deletions

119
app/ballet.hoon Normal file
View File

@ -0,0 +1,119 @@
/- *ballet
/+ tapp, stdio
::
:: Preamble
::
=>
|%
+$ state
$: next-election-num=@u
open-elections=(map id election)
closed-elections=(map id election)
==
+$ peek-data _!!
+$ in-poke-data
$% :: casts a ballot
::
[%ballot-cast =id =ring-signature =vote]
:: creates a new election
::
[%ballot-create =electorate =ballot closes=@da]
==
+$ out-poke-data
~
+$ in-peer-data
~
+$ out-peer-data
:: For observers, our wire interface is:
::
:: /[election-num]
::
election-diff
++ tapp (^tapp state peek-data in-poke-data out-poke-data in-peer-data out-peer-data)
++ stdio (^stdio out-poke-data out-peer-data)
--
=, async=async:tapp
=, tapp-async=tapp-async:tapp
=, stdio
::
:: The app
::
%- create-tapp-poke-peer:tapp
^- tapp-core-poke-peer:tapp
|_ [=bowl:gall =state]
::
:: Main function
::
++ handle-poke
|= =in-poke-data
=/ m tapp-async
^- form:m
::
?- -.in-poke-data
::
%ballot-cast
~& %ballot-cast
:: verify ballot is for a valid election
::
?~ election=(~(get by open-elections.state) id.in-poke-data)
~& [%invalid-election id.in-poke-data]
(pure:m state)
:: verify ballot has a valid signature
::
:: TODO: Right now, this is a no-op until the ring signature library is
:: completed.
::
?. =, in-poke-data
(verify-signature ring-signature `[%election id] vote)
~& [%invalid-signature ~]
(pure:m state)
:: is this person trying to vote twice?
::
?: (~(has by cast.u.election) ring-tag.ring-signature.in-poke-data)
~& [%attempting-to-vote-twice ring-tag.ring-signature.in-poke-data]
(pure:m state)
:: we have a valid vote. make it part of our state.
::
=. open-elections.state
%+ ~(jab by open-elections.state) id.in-poke-data
|= =^election
%_ election
cast
%+ ~(put by cast.election) ring-tag.ring-signature.in-poke-data
[ring-signature.in-poke-data vote.in-poke-data]
==
:: broadcast this valid vote to the world
::
;< ~ bind:m
=, in-poke-data
(give-result `path`/(scot %u election-num.id) `election-diff`[%vote ring-signature vote])
::
(pure:m state)
::
%ballot-create
=/ election-num next-election-num.state
=/ =id [our.bowl election-num]
~& [%this-ballot-id id]
::
=. next-election-num.state +(next-election-num.state)
=. open-elections.state
%+ ~(put by open-elections.state) id
^- election
:* id
electorate.in-poke-data
ballot.in-poke-data
closes.in-poke-data
cast=~
tally=~
==
::
(pure:m state)
==
::
++ handle-peer
|= =path
=/ m tapp-async
^- form:m
~& [%tapp-fetch-take-peer path]
(pure:m state)
--

13
gen/ballet/cast.hoon Normal file
View File

@ -0,0 +1,13 @@
/- *ballet
:: Creates a
::
:- %say
|= $: {now/@da eny/@uvJ byk/beak}
[[=id who=@p vote=@u ~] ~]
==
~! *ring-signature
:* %ballot-cast
id
`ring-signature`[0 ~ who]
[vote ~]
==

13
gen/ballet/create.hoon Normal file
View File

@ -0,0 +1,13 @@
:: Creates a
::
:- %say
|= $: {now/@da eny/@uvJ byk/beak}
[[ships=(list @p) answers=(list tape) ~] ~]
==
:* %ballot-create
`(set @p)`(sy ships)
:* "Test"
[[%radio "Question" answers] ~]
==
`@da`(add now ~d1)
==

82
sur/ballet.hoon Normal file
View File

@ -0,0 +1,82 @@
:: /sour/ballot
::
:: TODO: ring signature stuff should be provided by their own sur files, this is just
:: stubs for now.
::
|%
++ ring-tag
:: TODO: the ring-tag is really supposed to be a point on a elliptic curve:
:: [@ @]. But to make sure we have ring-tag uniqueness for now, just make
:: the structure a ship name.
::
@p
+$ ring-signature
[@ (list @) =ring-tag]
++ verify-signature
|= [=ring-signature linkage-tag=(unit *) data=*]
^- ?
~& %verify-signature-is-a-stub
::
%.y
--
|%
:: The electorate is the set of people who may vote in an election. This is
:: set during the creation of the election
::
++ electorate
(set @p)
:: The ballot is the set of questions which are then voted on.
::
++ ballot
$: preamble=tape
questions=(list question)
==
:: A question is either a select as many as you want %check or select one %radio
::
++ question
$% [%check preamble=tape vote=(list tape)]
[%radio preamble=tape votes=(list tape)]
==
:: A vote is a set of answers to questions on a ballot
::
++ vote
(list @ud)
:: A unique id which is used as linkage scope on signatures to votes
::
++ id
$: host=@p
election-num=@u
==
:: +election contains all the state of an election, and is releasable during
:: and after the fact
::
++ election
$: :: a unique id for this election
::
=id
:: who may vote
::
=electorate
:: what is being voted on
::
=ballot
:: when the election closes
::
closes=@da
:: cast votes, sorted on linkage tag
::
cast=(map ring-tag [=ring-signature =vote])
:: the current TODO TODO TODO
::
tally=(list (map index=@u count=@u))
==
:: +election-diff: a series of events which rebuilds an +election object
::
++ election-diff
$% [%snapshot =id =election]
[%vote =ring-signature =vote]
[%election-completed ~]
==
--