# ov-api / online voting client api

## About

This api provides a high level interface to the client-side crypto and
the server endpoints of the online voting protocol, with two main
interfaces:

- **OvApi** is a simple and straightforward api for the full protocol. It
  basically exposes three simple methods (authentication, send vote
  and cast vote) and transparently takes care of all the details and
  intermediate requests. Implementing a full voting client with this
  api is pretty trivial, so this is the preferred method.

- **OvWorker** is a helper interface for precomputing values in
  background during the session, while the user is interacting with
  the voting portal. This may significantly speed up the final vote
  encryption process.

This document is a general guide for setting up and using these
interfaces. 

    
## Setup

The library is distributed as a single bundle file containing all
necessary dependencies, including support for web workers for
asynchronous processing.
    
```html
  <script src="crypto/ov-api.js"></script>
```

Note: './crypto/' is the default location for the script. You may use
a different location but the API needs to be aware of this (this same
script will be dynamically loaded into web workers) so you will have
to pass the new location as a configuration option.


## Basic usage 

### Bootstrap
    
As soon as the host page is loaded, the api will automatically start
collecting entropy. However, you need a way to know when it is safe to
start invoking methods in the api. For this, you call the
_ovApi.init()_ method like so:


```JavaScript
window.ovApi = new OvApi({
    lib: 'my/custom/path/ov-api.js',
});
ovApi.init().then(function() {
     console.log('Online voting ready!');
});
```

Note that you _can_ invoke the api without doing this, but this is not
recommended. If you start making requests before enough entropy has
been collected, the api will simply work with lower quality
randomness, which you probably don't want.

### Asynchronous process

Most API methods are asynchronous and return *promises*. When called
they will return immediately a promise object. You can chain 'then',
'fail' and 'progress' event handlers to this promise object which will
be invoked as appropiate once the promise is resolved. All these
handlers are optional.

```JavaScript
ovApi.sendVote(voteoptions)

    .then(function(result) {
        // the method has completed ok and 'result' will
        // contain the return value
    })
    .fail(function(error) {
        // the method has failed and 'error' will
        // contain information about the error
    })
    .progress(function(percent) {
        // the method is still processing and 'percent' will
        // contain the estimated percentage completed (0-100 integer)
        // this is informative, and might get called multiple times
        // (or not at all)
    });
```

Note that these promises are implemented with Kris Kowal's "q" library
which supports several alternative ways to handle them. More info:
https://github.com/kriskowal/q/wiki/API-Reference

### Concurrency

Note that the API being asynchronous doesn't mean it is automatically
concurrent. You should have only one task running independently from the
main thread per instance of the API (i.e. per web worker). 

It is safe, however, to create several instances of the API and have
them running concurrently if you should ever need to do so.

    
# Using OvApi

Implementing a vote cycle with this API is quite simple.

## Initializing 

First create and initialize an instance and wait for the _init_ method
to resolve:

```JavaScript
window.ovApi = new OvApi({
     tenantId: 'someTenantId',
     electionEventId: $stateParams.eeid
});
ovApi.init().then(function() {
    
     // ovApi is safe to be used now!
});
```

Note that you can pass configuration options to the constructor.
    
## Authenticating and getting a ballot

Next, once you have asked the voter for his/her _startVotingKey_, just
call the _requestBallot_ method like so:

```JavaScript
ovApi.requestBallot(startVotingKey)
.then(function(ballotResponse) {

 // if you do want a parsed ballot, you can now call: 
 var ballot = ovApi.parseBallot(ballotResponse);

})
```

This is all it takes to get an authenticated session for the voter and
obtain the ballot.

### The ballot

The _ballot_ is basically an object tree with the full collection of
questions, votations and elections available to the voter, suitable
for navigation and rendering it to HTML. The structure will vary
depending on the type of elections, but every selectable option will
contain a '_prime_' property which is a number representing the actual
vote option. This number is the only relevant information for the
voting protocol, so you can do anything you want to the ballot object
(add properties to track selections, etc ...).

Note that the ballot will be in the language configured as default. If
you want to present it in a different language, just call
_translateBallot_.


```JavaScript
ovApi.translateBallot(ballot, 'fr_FR');
```

The _ballot_ object has two additional properties, _status_ and
_correctnessIds_, that you will need to be aware of:

## ballot.status / Checking vote status

This property indicates if the voter has already voted on this ballot
and wether the vote was fully completed or not.


```JavaScript
switch (ballot.status) {

     case 'SENT_BUT_NOT_CAST':

     // The voter already sent a vote for this ballot, but left the
     // portal before actually 'casting' it. You should ask him to do
     // that now. See OvApi.requestChoiceCodes

     case 'CAST':

     // The voter did cast a vote for this ballot. You can now remind
     // him that he already did so and show him his 'vote cast
     // code'. See OvApi.requestVoteCastCode

     case 'NOT_SENT':

     // The voter never voted on this ballot. You should present it to
     // him so he can make his choices.
```

## ballot.correctnessIds / Vote correctness map

This is a map of vote correctness identifiers for each representation
(_prime_) in the ballot. You will need to supply it as a parameter for
the _sendVote_ (see below).


## Sending the vote

Once the voter has made all his/her choices, assembling and sending a
vote is just a matter of calling _sendVote_, passing the vote options
as an array of strings representing (big) integers.

