Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions contracts/evoting/json/lightelection.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package json

import (
"github.com/dedis/d-voting/contracts/evoting/types"
"go.dedis.ch/dela/serde"
"go.dedis.ch/kyber/v3"
"golang.org/x/xerrors"
)

// lightElectionFormat defines how the election messages are encoded/decoded
// using the JSON format.
//
// - implements serde.FormatEngine
type lightElectionFormat struct{}

// Encode implements serde.FormatEngine
func (lightElectionFormat) Encode(ctx serde.Context, message serde.Message) ([]byte, error) {
return nil, xerrors.Errorf("encoding of a light election not supported")
}

// Decode implements serde.FormatEngine
func (lightElectionFormat) Decode(ctx serde.Context, data []byte) (serde.Message, error) {
var electionJSON LightElectionJSON

err := ctx.Unmarshal(data, &electionJSON)
if err != nil {
return nil, xerrors.Errorf("failed to unmarshal election: %v", err)
}

var pubKey kyber.Point

if electionJSON.Pubkey != nil {
pubKey = suite.Point()
err = pubKey.UnmarshalBinary(electionJSON.Pubkey)
if err != nil {
return nil, xerrors.Errorf("failed to unmarshal pubkey: %v", err)
}
}

return types.Election{
Configuration: types.Configuration{
MainTitle: electionJSON.Configuration.MainTitle,
},
ElectionID: electionJSON.ElectionID,
Status: types.Status(electionJSON.Status),
Pubkey: pubKey,
BallotSize: electionJSON.BallotSize,
}, nil
}

// LightConfiguration represents what is need from the configuration in the
// light election.
type LightConfiguration struct {
MainTitle string
}

// LightElectionJSON defines the Election in the JSON format
type LightElectionJSON struct {
Configuration LightConfiguration

// ElectionID is the hex-encoded SHA256 of the transaction ID that creates
// the election
ElectionID string

Status uint16
Pubkey []byte `json:"Pubkey,omitempty"`

// BallotSize represents the total size in bytes of one ballot. It is used
// to pad smaller ballots such that all ballots cast have the same size
BallotSize int
}
1 change: 1 addition & 0 deletions contracts/evoting/json/mod.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (

func init() {
types.RegisterElectionFormat(serde.FormatJSON, electionFormat{})
types.RegisterElectionFormat(types.LightElectionJSONFormat, lightElectionFormat{})
types.RegisterCiphervoteFormat(serde.FormatJSON, ciphervoteFormat{})
types.RegisterTransactionFormat(serde.FormatJSON, transactionFormat{})
}
4 changes: 4 additions & 0 deletions contracts/evoting/types/election.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ import (

var suite = suites.MustFind("Ed25519")

// LightElectionJSONFormat defines a special format to deserialize a light
// election.
var LightElectionJSONFormat serde.Format = "lightElectionJSON"

// ID defines the ID of a ballot question
type ID string

Expand Down
137 changes: 137 additions & 0 deletions proxy/election_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package proxy

import (
"encoding/hex"
"encoding/json"
"math/rand"
"net/http/httptest"
"testing"

"github.com/dedis/d-voting/contracts/evoting"
"github.com/dedis/d-voting/contracts/evoting/types"
"github.com/dedis/d-voting/internal/testing/fake"
"github.com/stretchr/testify/require"
"go.dedis.ch/dela/core/ordering"
"go.dedis.ch/dela/core/ordering/cosipbft/authority"
"go.dedis.ch/dela/serde"
sjson "go.dedis.ch/dela/serde/json"
)

type LightContextEngine struct {
serde.ContextEngine
}

func (LightContextEngine) GetFormat() serde.Format {
return types.LightElectionJSONFormat
}

func BenchmarkElectionsGET(b *testing.B) {
b.StopTimer()
rand.Seed(0)

ciphervoteFac := types.CiphervoteFactory{}
electionFac := types.NewElectionFactory(ciphervoteFac, fakeAuthorityFactory{})
ctx := serde.NewContext(LightContextEngine{ContextEngine: sjson.NewContext()})

// ctx = sjson.NewContext()

md := types.ElectionsMetadata{
ElectionsIDs: types.ElectionIDs{},
}

ctx2 := sjson.NewContext()

data := map[string][]byte{}

for i := 0; i < 50; i++ {
electionIDBuff := make([]byte, 8)

_, err := rand.Read(electionIDBuff)
require.NoError(b, err)

electionID := hex.EncodeToString(electionIDBuff)

elec := types.Election{
ElectionID: electionID,
Status: 0,
Pubkey: nil,
Suffragia: types.Suffragia{},
ShuffleInstances: make([]types.ShuffleInstance, 0),
DecryptedBallots: nil,
ShuffleThreshold: 0,
Roster: fake.Authority{},
}

md.ElectionsIDs.Add(electionID)

electionBuff, err := elec.Serialize(ctx2)
require.NoError(b, err)

data[string(electionIDBuff)] = electionBuff
}

mdJSON, err := json.Marshal(md)
require.NoError(b, err)

data[evoting.ElectionsMetadataKey] = mdJSON

e := election{
orderingSvc: fakeService{data: data},
context: ctx,
electionFac: electionFac,
}

rr := httptest.NewRecorder()

b.StartTimer()

for i := 0; i < b.N; i++ {
e.Elections(rr, nil)
}
}

// -----------------------------------------------------------------------------
// Utility functions

type fakeService struct {
ordering.Service
data map[string][]byte
}

func (f fakeService) GetProof(key []byte) (ordering.Proof, error) {
proof := fakeProof{
key: key,
value: f.data[string(key)],
}

return proof, nil
}

// fakeProof is a fake Proof
//
// - implements ordering.Proof
type fakeProof struct {
key []byte
value []byte
}

func (f fakeProof) GetKey() []byte {
return f.key
}

func (f fakeProof) GetValue() []byte {
return f.value
}

type fakeAuthorityFactory struct {
serde.Factory
}

func (f fakeAuthorityFactory) AuthorityOf(ctx serde.Context, rosterBuf []byte) (authority.Authority, error) {
fakeAuthority := fakeAuthority{}
return fakeAuthority, nil
}

type fakeAuthority struct {
authority.Authority
}