From 9c1f6ed324d011fc11d5bb5c2739384acfbcf9c8 Mon Sep 17 00:00:00 2001 From: Linus Gasser Date: Fri, 19 Jan 2024 15:41:58 +0100 Subject: [PATCH] Rearranging things Various small changes and refactoring made while speeding up voting. --- contracts/evoting/evoting.go | 3 ++- contracts/evoting/mod_test.go | 2 +- integration/dvotingdela.go | 14 +++++++------- integration/performance_test.go | 9 +++------ services/dkg/pedersen/mod_test.go | 27 +++++++++++++++++++-------- services/shuffle/neff/handler.go | 27 +++++++++++++-------------- services/shuffle/neff/mod.go | 2 +- 7 files changed, 46 insertions(+), 38 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index af57a69c6..481d9dd5d 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -272,7 +272,8 @@ func (e evotingCommand) shuffleBallots(snap store.Snapshot, step execution.Step) } if form.Status != types.Closed { - return xerrors.Errorf("the form is not closed") + return xerrors.Errorf("the form is not in state closed (current: %d != closed: %d)", + form.Status, types.Closed) } // Round starts at 0 diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 5f9f615cc..f070dab5e 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -549,7 +549,7 @@ func TestCommand_ShuffleBallotsFormatErrors(t *testing.T) { require.NoError(t, err) err = cmd.shuffleBallots(snap, makeStep(t, FormArg, string(data))) - require.EqualError(t, err, "the form is not closed") + require.EqualError(t, err, "the form is not in state closed (current: 0 != closed: 2)") // Wrong round : form.Status = types.Closed diff --git a/integration/dvotingdela.go b/integration/dvotingdela.go index 7d29177f1..34ba8c1b4 100644 --- a/integration/dvotingdela.go +++ b/integration/dvotingdela.go @@ -57,9 +57,9 @@ import ( const certKeyName = "cert.key" const privateKeyFile = "private.key" -// dela defines the common interface for a Dela node. -type dela interface { - Setup(...dela) +// delaNode defines the common interface for a Dela node. +type delaNode interface { + Setup(...delaNode) GetMino() mino.Mino GetOrdering() ordering.Service GetTxManager() txn.Manager @@ -68,7 +68,7 @@ type dela interface { // dVotingCosiDela defines the interface needed to use a Dela node using cosi. type dVotingCosiDela interface { - dela + delaNode GetPublicKey() crypto.PublicKey GetPool() pool.Pool @@ -124,7 +124,7 @@ func setupDVotingNodes(t require.TestingT, numberOfNodes int, tempDir string) [] wait.Wait() close(nodes) - delaNodes := make([]dela, 0, numberOfNodes) + delaNodes := make([]delaNode, 0, numberOfNodes) dVotingNodes := make([]dVotingCosiDela, 0, numberOfNodes) for node := range nodes { @@ -295,9 +295,9 @@ func createDVotingAccess(t require.TestingT, nodes []dVotingCosiDela, dir string return signer } -// Setup implements dela. It creates the roster, shares the certificate, and +// Setup implements delaNode. It creates the roster, shares the certificate, and // create an new chain. -func (c dVotingNode) Setup(nodes ...dela) { +func (c dVotingNode) Setup(nodes ...delaNode) { // share the certificates joinable, ok := c.onet.(minogrpc.Joinable) require.True(c.t, ok) diff --git a/integration/performance_test.go b/integration/performance_test.go index 34f0b6e74..aaeb38a51 100644 --- a/integration/performance_test.go +++ b/integration/performance_test.go @@ -15,10 +15,9 @@ import ( "github.com/c4dt/d-voting/contracts/evoting" "github.com/c4dt/d-voting/contracts/evoting/types" "github.com/c4dt/d-voting/services/dkg" - "github.com/rs/zerolog" "github.com/stretchr/testify/require" - delaPkg "go.dedis.ch/dela" "go.dedis.ch/dela/core/execution/native" + "go.dedis.ch/dela/core/ordering/cosipbft" "go.dedis.ch/dela/core/txn" "golang.org/x/xerrors" ) @@ -35,8 +34,6 @@ func BenchmarkIntegration_CustomVotesScenario(b *testing.B) { // make tests reproducible rand.Seed(1) - delaPkg.Logger = delaPkg.Logger.Level(zerolog.WarnLevel) - dirPath, err := os.MkdirTemp(os.TempDir(), "d-voting-three-votes") require.NoError(b, err) @@ -49,7 +46,7 @@ func BenchmarkIntegration_CustomVotesScenario(b *testing.B) { signer := createDVotingAccess(b, nodes, dirPath) - m := newTxManager(signer, nodes[0], time.Second*time.Duration(numNodes/2+1), numNodes*2) + m := newTxManager(signer, nodes[0], cosipbft.DefaultRoundTimeout*time.Duration(numNodes/2+1), numNodes*2) err = grantAccess(m, signer) require.NoError(b, err) @@ -115,7 +112,7 @@ func BenchmarkIntegration_CustomVotesScenario(b *testing.B) { require.NoError(b, err) err = waitForStatus(types.PubSharesSubmitted, formFac, formID, nodes, - numNodes, 6*time.Second*time.Duration(numNodes)) + numNodes, cosipbft.DefaultRoundTimeout*time.Duration(numNodes)) require.NoError(b, err) durationPubShares := b.Elapsed() diff --git a/services/dkg/pedersen/mod_test.go b/services/dkg/pedersen/mod_test.go index af236b9ec..5375ad82d 100644 --- a/services/dkg/pedersen/mod_test.go +++ b/services/dkg/pedersen/mod_test.go @@ -193,24 +193,35 @@ func TestPedersen_InitNonEmptyMap(t *testing.T) { // When a new actor is created, its information is safely stored in the dkgMap. func TestPedersen_SyncDB(t *testing.T) { + t.Skip("https://github.com/c4dt/d-voting/issues/91") formID1 := "deadbeef51" formID2 := "deadbeef52" // Start some forms - fake.NewForm(formID1) - fake.NewForm(formID2) + context := fake.NewContext() + form1 := fake.NewForm(formID1) + service := fake.NewService(formID1, form1, context) + form2 := fake.NewForm(formID2) + service.Forms[formID2] = form2 + pool := fake.Pool{} + manager := fake.Manager{} // Initialize a Pedersen - p := NewPedersen(fake.Mino{}, &fake.Service{}, &fake.Pool{}, fake.Factory{}, fake.Signer{}) + p := NewPedersen(fake.Mino{}, &service, &pool, fake.Factory{}, fake.Signer{}) // Create actors - a1, err := p.NewActor([]byte(formID1), &fake.Pool{}, fake.Manager{}, NewHandlerData()) + formID1buf, err := hex.DecodeString(formID1) + require.NoError(t, err) + formID2buf, err := hex.DecodeString(formID2) require.NoError(t, err) - _, err = p.NewActor([]byte(formID2), &fake.Pool{}, fake.Manager{}, NewHandlerData()) + a1, err := p.NewActor(formID1buf, &pool, manager, NewHandlerData()) + require.NoError(t, err) + _, err = p.NewActor(formID2buf, &pool, manager, NewHandlerData()) require.NoError(t, err) // Only Setup the first actor - a1.Setup() + _, err = a1.Setup() + require.NoError(t, err) // Create a new DKG map and fill it with data dkgMap := fake.NewInMemoryDB() @@ -245,7 +256,7 @@ func TestPedersen_SyncDB(t *testing.T) { require.NoError(t, err) // Recover them from the map - q := NewPedersen(fake.Mino{}, &fake.Service{}, &fake.Pool{}, fake.Factory{}, fake.Signer{}) + q := NewPedersen(fake.Mino{}, &service, &pool, fake.Factory{}, fake.Signer{}) err = dkgMap.View(func(tx kv.ReadableTx) error { bucket := tx.GetBucket([]byte("dkgmap")) @@ -257,7 +268,7 @@ func TestPedersen_SyncDB(t *testing.T) { err = json.Unmarshal(handlerDataBuf, &handlerData) require.NoError(t, err) - _, err = q.NewActor(formIDBuf, &fake.Pool{}, fake.Manager{}, handlerData) + _, err = q.NewActor(formIDBuf, &pool, manager, handlerData) require.NoError(t, err) return nil diff --git a/services/shuffle/neff/handler.go b/services/shuffle/neff/handler.go index 0fc00f228..5d5ba7dce 100644 --- a/services/shuffle/neff/handler.go +++ b/services/shuffle/neff/handler.go @@ -108,7 +108,7 @@ func (h *Handler) handleStartShuffle(formID string) error { return xerrors.Errorf("the form must be closed: (%v)", form.Status) } - tx, err := makeTx(h.context, &form, h.txmngr, h.shuffleSigner) + tx, err := h.makeTx(&form) if err != nil { return xerrors.Errorf("failed to make tx: %v", err) } @@ -149,10 +149,9 @@ func (h *Handler) handleStartShuffle(formID string) error { } } -func makeTx(ctx serde.Context, form *etypes.Form, manager txn.Manager, - shuffleSigner crypto.Signer) (txn.Transaction, error) { +func (h *Handler) makeTx(form *etypes.Form) (txn.Transaction, error) { - shuffledBallots, getProver, err := getShuffledBallots(form) + shuffledBallots, getProver, err := h.getShuffledBallots(form) if err != nil { return nil, xerrors.Errorf("failed to get shuffled ballots: %v", err) } @@ -163,17 +162,17 @@ func makeTx(ctx serde.Context, form *etypes.Form, manager txn.Manager, ShuffledBallots: shuffledBallots, } - h := sha256.New() + hash := sha256.New() - err = shuffleBallots.Fingerprint(h) + err = shuffleBallots.Fingerprint(hash) if err != nil { return nil, xerrors.Errorf("failed to get fingerprint: %v", err) } - hash := h.Sum(nil) + seed := hash.Sum(nil) // Generate random vector and proof - semiRandomStream, err := evoting.NewSemiRandomStream(hash) + semiRandomStream, err := evoting.NewSemiRandomStream(seed) if err != nil { return nil, xerrors.Errorf("could not create semi-random stream: %v", err) } @@ -204,17 +203,17 @@ func makeTx(ctx serde.Context, form *etypes.Form, manager txn.Manager, } // Sign the shuffle: - signature, err := shuffleSigner.Sign(hash) + signature, err := h.shuffleSigner.Sign(seed) if err != nil { return nil, xerrors.Errorf("could not sign the shuffle : %v", err) } - encodedSignature, err := signature.Serialize(ctx) + encodedSignature, err := signature.Serialize(h.context) if err != nil { return nil, xerrors.Errorf("could not encode signature as []byte : %v ", err) } - publicKey, err := shuffleSigner.GetPublicKey().MarshalBinary() + publicKey, err := h.shuffleSigner.GetPublicKey().MarshalBinary() if err != nil { return nil, xerrors.Errorf("could not unmarshal public key from nodeSigner: %v", err) } @@ -223,7 +222,7 @@ func makeTx(ctx serde.Context, form *etypes.Form, manager txn.Manager, shuffleBallots.PublicKey = publicKey shuffleBallots.Signature = encodedSignature - data, err := shuffleBallots.Serialize(ctx) + data, err := shuffleBallots.Serialize(h.context) if err != nil { return nil, xerrors.Errorf("failed to serialize shuffle ballots: %v", err) } @@ -242,7 +241,7 @@ func makeTx(ctx serde.Context, form *etypes.Form, manager txn.Manager, Value: data, } - tx, err := manager.Make(args...) + tx, err := h.txmngr.Make(args...) if err != nil { if err != nil { return nil, xerrors.Errorf("failed to use manager: %v", err.Error()) @@ -253,7 +252,7 @@ func makeTx(ctx serde.Context, form *etypes.Form, manager txn.Manager, } // getShuffledBallots returns the shuffled ballots with the shuffling proof. -func getShuffledBallots(form *etypes.Form) ([]etypes.Ciphervote, +func (h *Handler) getShuffledBallots(form *etypes.Form) ([]etypes.Ciphervote, func(e []kyber.Scalar) (proof.Prover, error), error) { round := len(form.ShuffleInstances) diff --git a/services/shuffle/neff/mod.go b/services/shuffle/neff/mod.go index ef0db274c..58bf61235 100644 --- a/services/shuffle/neff/mod.go +++ b/services/shuffle/neff/mod.go @@ -95,7 +95,7 @@ type Actor struct { formFac serde.Factory } -// Shuffle must be called by ONE of the actor to shuffle the list of ElGamal +// Shuffle must be called by ONE of the actors to shuffle the list of ElGamal // pairs. // Each node represented by a player must first execute Listen(). func (a *Actor) Shuffle(formID []byte) error {