```JavaScript
    
ovApi.sendVote(primesArray, 
    encrypterValues, 
    null, // precomputed partial choice codes, can be null
    null, // precomputed proof values, can be null
    ballot.correctnessIds,
    null, // writein (only present if writeins are enabled, can be null or omitted if later arguments also omitted)
    null, // verificationCode (only present if an additional verification step is enabled, can be null or omitted if later arguments also omitted)
    null) // disableOptimizations (intended for testing purposes, can be null or omitted)
    .then(function(choiceCodes) {

   // Once this point is reached, you should have the choice codes to show to the voter. The voter should be encouraged to make sure that they match.

```

The write-in options, if present, are informed as an array of strings.


## Casting the vote
    
If everything is ok, the voter will supply the _ballot casting key_ to
cast the vote. You just call:

```JavaScript
ovApi.castVote(ballotCastingKey)
  .then(function(voteCastCode) {

  // Once this point is reached, you have the vote cast code to show to the voter. Again,
  // they should make sure it matches.
```

That's all, we're done!

The voting process is now complete. The process of recovering from an
interrupted session ( _requestChoiceCodes_ method) and returning voters
( _requestVoteCastCodes_ method) is not covered in this guide, but it
follows the same pattern as above.
    
    
# Using OvWorker for precomputations

## Initializing 

First create and initialize an instance and wait for the _init_ method
to resolve, just like you do with _OvApi_ :

```JavaScript
window.ovApi = new OvApi(config);
window.ovWorker = new OvWorker(config);
        
ovApi.init().then(function() {
    ovWorker.init().then(function() {
        console.log('Online voting ready!');
    });
});
```
  
## Precomputations

The vote encryption step is quite compute intensive and can take a
while, specially on low end devices. To minimize this several
computations can be performed in advance, in a separate thread (i.e.,
a web worker) while the user is interacting with the voter portal. We
call these 'precomputations'.

To use precomputations you first invoke the appropiate method, store
the result when available and finally supply them to your vote
encryption method of choice.

There are 3 types of precomputations you can use:

- for encryption.
- for partial choice code generation
- for zero knowledge proofs
    

### Precomputations for encryption 

You need the election's _encryption parameters_ for these. The
encryption parameters are provided along with the ballot, so this
means you must have already called (and resolved)
_OvApi.requestBallot_ .

Once you did, you can recover the encryption parameters with
_ovApi.getSerializedEncryptionParams()_ and feed them to
_OvWorker.precomputeEncrypterValues()_ , like so:
    
```JavaScript
ovApi.getSerializedEncryptionParams()
    .then(function(serializedEncParams) {

        // start precomputing encrypter values
        ovWorker.precomputeEncrypterValues(serializedEncParams)
            .then(function(encrypterValues) {
                // got our encrypter values, store for later
                mySessionService.setEncrypterValues(encrypterValues);
```

To actually use these _encrypterValues_ you need to supply them to
the encryption method _OvApi.sendVote()_ , like so:

```JavaScript
ovApi.sendVote(
    primes,
    mySessionService.getEncrypterValues(),
    ...
```
    
Note that both methods accept this parameter to be _null_ or omitted,
in which case they simply will just not use any precomputed values.

### Precomputations for zero knowledge proofs

Once you have the encryption parameters and the precomputed encrypter
values you can also perform in advance several computations for the
zero knowledge proofs.


```JavaScript
// start precomputing proofs
ovWorker.precomputeProofValues(
    at.voterInformation.electionEventId,
    at.voterInformation.votingCardId,
    serializedEncParams,
    encrypterValues)
.then(function(proofValues) {
    // got our proof values, store for later
    mySessionService.setProofValues(proofValues);
    ...
```

To use these precomputed proof values just supply them to 
the encryption method  ( _OvApi.sendVote()_  ), like so:

    
```JavaScript
ovApi.sendVote(
    primes,
    mySessionService.getEncrypterValues(),
    ...
    mySessionService.getProofValues(proofValues)
    ...
```
    
### Precomputations for partial choice code generation

For these optimizations you need also a secret key contained in the
voter's keystore, which is provided by _OvApi.requestBallot_ 

    
```JavaScript
// get verification secret 
ovApi.getSerializedVerificationCardSecret()
    .then(function(serializedVerificationCardSecret) {
        // got our verification secret, store for later
        mySessionService.setVerificationKey(serializedVerificationCardSecret);
```

The _partial choice codes_ are precomputed individually. This is
because there can be a potentially large number of them and computing
them all might be considerable overkill or even choke the browser. So
the strategy is up to you and depends largely on the size of your
election (in terms of possible different vote options).

A sensible approach is to precompute just the options the user
actually selects since they are likely to be present in the final
vote. So, whenever the user makes a choice you can do something like
this:

```JavaScript
// user just selected 'option' ...
ovWorker.precomputePartialChoiceCode(
    mySessionService.getEncParams(),
    option.prime,
    mySessionService.getVerificationKey());
```

Note that this method is 'fire and forget'. It returns nothing, but
will silently compute the partial choice code in background and keep
it in a pool. You don't really have to care.

When the time comes to actually encrypt the vote you can call
_ovWorker.getPrecomputedPartialChoiceCodes()_ to obtain the pool of
precomputed partial choice codes up to that point:

```JavaScript
ovWorker.getPrecomputedPartialChoiceCodes()
    .then(function(precomputedPCC) {
        ovApi.sendVote(primes, sessionService.getEncrypterValues(), precomputedPCC)
```

You then pass these values to _OvApi.sendVote()_ . It will use any
partial choice codes present in the pool, and will compute the rest,
if any, on the fly. Again, this parameter can be _null_.