From 7998bd6dd7bcafe08e1d4f7147e29b77fd7381af Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Sun, 25 Feb 2024 12:01:12 +0100 Subject: [PATCH 001/114] change some error checking method --- contracts/evoting/mod_test.go | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index f070dab5e..f5756fa46 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -202,7 +202,7 @@ func TestCommand_CastVote(t *testing.T) { require.EqualError(t, err, unmarshalTransactionErr) err = cmd.castVote(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) - require.Contains(t, err.Error(), "failed to get key") + require.ErrorContains(t, err, "failed to get key") snap := fake.NewSnapshot() @@ -210,7 +210,7 @@ func TestCommand_CastVote(t *testing.T) { require.NoError(t, err) err = cmd.castVote(snap, makeStep(t, FormArg, string(data))) - require.Contains(t, err.Error(), deserializeErr) + require.ErrorContains(t, err, deserializeErr) err = snap.Set(dummyFormIDBuff, formBuf) require.NoError(t, err) @@ -330,7 +330,7 @@ func TestCommand_CloseForm(t *testing.T) { require.EqualError(t, err, unmarshalTransactionErr) err = cmd.closeForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) - require.Contains(t, err.Error(), "failed to get key") + require.ErrorContains(t, err, "failed to get key") snap := fake.NewSnapshot() @@ -338,7 +338,7 @@ func TestCommand_CloseForm(t *testing.T) { require.NoError(t, err) err = cmd.closeForm(snap, makeStep(t, FormArg, string(data))) - require.Contains(t, err.Error(), deserializeErr) + require.ErrorContains(t, err, deserializeErr) err = snap.Set(dummyFormIDBuff, formBuf) require.NoError(t, err) @@ -533,7 +533,7 @@ func TestCommand_ShuffleBallotsFormatErrors(t *testing.T) { require.EqualError(t, err, unmarshalTransactionErr) err = cmd.shuffleBallots(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) - require.Contains(t, err.Error(), "failed to get key") + require.ErrorContains(t, err, "failed to get key") // Wrong form id format snap := fake.NewSnapshot() @@ -542,7 +542,7 @@ func TestCommand_ShuffleBallotsFormatErrors(t *testing.T) { require.NoError(t, err) err = cmd.shuffleBallots(snap, makeStep(t, FormArg, string(data))) - require.Contains(t, err.Error(), deserializeErr) + require.ErrorContains(t, err, deserializeErr) // Form not closed err = snap.Set(dummyFormIDBuff, formBuf) @@ -759,7 +759,7 @@ func TestCommand_RegisterPubShares(t *testing.T) { require.EqualError(t, err, unmarshalTransactionErr) err = cmd.registerPubshares(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) - require.Contains(t, err.Error(), "failed to get key") + require.ErrorContains(t, err, "failed to get key") snap := fake.NewSnapshot() @@ -767,7 +767,7 @@ func TestCommand_RegisterPubShares(t *testing.T) { require.NoError(t, err) err = cmd.registerPubshares(snap, makeStep(t, FormArg, string(data))) - require.Contains(t, err.Error(), deserializeErr) + require.ErrorContains(t, err, deserializeErr) err = snap.Set(dummyFormIDBuff, formBuf) require.NoError(t, err) @@ -960,7 +960,7 @@ func TestCommand_DecryptBallots(t *testing.T) { require.EqualError(t, err, unmarshalTransactionErr) err = cmd.combineShares(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) - require.Contains(t, err.Error(), "failed to get key") + require.ErrorContains(t, err, "failed to get key") snap := fake.NewSnapshot() @@ -968,7 +968,7 @@ func TestCommand_DecryptBallots(t *testing.T) { require.NoError(t, err) err = cmd.combineShares(snap, makeStep(t, FormArg, string(data))) - require.Contains(t, err.Error(), deserializeErr) + require.ErrorContains(t, err, deserializeErr) err = snap.Set(dummyFormIDBuff, formBuf) require.NoError(t, err) @@ -1060,7 +1060,7 @@ func TestCommand_CancelForm(t *testing.T) { require.EqualError(t, err, unmarshalTransactionErr) err = cmd.cancelForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) - require.Contains(t, err.Error(), "failed to get key") + require.ErrorContains(t, err, "failed to get key") snap := fake.NewSnapshot() @@ -1068,7 +1068,7 @@ func TestCommand_CancelForm(t *testing.T) { require.NoError(t, err) err = cmd.cancelForm(snap, makeStep(t, FormArg, string(data))) - require.Contains(t, err.Error(), deserializeErr) + require.ErrorContains(t, err, deserializeErr) err = snap.Set(dummyFormIDBuff, formBuf) require.NoError(t, err) From 463b91ad6ea6be06efa404b2dd2d9eaebbfcae18 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Mon, 25 Mar 2024 16:09:40 +0100 Subject: [PATCH 002/114] add formAdmin struct --- .gitignore | 2 + contracts/evoting/admin_test.go | 45 ++++++++++++++++++ contracts/evoting/json/adminForm.go | 50 ++++++++++++++++++++ contracts/evoting/json/mod.go | 1 + contracts/evoting/types/admin.go | 71 +++++++++++++++++++++++++++++ web/backend/src/controllers/dela.ts | 1 - 6 files changed, 169 insertions(+), 1 deletion(-) create mode 100644 contracts/evoting/admin_test.go create mode 100644 contracts/evoting/json/adminForm.go create mode 100644 contracts/evoting/types/admin.go diff --git a/.gitignore b/.gitignore index 361116e9b..613ac6555 100644 --- a/.gitignore +++ b/.gitignore @@ -19,3 +19,5 @@ dela/ bin/ nodes/ cookies.txt + +.tool-versions \ No newline at end of file diff --git a/contracts/evoting/admin_test.go b/contracts/evoting/admin_test.go new file mode 100644 index 000000000..14da46317 --- /dev/null +++ b/contracts/evoting/admin_test.go @@ -0,0 +1,45 @@ +package evoting + +import ( + "github.com/c4dt/d-voting/contracts/evoting/types" + "github.com/stretchr/testify/require" + "go.dedis.ch/dela/serde" + sjson "go.dedis.ch/dela/serde/json" + "testing" +) + +var ctxAdminTest serde.Context + +var formFacAdminTest serde.Factory +var transactionFacAdminTest serde.Factory + +func init() { + ciphervoteFac := types.CiphervoteFactory{} + formFacAdminTest = types.NewFormFactory(ciphervoteFac, fakeAuthorityFactory{}) + transactionFacAdminTest = types.NewTransactionFactory(ciphervoteFac) + + ctxAdminTest = sjson.NewContext() +} + +func TestAdmin_serde(t *testing.T) { + adminFormID := "myID" + adminFormList := []int{111111, 222222, 333333, 123456} + + adminForm := types.AdminForm{FormID: adminFormID, AdminList: adminFormList} + + value, err := adminForm.Serialize(ctxAdminTest) + + require.NoError(t, err) + + // deserialization + newAdminForm := types.AdminForm{} + + msgs, err := newAdminForm.Deserialize(ctxAdminTest, value) + + require.NoError(t, err) + + updatedAdminForm := msgs.(types.AdminForm) + + require.Equal(t, adminFormID, updatedAdminForm.FormID) + require.Equal(t, adminFormList, updatedAdminForm.AdminList) +} diff --git a/contracts/evoting/json/adminForm.go b/contracts/evoting/json/adminForm.go new file mode 100644 index 000000000..64212dec4 --- /dev/null +++ b/contracts/evoting/json/adminForm.go @@ -0,0 +1,50 @@ +package json + +import ( + "github.com/c4dt/d-voting/contracts/evoting/types" + "go.dedis.ch/dela/serde" + "golang.org/x/xerrors" +) + +type adminFormFormat struct{} + +func (adminFormFormat) Encode(ctx serde.Context, message serde.Message) ([]byte, error) { + switch m := message.(type) { + case types.AdminForm: + adminFormJSON := AdminFormJSON{ + FormID: m.FormID, + AdminList: m.AdminList, + } + + buff, err := ctx.Marshal(&adminFormJSON) + if err != nil { + return nil, xerrors.Errorf("failed to marshal form: %v", err) + } + + return buff, nil + default: + return nil, xerrors.Errorf("Unknown format: %T", message) + } +} + +func (adminFormFormat) Decode(ctx serde.Context, data []byte) (serde.Message, error) { + var adminFormJSON AdminFormJSON + + err := ctx.Unmarshal(data, &adminFormJSON) + if err != nil { + return nil, xerrors.Errorf("failed to unmarshal form: %v", err) + } + + return types.AdminForm{ + FormID: adminFormJSON.FormID, + AdminList: adminFormJSON.AdminList, + }, nil +} + +type AdminFormJSON struct { + // FormID is the hex-encoded SHA265 of the Tx ID that creates the form + FormID string + + // List of SCIPER with admin rights + AdminList []int +} diff --git a/contracts/evoting/json/mod.go b/contracts/evoting/json/mod.go index c9845338a..be6023adc 100644 --- a/contracts/evoting/json/mod.go +++ b/contracts/evoting/json/mod.go @@ -12,4 +12,5 @@ func init() { types.RegisterSuffragiaFormat(serde.FormatJSON, suffragiaFormat{}) types.RegisterCiphervoteFormat(serde.FormatJSON, ciphervoteFormat{}) types.RegisterTransactionFormat(serde.FormatJSON, transactionFormat{}) + types.RegisterAdminFormFormat(serde.FormatJSON, adminFormFormat{}) } diff --git a/contracts/evoting/types/admin.go b/contracts/evoting/types/admin.go new file mode 100644 index 000000000..dd5ab0462 --- /dev/null +++ b/contracts/evoting/types/admin.go @@ -0,0 +1,71 @@ +package types + +import ( + "encoding/hex" + "go.dedis.ch/dela/core/store" + "go.dedis.ch/dela/serde" + "go.dedis.ch/dela/serde/registry" + "golang.org/x/xerrors" +) + +var adminFormFormat = registry.NewSimpleRegistry() + +func RegisterAdminFormFormat(format serde.Format, engine serde.FormatEngine) { + adminFormFormat.Register(format, engine) +} + +type AdminForm struct { + // FormID is the hex-encoded SHA265 of the Tx ID that creates the form + FormID string + + // List of SCIPER with admin rights + AdminList []int +} + +func (af AdminForm) Serialize(ctx serde.Context) ([]byte, error) { + format := adminFormFormat.Get(ctx.GetFormat()) + + data, err := format.Encode(ctx, af) + if err != nil { + return nil, xerrors.Errorf("Failed to encode AdminForm: %v", err) + } + + return data, nil +} + +func (af AdminForm) Deserialize(ctx serde.Context, data []byte) (serde.Message, error) { + format := adminFormFormat.Get(ctx.GetFormat()) + + message, err := format.Decode(ctx, data) + if err != nil { + return nil, xerrors.Errorf("Failed to decode: %v", err) + } + + return message, nil +} + +func AdminFormFromStore(ctx serde.Context, adminFormFac serde.Factory, adminFormIDHex string, store store.Readable) (AdminForm, error) { + adminForm := AdminForm{} + + adminFormIDBuf, err := hex.DecodeString(adminFormIDHex) + if err != nil { + return adminForm, xerrors.Errorf("Failed to decode adminFormIDHex: %v", err) + } + + adminFormBuf, err := store.Get(adminFormIDBuf) + if err != nil { + return adminForm, xerrors.Errorf("While getting data for form: %v", err) + } + if len(adminFormBuf) == 0 { + return adminForm, xerrors.Errorf("No form found") + } + + message, err := adminFormFac.Deserialize(ctx, adminFormBuf) + + adminForm, ok := message.(AdminForm) + if !ok { + return adminForm, xerrors.Errorf("Wrong message type: %T", message) + } + + return adminForm, nil +} diff --git a/web/backend/src/controllers/dela.ts b/web/backend/src/controllers/dela.ts index 8c725f9fc..3afd08a67 100644 --- a/web/backend/src/controllers/dela.ts +++ b/web/backend/src/controllers/dela.ts @@ -265,6 +265,5 @@ delaRouter.use('/*', (req, res) => { } const dataStr = JSON.stringify(bodyData); - sendToDela(dataStr, req, res); }); From b9e2bf704cdc75ff1b41816a977bd80a7e76b6d0 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Mon, 25 Mar 2024 16:20:10 +0100 Subject: [PATCH 003/114] patch linting --- contracts/evoting/types/admin.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contracts/evoting/types/admin.go b/contracts/evoting/types/admin.go index dd5ab0462..e5d26706e 100644 --- a/contracts/evoting/types/admin.go +++ b/contracts/evoting/types/admin.go @@ -61,6 +61,9 @@ func AdminFormFromStore(ctx serde.Context, adminFormFac serde.Factory, adminForm } message, err := adminFormFac.Deserialize(ctx, adminFormBuf) + if err != nil { + return adminForm, xerrors.Errorf("While deserializing: %v", err) + } adminForm, ok := message.(AdminForm) if !ok { From f35632ef392e05138cb9c53c0ee82938390a2f6e Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 27 Mar 2024 08:58:57 +0100 Subject: [PATCH 004/114] push working changes there --- contracts/evoting/admin_test.go | 3 +++ contracts/evoting/controller/action.go | 2 +- contracts/evoting/evoting.go | 2 ++ contracts/evoting/json/transaction.go | 6 +++--- contracts/evoting/mod_test.go | 2 +- contracts/evoting/types/transactions.go | 2 +- proxy/election.go | 2 +- proxy/types/election.go | 2 +- web/backend/src/controllers/dela.ts | 7 +++++-- 9 files changed, 18 insertions(+), 10 deletions(-) diff --git a/contracts/evoting/admin_test.go b/contracts/evoting/admin_test.go index 14da46317..9c1121d13 100644 --- a/contracts/evoting/admin_test.go +++ b/contracts/evoting/admin_test.go @@ -21,6 +21,9 @@ func init() { ctxAdminTest = sjson.NewContext() } +// This test create an Admin Form structure which is then serialized and +// deserialized to check whether these operations work as intended. +// Given an AdminForm we should retrieve the same AdminForm after these operations. func TestAdmin_serde(t *testing.T) { adminFormID := "myID" adminFormList := []int{111111, 222222, 333333, 123456} diff --git a/contracts/evoting/controller/action.go b/contracts/evoting/controller/action.go index 1b674e716..37da24e49 100644 --- a/contracts/evoting/controller/action.go +++ b/contracts/evoting/controller/action.go @@ -593,7 +593,7 @@ func setupSimpleForm(ctx node.Context, secret kyber.Scalar, proxyAddr1 string, createSimpleFormRequest := ptypes.CreateFormRequest{ Configuration: configuration, - AdminID: "adminId", + SciperID: "SciperID", } signed, err := createSignedRequest(secret, createSimpleFormRequest) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 082597c31..96c379cb6 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -60,6 +60,8 @@ func (e evotingCommand) createForm(snap store.Snapshot, step execution.Step) err return xerrors.Errorf(errWrongTx, msg) } + println("SCIPERRRRR: %i", tx.SciperID) + rosterBuf, err := snap.Get(viewchange.GetRosterKey()) if err != nil { return xerrors.Errorf("failed to get roster") diff --git a/contracts/evoting/json/transaction.go b/contracts/evoting/json/transaction.go index 1093416df..36075eed4 100644 --- a/contracts/evoting/json/transaction.go +++ b/contracts/evoting/json/transaction.go @@ -21,7 +21,7 @@ func (transactionFormat) Encode(ctx serde.Context, msg serde.Message) ([]byte, e case types.CreateForm: ce := CreateFormJSON{ Configuration: t.Configuration, - AdminID: t.AdminID, + SciperID: t.SciperID, } m = TransactionJSON{CreateForm: &ce} @@ -143,7 +143,7 @@ func (transactionFormat) Decode(ctx serde.Context, data []byte) (serde.Message, case m.CreateForm != nil: return types.CreateForm{ Configuration: m.CreateForm.Configuration, - AdminID: m.CreateForm.AdminID, + SciperID: m.CreateForm.SciperID, }, nil case m.OpenForm != nil: return types.OpenForm{ @@ -211,7 +211,7 @@ type TransactionJSON struct { // CreateFormJSON is the JSON representation of a CreateForm transaction type CreateFormJSON struct { Configuration types.Configuration - AdminID string + SciperID string } // OpenFormJSON is the JSON representation of a OpenForm transaction diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 994523d0f..e32c204b6 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -120,7 +120,7 @@ func TestCommand_CreateForm(t *testing.T) { } createForm := types.CreateForm{ - AdminID: "dummyAdminID", + SciperID: "dummyAdminID", } data, err := createForm.Serialize(ctx) diff --git a/contracts/evoting/types/transactions.go b/contracts/evoting/types/transactions.go index 48ff3733d..bfd6d5588 100644 --- a/contracts/evoting/types/transactions.go +++ b/contracts/evoting/types/transactions.go @@ -92,7 +92,7 @@ func (t TransactionFactory) Deserialize(ctx serde.Context, data []byte) (serde.M // - implements serde.Message type CreateForm struct { Configuration Configuration - AdminID string + SciperID string } // Serialize implements serde.Message diff --git a/proxy/election.go b/proxy/election.go index 7429e04ce..27b4a6682 100644 --- a/proxy/election.go +++ b/proxy/election.go @@ -83,7 +83,7 @@ func (h *form) NewForm(w http.ResponseWriter, r *http.Request) { createForm := types.CreateForm{ Configuration: req.Configuration, - AdminID: req.AdminID, + SciperID: req.SciperID, } // serialize the transaction diff --git a/proxy/types/election.go b/proxy/types/election.go index a6a8b5cfc..25c39bf0b 100644 --- a/proxy/types/election.go +++ b/proxy/types/election.go @@ -6,7 +6,7 @@ import ( // CreateFormRequest defines the HTTP request for creating a form type CreateFormRequest struct { - AdminID string + SciperID string Configuration etypes.Configuration } diff --git a/web/backend/src/controllers/dela.ts b/web/backend/src/controllers/dela.ts index 3afd08a67..7ce9e374a 100644 --- a/web/backend/src/controllers/dela.ts +++ b/web/backend/src/controllers/dela.ts @@ -253,17 +253,20 @@ delaRouter.use('/*', (req, res) => { if (process.env.REACT_APP_RANDOMIZE_VOTE_ID === 'true') { // DEBUG: this is only for debugging and needs to be replaced before production console.warn('DEV CODE - randomizing the SCIPER ID to allow for unlimited votes'); - bodyData.UserID = makeid(10); + bodyData.UserID = makeid(10); //VoterID } else { // We must set the UserID to know who this ballot is associated to. This is // only needed to allow users to cast multiple ballots, where only the last // ballot is taken into account. To preserve anonymity, the web-backend could // translate UserIDs to another random ID. - bodyData.UserID = req.session.userId.toString(); + bodyData.UserID = req.session.userId.toString(); // VoterID } } + bodyData.SciperID = req.session.userId.toString(); //UserID + const dataStr = JSON.stringify(bodyData); + sendToDela(dataStr, req, res); }); From 2a28803f14b925f6073b66564fa18182865e54ad Mon Sep 17 00:00:00 2001 From: Maxime <61186830+MaximeZmt@users.noreply.github.com> Date: Wed, 27 Mar 2024 09:02:09 +0100 Subject: [PATCH 005/114] Update .gitignore --- .gitignore | 2 -- 1 file changed, 2 deletions(-) diff --git a/.gitignore b/.gitignore index 613ac6555..361116e9b 100644 --- a/.gitignore +++ b/.gitignore @@ -19,5 +19,3 @@ dela/ bin/ nodes/ cookies.txt - -.tool-versions \ No newline at end of file From a1ec49afa503ab893b7d4525b570dfbfdcadba93 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 27 Mar 2024 09:05:42 +0100 Subject: [PATCH 006/114] address changes --- .gitignore | 4 +--- contracts/evoting/admin_test.go | 3 +++ web/backend/src/controllers/dela.ts | 1 + 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 613ac6555..5d296b0ec 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,4 @@ deb-package/dist/** dela/ bin/ nodes/ -cookies.txt - -.tool-versions \ No newline at end of file +cookies.txt \ No newline at end of file diff --git a/contracts/evoting/admin_test.go b/contracts/evoting/admin_test.go index 14da46317..9c1121d13 100644 --- a/contracts/evoting/admin_test.go +++ b/contracts/evoting/admin_test.go @@ -21,6 +21,9 @@ func init() { ctxAdminTest = sjson.NewContext() } +// This test create an Admin Form structure which is then serialized and +// deserialized to check whether these operations work as intended. +// Given an AdminForm we should retrieve the same AdminForm after these operations. func TestAdmin_serde(t *testing.T) { adminFormID := "myID" adminFormList := []int{111111, 222222, 333333, 123456} diff --git a/web/backend/src/controllers/dela.ts b/web/backend/src/controllers/dela.ts index 3afd08a67..8c725f9fc 100644 --- a/web/backend/src/controllers/dela.ts +++ b/web/backend/src/controllers/dela.ts @@ -265,5 +265,6 @@ delaRouter.use('/*', (req, res) => { } const dataStr = JSON.stringify(bodyData); + sendToDela(dataStr, req, res); }); From f35398f0e040c9dc851763188f0147631595ec40 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 27 Mar 2024 09:11:00 +0100 Subject: [PATCH 007/114] change comment formatting --- contracts/evoting/admin_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/evoting/admin_test.go b/contracts/evoting/admin_test.go index 9c1121d13..dee5ddde4 100644 --- a/contracts/evoting/admin_test.go +++ b/contracts/evoting/admin_test.go @@ -23,7 +23,7 @@ func init() { // This test create an Admin Form structure which is then serialized and // deserialized to check whether these operations work as intended. -// Given an AdminForm we should retrieve the same AdminForm after these operations. +// Serialization/Deserialization of an AdminForm should not change its values. func TestAdmin_serde(t *testing.T) { adminFormID := "myID" adminFormList := []int{111111, 222222, 333333, 123456} From 823103a4bf5abee6bedb8aa3cdcf59bd6d5eb0bd Mon Sep 17 00:00:00 2001 From: Maxime <61186830+MaximeZmt@users.noreply.github.com> Date: Wed, 27 Mar 2024 09:14:52 +0100 Subject: [PATCH 008/114] Update .gitignore edit .gitignore to add new line at the end as before --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5d296b0ec..361116e9b 100644 --- a/.gitignore +++ b/.gitignore @@ -18,4 +18,4 @@ deb-package/dist/** dela/ bin/ nodes/ -cookies.txt \ No newline at end of file +cookies.txt From 4a972d03a708fc1033d84b74ca93e434c769ea47 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 27 Mar 2024 09:25:38 +0100 Subject: [PATCH 009/114] make encode function logic simpler --- contracts/evoting/json/adminForm.go | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/contracts/evoting/json/adminForm.go b/contracts/evoting/json/adminForm.go index 64212dec4..29255548b 100644 --- a/contracts/evoting/json/adminForm.go +++ b/contracts/evoting/json/adminForm.go @@ -9,22 +9,22 @@ import ( type adminFormFormat struct{} func (adminFormFormat) Encode(ctx serde.Context, message serde.Message) ([]byte, error) { - switch m := message.(type) { - case types.AdminForm: - adminFormJSON := AdminFormJSON{ - FormID: m.FormID, - AdminList: m.AdminList, - } - - buff, err := ctx.Marshal(&adminFormJSON) - if err != nil { - return nil, xerrors.Errorf("failed to marshal form: %v", err) - } - - return buff, nil - default: + adminForm, ok := message.(types.AdminForm) + if !ok { return nil, xerrors.Errorf("Unknown format: %T", message) } + + adminFormJSON := AdminFormJSON{ + FormID: adminForm.FormID, + AdminList: adminForm.AdminList, + } + + buff, err := ctx.Marshal(&adminFormJSON) + if err != nil { + return nil, xerrors.Errorf("failed to marshal form: %v", err) + } + + return buff, nil } func (adminFormFormat) Decode(ctx serde.Context, data []byte) (serde.Message, error) { From 3ad2457e6ec9726bad4e8b2367dd7c668d10fe08 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 3 Apr 2024 09:43:16 +0200 Subject: [PATCH 010/114] change dela id --- web/backend/src/controllers/dela.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/backend/src/controllers/dela.ts b/web/backend/src/controllers/dela.ts index 7ce9e374a..f46c22d34 100644 --- a/web/backend/src/controllers/dela.ts +++ b/web/backend/src/controllers/dela.ts @@ -253,14 +253,14 @@ delaRouter.use('/*', (req, res) => { if (process.env.REACT_APP_RANDOMIZE_VOTE_ID === 'true') { // DEBUG: this is only for debugging and needs to be replaced before production console.warn('DEV CODE - randomizing the SCIPER ID to allow for unlimited votes'); - bodyData.UserID = makeid(10); //VoterID + bodyData.VoterID = makeid(10); } else { // We must set the UserID to know who this ballot is associated to. This is // only needed to allow users to cast multiple ballots, where only the last // ballot is taken into account. To preserve anonymity, the web-backend could // translate UserIDs to another random ID. - bodyData.UserID = req.session.userId.toString(); // VoterID + bodyData.VoterID = req.session.userId.toString(); } } From 0c596c83feaa53772e5e9fae2940665a20196e2f Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 3 Apr 2024 16:01:38 +0200 Subject: [PATCH 011/114] update UserID to VoterID --- contracts/evoting/controller/action.go | 12 ++++++------ contracts/evoting/evoting.go | 2 +- contracts/evoting/json/suffragia.go | 6 +++--- contracts/evoting/json/transaction.go | 10 +++++----- contracts/evoting/types/election.go | 2 +- contracts/evoting/types/suffragia.go | 12 ++++++------ contracts/evoting/types/transactions.go | 6 +++--- docs/api.md | 2 +- docs/smart_contract.md | 6 +++--- docs/verifiability_doc.md | 4 ++-- integration/ballot.go | 24 ++++++++++++------------ integration/form.go | 4 ++-- integration/performance_test.go | 10 +++++----- proxy/election.go | 8 ++++---- proxy/types/election.go | 2 +- 15 files changed, 55 insertions(+), 55 deletions(-) diff --git a/contracts/evoting/controller/action.go b/contracts/evoting/controller/action.go index 37da24e49..df90a238c 100644 --- a/contracts/evoting/controller/action.go +++ b/contracts/evoting/controller/action.go @@ -352,8 +352,8 @@ func (a *scenarioTestAction) Execute(ctx node.Context) error { } castVoteRequest := ptypes.CastVoteRequest{ - UserID: "user1", - Ballot: ballot1, + VoterID: "user1", + Ballot: ballot1, } signed, err := createSignedRequest(secret, castVoteRequest) @@ -377,8 +377,8 @@ func (a *scenarioTestAction) Execute(ctx node.Context) error { } castVoteRequest = ptypes.CastVoteRequest{ - UserID: "user2", - Ballot: ballot2, + VoterID: "user2", + Ballot: ballot2, } signed, err = createSignedRequest(secret, castVoteRequest) @@ -402,8 +402,8 @@ func (a *scenarioTestAction) Execute(ctx node.Context) error { } castVoteRequest = ptypes.CastVoteRequest{ - UserID: "user3", - Ballot: ballot3, + VoterID: "user3", + Ballot: ballot3, } signed, err = createSignedRequest(secret, castVoteRequest) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 96c379cb6..0f359e71b 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -232,7 +232,7 @@ func (e evotingCommand) castVote(snap store.Snapshot, step execution.Step) error len(tx.Ballot), form.ChunksPerBallot()) } - err = form.CastVote(e.context, snap, tx.UserID, tx.Ballot) + err = form.CastVote(e.context, snap, tx.VoterID, tx.Ballot) if err != nil { return xerrors.Errorf("couldn't cast vote: %v", err) } diff --git a/contracts/evoting/json/suffragia.go b/contracts/evoting/json/suffragia.go index 424c83910..221a06511 100644 --- a/contracts/evoting/json/suffragia.go +++ b/contracts/evoting/json/suffragia.go @@ -42,7 +42,7 @@ func (suffragiaFormat) Decode(ctx serde.Context, data []byte) (serde.Message, er // SuffragiaJSON defines the JSON representation of a suffragia. type SuffragiaJSON struct { - UserIDs []string + VoterIDs []string Ciphervotes []json.RawMessage } @@ -58,7 +58,7 @@ func encodeSuffragia(ctx serde.Context, suffragia types.Suffragia) (SuffragiaJSO ciphervotes[i] = buff } return SuffragiaJSON{ - UserIDs: suffragia.UserIDs, + VoterIDs: suffragia.VoterIDs, Ciphervotes: ciphervotes, }, nil } @@ -89,7 +89,7 @@ func decodeSuffragia(ctx serde.Context, suffragiaJSON SuffragiaJSON) (types.Suff } res = types.Suffragia{ - UserIDs: suffragiaJSON.UserIDs, + VoterIDs: suffragiaJSON.VoterIDs, Ciphervotes: ciphervotes, } diff --git a/contracts/evoting/json/transaction.go b/contracts/evoting/json/transaction.go index 36075eed4..b4725c7b2 100644 --- a/contracts/evoting/json/transaction.go +++ b/contracts/evoting/json/transaction.go @@ -39,7 +39,7 @@ func (transactionFormat) Encode(ctx serde.Context, msg serde.Message) ([]byte, e cv := CastVoteJSON{ FormID: t.FormID, - UserID: t.UserID, + VoterID: t.VoterID, Ciphervote: ballot, } @@ -222,7 +222,7 @@ type OpenFormJSON struct { // CastVoteJSON is the JSON representation of a CastVote transaction type CastVoteJSON struct { FormID string - UserID string + VoterID string Ciphervote json.RawMessage } @@ -285,9 +285,9 @@ func decodeCastVote(ctx serde.Context, m CastVoteJSON) (serde.Message, error) { } return types.CastVote{ - FormID: m.FormID, - UserID: m.UserID, - Ballot: ciphervote, + FormID: m.FormID, + VoterID: m.VoterID, + Ballot: ciphervote, }, nil } diff --git a/contracts/evoting/types/election.go b/contracts/evoting/types/election.go index bc2d41383..90858e0a4 100644 --- a/contracts/evoting/types/election.go +++ b/contracts/evoting/types/election.go @@ -275,7 +275,7 @@ func (s *Form) Suffragia(ctx serde.Context, rd store.Readable) (Suffragia, error return suff, xerrors.Errorf("couldn't unmarshal ballots block in cast: %v", err) } suffTmp := msg.(Suffragia) - for i, uid := range suffTmp.UserIDs { + for i, uid := range suffTmp.VoterIDs { suff.CastVote(uid, suffTmp.Ciphervotes[i]) } } diff --git a/contracts/evoting/types/suffragia.go b/contracts/evoting/types/suffragia.go index c8a507440..62f25bc65 100644 --- a/contracts/evoting/types/suffragia.go +++ b/contracts/evoting/types/suffragia.go @@ -19,7 +19,7 @@ func RegisterSuffragiaFormat(format serde.Format, engine serde.FormatEngine) { } type Suffragia struct { - UserIDs []string + VoterIDs []string Ciphervotes []Ciphervote } @@ -36,22 +36,22 @@ func (s Suffragia) Serialize(ctx serde.Context) ([]byte, error) { } // CastVote adds a new vote and its associated user or updates a user's vote. -func (s *Suffragia) CastVote(userID string, ciphervote Ciphervote) { - for i, u := range s.UserIDs { - if u == userID { +func (s *Suffragia) CastVote(voterID string, ciphervote Ciphervote) { + for i, u := range s.VoterIDs { + if u == voterID { s.Ciphervotes[i] = ciphervote return } } - s.UserIDs = append(s.UserIDs, userID) + s.VoterIDs = append(s.VoterIDs, voterID) s.Ciphervotes = append(s.Ciphervotes, ciphervote.Copy()) } // Hash returns the hash of this list of ballots. func (s *Suffragia) Hash(ctx serde.Context) ([]byte, error) { h := sha256.New() - for i, u := range s.UserIDs { + for i, u := range s.VoterIDs { h.Write([]byte(u)) buf, err := s.Ciphervotes[i].Serialize(ctx) if err != nil { diff --git a/contracts/evoting/types/transactions.go b/contracts/evoting/types/transactions.go index bfd6d5588..c53ad0fdc 100644 --- a/contracts/evoting/types/transactions.go +++ b/contracts/evoting/types/transactions.go @@ -132,9 +132,9 @@ func (oe OpenForm) Serialize(ctx serde.Context) ([]byte, error) { // - implements serde.Message type CastVote struct { // FormID is hex-encoded - FormID string - UserID string - Ballot Ciphervote + FormID string + VoterID string + Ballot Ciphervote } // Serialize implements serde.Message diff --git a/docs/api.md b/docs/api.md index 4186c2104..bd8fc1264 100644 --- a/docs/api.md +++ b/docs/api.md @@ -183,7 +183,7 @@ Return: ```json { - "UserID": "", + "VoterID": "", "Ballot": [ { "K": "", diff --git a/docs/smart_contract.md b/docs/smart_contract.md index 52a2dd1a6..b1f68ddba 100644 --- a/docs/smart_contract.md +++ b/docs/smart_contract.md @@ -71,7 +71,7 @@ This transaction requires the following 3 parameters: 1. `actor` of type dkg.Actor 2. `formID` (see Create Form above) -3. `userID` of the voter +3. `VoterID` of the voter 4. `vote` to be casted Key / Value pairs sent in the transaction in order to create a form: @@ -88,7 +88,7 @@ where: evoting.CastVoteArg = "evoting:cast_vote" castVoteBuf = a marshalled version of types.CastVoteTransaction{ FormID: hex.EncodeToString(formID), - UserID: userID, + VoterID: VoterID, Ballot: ballot, // a vote encrypted by the actor } evoting.CmdArg = "evoting:command" @@ -113,7 +113,7 @@ where: evoting.CloseFormArg = "evoting:close_form" closeFormBuf = marshalled version of types.CloseFormTransaction{ FormID: hex.EncodeToString(formID), - UserID: adminID, + VoterID: adminID, } evoting.CmdArg = "evoting:command" evoting.CmdCloseForm = "CLOSE_FORM" diff --git a/docs/verifiability_doc.md b/docs/verifiability_doc.md index 156214119..571cb1e23 100755 --- a/docs/verifiability_doc.md +++ b/docs/verifiability_doc.md @@ -20,7 +20,7 @@ The current d-voting [latest commit](https://github.com/c4dt/d-voting/commit/39a Note over User: encrypt ballot via Elgamal encryption using electionPubKey Note over User, Backend: data = encrypted ballot Note over Backend: check role and sign payload. - Note over Backend: add userID inside payload. + Note over Backend: add VoterID inside payload. Note over Backend: sign = kyber.sign.schnorr.sign(edCurve, scalar, hash); Backend ->>+ NodeX: POST /evoting/elections/ Note over Backend, NodeX: data: {"Payload": dataStrB64, "Signature": ""} @@ -96,7 +96,7 @@ sequenceDiagram Note over User: generate hash of encrypted ballot and show to user Note over User, Backend: data = encrypted ballot Note over Backend: check role and sign payload. - Note over Backend: add userID inside payload. + Note over Backend: add VoterID inside payload. Note over Backend: sign = kyber.sign.schnorr.sign(edCurve, scalar, hash); Backend ->>+ NodeX: POST /evoting/elections/ Note over Backend, NodeX: data: {"Payload": dataStrB64, "Signature": ""} diff --git a/integration/ballot.go b/integration/ballot.go index 9f24b8c44..3fec5d5bb 100644 --- a/integration/ballot.go +++ b/integration/ballot.go @@ -66,12 +66,12 @@ func castVotesRandomly(m txManager, actor dkg.Actor, form types.Form, return nil, xerrors.Errorf("failed to marshallBallot: %v", err) } - userID := "user " + strconv.Itoa(i) + voterID := "user " + strconv.Itoa(i) castVote := types.CastVote{ - FormID: form.FormID, - UserID: userID, - Ballot: ciphervote, + FormID: form.FormID, + VoterID: voterID, + Ballot: ciphervote, } data, err := castVote.Serialize(serdecontext) @@ -122,12 +122,12 @@ func castBadVote(m txManager, actor dkg.Actor, form types.Form, numberOfBadVotes return xerrors.Errorf("failed to marshallBallot: %v", err) } - userID := "badUser " + strconv.Itoa(i) + voterID := "badUser " + strconv.Itoa(i) castVote := types.CastVote{ - FormID: form.FormID, - UserID: userID, - Ballot: ciphervote, + FormID: form.FormID, + VoterID: voterID, + Ballot: ciphervote, } data, err := castVote.Serialize(serdecontext) @@ -348,8 +348,8 @@ func castVotesLoad(numVotesPerSec, numSec, BallotSize, chunksPerBallot int, form idx := i*numVotesPerSec + j randomproxy := proxyArray[rand.Intn(proxyCount)] castVoteRequest := ptypes.CastVoteRequest{ - UserID: "user" + strconv.Itoa(idx), - Ballot: ballot, + VoterID: "user" + strconv.Itoa(idx), + Ballot: ballot, } // cast asynchrounously and increment includedVoteCount // if the cast was succesfull @@ -450,8 +450,8 @@ func castVotesScenario(numVotes, BallotSize, chunksPerBallot int, formID, conten require.NoError(t, err) castVoteRequest := ptypes.CastVoteRequest{ - UserID: "user" + strconv.Itoa(i+1), - Ballot: ballot, + VoterID: "user" + strconv.Itoa(i+1), + Ballot: ballot, } randomproxy := proxyArray[rand.Intn(len(proxyArray))] diff --git a/integration/form.go b/integration/form.go index 502af5b5d..c52a44ee1 100644 --- a/integration/form.go +++ b/integration/form.go @@ -40,7 +40,7 @@ func createForm(m txManager, title string, admin string) ([]byte, error) { createForm := types.CreateForm{ Configuration: configuration, - AdminID: admin, + SciperID: admin, } data, err := createForm.Serialize(serdecontext) @@ -75,7 +75,7 @@ func createFormScenario(contentType, proxy string, secret kyber.Scalar, t *testi createSimpleFormRequest := ptypes.CreateFormRequest{ Configuration: configuration, - AdminID: "adminId", + SciperID: "adminId", } signed, err := createSignedRequest(secret, createSimpleFormRequest) diff --git a/integration/performance_test.go b/integration/performance_test.go index 9d4e542a9..8d76c037c 100644 --- a/integration/performance_test.go +++ b/integration/performance_test.go @@ -219,7 +219,7 @@ func createFormNChunks(m txManager, title types.Title, admin string, numChunks i createForm := types.CreateForm{ Configuration: configuration, - AdminID: admin, + SciperID: admin, } data, err := createForm.Serialize(serdecontext) @@ -272,12 +272,12 @@ func castVotesNChunks(m txManager, actor dkg.Actor, form types.Form, start := time.Now() for i := 0; i < numberOfVotes; i++ { - userID := "user " + strconv.Itoa(i) + voterID := "user " + strconv.Itoa(i) castVote := types.CastVote{ - FormID: form.FormID, - UserID: userID, - Ballot: ballot, + FormID: form.FormID, + VoterID: voterID, + Ballot: ballot, } data, err := castVote.Serialize(serdecontext) diff --git a/proxy/election.go b/proxy/election.go index 27b4a6682..e5bccb0b4 100644 --- a/proxy/election.go +++ b/proxy/election.go @@ -192,9 +192,9 @@ func (h *form) NewFormVote(w http.ResponseWriter, r *http.Request) { } castVote := types.CastVote{ - FormID: formID, - UserID: req.UserID, - Ballot: ciphervote, + FormID: formID, + VoterID: req.VoterID, + Ballot: ciphervote, } // serialize the vote @@ -451,7 +451,7 @@ func (h *form) Form(w http.ResponseWriter, r *http.Request) { Roster: roster, ChunksPerBallot: form.ChunksPerBallot(), BallotSize: form.BallotSize, - Voters: suff.UserIDs, + Voters: suff.VoterIDs, } txnmanager.SendResponse(w, response) diff --git a/proxy/types/election.go b/proxy/types/election.go index 25c39bf0b..c54b13bb7 100644 --- a/proxy/types/election.go +++ b/proxy/types/election.go @@ -18,7 +18,7 @@ type CreateFormResponse struct { // CastVoteRequest defines the HTTP request for casting a vote type CastVoteRequest struct { - UserID string + VoterID string // Marshalled representation of Ciphervote. It contains []{K:,C:} Ballot CiphervoteJSON } From d7ffa0e5ea79bef3ca563ca0227662c23291aca2 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 3 Apr 2024 17:15:45 +0200 Subject: [PATCH 012/114] happy linter --- contracts/evoting/mod_test.go | 6 +++--- web/backend/src/controllers/dela.ts | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index e32c204b6..8c4055c84 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -175,8 +175,8 @@ func TestCommand_CastVote(t *testing.T) { initMetrics() castVote := types.CastVote{ - FormID: fakeFormID, - UserID: "dummyUserId", + FormID: fakeFormID, + VoterID: "dummyVoterId", Ballot: types.Ciphervote{types.EGPair{ K: suite.Point(), C: suite.Point(), @@ -300,7 +300,7 @@ func TestCommand_CastVote(t *testing.T) { require.NoError(t, err) require.True(t, castVote.Ballot.Equal(suff.Ciphervotes[0])) - require.Equal(t, castVote.UserID, suff.UserIDs[0]) + require.Equal(t, castVote.VoterID, suff.VoterIDs[0]) require.Equal(t, float64(form.BallotCount), testutil.ToFloat64(PromFormBallots)) } diff --git a/web/backend/src/controllers/dela.ts b/web/backend/src/controllers/dela.ts index f46c22d34..edffccf44 100644 --- a/web/backend/src/controllers/dela.ts +++ b/web/backend/src/controllers/dela.ts @@ -264,7 +264,8 @@ delaRouter.use('/*', (req, res) => { } } - bodyData.SciperID = req.session.userId.toString(); //UserID + //UserID + bodyData.SciperID = req.session.userId.toString(); const dataStr = JSON.stringify(bodyData); From b218c64768905a29deb82bf3d300d954b38e8e7c Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 3 Apr 2024 17:22:01 +0200 Subject: [PATCH 013/114] happy linter bis --- web/backend/src/controllers/dela.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/backend/src/controllers/dela.ts b/web/backend/src/controllers/dela.ts index edffccf44..4742f5ac8 100644 --- a/web/backend/src/controllers/dela.ts +++ b/web/backend/src/controllers/dela.ts @@ -264,7 +264,7 @@ delaRouter.use('/*', (req, res) => { } } - //UserID + // UserID bodyData.SciperID = req.session.userId.toString(); const dataStr = JSON.stringify(bodyData); From 399d0f0bb8ffaaaaa4396d3f332ed8dc38c276c3 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 3 Apr 2024 17:46:00 +0200 Subject: [PATCH 014/114] change SciperID to UserID --- contracts/evoting/controller/action.go | 2 +- contracts/evoting/evoting.go | 2 +- contracts/evoting/json/transaction.go | 6 +++--- contracts/evoting/mod_test.go | 2 +- contracts/evoting/types/transactions.go | 2 +- integration/form.go | 4 ++-- integration/performance_test.go | 2 +- proxy/election.go | 2 +- proxy/types/election.go | 2 +- web/backend/src/controllers/dela.ts | 4 ++-- 10 files changed, 14 insertions(+), 14 deletions(-) diff --git a/contracts/evoting/controller/action.go b/contracts/evoting/controller/action.go index df90a238c..b62c03f1c 100644 --- a/contracts/evoting/controller/action.go +++ b/contracts/evoting/controller/action.go @@ -593,7 +593,7 @@ func setupSimpleForm(ctx node.Context, secret kyber.Scalar, proxyAddr1 string, createSimpleFormRequest := ptypes.CreateFormRequest{ Configuration: configuration, - SciperID: "SciperID", + UserID: "UserID", } signed, err := createSignedRequest(secret, createSimpleFormRequest) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 0f359e71b..746d044f9 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -60,7 +60,7 @@ func (e evotingCommand) createForm(snap store.Snapshot, step execution.Step) err return xerrors.Errorf(errWrongTx, msg) } - println("SCIPERRRRR: %i", tx.SciperID) + println("SCIPERRRRR: %i", tx.UserID) rosterBuf, err := snap.Get(viewchange.GetRosterKey()) if err != nil { diff --git a/contracts/evoting/json/transaction.go b/contracts/evoting/json/transaction.go index b4725c7b2..d0d79dd95 100644 --- a/contracts/evoting/json/transaction.go +++ b/contracts/evoting/json/transaction.go @@ -21,7 +21,7 @@ func (transactionFormat) Encode(ctx serde.Context, msg serde.Message) ([]byte, e case types.CreateForm: ce := CreateFormJSON{ Configuration: t.Configuration, - SciperID: t.SciperID, + UserID: t.UserID, } m = TransactionJSON{CreateForm: &ce} @@ -143,7 +143,7 @@ func (transactionFormat) Decode(ctx serde.Context, data []byte) (serde.Message, case m.CreateForm != nil: return types.CreateForm{ Configuration: m.CreateForm.Configuration, - SciperID: m.CreateForm.SciperID, + UserID: m.CreateForm.UserID, }, nil case m.OpenForm != nil: return types.OpenForm{ @@ -211,7 +211,7 @@ type TransactionJSON struct { // CreateFormJSON is the JSON representation of a CreateForm transaction type CreateFormJSON struct { Configuration types.Configuration - SciperID string + UserID string } // OpenFormJSON is the JSON representation of a OpenForm transaction diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 8c4055c84..eea18a7a4 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -120,7 +120,7 @@ func TestCommand_CreateForm(t *testing.T) { } createForm := types.CreateForm{ - SciperID: "dummyAdminID", + UserID: "dummyAdminID", } data, err := createForm.Serialize(ctx) diff --git a/contracts/evoting/types/transactions.go b/contracts/evoting/types/transactions.go index c53ad0fdc..df9930c85 100644 --- a/contracts/evoting/types/transactions.go +++ b/contracts/evoting/types/transactions.go @@ -92,7 +92,7 @@ func (t TransactionFactory) Deserialize(ctx serde.Context, data []byte) (serde.M // - implements serde.Message type CreateForm struct { Configuration Configuration - SciperID string + UserID string } // Serialize implements serde.Message diff --git a/integration/form.go b/integration/form.go index c52a44ee1..ee8301865 100644 --- a/integration/form.go +++ b/integration/form.go @@ -40,7 +40,7 @@ func createForm(m txManager, title string, admin string) ([]byte, error) { createForm := types.CreateForm{ Configuration: configuration, - SciperID: admin, + UserID: admin, } data, err := createForm.Serialize(serdecontext) @@ -75,7 +75,7 @@ func createFormScenario(contentType, proxy string, secret kyber.Scalar, t *testi createSimpleFormRequest := ptypes.CreateFormRequest{ Configuration: configuration, - SciperID: "adminId", + UserID: "adminId", } signed, err := createSignedRequest(secret, createSimpleFormRequest) diff --git a/integration/performance_test.go b/integration/performance_test.go index 8d76c037c..b8839d342 100644 --- a/integration/performance_test.go +++ b/integration/performance_test.go @@ -219,7 +219,7 @@ func createFormNChunks(m txManager, title types.Title, admin string, numChunks i createForm := types.CreateForm{ Configuration: configuration, - SciperID: admin, + UserID: admin, } data, err := createForm.Serialize(serdecontext) diff --git a/proxy/election.go b/proxy/election.go index e5bccb0b4..842766c4f 100644 --- a/proxy/election.go +++ b/proxy/election.go @@ -83,7 +83,7 @@ func (h *form) NewForm(w http.ResponseWriter, r *http.Request) { createForm := types.CreateForm{ Configuration: req.Configuration, - SciperID: req.SciperID, + UserID: req.UserID, } // serialize the transaction diff --git a/proxy/types/election.go b/proxy/types/election.go index c54b13bb7..fd8775d7b 100644 --- a/proxy/types/election.go +++ b/proxy/types/election.go @@ -6,7 +6,7 @@ import ( // CreateFormRequest defines the HTTP request for creating a form type CreateFormRequest struct { - SciperID string + UserID string Configuration etypes.Configuration } diff --git a/web/backend/src/controllers/dela.ts b/web/backend/src/controllers/dela.ts index 4742f5ac8..876e20156 100644 --- a/web/backend/src/controllers/dela.ts +++ b/web/backend/src/controllers/dela.ts @@ -264,8 +264,8 @@ delaRouter.use('/*', (req, res) => { } } - // UserID - bodyData.SciperID = req.session.userId.toString(); + // UserID for permission + bodyData.UserID = req.session.userId.toString(); const dataStr = JSON.stringify(bodyData); From 89739388e28cb057782ecd4cbd70b26b4211f196 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Tue, 16 Apr 2024 15:12:05 +0200 Subject: [PATCH 015/114] address Carine review --- contracts/evoting/evoting.go | 2 -- contracts/evoting/mod_test.go | 2 +- docs/smart_contract.md | 2 +- docs/verifiability_doc.md | 3 ++- 4 files changed, 4 insertions(+), 5 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 746d044f9..757e03bd9 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -60,8 +60,6 @@ func (e evotingCommand) createForm(snap store.Snapshot, step execution.Step) err return xerrors.Errorf(errWrongTx, msg) } - println("SCIPERRRRR: %i", tx.UserID) - rosterBuf, err := snap.Get(viewchange.GetRosterKey()) if err != nil { return xerrors.Errorf("failed to get roster") diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index eea18a7a4..fff1928a3 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -120,7 +120,7 @@ func TestCommand_CreateForm(t *testing.T) { } createForm := types.CreateForm{ - UserID: "dummyAdminID", + UserID: "dummyUserID", } data, err := createForm.Serialize(ctx) diff --git a/docs/smart_contract.md b/docs/smart_contract.md index b1f68ddba..0adff392c 100644 --- a/docs/smart_contract.md +++ b/docs/smart_contract.md @@ -113,7 +113,7 @@ where: evoting.CloseFormArg = "evoting:close_form" closeFormBuf = marshalled version of types.CloseFormTransaction{ FormID: hex.EncodeToString(formID), - VoterID: adminID, + UserID: adminID, } evoting.CmdArg = "evoting:command" evoting.CmdCloseForm = "CLOSE_FORM" diff --git a/docs/verifiability_doc.md b/docs/verifiability_doc.md index 571cb1e23..64fd5eea6 100755 --- a/docs/verifiability_doc.md +++ b/docs/verifiability_doc.md @@ -20,7 +20,8 @@ The current d-voting [latest commit](https://github.com/c4dt/d-voting/commit/39a Note over User: encrypt ballot via Elgamal encryption using electionPubKey Note over User, Backend: data = encrypted ballot Note over Backend: check role and sign payload. - Note over Backend: add VoterID inside payload. + Note over Backend: add voterID inside payload. + Note over Backend: add userID inside payload. Note over Backend: sign = kyber.sign.schnorr.sign(edCurve, scalar, hash); Backend ->>+ NodeX: POST /evoting/elections/ Note over Backend, NodeX: data: {"Payload": dataStrB64, "Signature": ""} From 31519024f5369f5c0c0422a4c2be062c3282d094 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 18 Apr 2024 13:18:05 +0200 Subject: [PATCH 016/114] add remove and is admin --- contracts/evoting/admin_test.go | 24 ++++++++++++++++- contracts/evoting/types/admin.go | 46 ++++++++++++++++++++++++++++++++ 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/contracts/evoting/admin_test.go b/contracts/evoting/admin_test.go index dee5ddde4..2a0427c79 100644 --- a/contracts/evoting/admin_test.go +++ b/contracts/evoting/admin_test.go @@ -24,7 +24,7 @@ func init() { // This test create an Admin Form structure which is then serialized and // deserialized to check whether these operations work as intended. // Serialization/Deserialization of an AdminForm should not change its values. -func TestAdmin_serde(t *testing.T) { +func TestAdmin_Serde(t *testing.T) { adminFormID := "myID" adminFormList := []int{111111, 222222, 333333, 123456} @@ -46,3 +46,25 @@ func TestAdmin_serde(t *testing.T) { require.Equal(t, adminFormID, updatedAdminForm.FormID) require.Equal(t, adminFormList, updatedAdminForm.AdminList) } + +func TestAdmin_AddAdminAndRemoveAdmin(t *testing.T) { + adminFormID := "myID" + adminFormList := []int{} + + myTestID := "123456" + + adminForm := types.AdminForm{FormID: adminFormID, AdminList: adminFormList} + + res := adminForm.IsAdmin(myTestID) + require.Equal(t, -1, res) + + err := adminForm.AddAdmin(myTestID) + require.NoError(t, err) + res = adminForm.IsAdmin(myTestID) + require.Equal(t, 0, res) + + err = adminForm.RemoveAdmin(myTestID) + require.NoError(t, err) + res = adminForm.IsAdmin(myTestID) + require.Equal(t, -1, res) +} diff --git a/contracts/evoting/types/admin.go b/contracts/evoting/types/admin.go index e5d26706e..fb82b42fd 100644 --- a/contracts/evoting/types/admin.go +++ b/contracts/evoting/types/admin.go @@ -6,6 +6,7 @@ import ( "go.dedis.ch/dela/serde" "go.dedis.ch/dela/serde/registry" "golang.org/x/xerrors" + "strconv" ) var adminFormFormat = registry.NewSimpleRegistry() @@ -44,6 +45,51 @@ func (af AdminForm) Deserialize(ctx serde.Context, data []byte) (serde.Message, return message, nil } +// AddAdmin add a new admin to the system. +func (af *AdminForm) AddAdmin(userID string) error { + sciperInt, err := strconv.Atoi(userID) + if err != nil { + return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) + } + + af.AdminList = append(af.AdminList, sciperInt) + + return nil +} + +// IsAdmin return the index of admin if userID is one, else return -1 +func (af *AdminForm) IsAdmin(userID string) int { + sciperInt, err := strconv.Atoi(userID) + if err != nil { + return -1 + } + + for i := 0; i < len(af.AdminList); i++ { + if af.AdminList[i] == sciperInt { + return i + } + } + + return -1 +} + +// RemoveAdmin add a new admin to the system. +func (af *AdminForm) RemoveAdmin(userID string) error { + _, err := strconv.Atoi(userID) + if err != nil { + return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) + } + + index := af.IsAdmin(userID) + + if index < 0 { + return xerrors.Errorf("Error while retrieving the index of the element.") + } + + af.AdminList = append(af.AdminList[:index], af.AdminList[index+1:]...) + return nil +} + func AdminFormFromStore(ctx serde.Context, adminFormFac serde.Factory, adminFormIDHex string, store store.Readable) (AdminForm, error) { adminForm := AdminForm{} From d1bdf22a8bf66891ab44b4ccd5279f08ec4a094a Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 18 Apr 2024 14:36:36 +0200 Subject: [PATCH 017/114] add ADD_ADMIN and REMOVE_ADMIN cmd --- contracts/evoting/evoting.go | 90 +++++++++++++++++++++++++ contracts/evoting/mod.go | 18 +++++ contracts/evoting/types/transactions.go | 42 ++++++++++++ 3 files changed, 150 insertions(+) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 757e03bd9..2ff95002f 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -771,6 +771,76 @@ func (e evotingCommand) deleteForm(snap store.Snapshot, step execution.Step) err return nil } +// addAdminForm implements commands. It performs the ADD_ADMIN command +func (e evotingCommand) addAdminForm(snap store.Snapshot, step execution.Step) error { + msg, err := e.getTransaction(step.Current) + if err != nil { + return xerrors.Errorf(errGetTransaction, err) + } + + tx, ok := msg.(types.AddAdmin) + if !ok { + return xerrors.Errorf(errWrongTx, msg) + } + + form, formID, err := e.getAdminForm(tx.FormID, snap) + if err != nil { + return xerrors.Errorf("failed to get AdminForm: %v", err) + } + + err = form.AddAdmin(tx.UserID) + if err != nil { + return xerrors.Errorf("couldn't add admin: %v", err) + } + + formBuf, err := form.Serialize(e.context) + if err != nil { + return xerrors.Errorf("failed to marshal Form : %v", err) + } + + err = snap.Set(formID, formBuf) + if err != nil { + return xerrors.Errorf("failed to set value: %v", err) + } + + return nil +} + +// removeAdminForm implements commands. It performs the REMOVE_ADMIN command +func (e evotingCommand) removeAdminForm(snap store.Snapshot, step execution.Step) error { + msg, err := e.getTransaction(step.Current) + if err != nil { + return xerrors.Errorf(errGetTransaction, err) + } + + tx, ok := msg.(types.RemoveAdmin) + if !ok { + return xerrors.Errorf(errWrongTx, msg) + } + + form, formID, err := e.getAdminForm(tx.FormID, snap) + if err != nil { + return xerrors.Errorf("failed to get AdminForm: %v", err) + } + + err = form.RemoveAdmin(tx.UserID) + if err != nil { + return xerrors.Errorf("couldn't remove admin: %v", err) + } + + formBuf, err := form.Serialize(e.context) + if err != nil { + return xerrors.Errorf("failed to marshal Form : %v", err) + } + + err = snap.Set(formID, formBuf) + if err != nil { + return xerrors.Errorf("failed to set value: %v", err) + } + + return nil +} + // isMemberOf is a utility function to verify if a public key is associated to a // member of the roster or not. Returns nil if it's the case. func isMemberOf(roster authority.Authority, publicKey []byte) error { @@ -856,6 +926,26 @@ func (e evotingCommand) getForm(formIDHex string, return form, formIDBuf, nil } +// getAdminForm gets the AdminForm from the snap. Returns the form ID NOT hex +// encoded. +func (e evotingCommand) getAdminForm(formIDHex string, + snap store.Snapshot) (types.AdminForm, []byte, error) { + + var form types.AdminForm + + formIDBuf, err := hex.DecodeString(formIDHex) + if err != nil { + return form, nil, xerrors.Errorf("failed to decode adminFormIDHex: %v", err) + } + + form, err = types.AdminFormFromStore(e.context, e.formFac, formIDHex, snap) + if err != nil { + return form, nil, xerrors.Errorf("failed to get key %q: %v", formIDBuf, err) + } + + return form, formIDBuf, nil +} + // getTransaction extracts the argument from the transaction. func (e evotingCommand) getTransaction(tx txn.Transaction) (serde.Message, error) { buff := tx.GetArg(FormArg) diff --git a/contracts/evoting/mod.go b/contracts/evoting/mod.go index b431bc445..7016ca68a 100644 --- a/contracts/evoting/mod.go +++ b/contracts/evoting/mod.go @@ -98,6 +98,9 @@ type commands interface { combineShares(snap store.Snapshot, step execution.Step) error cancelForm(snap store.Snapshot, step execution.Step) error deleteForm(snap store.Snapshot, step execution.Step) error + + addAdminForm(snap store.Snapshot, step execution.Step) error + removeAdminForm(snap store.Snapshot, step execution.Step) error } // Command defines a type of command for the value contract @@ -125,6 +128,11 @@ const ( // CmdDeleteForm is the command to delete a form CmdDeleteForm Command = "DELETE_FORM" + + // CmdAddAdminForm is the command to delete a form + CmdAddAdminForm Command = "ADD_ADMIN" + // CmdRemoveAdminForm is the command to delete a form + CmdRemoveAdminForm Command = "REMOVE_ADMIN" ) // NewCreds creates new credentials for a evoting contract execution. We might @@ -244,6 +252,16 @@ func (c Contract) Execute(snap store.Snapshot, step execution.Step) error { if err != nil { return xerrors.Errorf("failed to delete form: %v", err) } + case CmdAddAdminForm: + err := c.cmd.addAdminForm(snap, step) + if err != nil { + return xerrors.Errorf("failed to delete form: %v", err) + } + case CmdRemoveAdminForm: + err := c.cmd.removeAdminForm(snap, step) + if err != nil { + return xerrors.Errorf("failed to delete form: %v", err) + } default: return xerrors.Errorf("unknown command: %s", cmd) } diff --git a/contracts/evoting/types/transactions.go b/contracts/evoting/types/transactions.go index df9930c85..47adbc9ba 100644 --- a/contracts/evoting/types/transactions.go +++ b/contracts/evoting/types/transactions.go @@ -343,3 +343,45 @@ func (rp RegisterPubShares) Fingerprint(writer io.Writer) error { return nil } + +// AddAdmin defines the transaction to Add an Admin +// +// - implements serde.Message +type AddAdmin struct { + // FormID is hex-encoded + FormID string + UserID string +} + +// Serialize implements serde.Message +func (aa AddAdmin) Serialize(ctx serde.Context) ([]byte, error) { + format := transactionFormats.Get(ctx.GetFormat()) + + data, err := format.Encode(ctx, aa) + if err != nil { + return nil, xerrors.Errorf("failed to encode Add Admin: %v", err) + } + + return data, nil +} + +// RemoveAdmin defines the transaction to Remove an Admin +// +// - implements serde.Message +type RemoveAdmin struct { + // FormID is hex-encoded + FormID string + UserID string +} + +// Serialize implements serde.Message +func (ra RemoveAdmin) Serialize(ctx serde.Context) ([]byte, error) { + format := transactionFormats.Get(ctx.GetFormat()) + + data, err := format.Encode(ctx, ra) + if err != nil { + return nil, xerrors.Errorf("failed to encode remove admin: %v", err) + } + + return data, nil +} From 639b3466b3e855744e49789e7314217eef73dfd9 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 18 Apr 2024 14:42:25 +0200 Subject: [PATCH 018/114] patch current error --- contracts/evoting/mod.go | 4 ++-- contracts/evoting/mod_test.go | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/contracts/evoting/mod.go b/contracts/evoting/mod.go index 7016ca68a..f0e765b1d 100644 --- a/contracts/evoting/mod.go +++ b/contracts/evoting/mod.go @@ -255,12 +255,12 @@ func (c Contract) Execute(snap store.Snapshot, step execution.Step) error { case CmdAddAdminForm: err := c.cmd.addAdminForm(snap, step) if err != nil { - return xerrors.Errorf("failed to delete form: %v", err) + return xerrors.Errorf("failed to add admin: %v", err) } case CmdRemoveAdminForm: err := c.cmd.removeAdminForm(snap, step) if err != nil { - return xerrors.Errorf("failed to delete form: %v", err) + return xerrors.Errorf("failed to remove admin: %v", err) } default: return xerrors.Errorf("unknown command: %s", cmd) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index fff1928a3..a83365b9a 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -97,6 +97,12 @@ func TestExecute(t *testing.T) { err = contract.Execute(fakeStore{}, makeStep(t, CmdArg, string(CmdCancelForm))) require.EqualError(t, err, fake.Err("failed to cancel form")) + err = contract.Execute(fakeStore{}, makeStep(t, CmdArg, string(CmdAddAdminForm))) + require.EqualError(t, err, fake.Err("failed to add admin")) + + err = contract.Execute(fakeStore{}, makeStep(t, CmdArg, string(CmdRemoveAdminForm))) + require.EqualError(t, err, fake.Err("failed to remove admin")) + err = contract.Execute(fakeStore{}, makeStep(t, CmdArg, "fake")) require.EqualError(t, err, "unknown command: fake") @@ -1331,6 +1337,14 @@ type fakeCmd struct { err error } +func (c fakeCmd) addAdminForm(snap store.Snapshot, step execution.Step) error { + return c.err +} + +func (c fakeCmd) removeAdminForm(snap store.Snapshot, step execution.Step) error { + return c.err +} + func (c fakeCmd) createForm(snap store.Snapshot, step execution.Step) error { return c.err } From ec8e93fc75970a778711f65478161b3a2f4a6ba0 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 18 Apr 2024 15:50:25 +0200 Subject: [PATCH 019/114] create admin form test --- contracts/evoting/json/transaction.go | 40 +++++++++ contracts/evoting/mod_test.go | 122 ++++++++++++++++++++++++++ 2 files changed, 162 insertions(+) diff --git a/contracts/evoting/json/transaction.go b/contracts/evoting/json/transaction.go index d0d79dd95..a9ff461c7 100644 --- a/contracts/evoting/json/transaction.go +++ b/contracts/evoting/json/transaction.go @@ -118,6 +118,20 @@ func (transactionFormat) Encode(ctx serde.Context, msg serde.Message) ([]byte, e } m = TransactionJSON{DeleteForm: &de} + case types.AddAdmin: + aa := AddAdminJSON{ + FormID: t.FormID, + UserID: t.UserID, + } + + m = TransactionJSON{AddAdmin: &aa} + case types.RemoveAdmin: + ra := RemoveAdminJSON{ + FormID: t.FormID, + UserID: t.UserID, + } + + m = TransactionJSON{RemoveAdmin: &ra} default: return nil, xerrors.Errorf("unknown type: '%T", msg) } @@ -189,6 +203,16 @@ func (transactionFormat) Decode(ctx serde.Context, data []byte) (serde.Message, return types.DeleteForm{ FormID: m.DeleteForm.FormID, }, nil + case m.AddAdmin != nil: + return types.AddAdmin{ + FormID: m.AddAdmin.FormID, + UserID: m.AddAdmin.UserID, + }, nil + case m.RemoveAdmin != nil: + return types.RemoveAdmin{ + FormID: m.RemoveAdmin.FormID, + UserID: m.RemoveAdmin.UserID, + }, nil } return nil, xerrors.Errorf("empty type: %s", data) @@ -206,6 +230,8 @@ type TransactionJSON struct { CombineShares *CombineSharesJSON `json:",omitempty"` CancelForm *CancelFormJSON `json:",omitempty"` DeleteForm *DeleteFormJSON `json:",omitempty"` + AddAdmin *AddAdminJSON `json:",omitempty"` + RemoveAdmin *RemoveAdminJSON `json:",omitempty"` } // CreateFormJSON is the JSON representation of a CreateForm transaction @@ -268,6 +294,20 @@ type DeleteFormJSON struct { FormID string } +// AdminForm + +// AddAdminJSON is the JSON representation of a AddAdmin transaction +type AddAdminJSON struct { + FormID string + UserID string +} + +// RemoveAdminJSON is the JSON representation of a RemoveAdmin transaction +type RemoveAdminJSON struct { + FormID string + UserID string +} + func decodeCastVote(ctx serde.Context, m CastVoteJSON) (serde.Message, error) { factory := ctx.GetFactory(types.CiphervoteKey{}) if factory == nil { diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index a83365b9a..a4222d648 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1101,6 +1101,128 @@ func TestRegisterContract(t *testing.T) { RegisterContract(native.NewExecution(), Contract{}) } +// =============== +// Admin Form Test + +func TestCommand_AdminForm(t *testing.T) { + initMetrics() + + dummyUID := "123456" + + addAdmin := types.AddAdmin{FormID: fakeFormID, UserID: dummyUID} + data, err := addAdmin.Serialize(ctx) + require.NoError(t, err) + + adminForm := types.AdminForm{FormID: fakeFormID, AdminList: make([]int, 0)} + adminFormBuf, err := adminForm.Serialize(ctx) + require.NoError(t, err) + + dummyForm, contract := initFormAndContract() + _, err = dummyForm.Serialize(ctx) + require.NoError(t, err) + + cmd := evotingCommand{ + Contract: &contract, + } + + err = cmd.addAdminForm(fake.NewSnapshot(), makeStep(t)) + require.EqualError(t, err, getTransactionErr) + + err = cmd.addAdminForm(fake.NewSnapshot(), makeStep(t, FormArg, "dummy")) + require.EqualError(t, err, unmarshalTransactionErr) + + err = cmd.addAdminForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) + require.ErrorContains(t, err, "failed to get key") + + snap := fake.NewSnapshot() + + err = snap.Set(dummyFormIDBuff, invalidForm) + require.NoError(t, err) + + err = cmd.addAdminForm(snap, makeStep(t, FormArg, string(data))) + require.ErrorContains(t, err, deserializeErr) + + err = snap.Set(dummyFormIDBuff, adminFormBuf) //instead of formBuf + require.NoError(t, err) + + fmt.Printf("test") + + /*dummyForm.BallotSize = 29 + + formBuf, err = dummyForm.Serialize(ctx) + require.NoError(t, err) + + err = snap.Set(dummyFormIDBuff, formBuf) + require.NoError(t, err) + + // encrypt a real message : + RandomStream := suite.RandomStream() + h := suite.Scalar().Pick(RandomStream) + pubKey := suite.Point().Mul(h, nil) + + M := suite.Point().Embed([]byte("fakeVote"), random.New()) + + // ElGamal-encrypt the point to produce ciphertext (K,C). + k := suite.Scalar().Pick(random.New()) // ephemeral private key + K := suite.Point().Mul(k, nil) // ephemeral DH public key + S := suite.Point().Mul(k, pubKey) // ephemeral DH shared secret + C := S.Add(S, M) // message blinded with secret + + castVote.Ballot = types.Ciphervote{ + types.EGPair{ + K: K, + C: C, + }, + } + + castVote.FormID = "X" + + data, err = castVote.Serialize(ctx) + require.NoError(t, err) + + err = snap.Set(dummyFormIDBuff, formBuf) + require.NoError(t, err) + + err = cmd.castVote(snap, makeStep(t, FormArg, string(data))) + require.EqualError(t, err, "failed to get form: failed to decode "+ + "formIDHex: encoding/hex: invalid byte: U+0058 'X'") + + dummyForm.FormID = fakeFormID + + formBuf, err = dummyForm.Serialize(ctx) + require.NoError(t, err) + + err = snap.Set(dummyFormIDBuff, formBuf) + require.NoError(t, err) + + castVote.FormID = fakeFormID + + data, err = castVote.Serialize(ctx) + require.NoError(t, err) + + err = cmd.castVote(snap, makeStep(t, FormArg, string(data))) + require.NoError(t, err) + + res, err := snap.Get(dummyFormIDBuff) + require.NoError(t, err) + + message, err := formFac.Deserialize(ctx, res) + require.NoError(t, err) + + form, ok := message.(types.Form) + require.True(t, ok) + + require.Equal(t, uint32(1), form.BallotCount) + suff, err := form.Suffragia(ctx, snap) + require.NoError(t, err) + require.True(t, castVote.Ballot.Equal(suff.Ciphervotes[0])) + + require.Equal(t, castVote.VoterID, suff.VoterIDs[0]) + require.Equal(t, float64(form.BallotCount), testutil.ToFloat64(PromFormBallots)) + + */ +} + // ----------------------------------------------------------------------------- // Utility functions From 9732d06d5fca8cd65e6c99b011ce5cdb94ddcdea Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Mon, 22 Apr 2024 00:18:33 +0200 Subject: [PATCH 020/114] working on the testing part --- contracts/evoting/mod_test.go | 93 +++++++++++--------------------- contracts/evoting/types/admin.go | 2 +- 2 files changed, 31 insertions(+), 64 deletions(-) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index a4222d648..96caaf440 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -30,6 +30,7 @@ import ( ) var dummyFormIDBuff = []byte("dummyID") +var dummyAdminFormIDBuff = []byte("dummyAdminID") var fakeFormID = hex.EncodeToString(dummyFormIDBuff) var fakeCommonSigner = bls.NewSigner() @@ -1107,6 +1108,8 @@ func TestRegisterContract(t *testing.T) { func TestCommand_AdminForm(t *testing.T) { initMetrics() + _, contract := initFormAndContract() + dummyUID := "123456" addAdmin := types.AddAdmin{FormID: fakeFormID, UserID: dummyUID} @@ -1117,10 +1120,6 @@ func TestCommand_AdminForm(t *testing.T) { adminFormBuf, err := adminForm.Serialize(ctx) require.NoError(t, err) - dummyForm, contract := initFormAndContract() - _, err = dummyForm.Serialize(ctx) - require.NoError(t, err) - cmd := evotingCommand{ Contract: &contract, } @@ -1136,89 +1135,57 @@ func TestCommand_AdminForm(t *testing.T) { snap := fake.NewSnapshot() - err = snap.Set(dummyFormIDBuff, invalidForm) + err = snap.Set(dummyAdminFormIDBuff, invalidForm) require.NoError(t, err) err = cmd.addAdminForm(snap, makeStep(t, FormArg, string(data))) - require.ErrorContains(t, err, deserializeErr) - - err = snap.Set(dummyFormIDBuff, adminFormBuf) //instead of formBuf - require.NoError(t, err) + require.ErrorContains(t, err, "failed to deserialize AdminForm") - fmt.Printf("test") - - /*dummyForm.BallotSize = 29 - - formBuf, err = dummyForm.Serialize(ctx) - require.NoError(t, err) - - err = snap.Set(dummyFormIDBuff, formBuf) + err = snap.Set(dummyAdminFormIDBuff, adminFormBuf) //instead of formBuf require.NoError(t, err) - // encrypt a real message : - RandomStream := suite.RandomStream() - h := suite.Scalar().Pick(RandomStream) - pubKey := suite.Point().Mul(h, nil) - - M := suite.Point().Embed([]byte("fakeVote"), random.New()) - - // ElGamal-encrypt the point to produce ciphertext (K,C). - k := suite.Scalar().Pick(random.New()) // ephemeral private key - K := suite.Point().Mul(k, nil) // ephemeral DH public key - S := suite.Point().Mul(k, pubKey) // ephemeral DH shared secret - C := S.Add(S, M) // message blinded with secret - - castVote.Ballot = types.Ciphervote{ - types.EGPair{ - K: K, - C: C, - }, - } - - castVote.FormID = "X" - - data, err = castVote.Serialize(ctx) + adminFormBuf, err = adminForm.Serialize(ctx) require.NoError(t, err) - err = snap.Set(dummyFormIDBuff, formBuf) + err = snap.Set(dummyAdminFormIDBuff, adminFormBuf) require.NoError(t, err) - err = cmd.castVote(snap, makeStep(t, FormArg, string(data))) - require.EqualError(t, err, "failed to get form: failed to decode "+ - "formIDHex: encoding/hex: invalid byte: U+0058 'X'") + err = cmd.addAdminForm(snap, makeStep(t, FormArg, string(data))) + require.ErrorContains(t, err, "failed to get AdminForm: failed to get key ") - dummyForm.FormID = fakeFormID + //dummyForm.FormID = fakeFormID + adminForm.FormID = fakeFormID - formBuf, err = dummyForm.Serialize(ctx) + adminFormBuf, err = adminForm.Serialize(ctx) require.NoError(t, err) - err = snap.Set(dummyFormIDBuff, formBuf) + err = snap.Set(dummyAdminFormIDBuff, adminFormBuf) require.NoError(t, err) - castVote.FormID = fakeFormID + addAdmin.FormID = fakeFormID - data, err = castVote.Serialize(ctx) + data, err = addAdmin.Serialize(ctx) require.NoError(t, err) - err = cmd.castVote(snap, makeStep(t, FormArg, string(data))) + err = cmd.addAdminForm(snap, makeStep(t, FormArg, string(data))) require.NoError(t, err) + /* + res, err := snap.Get(dummyFormIDBuff) + require.NoError(t, err) - res, err := snap.Get(dummyFormIDBuff) - require.NoError(t, err) + message, err := formFac.Deserialize(ctx, res) + require.NoError(t, err) - message, err := formFac.Deserialize(ctx, res) - require.NoError(t, err) + form, ok := message.(types.Form) + require.True(t, ok) - form, ok := message.(types.Form) - require.True(t, ok) + require.Equal(t, uint32(1), form.BallotCount) + suff, err := form.Suffragia(ctx, snap) + require.NoError(t, err) + require.True(t, castVote.Ballot.Equal(suff.Ciphervotes[0])) - require.Equal(t, uint32(1), form.BallotCount) - suff, err := form.Suffragia(ctx, snap) - require.NoError(t, err) - require.True(t, castVote.Ballot.Equal(suff.Ciphervotes[0])) - - require.Equal(t, castVote.VoterID, suff.VoterIDs[0]) - require.Equal(t, float64(form.BallotCount), testutil.ToFloat64(PromFormBallots)) + require.Equal(t, castVote.VoterID, suff.VoterIDs[0]) + require.Equal(t, float64(form.BallotCount), testutil.ToFloat64(PromFormBallots)) */ } diff --git a/contracts/evoting/types/admin.go b/contracts/evoting/types/admin.go index fb82b42fd..99fc0ed94 100644 --- a/contracts/evoting/types/admin.go +++ b/contracts/evoting/types/admin.go @@ -108,7 +108,7 @@ func AdminFormFromStore(ctx serde.Context, adminFormFac serde.Factory, adminForm message, err := adminFormFac.Deserialize(ctx, adminFormBuf) if err != nil { - return adminForm, xerrors.Errorf("While deserializing: %v", err) + return adminForm, xerrors.Errorf("failed to deserialize AdminForm: %v", err) } adminForm, ok := message.(AdminForm) From 589dfbf9c60cad96c9d2d7f1d4c5f91bbf285071 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Mon, 22 Apr 2024 12:42:35 +0200 Subject: [PATCH 021/114] patch test mistake --- contracts/evoting/mod_test.go | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 96caaf440..28a37ccb3 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -32,6 +32,7 @@ import ( var dummyFormIDBuff = []byte("dummyID") var dummyAdminFormIDBuff = []byte("dummyAdminID") var fakeFormID = hex.EncodeToString(dummyFormIDBuff) +var fakeAdminFormID = hex.EncodeToString(dummyAdminFormIDBuff) var fakeCommonSigner = bls.NewSigner() const getTransactionErr = "failed to get transaction: \"evoting:arg\" not found in tx arg" @@ -1108,15 +1109,14 @@ func TestRegisterContract(t *testing.T) { func TestCommand_AdminForm(t *testing.T) { initMetrics() - _, contract := initFormAndContract() + adminForm, contract := initAdminFormAndContract() dummyUID := "123456" - addAdmin := types.AddAdmin{FormID: fakeFormID, UserID: dummyUID} + addAdmin := types.AddAdmin{FormID: fakeAdminFormID, UserID: dummyUID} data, err := addAdmin.Serialize(ctx) require.NoError(t, err) - adminForm := types.AdminForm{FormID: fakeFormID, AdminList: make([]int, 0)} adminFormBuf, err := adminForm.Serialize(ctx) require.NoError(t, err) @@ -1154,7 +1154,7 @@ func TestCommand_AdminForm(t *testing.T) { require.ErrorContains(t, err, "failed to get AdminForm: failed to get key ") //dummyForm.FormID = fakeFormID - adminForm.FormID = fakeFormID + adminForm.FormID = fakeAdminFormID adminFormBuf, err = adminForm.Serialize(ctx) require.NoError(t, err) @@ -1162,7 +1162,7 @@ func TestCommand_AdminForm(t *testing.T) { err = snap.Set(dummyAdminFormIDBuff, adminFormBuf) require.NoError(t, err) - addAdmin.FormID = fakeFormID + addAdmin.FormID = fakeAdminFormID data, err = addAdmin.Serialize(ctx) require.NoError(t, err) @@ -1224,6 +1224,25 @@ func initFormAndContract() (types.Form, Contract) { return dummyForm, contract } +func initAdminFormAndContract() (types.AdminForm, Contract) { + fakeDkg := fakeDKG{ + actor: fakeDkgActor{}, + err: nil, + } + + dummyForm := types.AdminForm{ + FormID: fakeAdminFormID, + AdminList: make([]int, 0), + } + + service := fakeAccess{err: fake.GetError()} + rosterFac := fakeAuthorityFactory{} + + contract := NewContract(service, fakeDkg, rosterFac) + + return dummyForm, contract +} + func initGoodShuffleBallot(t *testing.T, k int) (store.Snapshot, types.Form, types.ShuffleBallots, Contract) { form, shuffleBallots, contract := initBadShuffleBallot(3) form.Status = types.Closed From d652b1bd0ba8ff0c34d67c7f7dd56223b5ce1290 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Mon, 22 Apr 2024 13:01:46 +0200 Subject: [PATCH 022/114] fully working adminForm test --- contracts/evoting/evoting.go | 2 +- contracts/evoting/mod.go | 3 +++ contracts/evoting/mod_test.go | 43 +++++++++++++++++++------------- contracts/evoting/types/admin.go | 18 +++++++++++++ 4 files changed, 48 insertions(+), 18 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 2ff95002f..d927a7576 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -938,7 +938,7 @@ func (e evotingCommand) getAdminForm(formIDHex string, return form, nil, xerrors.Errorf("failed to decode adminFormIDHex: %v", err) } - form, err = types.AdminFormFromStore(e.context, e.formFac, formIDHex, snap) + form, err = types.AdminFormFromStore(e.context, e.adminFormFac, formIDHex, snap) if err != nil { return form, nil, xerrors.Errorf("failed to get key %q: %v", formIDBuf, err) } diff --git a/contracts/evoting/mod.go b/contracts/evoting/mod.go index f0e765b1d..08d5b9dc9 100644 --- a/contracts/evoting/mod.go +++ b/contracts/evoting/mod.go @@ -161,6 +161,7 @@ type Contract struct { context serde.Context formFac serde.Factory + adminFormFac serde.Factory rosterFac authority.Factory transactionFac serde.Factory } @@ -174,6 +175,7 @@ func NewContract(srvc access.Service, ciphervoteFac := types.CiphervoteFactory{} formFac := types.NewFormFactory(ciphervoteFac, rosterFac) transactionFac := types.NewTransactionFactory(ciphervoteFac) + adminFormFac := types.AdminFormFactory{} contract := Contract{ access: srvc, @@ -182,6 +184,7 @@ func NewContract(srvc access.Service, context: ctx, formFac: formFac, + adminFormFac: adminFormFac, rosterFac: rosterFac, transactionFac: transactionFac, } diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 28a37ccb3..5523874c1 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -46,11 +46,13 @@ var invalidForm = []byte("fake form") var ctx serde.Context var formFac serde.Factory +var adminFormFac serde.Factory var transactionFac serde.Factory func init() { ciphervoteFac := types.CiphervoteFactory{} formFac = types.NewFormFactory(ciphervoteFac, fakeAuthorityFactory{}) + adminFormFac = types.AdminFormFactory{} transactionFac = types.NewTransactionFactory(ciphervoteFac) ctx = sjson.NewContext() @@ -1150,9 +1152,6 @@ func TestCommand_AdminForm(t *testing.T) { err = snap.Set(dummyAdminFormIDBuff, adminFormBuf) require.NoError(t, err) - err = cmd.addAdminForm(snap, makeStep(t, FormArg, string(data))) - require.ErrorContains(t, err, "failed to get AdminForm: failed to get key ") - //dummyForm.FormID = fakeFormID adminForm.FormID = fakeAdminFormID @@ -1169,25 +1168,35 @@ func TestCommand_AdminForm(t *testing.T) { err = cmd.addAdminForm(snap, makeStep(t, FormArg, string(data))) require.NoError(t, err) - /* - res, err := snap.Get(dummyFormIDBuff) - require.NoError(t, err) - message, err := formFac.Deserialize(ctx, res) - require.NoError(t, err) + res, err := snap.Get(dummyAdminFormIDBuff) + require.NoError(t, err) + + message, err := adminFormFac.Deserialize(ctx, res) + require.NoError(t, err) + + adminForm, ok := message.(types.AdminForm) + require.True(t, ok) - form, ok := message.(types.Form) - require.True(t, ok) + require.True(t, adminForm.IsAdmin(dummyUID) > -1) - require.Equal(t, uint32(1), form.BallotCount) - suff, err := form.Suffragia(ctx, snap) - require.NoError(t, err) - require.True(t, castVote.Ballot.Equal(suff.Ciphervotes[0])) + removeAdmin := types.RemoveAdmin{FormID: fakeAdminFormID, UserID: dummyUID} + data, err = removeAdmin.Serialize(ctx) + require.NoError(t, err) - require.Equal(t, castVote.VoterID, suff.VoterIDs[0]) - require.Equal(t, float64(form.BallotCount), testutil.ToFloat64(PromFormBallots)) + err = cmd.removeAdminForm(snap, makeStep(t, FormArg, string(data))) + require.NoError(t, err) + + res, err = snap.Get(dummyAdminFormIDBuff) + require.NoError(t, err) + + message, err = adminFormFac.Deserialize(ctx, res) + require.NoError(t, err) + + adminForm, ok = message.(types.AdminForm) + require.True(t, ok) - */ + require.True(t, adminForm.IsAdmin(dummyUID) == -1) } // ----------------------------------------------------------------------------- diff --git a/contracts/evoting/types/admin.go b/contracts/evoting/types/admin.go index 99fc0ed94..ce5da05a0 100644 --- a/contracts/evoting/types/admin.go +++ b/contracts/evoting/types/admin.go @@ -118,3 +118,21 @@ func AdminFormFromStore(ctx serde.Context, adminFormFac serde.Factory, adminForm return adminForm, nil } + +// AdminFormFactory provides the mean to deserialize a AdminForm. It naturally +// uses the formFormat. +// +// - implements serde.Factory +type AdminFormFactory struct{} + +// Deserialize implements serde.Factory +func (AdminFormFactory) Deserialize(ctx serde.Context, data []byte) (serde.Message, error) { + format := adminFormFormat.Get(ctx.GetFormat()) + + message, err := format.Decode(ctx, data) + if err != nil { + return nil, xerrors.Errorf("failed to decode: %v", err) + } + + return message, nil +} From c40ff49378dc14db2682c64c1903a79e1df26686 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Mon, 22 Apr 2024 13:10:03 +0200 Subject: [PATCH 023/114] clean test --- contracts/evoting/mod_test.go | 41 +++++++++++++++++------------------ 1 file changed, 20 insertions(+), 21 deletions(-) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 5523874c1..26fe9bf5a 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1111,21 +1111,25 @@ func TestRegisterContract(t *testing.T) { func TestCommand_AdminForm(t *testing.T) { initMetrics() + // Initialize a contract and an AdminForm adminForm, contract := initAdminFormAndContract() - - dummyUID := "123456" - - addAdmin := types.AddAdmin{FormID: fakeAdminFormID, UserID: dummyUID} - data, err := addAdmin.Serialize(ctx) - require.NoError(t, err) - adminFormBuf, err := adminForm.Serialize(ctx) require.NoError(t, err) + // Initialize the command handler to post on the ledger cmd := evotingCommand{ Contract: &contract, } + // We define a dummy userID which we are going to add admin permission. + dummyUID := "123456" + + // We initialize the command to add permission. + addAdmin := types.AddAdmin{FormID: fakeAdminFormID, UserID: dummyUID} + data, err := addAdmin.Serialize(ctx) + require.NoError(t, err) + + // The following test are there to check error handling err = cmd.addAdminForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -1143,32 +1147,21 @@ func TestCommand_AdminForm(t *testing.T) { err = cmd.addAdminForm(snap, makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to deserialize AdminForm") - err = snap.Set(dummyAdminFormIDBuff, adminFormBuf) //instead of formBuf - require.NoError(t, err) - + // We reset everything to perform the real test adminFormBuf, err = adminForm.Serialize(ctx) require.NoError(t, err) err = snap.Set(dummyAdminFormIDBuff, adminFormBuf) require.NoError(t, err) - //dummyForm.FormID = fakeFormID - adminForm.FormID = fakeAdminFormID - - adminFormBuf, err = adminForm.Serialize(ctx) - require.NoError(t, err) - - err = snap.Set(dummyAdminFormIDBuff, adminFormBuf) - require.NoError(t, err) - - addAdmin.FormID = fakeAdminFormID - data, err = addAdmin.Serialize(ctx) require.NoError(t, err) + // We perform below the command on the ledger err = cmd.addAdminForm(snap, makeStep(t, FormArg, string(data))) require.NoError(t, err) + // We retrieve the form on the ledger res, err := snap.Get(dummyAdminFormIDBuff) require.NoError(t, err) @@ -1178,15 +1171,20 @@ func TestCommand_AdminForm(t *testing.T) { adminForm, ok := message.(types.AdminForm) require.True(t, ok) + // We check that our dummy User is now admin (if not admin return -1; else return admin index in AdminForm). require.True(t, adminForm.IsAdmin(dummyUID) > -1) + // Now we want to remove its admin privilege. + // Initialization of the command removeAdmin := types.RemoveAdmin{FormID: fakeAdminFormID, UserID: dummyUID} data, err = removeAdmin.Serialize(ctx) require.NoError(t, err) + // Publish the command on the ledger. err = cmd.removeAdminForm(snap, makeStep(t, FormArg, string(data))) require.NoError(t, err) + // We retrieve the Admin Form from the ledger. res, err = snap.Get(dummyAdminFormIDBuff) require.NoError(t, err) @@ -1196,6 +1194,7 @@ func TestCommand_AdminForm(t *testing.T) { adminForm, ok = message.(types.AdminForm) require.True(t, ok) + // We check that now our dummy user is not admin anymore (return -1) require.True(t, adminForm.IsAdmin(dummyUID) == -1) } From 721ba906a64b19a606b8a68a03068df17460ada6 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Mon, 22 Apr 2024 13:12:18 +0200 Subject: [PATCH 024/114] linter compliance --- contracts/evoting/mod_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 26fe9bf5a..9c57c3dd7 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1113,7 +1113,7 @@ func TestCommand_AdminForm(t *testing.T) { // Initialize a contract and an AdminForm adminForm, contract := initAdminFormAndContract() - adminFormBuf, err := adminForm.Serialize(ctx) + _, err := adminForm.Serialize(ctx) require.NoError(t, err) // Initialize the command handler to post on the ledger @@ -1148,7 +1148,7 @@ func TestCommand_AdminForm(t *testing.T) { require.ErrorContains(t, err, "failed to deserialize AdminForm") // We reset everything to perform the real test - adminFormBuf, err = adminForm.Serialize(ctx) + adminFormBuf, err := adminForm.Serialize(ctx) require.NoError(t, err) err = snap.Set(dummyAdminFormIDBuff, adminFormBuf) From c7c1323ba86289c0cbded821b7019a95e4c36964 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Mon, 22 Apr 2024 13:13:58 +0200 Subject: [PATCH 025/114] linter compliance part 2 --- contracts/evoting/mod_test.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 9c57c3dd7..81354ef95 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1171,7 +1171,8 @@ func TestCommand_AdminForm(t *testing.T) { adminForm, ok := message.(types.AdminForm) require.True(t, ok) - // We check that our dummy User is now admin (if not admin return -1; else return admin index in AdminForm). + // We check that our dummy User is now admin + // (if not admin return -1; else return admin index in AdminForm). require.True(t, adminForm.IsAdmin(dummyUID) > -1) // Now we want to remove its admin privilege. From 9439cdafb1add6ba50e151dcbe1ce5062c976f91 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Tue, 23 Apr 2024 09:28:47 +0200 Subject: [PATCH 026/114] remove double name var on my new code plus some other spotted places --- contracts/evoting/types/admin.go | 22 +++++----- contracts/evoting/types/transactions.go | 58 ++++++++++++------------- 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/contracts/evoting/types/admin.go b/contracts/evoting/types/admin.go index ce5da05a0..955768074 100644 --- a/contracts/evoting/types/admin.go +++ b/contracts/evoting/types/admin.go @@ -23,10 +23,10 @@ type AdminForm struct { AdminList []int } -func (af AdminForm) Serialize(ctx serde.Context) ([]byte, error) { +func (a AdminForm) Serialize(ctx serde.Context) ([]byte, error) { format := adminFormFormat.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, af) + data, err := format.Encode(ctx, a) if err != nil { return nil, xerrors.Errorf("Failed to encode AdminForm: %v", err) } @@ -34,7 +34,7 @@ func (af AdminForm) Serialize(ctx serde.Context) ([]byte, error) { return data, nil } -func (af AdminForm) Deserialize(ctx serde.Context, data []byte) (serde.Message, error) { +func (a AdminForm) Deserialize(ctx serde.Context, data []byte) (serde.Message, error) { format := adminFormFormat.Get(ctx.GetFormat()) message, err := format.Decode(ctx, data) @@ -46,26 +46,26 @@ func (af AdminForm) Deserialize(ctx serde.Context, data []byte) (serde.Message, } // AddAdmin add a new admin to the system. -func (af *AdminForm) AddAdmin(userID string) error { +func (a *AdminForm) AddAdmin(userID string) error { sciperInt, err := strconv.Atoi(userID) if err != nil { return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) } - af.AdminList = append(af.AdminList, sciperInt) + a.AdminList = append(a.AdminList, sciperInt) return nil } // IsAdmin return the index of admin if userID is one, else return -1 -func (af *AdminForm) IsAdmin(userID string) int { +func (a *AdminForm) IsAdmin(userID string) int { sciperInt, err := strconv.Atoi(userID) if err != nil { return -1 } - for i := 0; i < len(af.AdminList); i++ { - if af.AdminList[i] == sciperInt { + for i := 0; i < len(a.AdminList); i++ { + if a.AdminList[i] == sciperInt { return i } } @@ -74,19 +74,19 @@ func (af *AdminForm) IsAdmin(userID string) int { } // RemoveAdmin add a new admin to the system. -func (af *AdminForm) RemoveAdmin(userID string) error { +func (a *AdminForm) RemoveAdmin(userID string) error { _, err := strconv.Atoi(userID) if err != nil { return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) } - index := af.IsAdmin(userID) + index := a.IsAdmin(userID) if index < 0 { return xerrors.Errorf("Error while retrieving the index of the element.") } - af.AdminList = append(af.AdminList[:index], af.AdminList[index+1:]...) + a.AdminList = append(a.AdminList[:index], a.AdminList[index+1:]...) return nil } diff --git a/contracts/evoting/types/transactions.go b/contracts/evoting/types/transactions.go index 47adbc9ba..01d5c8a4e 100644 --- a/contracts/evoting/types/transactions.go +++ b/contracts/evoting/types/transactions.go @@ -96,10 +96,10 @@ type CreateForm struct { } // Serialize implements serde.Message -func (ce CreateForm) Serialize(ctx serde.Context) ([]byte, error) { +func (c CreateForm) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, ce) + data, err := format.Encode(ctx, c) if err != nil { return nil, xerrors.Errorf("failed to encode create form: %v", err) } @@ -116,10 +116,10 @@ type OpenForm struct { } // Serialize implements serde.Message -func (oe OpenForm) Serialize(ctx serde.Context) ([]byte, error) { +func (o OpenForm) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, oe) + data, err := format.Encode(ctx, o) if err != nil { return nil, xerrors.Errorf("failed to encode open form: %v", err) } @@ -138,10 +138,10 @@ type CastVote struct { } // Serialize implements serde.Message -func (cv CastVote) Serialize(ctx serde.Context) ([]byte, error) { +func (c CastVote) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, cv) + data, err := format.Encode(ctx, c) if err != nil { return nil, xerrors.Errorf("failed to encode cast vote: %v", err) } @@ -159,10 +159,10 @@ type CloseForm struct { } // Serialize implements serde.Message -func (ce CloseForm) Serialize(ctx serde.Context) ([]byte, error) { +func (c CloseForm) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, ce) + data, err := format.Encode(ctx, c) if err != nil { return nil, xerrors.Errorf("failed to encode close form: %v", err) } @@ -191,10 +191,10 @@ type ShuffleBallots struct { } // Serialize implements serde.Message -func (sb ShuffleBallots) Serialize(ctx serde.Context) ([]byte, error) { +func (s ShuffleBallots) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, sb) + data, err := format.Encode(ctx, s) if err != nil { return nil, xerrors.Errorf("failed to encode shuffle ballots: %v", err) } @@ -221,10 +221,10 @@ type RegisterPubShares struct { } // Serialize implements serde.Message -func (rp RegisterPubShares) Serialize(ctx serde.Context) ([]byte, error) { +func (r RegisterPubShares) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, rp) + data, err := format.Encode(ctx, r) if err != nil { return nil, xerrors.Errorf("failed to encode register pubShares: %v", err) } @@ -243,10 +243,10 @@ type CombineShares struct { } // Serialize implements serde.Message -func (db CombineShares) Serialize(ctx serde.Context) ([]byte, error) { +func (c CombineShares) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, db) + data, err := format.Encode(ctx, c) if err != nil { return nil, xerrors.Errorf("failed to encode decrypt ballot: %v", err) } @@ -264,10 +264,10 @@ type CancelForm struct { } // Serialize implements serde.Message -func (ce CancelForm) Serialize(ctx serde.Context) ([]byte, error) { +func (c CancelForm) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, ce) + data, err := format.Encode(ctx, c) if err != nil { return nil, xerrors.Errorf("failed to encode cancel form: %v", err) } @@ -284,10 +284,10 @@ type DeleteForm struct { } // Serialize implements serde.Message -func (ce DeleteForm) Serialize(ctx serde.Context) ([]byte, error) { +func (d DeleteForm) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, ce) + data, err := format.Encode(ctx, d) if err != nil { return nil, xerrors.Errorf("failed to encode cancel form: %v", err) } @@ -308,13 +308,13 @@ func RandomID() (string, error) { // Fingerprint implements serde.Fingerprinter. If creates a fingerprint only // based on the formID and the shuffled ballots. -func (sb ShuffleBallots) Fingerprint(writer io.Writer) error { - _, err := writer.Write([]byte(sb.FormID)) +func (s ShuffleBallots) Fingerprint(writer io.Writer) error { + _, err := writer.Write([]byte(s.FormID)) if err != nil { return xerrors.Errorf("failed to write the form ID: %v", err) } - for _, ballot := range sb.ShuffledBallots { + for _, ballot := range s.ShuffledBallots { err := ballot.FingerPrint(writer) if err != nil { return xerrors.Errorf("failed to fingerprint shuffled ballot: %v", err) @@ -325,18 +325,18 @@ func (sb ShuffleBallots) Fingerprint(writer io.Writer) error { } // Fingerprint implements serde.Fingerprinter -func (rp RegisterPubShares) Fingerprint(writer io.Writer) error { - _, err := writer.Write([]byte(rp.FormID)) +func (r RegisterPubShares) Fingerprint(writer io.Writer) error { + _, err := writer.Write([]byte(r.FormID)) if err != nil { return xerrors.Errorf("failed to write the form ID: %v", err) } - _, err = writer.Write([]byte(strconv.Itoa(rp.Index))) + _, err = writer.Write([]byte(strconv.Itoa(r.Index))) if err != nil { return xerrors.Errorf("failed to write the pubShare index: %v", err) } - err = rp.Pubshares.Fingerprint(writer) + err = r.Pubshares.Fingerprint(writer) if err != nil { return xerrors.Errorf("failed to fingerprint pubShares: %V", err) } @@ -354,10 +354,10 @@ type AddAdmin struct { } // Serialize implements serde.Message -func (aa AddAdmin) Serialize(ctx serde.Context) ([]byte, error) { +func (a AddAdmin) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, aa) + data, err := format.Encode(ctx, a) if err != nil { return nil, xerrors.Errorf("failed to encode Add Admin: %v", err) } @@ -375,10 +375,10 @@ type RemoveAdmin struct { } // Serialize implements serde.Message -func (ra RemoveAdmin) Serialize(ctx serde.Context) ([]byte, error) { +func (r RemoveAdmin) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, ra) + data, err := format.Encode(ctx, r) if err != nil { return nil, xerrors.Errorf("failed to encode remove admin: %v", err) } From 49fd9a2fa02739d549af7d5b56d528d04aecad9c Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Tue, 23 Apr 2024 14:36:36 +0200 Subject: [PATCH 027/114] improve refactoring --- contracts/evoting/evoting.go | 145 ++++++++++++++++++++++++---------- contracts/evoting/mod.go | 17 ++-- contracts/evoting/mod_test.go | 21 +++-- 3 files changed, 125 insertions(+), 58 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index d927a7576..48c14ae0c 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -771,61 +771,52 @@ func (e evotingCommand) deleteForm(snap store.Snapshot, step execution.Step) err return nil } -// addAdminForm implements commands. It performs the ADD_ADMIN command -func (e evotingCommand) addAdminForm(snap store.Snapshot, step execution.Step) error { +// manageAdminForm implements commands. It performs the ADD or REMOVE ADMIN command +func (e evotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step, action AdminFormAction) error { msg, err := e.getTransaction(step.Current) if err != nil { return xerrors.Errorf(errGetTransaction, err) } - tx, ok := msg.(types.AddAdmin) - if !ok { - return xerrors.Errorf(errWrongTx, msg) - } - - form, formID, err := e.getAdminForm(tx.FormID, snap) - if err != nil { - return xerrors.Errorf("failed to get AdminForm: %v", err) - } + var form types.AdminForm + var formID []byte - err = form.AddAdmin(tx.UserID) - if err != nil { - return xerrors.Errorf("couldn't add admin: %v", err) - } + switch action { + case ADD: + tx, ok := msg.(types.AddAdmin) + if !ok { + return xerrors.Errorf(errWrongTx, msg) + } - formBuf, err := form.Serialize(e.context) - if err != nil { - return xerrors.Errorf("failed to marshal Form : %v", err) - } + form, formID, err = e.getAdminForm(tx.FormID, snap) + if err != nil { + return xerrors.Errorf("failed to get AdminForm: %v", err) + } - err = snap.Set(formID, formBuf) - if err != nil { - return xerrors.Errorf("failed to set value: %v", err) - } + err = form.AddAdmin(tx.UserID) + if err != nil { + return xerrors.Errorf("couldn't add admin: %v", err) + } - return nil -} + case REMOVE: + tx, ok := msg.(types.RemoveAdmin) + if !ok { + return xerrors.Errorf(errWrongTx, msg) + } -// removeAdminForm implements commands. It performs the REMOVE_ADMIN command -func (e evotingCommand) removeAdminForm(snap store.Snapshot, step execution.Step) error { - msg, err := e.getTransaction(step.Current) - if err != nil { - return xerrors.Errorf(errGetTransaction, err) - } + form, formID, err = e.getAdminForm(tx.FormID, snap) + if err != nil { + return xerrors.Errorf("failed to get AdminForm: %v", err) + } - tx, ok := msg.(types.RemoveAdmin) - if !ok { - return xerrors.Errorf(errWrongTx, msg) - } + err = form.RemoveAdmin(tx.UserID) + if err != nil { + return xerrors.Errorf("couldn't remove admin: %v", err) + } - form, formID, err := e.getAdminForm(tx.FormID, snap) - if err != nil { - return xerrors.Errorf("failed to get AdminForm: %v", err) - } + default: + return xerrors.Errorf("couldn't match the AdminForm action provided") - err = form.RemoveAdmin(tx.UserID) - if err != nil { - return xerrors.Errorf("couldn't remove admin: %v", err) } formBuf, err := form.Serialize(e.context) @@ -841,6 +832,76 @@ func (e evotingCommand) removeAdminForm(snap store.Snapshot, step execution.Step return nil } +//// addAdminForm implements commands. It performs the ADD_ADMIN command +//func (e evotingCommand) addAdminForm(snap store.Snapshot, step execution.Step) error { +// msg, err := e.getTransaction(step.Current) +// if err != nil { +// return xerrors.Errorf(errGetTransaction, err) +// } +// +// tx, ok := msg.(types.AddAdmin) +// if !ok { +// return xerrors.Errorf(errWrongTx, msg) +// } +// +// form, formID, err := e.getAdminForm(tx.FormID, snap) +// if err != nil { +// return xerrors.Errorf("failed to get AdminForm: %v", err) +// } +// +// err = form.AddAdmin(tx.UserID) +// if err != nil { +// return xerrors.Errorf("couldn't add admin: %v", err) +// } +// +// formBuf, err := form.Serialize(e.context) +// if err != nil { +// return xerrors.Errorf("failed to marshal Form : %v", err) +// } +// +// err = snap.Set(formID, formBuf) +// if err != nil { +// return xerrors.Errorf("failed to set value: %v", err) +// } +// +// return nil +//} +// +//// removeAdminForm implements commands. It performs the REMOVE_ADMIN command +//func (e evotingCommand) removeAdminForm(snap store.Snapshot, step execution.Step) error { +// msg, err := e.getTransaction(step.Current) +// if err != nil { +// return xerrors.Errorf(errGetTransaction, err) +// } +// +// tx, ok := msg.(types.RemoveAdmin) +// if !ok { +// return xerrors.Errorf(errWrongTx, msg) +// } +// +// form, formID, err := e.getAdminForm(tx.FormID, snap) +// if err != nil { +// return xerrors.Errorf("failed to get AdminForm: %v", err) +// } +// +// err = form.RemoveAdmin(tx.UserID) +// if err != nil { +// return xerrors.Errorf("couldn't remove admin: %v", err) +// } +// +// formBuf, err := form.Serialize(e.context) +// if err != nil { +// return xerrors.Errorf("failed to marshal Form : %v", err) +// } +// +// err = snap.Set(formID, formBuf) +// if err != nil { +// return xerrors.Errorf("failed to set value: %v", err) +// } +// +// return nil +//} + // isMemberOf is a utility function to verify if a public key is associated to a // member of the roster or not. Returns nil if it's the case. func isMemberOf(roster authority.Authority, publicKey []byte) error { diff --git a/contracts/evoting/mod.go b/contracts/evoting/mod.go index 08d5b9dc9..4700cf1d0 100644 --- a/contracts/evoting/mod.go +++ b/contracts/evoting/mod.go @@ -98,9 +98,7 @@ type commands interface { combineShares(snap store.Snapshot, step execution.Step) error cancelForm(snap store.Snapshot, step execution.Step) error deleteForm(snap store.Snapshot, step execution.Step) error - - addAdminForm(snap store.Snapshot, step execution.Step) error - removeAdminForm(snap store.Snapshot, step execution.Step) error + manageAdminForm(snap store.Snapshot, step execution.Step, action AdminFormAction) error } // Command defines a type of command for the value contract @@ -133,6 +131,15 @@ const ( CmdAddAdminForm Command = "ADD_ADMIN" // CmdRemoveAdminForm is the command to delete a form CmdRemoveAdminForm Command = "REMOVE_ADMIN" + // CmdRemoveAdminForm is the command to delete a form + CmdManageAdminForm Command = "MANAGE_ADMIN" +) + +type AdminFormAction int + +const ( + ADD AdminFormAction = iota + REMOVE ) // NewCreds creates new credentials for a evoting contract execution. We might @@ -256,12 +263,12 @@ func (c Contract) Execute(snap store.Snapshot, step execution.Step) error { return xerrors.Errorf("failed to delete form: %v", err) } case CmdAddAdminForm: - err := c.cmd.addAdminForm(snap, step) + err := c.cmd.manageAdminForm(snap, step, ADD) if err != nil { return xerrors.Errorf("failed to add admin: %v", err) } case CmdRemoveAdminForm: - err := c.cmd.removeAdminForm(snap, step) + err := c.cmd.manageAdminForm(snap, step, REMOVE) if err != nil { return xerrors.Errorf("failed to remove admin: %v", err) } diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 81354ef95..2019c90cc 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -107,6 +107,9 @@ func TestExecute(t *testing.T) { err = contract.Execute(fakeStore{}, makeStep(t, CmdArg, string(CmdRemoveAdminForm))) require.EqualError(t, err, fake.Err("failed to remove admin")) + err = contract.Execute(fakeStore{}, makeStep(t, CmdArg, string(CmdManageAdminForm))) + require.EqualError(t, err, fake.Err("failed to remove admin")) + err = contract.Execute(fakeStore{}, makeStep(t, CmdArg, "fake")) require.EqualError(t, err, "unknown command: fake") @@ -1130,13 +1133,13 @@ func TestCommand_AdminForm(t *testing.T) { require.NoError(t, err) // The following test are there to check error handling - err = cmd.addAdminForm(fake.NewSnapshot(), makeStep(t)) + err = cmd.manageAdminForm(fake.NewSnapshot(), makeStep(t), ADD) require.EqualError(t, err, getTransactionErr) - err = cmd.addAdminForm(fake.NewSnapshot(), makeStep(t, FormArg, "dummy")) + err = cmd.manageAdminForm(fake.NewSnapshot(), makeStep(t, FormArg, "dummy"), ADD) require.EqualError(t, err, unmarshalTransactionErr) - err = cmd.addAdminForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) + err = cmd.manageAdminForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data)), ADD) require.ErrorContains(t, err, "failed to get key") snap := fake.NewSnapshot() @@ -1144,7 +1147,7 @@ func TestCommand_AdminForm(t *testing.T) { err = snap.Set(dummyAdminFormIDBuff, invalidForm) require.NoError(t, err) - err = cmd.addAdminForm(snap, makeStep(t, FormArg, string(data))) + err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data)), ADD) require.ErrorContains(t, err, "failed to deserialize AdminForm") // We reset everything to perform the real test @@ -1158,7 +1161,7 @@ func TestCommand_AdminForm(t *testing.T) { require.NoError(t, err) // We perform below the command on the ledger - err = cmd.addAdminForm(snap, makeStep(t, FormArg, string(data))) + err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data)), ADD) require.NoError(t, err) // We retrieve the form on the ledger @@ -1182,7 +1185,7 @@ func TestCommand_AdminForm(t *testing.T) { require.NoError(t, err) // Publish the command on the ledger. - err = cmd.removeAdminForm(snap, makeStep(t, FormArg, string(data))) + err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data)), REMOVE) require.NoError(t, err) // We retrieve the Admin Form from the ledger. @@ -1454,11 +1457,7 @@ type fakeCmd struct { err error } -func (c fakeCmd) addAdminForm(snap store.Snapshot, step execution.Step) error { - return c.err -} - -func (c fakeCmd) removeAdminForm(snap store.Snapshot, step execution.Step) error { +func (c fakeCmd) manageAdminForm(snap store.Snapshot, step execution.Step, action AdminFormAction) error { return c.err } From fa9af1cc68fc76c5705db5adf9eb6f34563b5d81 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Tue, 23 Apr 2024 14:40:11 +0200 Subject: [PATCH 028/114] patch #1 --- contracts/evoting/mod.go | 2 -- contracts/evoting/mod_test.go | 3 --- 2 files changed, 5 deletions(-) diff --git a/contracts/evoting/mod.go b/contracts/evoting/mod.go index 4700cf1d0..12e9cc2bc 100644 --- a/contracts/evoting/mod.go +++ b/contracts/evoting/mod.go @@ -131,8 +131,6 @@ const ( CmdAddAdminForm Command = "ADD_ADMIN" // CmdRemoveAdminForm is the command to delete a form CmdRemoveAdminForm Command = "REMOVE_ADMIN" - // CmdRemoveAdminForm is the command to delete a form - CmdManageAdminForm Command = "MANAGE_ADMIN" ) type AdminFormAction int diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 2019c90cc..bd69af083 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -107,9 +107,6 @@ func TestExecute(t *testing.T) { err = contract.Execute(fakeStore{}, makeStep(t, CmdArg, string(CmdRemoveAdminForm))) require.EqualError(t, err, fake.Err("failed to remove admin")) - err = contract.Execute(fakeStore{}, makeStep(t, CmdArg, string(CmdManageAdminForm))) - require.EqualError(t, err, fake.Err("failed to remove admin")) - err = contract.Execute(fakeStore{}, makeStep(t, CmdArg, "fake")) require.EqualError(t, err, "unknown command: fake") From da0a080c44fba09e71fe0a922f7b77b91fb3f912 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Tue, 23 Apr 2024 14:43:16 +0200 Subject: [PATCH 029/114] remove old code --- contracts/evoting/evoting.go | 70 ------------------------------------ 1 file changed, 70 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 48c14ae0c..6638e23b1 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -832,76 +832,6 @@ func (e evotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step return nil } -//// addAdminForm implements commands. It performs the ADD_ADMIN command -//func (e evotingCommand) addAdminForm(snap store.Snapshot, step execution.Step) error { -// msg, err := e.getTransaction(step.Current) -// if err != nil { -// return xerrors.Errorf(errGetTransaction, err) -// } -// -// tx, ok := msg.(types.AddAdmin) -// if !ok { -// return xerrors.Errorf(errWrongTx, msg) -// } -// -// form, formID, err := e.getAdminForm(tx.FormID, snap) -// if err != nil { -// return xerrors.Errorf("failed to get AdminForm: %v", err) -// } -// -// err = form.AddAdmin(tx.UserID) -// if err != nil { -// return xerrors.Errorf("couldn't add admin: %v", err) -// } -// -// formBuf, err := form.Serialize(e.context) -// if err != nil { -// return xerrors.Errorf("failed to marshal Form : %v", err) -// } -// -// err = snap.Set(formID, formBuf) -// if err != nil { -// return xerrors.Errorf("failed to set value: %v", err) -// } -// -// return nil -//} -// -//// removeAdminForm implements commands. It performs the REMOVE_ADMIN command -//func (e evotingCommand) removeAdminForm(snap store.Snapshot, step execution.Step) error { -// msg, err := e.getTransaction(step.Current) -// if err != nil { -// return xerrors.Errorf(errGetTransaction, err) -// } -// -// tx, ok := msg.(types.RemoveAdmin) -// if !ok { -// return xerrors.Errorf(errWrongTx, msg) -// } -// -// form, formID, err := e.getAdminForm(tx.FormID, snap) -// if err != nil { -// return xerrors.Errorf("failed to get AdminForm: %v", err) -// } -// -// err = form.RemoveAdmin(tx.UserID) -// if err != nil { -// return xerrors.Errorf("couldn't remove admin: %v", err) -// } -// -// formBuf, err := form.Serialize(e.context) -// if err != nil { -// return xerrors.Errorf("failed to marshal Form : %v", err) -// } -// -// err = snap.Set(formID, formBuf) -// if err != nil { -// return xerrors.Errorf("failed to set value: %v", err) -// } -// -// return nil -//} - // isMemberOf is a utility function to verify if a public key is associated to a // member of the roster or not. Returns nil if it's the case. func isMemberOf(roster authority.Authority, publicKey []byte) error { From 28939bb8acdf7983f1454cfe58979f1646805870 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Tue, 23 Apr 2024 14:51:13 +0200 Subject: [PATCH 030/114] revert to longer var name --- contracts/evoting/types/admin.go | 22 +++---- contracts/evoting/types/transactions.go | 78 ++++++++++++------------- 2 files changed, 50 insertions(+), 50 deletions(-) diff --git a/contracts/evoting/types/admin.go b/contracts/evoting/types/admin.go index 955768074..c64a320ed 100644 --- a/contracts/evoting/types/admin.go +++ b/contracts/evoting/types/admin.go @@ -23,10 +23,10 @@ type AdminForm struct { AdminList []int } -func (a AdminForm) Serialize(ctx serde.Context) ([]byte, error) { +func (adminForm AdminForm) Serialize(ctx serde.Context) ([]byte, error) { format := adminFormFormat.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, a) + data, err := format.Encode(ctx, adminForm) if err != nil { return nil, xerrors.Errorf("Failed to encode AdminForm: %v", err) } @@ -34,7 +34,7 @@ func (a AdminForm) Serialize(ctx serde.Context) ([]byte, error) { return data, nil } -func (a AdminForm) Deserialize(ctx serde.Context, data []byte) (serde.Message, error) { +func (adminForm AdminForm) Deserialize(ctx serde.Context, data []byte) (serde.Message, error) { format := adminFormFormat.Get(ctx.GetFormat()) message, err := format.Decode(ctx, data) @@ -46,26 +46,26 @@ func (a AdminForm) Deserialize(ctx serde.Context, data []byte) (serde.Message, e } // AddAdmin add a new admin to the system. -func (a *AdminForm) AddAdmin(userID string) error { +func (adminForm *AdminForm) AddAdmin(userID string) error { sciperInt, err := strconv.Atoi(userID) if err != nil { return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) } - a.AdminList = append(a.AdminList, sciperInt) + adminForm.AdminList = append(adminForm.AdminList, sciperInt) return nil } // IsAdmin return the index of admin if userID is one, else return -1 -func (a *AdminForm) IsAdmin(userID string) int { +func (adminForm *AdminForm) IsAdmin(userID string) int { sciperInt, err := strconv.Atoi(userID) if err != nil { return -1 } - for i := 0; i < len(a.AdminList); i++ { - if a.AdminList[i] == sciperInt { + for i := 0; i < len(adminForm.AdminList); i++ { + if adminForm.AdminList[i] == sciperInt { return i } } @@ -74,19 +74,19 @@ func (a *AdminForm) IsAdmin(userID string) int { } // RemoveAdmin add a new admin to the system. -func (a *AdminForm) RemoveAdmin(userID string) error { +func (adminForm *AdminForm) RemoveAdmin(userID string) error { _, err := strconv.Atoi(userID) if err != nil { return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) } - index := a.IsAdmin(userID) + index := adminForm.IsAdmin(userID) if index < 0 { return xerrors.Errorf("Error while retrieving the index of the element.") } - a.AdminList = append(a.AdminList[:index], a.AdminList[index+1:]...) + adminForm.AdminList = append(adminForm.AdminList[:index], adminForm.AdminList[index+1:]...) return nil } diff --git a/contracts/evoting/types/transactions.go b/contracts/evoting/types/transactions.go index 01d5c8a4e..c04aca934 100644 --- a/contracts/evoting/types/transactions.go +++ b/contracts/evoting/types/transactions.go @@ -30,8 +30,8 @@ type FormsMetadata struct { type FormIDs []string // Contains checks if el is present. Return < 0 if not. -func (e FormIDs) Contains(el string) int { - for i, e1 := range e { +func (formID FormIDs) Contains(el string) int { + for i, e1 := range formID { if e1 == el { return i } @@ -41,21 +41,21 @@ func (e FormIDs) Contains(el string) int { } // Add adds a form ID or returns an error if already present -func (e *FormIDs) Add(id string) error { - if e.Contains(id) >= 0 { +func (formID *FormIDs) Add(id string) error { + if formID.Contains(id) >= 0 { return xerrors.Errorf("id %q already exist", id) } - *e = append(*e, id) + *formID = append(*formID, id) return nil } // Remove removes a form ID from the list, if it exists -func (e *FormIDs) Remove(id string) { - i := e.Contains(id) +func (formID *FormIDs) Remove(id string) { + i := formID.Contains(id) if i >= 0 { - *e = append((*e)[:i], (*e)[i+1:]...) + *formID = append((*formID)[:i], (*formID)[i+1:]...) } } @@ -74,10 +74,10 @@ func NewTransactionFactory(cf serde.Factory) TransactionFactory { } // Deserialize implements serde.Factory -func (t TransactionFactory) Deserialize(ctx serde.Context, data []byte) (serde.Message, error) { +func (transactionFactory TransactionFactory) Deserialize(ctx serde.Context, data []byte) (serde.Message, error) { format := transactionFormats.Get(ctx.GetFormat()) - ctx = serde.WithFactory(ctx, CiphervoteKey{}, t.ciphervoteFac) + ctx = serde.WithFactory(ctx, CiphervoteKey{}, transactionFactory.ciphervoteFac) message, err := format.Decode(ctx, data) if err != nil { @@ -96,10 +96,10 @@ type CreateForm struct { } // Serialize implements serde.Message -func (c CreateForm) Serialize(ctx serde.Context) ([]byte, error) { +func (createForm CreateForm) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, c) + data, err := format.Encode(ctx, createForm) if err != nil { return nil, xerrors.Errorf("failed to encode create form: %v", err) } @@ -116,10 +116,10 @@ type OpenForm struct { } // Serialize implements serde.Message -func (o OpenForm) Serialize(ctx serde.Context) ([]byte, error) { +func (openForm OpenForm) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, o) + data, err := format.Encode(ctx, openForm) if err != nil { return nil, xerrors.Errorf("failed to encode open form: %v", err) } @@ -138,10 +138,10 @@ type CastVote struct { } // Serialize implements serde.Message -func (c CastVote) Serialize(ctx serde.Context) ([]byte, error) { +func (castVote CastVote) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, c) + data, err := format.Encode(ctx, castVote) if err != nil { return nil, xerrors.Errorf("failed to encode cast vote: %v", err) } @@ -159,10 +159,10 @@ type CloseForm struct { } // Serialize implements serde.Message -func (c CloseForm) Serialize(ctx serde.Context) ([]byte, error) { +func (closeForm CloseForm) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, c) + data, err := format.Encode(ctx, closeForm) if err != nil { return nil, xerrors.Errorf("failed to encode close form: %v", err) } @@ -191,10 +191,10 @@ type ShuffleBallots struct { } // Serialize implements serde.Message -func (s ShuffleBallots) Serialize(ctx serde.Context) ([]byte, error) { +func (shuffleBallots ShuffleBallots) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, s) + data, err := format.Encode(ctx, shuffleBallots) if err != nil { return nil, xerrors.Errorf("failed to encode shuffle ballots: %v", err) } @@ -221,10 +221,10 @@ type RegisterPubShares struct { } // Serialize implements serde.Message -func (r RegisterPubShares) Serialize(ctx serde.Context) ([]byte, error) { +func (registerPubShares RegisterPubShares) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, r) + data, err := format.Encode(ctx, registerPubShares) if err != nil { return nil, xerrors.Errorf("failed to encode register pubShares: %v", err) } @@ -243,10 +243,10 @@ type CombineShares struct { } // Serialize implements serde.Message -func (c CombineShares) Serialize(ctx serde.Context) ([]byte, error) { +func (combineShares CombineShares) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, c) + data, err := format.Encode(ctx, combineShares) if err != nil { return nil, xerrors.Errorf("failed to encode decrypt ballot: %v", err) } @@ -264,10 +264,10 @@ type CancelForm struct { } // Serialize implements serde.Message -func (c CancelForm) Serialize(ctx serde.Context) ([]byte, error) { +func (cancelForm CancelForm) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, c) + data, err := format.Encode(ctx, cancelForm) if err != nil { return nil, xerrors.Errorf("failed to encode cancel form: %v", err) } @@ -284,10 +284,10 @@ type DeleteForm struct { } // Serialize implements serde.Message -func (d DeleteForm) Serialize(ctx serde.Context) ([]byte, error) { +func (deleteForm DeleteForm) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, d) + data, err := format.Encode(ctx, deleteForm) if err != nil { return nil, xerrors.Errorf("failed to encode cancel form: %v", err) } @@ -308,13 +308,13 @@ func RandomID() (string, error) { // Fingerprint implements serde.Fingerprinter. If creates a fingerprint only // based on the formID and the shuffled ballots. -func (s ShuffleBallots) Fingerprint(writer io.Writer) error { - _, err := writer.Write([]byte(s.FormID)) +func (shuffleBallots ShuffleBallots) Fingerprint(writer io.Writer) error { + _, err := writer.Write([]byte(shuffleBallots.FormID)) if err != nil { return xerrors.Errorf("failed to write the form ID: %v", err) } - for _, ballot := range s.ShuffledBallots { + for _, ballot := range shuffleBallots.ShuffledBallots { err := ballot.FingerPrint(writer) if err != nil { return xerrors.Errorf("failed to fingerprint shuffled ballot: %v", err) @@ -325,18 +325,18 @@ func (s ShuffleBallots) Fingerprint(writer io.Writer) error { } // Fingerprint implements serde.Fingerprinter -func (r RegisterPubShares) Fingerprint(writer io.Writer) error { - _, err := writer.Write([]byte(r.FormID)) +func (registerPubShares RegisterPubShares) Fingerprint(writer io.Writer) error { + _, err := writer.Write([]byte(registerPubShares.FormID)) if err != nil { return xerrors.Errorf("failed to write the form ID: %v", err) } - _, err = writer.Write([]byte(strconv.Itoa(r.Index))) + _, err = writer.Write([]byte(strconv.Itoa(registerPubShares.Index))) if err != nil { return xerrors.Errorf("failed to write the pubShare index: %v", err) } - err = r.Pubshares.Fingerprint(writer) + err = registerPubShares.Pubshares.Fingerprint(writer) if err != nil { return xerrors.Errorf("failed to fingerprint pubShares: %V", err) } @@ -354,10 +354,10 @@ type AddAdmin struct { } // Serialize implements serde.Message -func (a AddAdmin) Serialize(ctx serde.Context) ([]byte, error) { +func (addAdmin AddAdmin) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, a) + data, err := format.Encode(ctx, addAdmin) if err != nil { return nil, xerrors.Errorf("failed to encode Add Admin: %v", err) } @@ -375,10 +375,10 @@ type RemoveAdmin struct { } // Serialize implements serde.Message -func (r RemoveAdmin) Serialize(ctx serde.Context) ([]byte, error) { +func (removeAdmin RemoveAdmin) Serialize(ctx serde.Context) ([]byte, error) { format := transactionFormats.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, r) + data, err := format.Encode(ctx, removeAdmin) if err != nil { return nil, xerrors.Errorf("failed to encode remove admin: %v", err) } From 9f1de8bb426071517dc0bcfd3467fa05ebdf433a Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Tue, 23 Apr 2024 15:20:24 +0200 Subject: [PATCH 031/114] attempt to simplify the code --- contracts/evoting/evoting.go | 33 +++++++++++---------------------- contracts/evoting/mod.go | 13 +++---------- contracts/evoting/mod_test.go | 14 +++++++------- 3 files changed, 21 insertions(+), 39 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 6638e23b1..e697f7b68 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -772,7 +772,7 @@ func (e evotingCommand) deleteForm(snap store.Snapshot, step execution.Step) err } // manageAdminForm implements commands. It performs the ADD or REMOVE ADMIN command -func (e evotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step, action AdminFormAction) error { +func (e evotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { return xerrors.Errorf(errGetTransaction, err) @@ -781,42 +781,31 @@ func (e evotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step var form types.AdminForm var formID []byte - switch action { - case ADD: - tx, ok := msg.(types.AddAdmin) - if !ok { - return xerrors.Errorf(errWrongTx, msg) - } + txAddAdmin, okAddAdmin := msg.(types.AddAdmin) + txRemoveAdmin, okRemoveAdmin := msg.(types.RemoveAdmin) - form, formID, err = e.getAdminForm(tx.FormID, snap) + if okAddAdmin { + form, formID, err = e.getAdminForm(txAddAdmin.FormID, snap) if err != nil { return xerrors.Errorf("failed to get AdminForm: %v", err) } - err = form.AddAdmin(tx.UserID) + err = form.AddAdmin(txAddAdmin.UserID) if err != nil { return xerrors.Errorf("couldn't add admin: %v", err) } - - case REMOVE: - tx, ok := msg.(types.RemoveAdmin) - if !ok { - return xerrors.Errorf(errWrongTx, msg) - } - - form, formID, err = e.getAdminForm(tx.FormID, snap) + } else if okRemoveAdmin { + form, formID, err = e.getAdminForm(txRemoveAdmin.FormID, snap) if err != nil { return xerrors.Errorf("failed to get AdminForm: %v", err) } - err = form.RemoveAdmin(tx.UserID) + err = form.RemoveAdmin(txRemoveAdmin.UserID) if err != nil { return xerrors.Errorf("couldn't remove admin: %v", err) } - - default: - return xerrors.Errorf("couldn't match the AdminForm action provided") - + } else { + return xerrors.Errorf(errWrongTx, msg) } formBuf, err := form.Serialize(e.context) diff --git a/contracts/evoting/mod.go b/contracts/evoting/mod.go index 12e9cc2bc..5cdf3b803 100644 --- a/contracts/evoting/mod.go +++ b/contracts/evoting/mod.go @@ -98,7 +98,7 @@ type commands interface { combineShares(snap store.Snapshot, step execution.Step) error cancelForm(snap store.Snapshot, step execution.Step) error deleteForm(snap store.Snapshot, step execution.Step) error - manageAdminForm(snap store.Snapshot, step execution.Step, action AdminFormAction) error + manageAdminForm(snap store.Snapshot, step execution.Step) error } // Command defines a type of command for the value contract @@ -133,13 +133,6 @@ const ( CmdRemoveAdminForm Command = "REMOVE_ADMIN" ) -type AdminFormAction int - -const ( - ADD AdminFormAction = iota - REMOVE -) - // NewCreds creates new credentials for a evoting contract execution. We might // want to use in the future a separate credential for each command. func NewCreds() access.Credential { @@ -261,12 +254,12 @@ func (c Contract) Execute(snap store.Snapshot, step execution.Step) error { return xerrors.Errorf("failed to delete form: %v", err) } case CmdAddAdminForm: - err := c.cmd.manageAdminForm(snap, step, ADD) + err := c.cmd.manageAdminForm(snap, step) if err != nil { return xerrors.Errorf("failed to add admin: %v", err) } case CmdRemoveAdminForm: - err := c.cmd.manageAdminForm(snap, step, REMOVE) + err := c.cmd.manageAdminForm(snap, step) if err != nil { return xerrors.Errorf("failed to remove admin: %v", err) } diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index bd69af083..9a0b77d32 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1130,13 +1130,13 @@ func TestCommand_AdminForm(t *testing.T) { require.NoError(t, err) // The following test are there to check error handling - err = cmd.manageAdminForm(fake.NewSnapshot(), makeStep(t), ADD) + err = cmd.manageAdminForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) - err = cmd.manageAdminForm(fake.NewSnapshot(), makeStep(t, FormArg, "dummy"), ADD) + err = cmd.manageAdminForm(fake.NewSnapshot(), makeStep(t, FormArg, "dummy")) require.EqualError(t, err, unmarshalTransactionErr) - err = cmd.manageAdminForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data)), ADD) + err = cmd.manageAdminForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to get key") snap := fake.NewSnapshot() @@ -1144,7 +1144,7 @@ func TestCommand_AdminForm(t *testing.T) { err = snap.Set(dummyAdminFormIDBuff, invalidForm) require.NoError(t, err) - err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data)), ADD) + err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to deserialize AdminForm") // We reset everything to perform the real test @@ -1158,7 +1158,7 @@ func TestCommand_AdminForm(t *testing.T) { require.NoError(t, err) // We perform below the command on the ledger - err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data)), ADD) + err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data))) require.NoError(t, err) // We retrieve the form on the ledger @@ -1182,7 +1182,7 @@ func TestCommand_AdminForm(t *testing.T) { require.NoError(t, err) // Publish the command on the ledger. - err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data)), REMOVE) + err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data))) require.NoError(t, err) // We retrieve the Admin Form from the ledger. @@ -1454,7 +1454,7 @@ type fakeCmd struct { err error } -func (c fakeCmd) manageAdminForm(snap store.Snapshot, step execution.Step, action AdminFormAction) error { +func (c fakeCmd) manageAdminForm(snap store.Snapshot, step execution.Step) error { return c.err } From 202a266ac5be80d49d3ecda3495b65b9c7dd1815 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 25 Apr 2024 09:53:54 +0200 Subject: [PATCH 032/114] address review --- contracts/evoting/admin_test.go | 6 +++--- contracts/evoting/mod_test.go | 12 +++++++++--- contracts/evoting/types/admin.go | 6 +++--- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/contracts/evoting/admin_test.go b/contracts/evoting/admin_test.go index 2a0427c79..d0fe8e419 100644 --- a/contracts/evoting/admin_test.go +++ b/contracts/evoting/admin_test.go @@ -55,16 +55,16 @@ func TestAdmin_AddAdminAndRemoveAdmin(t *testing.T) { adminForm := types.AdminForm{FormID: adminFormID, AdminList: adminFormList} - res := adminForm.IsAdmin(myTestID) + res := adminForm.GetAdminIndex(myTestID) require.Equal(t, -1, res) err := adminForm.AddAdmin(myTestID) require.NoError(t, err) - res = adminForm.IsAdmin(myTestID) + res = adminForm.GetAdminIndex(myTestID) require.Equal(t, 0, res) err = adminForm.RemoveAdmin(myTestID) require.NoError(t, err) - res = adminForm.IsAdmin(myTestID) + res = adminForm.GetAdminIndex(myTestID) require.Equal(t, -1, res) } diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 9a0b77d32..45bcac2d8 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1130,20 +1130,26 @@ func TestCommand_AdminForm(t *testing.T) { require.NoError(t, err) // The following test are there to check error handling + + // Checking that on a Fake Snapshot it won't be able to find the transaction err = cmd.manageAdminForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) + // Checking that providing a dummy data as argument, the form will not recognize it + // and won't be able to unmarshal it. err = cmd.manageAdminForm(fake.NewSnapshot(), makeStep(t, FormArg, "dummy")) require.EqualError(t, err, unmarshalTransactionErr) + // Checking that given a BadSnapshot, it will not be able to retrieve the AdminForm on the store. err = cmd.manageAdminForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to get key") snap := fake.NewSnapshot() + // Checking that given the form set in the Snapshot which is invalid, then it will not be able + // to deserialize the AdminForm to perform the command. err = snap.Set(dummyAdminFormIDBuff, invalidForm) require.NoError(t, err) - err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to deserialize AdminForm") @@ -1173,7 +1179,7 @@ func TestCommand_AdminForm(t *testing.T) { // We check that our dummy User is now admin // (if not admin return -1; else return admin index in AdminForm). - require.True(t, adminForm.IsAdmin(dummyUID) > -1) + require.True(t, adminForm.GetAdminIndex(dummyUID) > -1) // Now we want to remove its admin privilege. // Initialization of the command @@ -1196,7 +1202,7 @@ func TestCommand_AdminForm(t *testing.T) { require.True(t, ok) // We check that now our dummy user is not admin anymore (return -1) - require.True(t, adminForm.IsAdmin(dummyUID) == -1) + require.True(t, adminForm.GetAdminIndex(dummyUID) == -1) } // ----------------------------------------------------------------------------- diff --git a/contracts/evoting/types/admin.go b/contracts/evoting/types/admin.go index c64a320ed..aa57c72e3 100644 --- a/contracts/evoting/types/admin.go +++ b/contracts/evoting/types/admin.go @@ -57,8 +57,8 @@ func (adminForm *AdminForm) AddAdmin(userID string) error { return nil } -// IsAdmin return the index of admin if userID is one, else return -1 -func (adminForm *AdminForm) IsAdmin(userID string) int { +// GetAdminIndex return the index of admin if userID is one, else return -1 +func (adminForm *AdminForm) GetAdminIndex(userID string) int { sciperInt, err := strconv.Atoi(userID) if err != nil { return -1 @@ -80,7 +80,7 @@ func (adminForm *AdminForm) RemoveAdmin(userID string) error { return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) } - index := adminForm.IsAdmin(userID) + index := adminForm.GetAdminIndex(userID) if index < 0 { return xerrors.Errorf("Error while retrieving the index of the element.") From 4a6d8789dd320b03868f7f1316530670ec83bd10 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 25 Apr 2024 09:58:49 +0200 Subject: [PATCH 033/114] patch vet check --- contracts/evoting/mod_test.go | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 45bcac2d8..5f4652eee 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1135,19 +1135,20 @@ func TestCommand_AdminForm(t *testing.T) { err = cmd.manageAdminForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) - // Checking that providing a dummy data as argument, the form will not recognize it - // and won't be able to unmarshal it. + // Checking that providing a dummy data as argument, the form will not + // recognize it and won't be able to unmarshal it. err = cmd.manageAdminForm(fake.NewSnapshot(), makeStep(t, FormArg, "dummy")) require.EqualError(t, err, unmarshalTransactionErr) - // Checking that given a BadSnapshot, it will not be able to retrieve the AdminForm on the store. + // Checking that given a BadSnapshot, it will not be able to retrieve + // the AdminForm on the store. err = cmd.manageAdminForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to get key") snap := fake.NewSnapshot() - // Checking that given the form set in the Snapshot which is invalid, then it will not be able - // to deserialize the AdminForm to perform the command. + // Checking that given the form set in the Snapshot which is invalid, then it + // will not be able to deserialize the AdminForm to perform the command. err = snap.Set(dummyAdminFormIDBuff, invalidForm) require.NoError(t, err) err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data))) From 78e854256ab89108708aefefade2a08f9d1cb827 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 25 Apr 2024 16:17:23 +0200 Subject: [PATCH 034/114] final review --- contracts/evoting/mod_test.go | 7 ++++--- contracts/evoting/types/admin.go | 9 ++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 5f4652eee..1fa472e0d 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1131,7 +1131,8 @@ func TestCommand_AdminForm(t *testing.T) { // The following test are there to check error handling - // Checking that on a Fake Snapshot it won't be able to find the transaction + // Checking that if no AdminForm is on the blockchain, + // It won't be able to find the transaction. err = cmd.manageAdminForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -1140,8 +1141,8 @@ func TestCommand_AdminForm(t *testing.T) { err = cmd.manageAdminForm(fake.NewSnapshot(), makeStep(t, FormArg, "dummy")) require.EqualError(t, err, unmarshalTransactionErr) - // Checking that given a BadSnapshot, it will not be able to retrieve - // the AdminForm on the store. + // Checking that given a Blockchain that always returns an error, + // it will not be able to retrieve the AdminForm on the store. err = cmd.manageAdminForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to get key") diff --git a/contracts/evoting/types/admin.go b/contracts/evoting/types/admin.go index aa57c72e3..46af6f087 100644 --- a/contracts/evoting/types/admin.go +++ b/contracts/evoting/types/admin.go @@ -52,6 +52,10 @@ func (adminForm *AdminForm) AddAdmin(userID string) error { return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) } + if sciperInt < 100000 || sciperInt > 999999 { + return xerrors.Errorf("SCIPER %v is out of range.", sciperInt) + } + adminForm.AdminList = append(adminForm.AdminList, sciperInt) return nil @@ -75,11 +79,6 @@ func (adminForm *AdminForm) GetAdminIndex(userID string) int { // RemoveAdmin add a new admin to the system. func (adminForm *AdminForm) RemoveAdmin(userID string) error { - _, err := strconv.Atoi(userID) - if err != nil { - return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) - } - index := adminForm.GetAdminIndex(userID) if index < 0 { From 5f1827af1446ccff869117671ec894a3d879febc Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Mon, 22 Apr 2024 14:03:04 +0200 Subject: [PATCH 035/114] modification of data struct + create form --- contracts/evoting/evoting.go | 6 ++++++ contracts/evoting/json/forms.go | 10 ++++++++++ contracts/evoting/types/election.go | 6 ++++++ 3 files changed, 22 insertions(+) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index e697f7b68..176a437f8 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -85,6 +85,10 @@ func (e evotingCommand) createForm(snap store.Snapshot, step execution.Step) err Indexes: make([]int, 0), } + // Initial owner is the creator + owners := make([]string, 1) + owners[0] = tx.UserID + form := types.Form{ FormID: hex.EncodeToString(formIDBuf), Configuration: tx.Configuration, @@ -98,6 +102,8 @@ func (e evotingCommand) createForm(snap store.Snapshot, step execution.Step) err // that 1/3 of the participants go away, the form will never end. Roster: roster, ShuffleThreshold: threshold.ByzantineThreshold(roster.Len()), + Owners: owners, + Voters: make([]string, 0), } PromFormStatus.WithLabelValues(form.FormID).Set(float64(form.Status)) diff --git a/contracts/evoting/json/forms.go b/contracts/evoting/json/forms.go index 2640cfd80..430a0788a 100644 --- a/contracts/evoting/json/forms.go +++ b/contracts/evoting/json/forms.go @@ -76,6 +76,8 @@ func (formFormat) Encode(ctx serde.Context, message serde.Message) ([]byte, erro PubsharesUnits: pubsharesUnits, DecryptedBallots: m.DecryptedBallots, RosterBuf: rosterBuf, + Owners: m.Owners, + Voters: m.Voters, } buff, err := ctx.Marshal(&formJSON) @@ -159,6 +161,8 @@ func (formFormat) Decode(ctx serde.Context, data []byte) (serde.Message, error) PubsharesUnits: pubSharesSubmissions, DecryptedBallots: formJSON.DecryptedBallots, Roster: roster, + Owners: formJSON.Owners, + Voters: formJSON.Voters, }, nil } @@ -206,6 +210,12 @@ type FormJSON struct { // authority.Authority. RosterBuf []byte + + // Store the list of admins SCIPER that are Owners of the form. + Owners []string + + // Store the list of SCIPER of user that are Voters on the form. + Voters []string } // ShuffleInstanceJSON defines the JSON representation of a shuffle instance diff --git a/contracts/evoting/types/election.go b/contracts/evoting/types/election.go index 90858e0a4..04c4b4f9b 100644 --- a/contracts/evoting/types/election.go +++ b/contracts/evoting/types/election.go @@ -112,6 +112,12 @@ type Form struct { // authority.Authority. Roster authority.Authority + + // Store the list of admins SCIPER that are Owners of the form. + Owners []string + + // Store the list of SCIPER of user that are Voters on the form. + Voters []string } // Serialize implements serde.Message From 8b5a014900192dd1c5d1858bd57a324923cf74bf Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Mon, 22 Apr 2024 14:29:36 +0200 Subject: [PATCH 036/114] implement the basic logic for owners and voters --- contracts/evoting/json/forms.go | 4 +- contracts/evoting/types/election.go | 102 +++++++++++++++++++++++++++- 2 files changed, 102 insertions(+), 4 deletions(-) diff --git a/contracts/evoting/json/forms.go b/contracts/evoting/json/forms.go index 430a0788a..7a0fc7f84 100644 --- a/contracts/evoting/json/forms.go +++ b/contracts/evoting/json/forms.go @@ -212,10 +212,10 @@ type FormJSON struct { RosterBuf []byte // Store the list of admins SCIPER that are Owners of the form. - Owners []string + Owners []int // Store the list of SCIPER of user that are Voters on the form. - Voters []string + Voters []int } // ShuffleInstanceJSON defines the JSON representation of a shuffle instance diff --git a/contracts/evoting/types/election.go b/contracts/evoting/types/election.go index 04c4b4f9b..68509392e 100644 --- a/contracts/evoting/types/election.go +++ b/contracts/evoting/types/election.go @@ -6,6 +6,7 @@ import ( "encoding/hex" "fmt" "io" + "strconv" "go.dedis.ch/dela/core/ordering/cosipbft/authority" ctypes "go.dedis.ch/dela/core/ordering/cosipbft/types" @@ -114,10 +115,10 @@ type Form struct { Roster authority.Authority // Store the list of admins SCIPER that are Owners of the form. - Owners []string + Owners []int // Store the list of SCIPER of user that are Voters on the form. - Voters []string + Voters []int } // Serialize implements serde.Message @@ -415,3 +416,100 @@ type PubsharesUnits struct { // PubsharesUnit Indexes []int } + +// AddVoter add a new admin to the system. +func (s *Form) AddVoter(userID string) error { + sciperInt, err := strconv.Atoi(userID) + if err != nil { + return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) + } + + s.Voters = append(s.Voters, sciperInt) + + return nil +} + +// IsVoter return the index of admin if userID is one, else return -1 +func (s *Form) IsVoter(userID string) int { + sciperInt, err := strconv.Atoi(userID) + if err != nil { + return -1 + } + + for i := 0; i < len(s.Voters); i++ { + if s.Voters[i] == sciperInt { + return i + } + } + + return -1 +} + +// RemoveVoter add a new admin to the system. +func (s *Form) RemoveVoter(userID string) error { + _, err := strconv.Atoi(userID) + if err != nil { + return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) + } + + index := s.IsVoter(userID) + + if index < 0 { + return xerrors.Errorf("Error while retrieving the index of the element.") + } + + s.Voters = append(s.Voters[:index], s.Voters[index+1:]...) + return nil +} + +// AddOwner add a new admin to the system. +func (s *Form) AddOwner(userID string) error { + sciperInt, err := strconv.Atoi(userID) + if err != nil { + return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) + } + + // TODO need to check that the new user is admin ! + s.Owners = append(s.Owners, sciperInt) + + return nil +} + +// IsOwner return the index of admin if userID is one, else return -1 +func (s *Form) IsOwner(userID string) int { + sciperInt, err := strconv.Atoi(userID) + if err != nil { + return -1 + } + + for i := 0; i < len(s.Owners); i++ { + if s.Owners[i] == sciperInt { + return i + } + } + + return -1 +} + +// RemoveOwner add a new admin to the system. +func (s *Form) RemoveOwner(userID string) error { + _, err := strconv.Atoi(userID) + if err != nil { + return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) + } + + index := s.IsOwner(userID) + + if index < 0 { + return xerrors.Errorf("Error while retrieving the index of the element.") + } + + // We don't want to have a form without any Owners. + if len(s.Owners) <= 1 { + return xerrors.Errorf("Error, cannot remove this owner because it is the " + + "only one remaining for this form") + } + + s.Owners = append(s.Owners[:index], s.Owners[index+1:]...) + return nil +} From f1170815cf679b6c7c59df95b915cb685a70d826 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Mon, 22 Apr 2024 14:32:58 +0200 Subject: [PATCH 037/114] patch sciper type --- contracts/evoting/evoting.go | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 176a437f8..bec36c76c 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -9,6 +9,7 @@ import ( "encoding/hex" "encoding/json" "math/rand" + "strconv" "strings" "go.dedis.ch/dela" @@ -86,8 +87,14 @@ func (e evotingCommand) createForm(snap store.Snapshot, step execution.Step) err } // Initial owner is the creator - owners := make([]string, 1) - owners[0] = tx.UserID + owners := make([]int, 1) + + sciperInt, err := strconv.Atoi(tx.UserID) + if err != nil { + return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) + } + + owners[0] = sciperInt form := types.Form{ FormID: hex.EncodeToString(formIDBuf), @@ -103,7 +110,7 @@ func (e evotingCommand) createForm(snap store.Snapshot, step execution.Step) err Roster: roster, ShuffleThreshold: threshold.ByzantineThreshold(roster.Len()), Owners: owners, - Voters: make([]string, 0), + Voters: make([]int, 0), } PromFormStatus.WithLabelValues(form.FormID).Set(float64(form.Status)) From fff22fec77463f146c36ef9ee05f213f4885b32c Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Mon, 22 Apr 2024 14:40:19 +0200 Subject: [PATCH 038/114] patch dummy userid to sciper format --- contracts/evoting/mod_test.go | 9 +++++---- integration/integration_test.go | 3 ++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 1fa472e0d..62b8560c1 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -34,6 +34,7 @@ var dummyAdminFormIDBuff = []byte("dummyAdminID") var fakeFormID = hex.EncodeToString(dummyFormIDBuff) var fakeAdminFormID = hex.EncodeToString(dummyAdminFormIDBuff) var fakeCommonSigner = bls.NewSigner() +var dummyUserID = "123456" const getTransactionErr = "failed to get transaction: \"evoting:arg\" not found in tx arg" const unmarshalTransactionErr = "failed to get transaction: failed to deserialize " + @@ -130,7 +131,7 @@ func TestCommand_CreateForm(t *testing.T) { } createForm := types.CreateForm{ - UserID: "dummyUserID", + UserID: dummyUserID, } data, err := createForm.Serialize(ctx) @@ -319,7 +320,7 @@ func TestCommand_CloseForm(t *testing.T) { closeForm := types.CloseForm{ FormID: fakeFormID, - UserID: "dummyUserId", + UserID: dummyUserID, } data, err := closeForm.Serialize(ctx) @@ -945,7 +946,7 @@ func TestCommand_RegisterPubShares(t *testing.T) { func TestCommand_DecryptBallots(t *testing.T) { decryptBallot := types.CombineShares{ FormID: fakeFormID, - UserID: hex.EncodeToString([]byte("dummyUserId")), + UserID: dummyUserID, } data, err := decryptBallot.Serialize(ctx) @@ -1044,7 +1045,7 @@ func TestCommand_DecryptBallots(t *testing.T) { func TestCommand_CancelForm(t *testing.T) { cancelForm := types.CancelForm{ FormID: fakeFormID, - UserID: "dummyUserId", + UserID: dummyUserID, } data, err := cancelForm.Serialize(ctx) diff --git a/integration/integration_test.go b/integration/integration_test.go index 4833a3663..453e223d9 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -34,7 +34,8 @@ func getIntegrationTest(numNodes, numVotes int) func(*testing.T) { return func(t *testing.T) { t.Parallel() - adminID := "first admin" + // Dummy UserID in SCIPER format + adminID := "123456" // ##### SETUP ENV ##### From e9f505abad26aee06a4c986bc108dd54f42d97de Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Mon, 22 Apr 2024 14:51:15 +0200 Subject: [PATCH 039/114] patch dummy userid to sciper format part 2 --- integration/integration_test.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/integration/integration_test.go b/integration/integration_test.go index 453e223d9..6b8489126 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -174,7 +174,8 @@ func getIntegrationTestCrash(numNodes, numVotes, failingNodes int) func(*testing return func(t *testing.T) { t.Parallel() - adminID := "first admin" + // Dummy UserID in SCIPER format + adminID := "123456" // ##### SETUP ENV ##### @@ -322,7 +323,8 @@ func getIntegrationTestCrash(numNodes, numVotes, failingNodes int) func(*testing func getIntegrationBenchmark(numNodes, numVotes int) func(*testing.B) { return func(b *testing.B) { - adminID := "first admin" + // Dummy UserID in SCIPER format + adminID := "123456" // ##### SETUP ENV ##### From c767aa7dff97e890c34eedf2000a3925952e8d41 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 24 Apr 2024 12:53:30 +0200 Subject: [PATCH 040/114] improve code readability --- contracts/evoting/types/election.go | 102 ++++++++++++++-------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/contracts/evoting/types/election.go b/contracts/evoting/types/election.go index 68509392e..58b4135a0 100644 --- a/contracts/evoting/types/election.go +++ b/contracts/evoting/types/election.go @@ -122,10 +122,10 @@ type Form struct { } // Serialize implements serde.Message -func (e Form) Serialize(ctx serde.Context) ([]byte, error) { +func (form Form) Serialize(ctx serde.Context) ([]byte, error) { format := formFormat.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, e) + data, err := format.Encode(ctx, form) if err != nil { return nil, xerrors.Errorf("failed to encode form: %v", err) } @@ -151,11 +151,11 @@ func NewFormFactory(cf serde.Factory, rf authority.Factory) FormFactory { } // Deserialize implements serde.Factory -func (e FormFactory) Deserialize(ctx serde.Context, data []byte) (serde.Message, error) { +func (formFactory FormFactory) Deserialize(ctx serde.Context, data []byte) (serde.Message, error) { format := formFormat.Get(ctx.GetFormat()) - ctx = serde.WithFactory(ctx, CiphervoteKey{}, e.ciphervoteFac) - ctx = serde.WithFactory(ctx, ctypes.RosterKey{}, e.rosterFac) + ctx = serde.WithFactory(ctx, CiphervoteKey{}, formFactory.ciphervoteFac) + ctx = serde.WithFactory(ctx, ctypes.RosterKey{}, formFactory.rosterFac) message, err := format.Decode(ctx, data) if err != nil { @@ -200,38 +200,38 @@ func FormFromStore(ctx serde.Context, formFac serde.Factory, formIDHex string, // ChunksPerBallot returns the number of chunks of El Gamal pairs needed to // represent an encrypted ballot, knowing that one chunk is 29 bytes at most. -func (e *Form) ChunksPerBallot() int { - if e.BallotSize%29 == 0 { - return e.BallotSize / 29 +func (form *Form) ChunksPerBallot() int { + if form.BallotSize%29 == 0 { + return form.BallotSize / 29 } - return e.BallotSize/29 + 1 + return form.BallotSize/29 + 1 } // CastVote stores the new vote in the memory. -func (s *Form) CastVote(ctx serde.Context, st store.Snapshot, userID string, ciphervote Ciphervote) error { +func (form *Form) CastVote(ctx serde.Context, st store.Snapshot, userID string, ciphervote Ciphervote) error { var suff Suffragia var blockID []byte - if s.BallotCount%BallotsPerBlock == 0 { + if form.BallotCount%BallotsPerBlock == 0 { // Need to create a random ID for storing the ballots. // H( formID | ballotcount ) // should be random enough, even if it's previsible. - id, err := hex.DecodeString(s.FormID) + id, err := hex.DecodeString(form.FormID) if err != nil { return xerrors.Errorf("couldn't decode formID: %v", err) } h := sha256.New() h.Write(id) - binary.LittleEndian.PutUint32(id, s.BallotCount) + binary.LittleEndian.PutUint32(id, form.BallotCount) blockID = h.Sum(id[0:4])[:32] err = st.Set(blockID, []byte{}) if err != nil { return xerrors.Errorf("couldn't store new ballot block: %v", err) } - s.SuffragiaIDs = append(s.SuffragiaIDs, blockID) - s.SuffragiaHashes = append(s.SuffragiaHashes, []byte{}) + form.SuffragiaIDs = append(form.SuffragiaIDs, blockID) + form.SuffragiaHashes = append(form.SuffragiaHashes, []byte{}) } else { - blockID = s.SuffragiaIDs[len(s.SuffragiaIDs)-1] + blockID = form.SuffragiaIDs[len(form.SuffragiaIDs)-1] buf, err := st.Get(blockID) if err != nil { return xerrors.Errorf("couldn't get ballots block: %v", err) @@ -250,7 +250,7 @@ func (s *Form) CastVote(ctx serde.Context, st store.Snapshot, userID string, cip for i := uint32(1); i < BallotsPerBlock; i++ { suff.CastVote(fmt.Sprintf("%s-%d", userID, i), ciphervote) } - s.BallotCount += BallotsPerBlock - 1 + form.BallotCount += BallotsPerBlock - 1 } buf, err := suff.Serialize(ctx) if err != nil { @@ -260,7 +260,7 @@ func (s *Form) CastVote(ctx serde.Context, st store.Snapshot, userID string, cip if err != nil { xerrors.Errorf("couldn't set new ballots block: %v", err) } - s.BallotCount += 1 + form.BallotCount += 1 return nil } @@ -268,9 +268,9 @@ func (s *Form) CastVote(ctx serde.Context, st store.Snapshot, userID string, cip // be called rarely, as it might take a long time. // It overwrites ballots cast by the same user and keeps only // the latest ballot. -func (s *Form) Suffragia(ctx serde.Context, rd store.Readable) (Suffragia, error) { +func (form *Form) Suffragia(ctx serde.Context, rd store.Readable) (Suffragia, error) { var suff Suffragia - for _, id := range s.SuffragiaIDs { + for _, id := range form.SuffragiaIDs { buf, err := rd.Get(id) if err != nil { return suff, xerrors.Errorf("couldn't get ballot block: %v", err) @@ -294,10 +294,10 @@ func (s *Form) Suffragia(ctx serde.Context, rd store.Readable) (Suffragia, error type RandomVector [][]byte // Unmarshal returns the native type of a random vector -func (r RandomVector) Unmarshal() ([]kyber.Scalar, error) { - e := make([]kyber.Scalar, len(r)) +func (randomVector RandomVector) Unmarshal() ([]kyber.Scalar, error) { + e := make([]kyber.Scalar, len(randomVector)) - for i, v := range r { + for i, v := range randomVector { scalar := suite.Scalar() err := scalar.UnmarshalBinary(v) if err != nil { @@ -311,15 +311,15 @@ func (r RandomVector) Unmarshal() ([]kyber.Scalar, error) { // LoadFromScalars marshals a given vector of scalars into the current // RandomVector -func (r *RandomVector) LoadFromScalars(e []kyber.Scalar) error { - *r = make([][]byte, len(e)) +func (randomVector *RandomVector) LoadFromScalars(e []kyber.Scalar) error { + *randomVector = make([][]byte, len(e)) for i, scalar := range e { v, err := scalar.MarshalBinary() if err != nil { return xerrors.Errorf("could not marshal random vector: %v", err) } - (*r)[i] = v + (*randomVector)[i] = v } return nil @@ -346,9 +346,9 @@ type Configuration struct { } // MaxBallotSize returns the maximum number of bytes required to store a ballot -func (c *Configuration) MaxBallotSize() int { +func (configuration *Configuration) MaxBallotSize() int { size := 0 - for _, subject := range c.Scaffold { + for _, subject := range configuration.Scaffold { size += subject.MaxEncodedSize() } return size @@ -356,8 +356,8 @@ func (c *Configuration) MaxBallotSize() int { // GetQuestion finds the question associated to a given ID and returns it. // Returns nil if no question found. -func (c *Configuration) GetQuestion(ID ID) Question { - for _, subject := range c.Scaffold { +func (configuration *Configuration) GetQuestion(ID ID) Question { + for _, subject := range configuration.Scaffold { question := subject.GetQuestion(ID) if question != nil { @@ -370,11 +370,11 @@ func (c *Configuration) GetQuestion(ID ID) Question { // IsValid returns true if and only if the whole configuration is coherent and // valid. -func (c *Configuration) IsValid() bool { +func (configuration *Configuration) IsValid() bool { // serves as a set to check each ID is unique uniqueIDs := make(map[ID]bool) - for _, subject := range c.Scaffold { + for _, subject := range configuration.Scaffold { if !subject.isValid(uniqueIDs) { return false } @@ -391,8 +391,8 @@ type Pubshare kyber.Point type PubsharesUnit [][]Pubshare // Fingerprint implements serde.Fingerprinter -func (p PubsharesUnit) Fingerprint(writer io.Writer) error { - for _, ballotShares := range p { +func (pubshareUnit PubsharesUnit) Fingerprint(writer io.Writer) error { + for _, ballotShares := range pubshareUnit { for _, pubShare := range ballotShares { _, err := pubShare.MarshalTo(writer) if err != nil { @@ -418,26 +418,26 @@ type PubsharesUnits struct { } // AddVoter add a new admin to the system. -func (s *Form) AddVoter(userID string) error { +func (form *Form) AddVoter(userID string) error { sciperInt, err := strconv.Atoi(userID) if err != nil { return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) } - s.Voters = append(s.Voters, sciperInt) + form.Voters = append(form.Voters, sciperInt) return nil } // IsVoter return the index of admin if userID is one, else return -1 -func (s *Form) IsVoter(userID string) int { +func (form *Form) IsVoter(userID string) int { sciperInt, err := strconv.Atoi(userID) if err != nil { return -1 } - for i := 0; i < len(s.Voters); i++ { - if s.Voters[i] == sciperInt { + for i := 0; i < len(form.Voters); i++ { + if form.Voters[i] == sciperInt { return i } } @@ -446,44 +446,44 @@ func (s *Form) IsVoter(userID string) int { } // RemoveVoter add a new admin to the system. -func (s *Form) RemoveVoter(userID string) error { +func (form *Form) RemoveVoter(userID string) error { _, err := strconv.Atoi(userID) if err != nil { return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) } - index := s.IsVoter(userID) + index := form.IsVoter(userID) if index < 0 { return xerrors.Errorf("Error while retrieving the index of the element.") } - s.Voters = append(s.Voters[:index], s.Voters[index+1:]...) + form.Voters = append(form.Voters[:index], form.Voters[index+1:]...) return nil } // AddOwner add a new admin to the system. -func (s *Form) AddOwner(userID string) error { +func (form *Form) AddOwner(userID string) error { sciperInt, err := strconv.Atoi(userID) if err != nil { return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) } // TODO need to check that the new user is admin ! - s.Owners = append(s.Owners, sciperInt) + form.Owners = append(form.Owners, sciperInt) return nil } // IsOwner return the index of admin if userID is one, else return -1 -func (s *Form) IsOwner(userID string) int { +func (form *Form) IsOwner(userID string) int { sciperInt, err := strconv.Atoi(userID) if err != nil { return -1 } - for i := 0; i < len(s.Owners); i++ { - if s.Owners[i] == sciperInt { + for i := 0; i < len(form.Owners); i++ { + if form.Owners[i] == sciperInt { return i } } @@ -492,24 +492,24 @@ func (s *Form) IsOwner(userID string) int { } // RemoveOwner add a new admin to the system. -func (s *Form) RemoveOwner(userID string) error { +func (form *Form) RemoveOwner(userID string) error { _, err := strconv.Atoi(userID) if err != nil { return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) } - index := s.IsOwner(userID) + index := form.IsOwner(userID) if index < 0 { return xerrors.Errorf("Error while retrieving the index of the element.") } // We don't want to have a form without any Owners. - if len(s.Owners) <= 1 { + if len(form.Owners) <= 1 { return xerrors.Errorf("Error, cannot remove this owner because it is the " + "only one remaining for this form") } - s.Owners = append(s.Owners[:index], s.Owners[index+1:]...) + form.Owners = append(form.Owners[:index], form.Owners[index+1:]...) return nil } From 104bbbd1ac4e881ab1a9172b028cf9a9debf11c3 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 24 Apr 2024 13:35:35 +0200 Subject: [PATCH 041/114] add necessary command and data struct --- contracts/evoting/evoting.go | 51 +++++++++++++++ contracts/evoting/mod.go | 10 +++ contracts/evoting/types/transactions.go | 84 +++++++++++++++++++++++++ 3 files changed, 145 insertions(+) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index bec36c76c..8bfbde90b 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -834,6 +834,57 @@ func (e evotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step return nil } +// TODO modify +// manageVotersForm implements commands. It performs the ADD or REMOVE VOTERS command +func (e evotingCommand) manageVotersForm(snap store.Snapshot, step execution.Step) error { + msg, err := e.getTransaction(step.Current) + if err != nil { + return xerrors.Errorf(errGetTransaction, err) + } + + var form types.AdminForm + var formID []byte + + txAddAdmin, okAddAdmin := msg.(types.AddAdmin) + txRemoveAdmin, okRemoveAdmin := msg.(types.RemoveAdmin) + + if okAddAdmin { + form, formID, err = e.getAdminForm(txAddAdmin.FormID, snap) + if err != nil { + return xerrors.Errorf("failed to get AdminForm: %v", err) + } + + err = form.AddAdmin(txAddAdmin.UserID) + if err != nil { + return xerrors.Errorf("couldn't add admin: %v", err) + } + } else if okRemoveAdmin { + form, formID, err = e.getAdminForm(txRemoveAdmin.FormID, snap) + if err != nil { + return xerrors.Errorf("failed to get AdminForm: %v", err) + } + + err = form.RemoveAdmin(txRemoveAdmin.UserID) + if err != nil { + return xerrors.Errorf("couldn't remove admin: %v", err) + } + } else { + return xerrors.Errorf(errWrongTx, msg) + } + + formBuf, err := form.Serialize(e.context) + if err != nil { + return xerrors.Errorf("failed to marshal Form : %v", err) + } + + err = snap.Set(formID, formBuf) + if err != nil { + return xerrors.Errorf("failed to set value: %v", err) + } + + return nil +} + // isMemberOf is a utility function to verify if a public key is associated to a // member of the roster or not. Returns nil if it's the case. func isMemberOf(roster authority.Authority, publicKey []byte) error { diff --git a/contracts/evoting/mod.go b/contracts/evoting/mod.go index 5cdf3b803..643aa04d9 100644 --- a/contracts/evoting/mod.go +++ b/contracts/evoting/mod.go @@ -131,6 +131,16 @@ const ( CmdAddAdminForm Command = "ADD_ADMIN" // CmdRemoveAdminForm is the command to delete a form CmdRemoveAdminForm Command = "REMOVE_ADMIN" + + // CmdAddOwnerForm is the command to add an Owner to a form + CmdAddOwnerForm Command = "ADD_OWNER" + // CmdRemoveOwnerForm is the command to remove an Owner to a form + CmdRemoveOwnerForm Command = "REMOVE_OWNER" + + // CmdAddVoterForm is the command to add an Voter to a form + CmdAddVoterForm Command = "ADD_VOTER" + // CmdRemoveVoterForm is the command to remove an Voter to a form + CmdRemoveVoterForm Command = "REMOVE_VOTER" ) // NewCreds creates new credentials for a evoting contract execution. We might diff --git a/contracts/evoting/types/transactions.go b/contracts/evoting/types/transactions.go index c04aca934..aca85057d 100644 --- a/contracts/evoting/types/transactions.go +++ b/contracts/evoting/types/transactions.go @@ -385,3 +385,87 @@ func (removeAdmin RemoveAdmin) Serialize(ctx serde.Context) ([]byte, error) { return data, nil } + +// AddVoter defines the transaction to Add an Voter +// +// - implements serde.Message +type AddVoter struct { + // FormID is hex-encoded + FormID string + UserID string +} + +// Serialize implements serde.Message +func (addVoter AddVoter) Serialize(ctx serde.Context) ([]byte, error) { + format := transactionFormats.Get(ctx.GetFormat()) + + data, err := format.Encode(ctx, addVoter) + if err != nil { + return nil, xerrors.Errorf("failed to encode Add Voter: %v", err) + } + + return data, nil +} + +// RemoveVoter defines the transaction to Remove an Voter +// +// - implements serde.Message +type RemoveVoter struct { + // FormID is hex-encoded + FormID string + UserID string +} + +// Serialize implements serde.Message +func (removeVoter RemoveVoter) Serialize(ctx serde.Context) ([]byte, error) { + format := transactionFormats.Get(ctx.GetFormat()) + + data, err := format.Encode(ctx, removeVoter) + if err != nil { + return nil, xerrors.Errorf("failed to encode Remove Admin: %v", err) + } + + return data, nil +} + +// AddOwner defines the transaction to Add an Owner +// +// - implements serde.Message +type AddOwner struct { + // FormID is hex-encoded + FormID string + UserID string +} + +// Serialize implements serde.Message +func (addOwner AddOwner) Serialize(ctx serde.Context) ([]byte, error) { + format := transactionFormats.Get(ctx.GetFormat()) + + data, err := format.Encode(ctx, addOwner) + if err != nil { + return nil, xerrors.Errorf("failed to encode Add Owner: %v", err) + } + + return data, nil +} + +// RemoveOwner defines the transaction to Remove an Owner +// +// - implements serde.Message +type RemoveOwner struct { + // FormID is hex-encoded + FormID string + UserID string +} + +// Serialize implements serde.Message +func (removeOwner RemoveOwner) Serialize(ctx serde.Context) ([]byte, error) { + format := transactionFormats.Get(ctx.GetFormat()) + + data, err := format.Encode(ctx, removeOwner) + if err != nil { + return nil, xerrors.Errorf("failed to encode Remove Owner: %v", err) + } + + return data, nil +} From 179cb94f70a6ec6f01890b647734536c46a0caac Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Sun, 28 Apr 2024 22:34:23 +0200 Subject: [PATCH 042/114] add template of owner and voter manager --- contracts/evoting/evoting.go | 51 ++++++++++++++++++++++++++++++++++++ contracts/evoting/mod.go | 22 ++++++++++++++++ 2 files changed, 73 insertions(+) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 8bfbde90b..17c280fb0 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -885,6 +885,57 @@ func (e evotingCommand) manageVotersForm(snap store.Snapshot, step execution.Ste return nil } +// TODO modify +// manageOwnersForm implements commands. It performs the ADD or REMOVE Owners command +func (e evotingCommand) manageOwnersForm(snap store.Snapshot, step execution.Step) error { + msg, err := e.getTransaction(step.Current) + if err != nil { + return xerrors.Errorf(errGetTransaction, err) + } + + var form types.AdminForm + var formID []byte + + txAddAdmin, okAddAdmin := msg.(types.AddAdmin) + txRemoveAdmin, okRemoveAdmin := msg.(types.RemoveAdmin) + + if okAddAdmin { + form, formID, err = e.getAdminForm(txAddAdmin.FormID, snap) + if err != nil { + return xerrors.Errorf("failed to get AdminForm: %v", err) + } + + err = form.AddAdmin(txAddAdmin.UserID) + if err != nil { + return xerrors.Errorf("couldn't add admin: %v", err) + } + } else if okRemoveAdmin { + form, formID, err = e.getAdminForm(txRemoveAdmin.FormID, snap) + if err != nil { + return xerrors.Errorf("failed to get AdminForm: %v", err) + } + + err = form.RemoveAdmin(txRemoveAdmin.UserID) + if err != nil { + return xerrors.Errorf("couldn't remove admin: %v", err) + } + } else { + return xerrors.Errorf(errWrongTx, msg) + } + + formBuf, err := form.Serialize(e.context) + if err != nil { + return xerrors.Errorf("failed to marshal Form : %v", err) + } + + err = snap.Set(formID, formBuf) + if err != nil { + return xerrors.Errorf("failed to set value: %v", err) + } + + return nil +} + // isMemberOf is a utility function to verify if a public key is associated to a // member of the roster or not. Returns nil if it's the case. func isMemberOf(roster authority.Authority, publicKey []byte) error { diff --git a/contracts/evoting/mod.go b/contracts/evoting/mod.go index 643aa04d9..f42c599d0 100644 --- a/contracts/evoting/mod.go +++ b/contracts/evoting/mod.go @@ -99,6 +99,8 @@ type commands interface { cancelForm(snap store.Snapshot, step execution.Step) error deleteForm(snap store.Snapshot, step execution.Step) error manageAdminForm(snap store.Snapshot, step execution.Step) error + manageOwnersForm(snap store.Snapshot, step execution.Step) error + manageVotersForm(snap store.Snapshot, step execution.Step) error } // Command defines a type of command for the value contract @@ -273,6 +275,26 @@ func (c Contract) Execute(snap store.Snapshot, step execution.Step) error { if err != nil { return xerrors.Errorf("failed to remove admin: %v", err) } + case CmdAddOwnerForm: + err := c.cmd.manageOwnersForm(snap, step) + if err != nil { + return xerrors.Errorf("failed to add owner: %v", err) + } + case CmdRemoveOwnerForm: + err := c.cmd.manageOwnersForm(snap, step) + if err != nil { + return xerrors.Errorf("failed to remove owner: %v", err) + } + case CmdAddVoterForm: + err := c.cmd.manageVotersForm(snap, step) + if err != nil { + return xerrors.Errorf("failed to add voter: %v", err) + } + case CmdRemoveVoterForm: + err := c.cmd.manageVotersForm(snap, step) + if err != nil { + return xerrors.Errorf("failed to remove voter: %v", err) + } default: return xerrors.Errorf("unknown command: %s", cmd) } From a4720c4c963d5fe43428a4ae0aa5c93e20b01164 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Mon, 29 Apr 2024 00:02:12 +0200 Subject: [PATCH 043/114] add logic for managers voters and owners --- contracts/evoting/evoting.go | 52 +++++++++++++++++------------------ contracts/evoting/mod_test.go | 8 ++++++ 2 files changed, 34 insertions(+), 26 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 17c280fb0..87004f3f1 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -842,31 +842,31 @@ func (e evotingCommand) manageVotersForm(snap store.Snapshot, step execution.Ste return xerrors.Errorf(errGetTransaction, err) } - var form types.AdminForm + var form types.Form var formID []byte - txAddAdmin, okAddAdmin := msg.(types.AddAdmin) - txRemoveAdmin, okRemoveAdmin := msg.(types.RemoveAdmin) + txAddVoter, okAddVoter := msg.(types.AddVoter) + txRemoveVoter, okRemoveVoter := msg.(types.RemoveVoter) - if okAddAdmin { - form, formID, err = e.getAdminForm(txAddAdmin.FormID, snap) + if okAddVoter { + form, formID, err = e.getForm(txAddVoter.FormID, snap) if err != nil { - return xerrors.Errorf("failed to get AdminForm: %v", err) + return xerrors.Errorf(errGetForm, err) } - err = form.AddAdmin(txAddAdmin.UserID) + err = form.AddVoter(txAddVoter.UserID) if err != nil { - return xerrors.Errorf("couldn't add admin: %v", err) + return xerrors.Errorf("couldn't add voter: %v", err) } - } else if okRemoveAdmin { - form, formID, err = e.getAdminForm(txRemoveAdmin.FormID, snap) + } else if okRemoveVoter { + form, formID, err = e.getForm(txRemoveVoter.FormID, snap) if err != nil { - return xerrors.Errorf("failed to get AdminForm: %v", err) + return xerrors.Errorf(errGetForm, err) } - err = form.RemoveAdmin(txRemoveAdmin.UserID) + err = form.RemoveVoter(txRemoveVoter.UserID) if err != nil { - return xerrors.Errorf("couldn't remove admin: %v", err) + return xerrors.Errorf("couldn't remove voter: %v", err) } } else { return xerrors.Errorf(errWrongTx, msg) @@ -893,31 +893,31 @@ func (e evotingCommand) manageOwnersForm(snap store.Snapshot, step execution.Ste return xerrors.Errorf(errGetTransaction, err) } - var form types.AdminForm + var form types.Form var formID []byte - txAddAdmin, okAddAdmin := msg.(types.AddAdmin) - txRemoveAdmin, okRemoveAdmin := msg.(types.RemoveAdmin) + txAddOwner, okAddOwner := msg.(types.AddAdmin) + txRemoveOwner, okRemoveOwner := msg.(types.RemoveAdmin) - if okAddAdmin { - form, formID, err = e.getAdminForm(txAddAdmin.FormID, snap) + if okAddOwner { + form, formID, err = e.getForm(txAddOwner.FormID, snap) if err != nil { - return xerrors.Errorf("failed to get AdminForm: %v", err) + return xerrors.Errorf(errGetForm, err) } - err = form.AddAdmin(txAddAdmin.UserID) + err = form.AddOwner(txAddOwner.UserID) if err != nil { - return xerrors.Errorf("couldn't add admin: %v", err) + return xerrors.Errorf("couldn't add owner: %v", err) } - } else if okRemoveAdmin { - form, formID, err = e.getAdminForm(txRemoveAdmin.FormID, snap) + } else if okRemoveOwner { + form, formID, err = e.getForm(txRemoveOwner.FormID, snap) if err != nil { - return xerrors.Errorf("failed to get AdminForm: %v", err) + return xerrors.Errorf(errGetForm, err) } - err = form.RemoveAdmin(txRemoveAdmin.UserID) + err = form.RemoveOwner(txRemoveOwner.UserID) if err != nil { - return xerrors.Errorf("couldn't remove admin: %v", err) + return xerrors.Errorf("couldn't remove owner: %v", err) } } else { return xerrors.Errorf(errWrongTx, msg) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 62b8560c1..46f2ec033 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1467,6 +1467,14 @@ func (c fakeCmd) manageAdminForm(snap store.Snapshot, step execution.Step) error return c.err } +func (c fakeCmd) manageOwnersForm(snap store.Snapshot, step execution.Step) error { + return c.err +} + +func (c fakeCmd) manageVotersForm(snap store.Snapshot, step execution.Step) error { + return c.err +} + func (c fakeCmd) createForm(snap store.Snapshot, step execution.Step) error { return c.err } From 616032594cfc0114dd9eeaaf351321a569b2d6b3 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Mon, 29 Apr 2024 16:40:53 +0200 Subject: [PATCH 044/114] implem test --- contracts/evoting/evoting.go | 4 +- contracts/evoting/json/transaction.go | 80 +++++++++++++++ contracts/evoting/mod_test.go | 142 ++++++++++++++++++++++++++ contracts/evoting/types/election.go | 12 +-- 4 files changed, 230 insertions(+), 8 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 87004f3f1..f8d55c3db 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -896,8 +896,8 @@ func (e evotingCommand) manageOwnersForm(snap store.Snapshot, step execution.Ste var form types.Form var formID []byte - txAddOwner, okAddOwner := msg.(types.AddAdmin) - txRemoveOwner, okRemoveOwner := msg.(types.RemoveAdmin) + txAddOwner, okAddOwner := msg.(types.AddOwner) + txRemoveOwner, okRemoveOwner := msg.(types.RemoveOwner) if okAddOwner { form, formID, err = e.getForm(txAddOwner.FormID, snap) diff --git a/contracts/evoting/json/transaction.go b/contracts/evoting/json/transaction.go index a9ff461c7..22642f641 100644 --- a/contracts/evoting/json/transaction.go +++ b/contracts/evoting/json/transaction.go @@ -132,6 +132,34 @@ func (transactionFormat) Encode(ctx serde.Context, msg serde.Message) ([]byte, e } m = TransactionJSON{RemoveAdmin: &ra} + case types.AddOwner: + addOwner := AddOwnerJSON{ + FormID: t.FormID, + UserID: t.UserID, + } + + m = TransactionJSON{AddOwner: &addOwner} + case types.RemoveOwner: + removeOwner := RemoveOwnerJSON{ + FormID: t.FormID, + UserID: t.UserID, + } + + m = TransactionJSON{RemoveOwner: &removeOwner} + case types.AddVoter: + addVoter := AddVoterJSON{ + FormID: t.FormID, + UserID: t.UserID, + } + + m = TransactionJSON{AddVoter: &addVoter} + case types.RemoveVoter: + removeVoter := RemoveVoterJSON{ + FormID: t.FormID, + UserID: t.UserID, + } + + m = TransactionJSON{RemoveVoter: &removeVoter} default: return nil, xerrors.Errorf("unknown type: '%T", msg) } @@ -213,6 +241,26 @@ func (transactionFormat) Decode(ctx serde.Context, data []byte) (serde.Message, FormID: m.RemoveAdmin.FormID, UserID: m.RemoveAdmin.UserID, }, nil + case m.AddOwner != nil: + return types.AddOwner{ + FormID: m.AddOwner.FormID, + UserID: m.AddOwner.UserID, + }, nil + case m.RemoveOwner != nil: + return types.RemoveOwner{ + FormID: m.RemoveOwner.FormID, + UserID: m.RemoveOwner.UserID, + }, nil + case m.AddVoter != nil: + return types.AddVoter{ + FormID: m.AddVoter.FormID, + UserID: m.AddVoter.UserID, + }, nil + case m.RemoveVoter != nil: + return types.RemoveVoter{ + FormID: m.RemoveVoter.FormID, + UserID: m.RemoveVoter.UserID, + }, nil } return nil, xerrors.Errorf("empty type: %s", data) @@ -232,6 +280,10 @@ type TransactionJSON struct { DeleteForm *DeleteFormJSON `json:",omitempty"` AddAdmin *AddAdminJSON `json:",omitempty"` RemoveAdmin *RemoveAdminJSON `json:",omitempty"` + AddOwner *AddOwnerJSON `json:",omitempty"` + RemoveOwner *RemoveOwnerJSON `json:",omitempty"` + AddVoter *AddVoterJSON `json:",omitempty"` + RemoveVoter *RemoveVoterJSON `json:",omitempty"` } // CreateFormJSON is the JSON representation of a CreateForm transaction @@ -308,6 +360,34 @@ type RemoveAdminJSON struct { UserID string } +// OwnerForm + +// AddOwnerJSON is the JSON representation of a AddOwner transaction +type AddOwnerJSON struct { + FormID string + UserID string +} + +// RemoveOwnerJSON is the JSON representation of a RemoveOwner transaction +type RemoveOwnerJSON struct { + FormID string + UserID string +} + +// VoterForm + +// AddVoterJSON is the JSON representation of a AddVoter transaction +type AddVoterJSON struct { + FormID string + UserID string +} + +// RemoveVoterJSON is the JSON representation of a RemoveVoter transaction +type RemoveVoterJSON struct { + FormID string + UserID string +} + func decodeCastVote(ctx serde.Context, m CastVoteJSON) (serde.Message, error) { factory := ctx.GetFactory(types.CiphervoteKey{}) if factory == nil { diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 46f2ec033..4bae59805 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1208,6 +1208,148 @@ func TestCommand_AdminForm(t *testing.T) { require.True(t, adminForm.GetAdminIndex(dummyUID) == -1) } +func TestCommand_OwnerForm(t *testing.T) { + addOwner := types.AddOwner{ + FormID: fakeFormID, + UserID: dummyUserID, + } + + // Test Serialization of AddOwner command + dataAdd, err := addOwner.Serialize(ctx) + require.NoError(t, err) + + removeOwner := types.RemoveOwner{ + FormID: fakeFormID, + UserID: dummyUserID, + } + + // Test Serialization of RemoveOwner command + dataRemove, err := removeOwner.Serialize(ctx) + require.NoError(t, err) + + // Initialize the form and contract chain + dummyForm, contract := initFormAndContract() + dummyForm.FormID = fakeFormID + + // Test the serialization of the Ledger + formBuf, err := dummyForm.Serialize(ctx) + require.NoError(t, err) + + // Create an evoting command. + cmd := evotingCommand{ + Contract: &contract, + } + + err = cmd.manageOwnersForm(fake.NewSnapshot(), makeStep(t)) + require.EqualError(t, err, getTransactionErr) + + err = cmd.manageOwnersForm(fake.NewSnapshot(), makeStep(t, FormArg, "dummy")) + require.EqualError(t, err, unmarshalTransactionErr) + + err = cmd.manageOwnersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataAdd))) + require.ErrorContains(t, err, "failed to get key") + + err = cmd.manageOwnersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataRemove))) + require.ErrorContains(t, err, "failed to get key") + + snap := fake.NewSnapshot() + + err = snap.Set(dummyFormIDBuff, invalidForm) + require.NoError(t, err) + + err = cmd.manageOwnersForm(snap, makeStep(t, FormArg, string(dataAdd))) + require.ErrorContains(t, err, deserializeErr) + + err = snap.Set(dummyFormIDBuff, formBuf) + require.NoError(t, err) + + // We retrieve the Admin Form from the ledger. + res, err := snap.Get(dummyFormIDBuff) + require.NoError(t, err) + + message, err := formFac.Deserialize(ctx, res) + require.NoError(t, err) + + form, ok := message.(types.Form) + require.True(t, ok) + + // We check that now our dummy user is not admin anymore (return -1) + require.True(t, form.GetOwnerIndex(dummyUserID) == -1) + + // ===== + // Now perform the real test + // ===== + + err = snap.Set(dummyFormIDBuff, formBuf) + require.NoError(t, err) + + // We perform below the command on the ledger + err = cmd.manageOwnersForm(snap, makeStep(t, FormArg, string(dataAdd))) + require.NoError(t, err) + + res, err = snap.Get(dummyFormIDBuff) + require.NoError(t, err) + + message, err = formFac.Deserialize(ctx, res) + require.NoError(t, err) + + form, ok = message.(types.Form) + require.True(t, ok) + + // We check that now our dummy user is an owner (return 0) + require.True(t, form.GetOwnerIndex(dummyUserID) == 0) + + // === + // Now let's remove it + // === + + // We perform below the command on the ledger + err = cmd.manageOwnersForm(snap, makeStep(t, FormArg, string(dataRemove))) + require.ErrorContains(t, err, "cannot remove this owner because it is the only one remaining for this form") + + addOwner2 := types.AddOwner{ + FormID: fakeFormID, + UserID: "234567", + } + + // Test Serialization of AddOwner command + dataAdd2, err := addOwner2.Serialize(ctx) + require.NoError(t, err) + + // We perform below the command on the ledger + err = cmd.manageOwnersForm(snap, makeStep(t, FormArg, string(dataAdd2))) + require.NoError(t, err) + + res, err = snap.Get(dummyFormIDBuff) + require.NoError(t, err) + + message, err = formFac.Deserialize(ctx, res) + require.NoError(t, err) + + form, ok = message.(types.Form) + require.True(t, ok) + + // We check that now our dummy user is an owner (return 0) + require.True(t, form.GetOwnerIndex("234567") == 1) + + // now remove successfully the first one + + err = cmd.manageOwnersForm(snap, makeStep(t, FormArg, string(dataRemove))) + require.NoError(t, err) + + res, err = snap.Get(dummyFormIDBuff) + require.NoError(t, err) + + message, err = formFac.Deserialize(ctx, res) + require.NoError(t, err) + + form, ok = message.(types.Form) + require.True(t, ok) + + // We check that now our dummy user is not an owner anymore (return -1) + require.True(t, form.GetOwnerIndex(dummyUserID) == -1) +} + // ----------------------------------------------------------------------------- // Utility functions diff --git a/contracts/evoting/types/election.go b/contracts/evoting/types/election.go index 58b4135a0..5b488bf4d 100644 --- a/contracts/evoting/types/election.go +++ b/contracts/evoting/types/election.go @@ -429,8 +429,8 @@ func (form *Form) AddVoter(userID string) error { return nil } -// IsVoter return the index of admin if userID is one, else return -1 -func (form *Form) IsVoter(userID string) int { +// GetVoterIndex return the index of admin if userID is one, else return -1 +func (form *Form) GetVoterIndex(userID string) int { sciperInt, err := strconv.Atoi(userID) if err != nil { return -1 @@ -452,7 +452,7 @@ func (form *Form) RemoveVoter(userID string) error { return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) } - index := form.IsVoter(userID) + index := form.GetVoterIndex(userID) if index < 0 { return xerrors.Errorf("Error while retrieving the index of the element.") @@ -475,8 +475,8 @@ func (form *Form) AddOwner(userID string) error { return nil } -// IsOwner return the index of admin if userID is one, else return -1 -func (form *Form) IsOwner(userID string) int { +// GetOwnerIndex return the index of admin if userID is one, else return -1 +func (form *Form) GetOwnerIndex(userID string) int { sciperInt, err := strconv.Atoi(userID) if err != nil { return -1 @@ -498,7 +498,7 @@ func (form *Form) RemoveOwner(userID string) error { return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) } - index := form.IsOwner(userID) + index := form.GetOwnerIndex(userID) if index < 0 { return xerrors.Errorf("Error while retrieving the index of the element.") From d376a0a9067a4b703fcdc0efbddffd31bcbc77c7 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Mon, 29 Apr 2024 16:53:47 +0200 Subject: [PATCH 045/114] add test voters list --- contracts/evoting/mod_test.go | 112 ++++++++++++++++++++++++++++++++++ 1 file changed, 112 insertions(+) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 4bae59805..4175daa99 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1350,6 +1350,118 @@ func TestCommand_OwnerForm(t *testing.T) { require.True(t, form.GetOwnerIndex(dummyUserID) == -1) } +func TestCommand_VoterForm(t *testing.T) { + addVoter := types.AddVoter{ + FormID: fakeFormID, + UserID: dummyUserID, + } + + // Test Serialization of AddVoter command + dataAdd, err := addVoter.Serialize(ctx) + require.NoError(t, err) + + removeVoter := types.RemoveVoter{ + FormID: fakeFormID, + UserID: dummyUserID, + } + + // Test Serialization of RemoveVoter command + dataRemove, err := removeVoter.Serialize(ctx) + require.NoError(t, err) + + // Initialize the form and contract chain + dummyForm, contract := initFormAndContract() + dummyForm.FormID = fakeFormID + + // Test the serialization of the Ledger + formBuf, err := dummyForm.Serialize(ctx) + require.NoError(t, err) + + // Create an evoting command. + cmd := evotingCommand{ + Contract: &contract, + } + + err = cmd.manageVotersForm(fake.NewSnapshot(), makeStep(t)) + require.EqualError(t, err, getTransactionErr) + + err = cmd.manageVotersForm(fake.NewSnapshot(), makeStep(t, FormArg, "dummy")) + require.EqualError(t, err, unmarshalTransactionErr) + + err = cmd.manageVotersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataAdd))) + require.ErrorContains(t, err, "failed to get key") + + err = cmd.manageVotersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataRemove))) + require.ErrorContains(t, err, "failed to get key") + + snap := fake.NewSnapshot() + + err = snap.Set(dummyFormIDBuff, invalidForm) + require.NoError(t, err) + + err = cmd.manageVotersForm(snap, makeStep(t, FormArg, string(dataAdd))) + require.ErrorContains(t, err, deserializeErr) + + err = snap.Set(dummyFormIDBuff, formBuf) + require.NoError(t, err) + + // We retrieve the Admin Form from the ledger. + res, err := snap.Get(dummyFormIDBuff) + require.NoError(t, err) + + message, err := formFac.Deserialize(ctx, res) + require.NoError(t, err) + + form, ok := message.(types.Form) + require.True(t, ok) + + // We check that now our dummy user is not admin anymore (return -1) + require.True(t, form.GetVoterIndex(dummyUserID) == -1) + + // ===== + // Now perform the real test + // ===== + + err = snap.Set(dummyFormIDBuff, formBuf) + require.NoError(t, err) + + // We perform below the command on the ledger + err = cmd.manageVotersForm(snap, makeStep(t, FormArg, string(dataAdd))) + require.NoError(t, err) + + res, err = snap.Get(dummyFormIDBuff) + require.NoError(t, err) + + message, err = formFac.Deserialize(ctx, res) + require.NoError(t, err) + + form, ok = message.(types.Form) + require.True(t, ok) + + // We check that now our dummy user is an owner (return 0) + require.True(t, form.GetVoterIndex(dummyUserID) == 0) + + // === + // Now let's remove it + // === + + // We perform below the command on the ledger + err = cmd.manageVotersForm(snap, makeStep(t, FormArg, string(dataRemove))) + require.NoError(t, err) + + res, err = snap.Get(dummyFormIDBuff) + require.NoError(t, err) + + message, err = formFac.Deserialize(ctx, res) + require.NoError(t, err) + + form, ok = message.(types.Form) + require.True(t, ok) + + // We check that now our dummy user is an owner (return 0) + require.True(t, form.GetVoterIndex(dummyUserID) == -1) +} + // ----------------------------------------------------------------------------- // Utility functions From dd183a6f5835673ed5d3968393769612ec749179 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Mon, 29 Apr 2024 17:25:01 +0200 Subject: [PATCH 046/114] clean + comment test --- contracts/evoting/mod_test.go | 94 ++++++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 29 deletions(-) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 4175daa99..ebc5acf79 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1208,6 +1208,15 @@ func TestCommand_AdminForm(t *testing.T) { require.True(t, adminForm.GetAdminIndex(dummyUID) == -1) } +/* + Testing Scenario: + - We check that the owner field is empty + - We add user: 123456 + - We check that 123456 is owner + - We try to remove it. -> failure cause is the only owner. + - We add a second user: 234567 + - Now we can remove ownership to: 123456 +*/ func TestCommand_OwnerForm(t *testing.T) { addOwner := types.AddOwner{ FormID: fakeFormID, @@ -1240,26 +1249,42 @@ func TestCommand_OwnerForm(t *testing.T) { Contract: &contract, } + // The following test are there to check error handling + + // Checking that if no AdminForm is on the blockchain, + // It won't be able to find the transaction. err = cmd.manageOwnersForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) + // Checking that providing a dummy data as argument, the form will not + // recognize it and won't be able to unmarshal it. err = cmd.manageOwnersForm(fake.NewSnapshot(), makeStep(t, FormArg, "dummy")) require.EqualError(t, err, unmarshalTransactionErr) + // Checking that given a Blockchain that always returns an error with an Add cmd, + // it will not be able to retrieve the Form on the store. err = cmd.manageOwnersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataAdd))) require.ErrorContains(t, err, "failed to get key") + // Checking that given a Blockchain that always returns an error with an Remove cmd, + // it will not be able to retrieve the Form on the store. err = cmd.manageOwnersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataRemove))) require.ErrorContains(t, err, "failed to get key") snap := fake.NewSnapshot() + // Checking that given the form set in the Snapshot which is invalid, then it + // will not be able to deserialize the Form to perform the command. err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) - err = cmd.manageOwnersForm(snap, makeStep(t, FormArg, string(dataAdd))) require.ErrorContains(t, err, deserializeErr) + // ==== + // Now that we've performed check on the error, let's + // reset everything to perform the real test + // ==== + err = snap.Set(dummyFormIDBuff, formBuf) require.NoError(t, err) @@ -1273,20 +1298,14 @@ func TestCommand_OwnerForm(t *testing.T) { form, ok := message.(types.Form) require.True(t, ok) - // We check that now our dummy user is not admin anymore (return -1) + // We check that now our dummy user is not owner yet (return -1) require.True(t, form.GetOwnerIndex(dummyUserID) == -1) - // ===== - // Now perform the real test - // ===== - - err = snap.Set(dummyFormIDBuff, formBuf) - require.NoError(t, err) - - // We perform below the command on the ledger + // We perform the Add command on the ledger err = cmd.manageOwnersForm(snap, makeStep(t, FormArg, string(dataAdd))) require.NoError(t, err) + // Let's see if it added the owner successfully res, err = snap.Get(dummyFormIDBuff) require.NoError(t, err) @@ -1299,14 +1318,14 @@ func TestCommand_OwnerForm(t *testing.T) { // We check that now our dummy user is an owner (return 0) require.True(t, form.GetOwnerIndex(dummyUserID) == 0) - // === // Now let's remove it - // === - // We perform below the command on the ledger + // We perform the Remove command on the ledger + // but it fails because it is the only owner. err = cmd.manageOwnersForm(snap, makeStep(t, FormArg, string(dataRemove))) require.ErrorContains(t, err, "cannot remove this owner because it is the only one remaining for this form") + // So first let's add a second owner addOwner2 := types.AddOwner{ FormID: fakeFormID, UserID: "234567", @@ -1329,14 +1348,14 @@ func TestCommand_OwnerForm(t *testing.T) { form, ok = message.(types.Form) require.True(t, ok) - // We check that now our dummy user is an owner (return 0) + // We check that now our second dummy user is also an owner (return 0). require.True(t, form.GetOwnerIndex("234567") == 1) - // now remove successfully the first one - + // Now remove successfully the first one. err = cmd.manageOwnersForm(snap, makeStep(t, FormArg, string(dataRemove))) require.NoError(t, err) + // Let's retrieve the form to check whether it worked res, err = snap.Get(dummyFormIDBuff) require.NoError(t, err) @@ -1346,10 +1365,19 @@ func TestCommand_OwnerForm(t *testing.T) { form, ok = message.(types.Form) require.True(t, ok) - // We check that now our dummy user is not an owner anymore (return -1) + // We check that now our first dummy user is not an owner anymore (return -1) require.True(t, form.GetOwnerIndex(dummyUserID) == -1) + // But that the second one is still an admin (return != -1) + require.True(t, form.GetOwnerIndex("234567") != -1) } +/* + Testing Scenario: + - We check that the voter field is empty + - We add user: 123456 + - We check that 123456 is voter + - We remove 123456 from the voter list. +*/ func TestCommand_VoterForm(t *testing.T) { addVoter := types.AddVoter{ FormID: fakeFormID, @@ -1382,26 +1410,42 @@ func TestCommand_VoterForm(t *testing.T) { Contract: &contract, } + // The following test are there to check error handling + + // Checking that if no AdminForm is on the blockchain, + // It won't be able to find the transaction. err = cmd.manageVotersForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) + // Checking that providing a dummy data as argument, the form will not + // recognize it and won't be able to unmarshal it. err = cmd.manageVotersForm(fake.NewSnapshot(), makeStep(t, FormArg, "dummy")) require.EqualError(t, err, unmarshalTransactionErr) + // Checking that given a Blockchain that always returns an error with an Add cmd, + // it will not be able to retrieve the Form on the store. err = cmd.manageVotersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataAdd))) require.ErrorContains(t, err, "failed to get key") + // Checking that given a Blockchain that always returns an error with an Remove cmd, + // it will not be able to retrieve the Form on the store. err = cmd.manageVotersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataRemove))) require.ErrorContains(t, err, "failed to get key") snap := fake.NewSnapshot() + // Checking that given the form set in the Snapshot which is invalid, then it + // will not be able to deserialize the Form to perform the command. err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) - err = cmd.manageVotersForm(snap, makeStep(t, FormArg, string(dataAdd))) require.ErrorContains(t, err, deserializeErr) + // ==== + // Now that we've performed check on the error, let's + // reset everything to perform the real test + // ==== + err = snap.Set(dummyFormIDBuff, formBuf) require.NoError(t, err) @@ -1415,20 +1459,14 @@ func TestCommand_VoterForm(t *testing.T) { form, ok := message.(types.Form) require.True(t, ok) - // We check that now our dummy user is not admin anymore (return -1) + // We check that now our dummy user is not a voter yet (return -1) require.True(t, form.GetVoterIndex(dummyUserID) == -1) - // ===== - // Now perform the real test - // ===== - - err = snap.Set(dummyFormIDBuff, formBuf) - require.NoError(t, err) - - // We perform below the command on the ledger + // We perform the Add command on the ledger err = cmd.manageVotersForm(snap, makeStep(t, FormArg, string(dataAdd))) require.NoError(t, err) + // We then check that the Add command was a success res, err = snap.Get(dummyFormIDBuff) require.NoError(t, err) @@ -1441,9 +1479,7 @@ func TestCommand_VoterForm(t *testing.T) { // We check that now our dummy user is an owner (return 0) require.True(t, form.GetVoterIndex(dummyUserID) == 0) - // === // Now let's remove it - // === // We perform below the command on the ledger err = cmd.manageVotersForm(snap, makeStep(t, FormArg, string(dataRemove))) From 835ce877b2dfafdac335fa1bec494885b3bb5446 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Mon, 29 Apr 2024 17:29:03 +0200 Subject: [PATCH 047/114] patch for vet --- contracts/evoting/mod_test.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index ebc5acf79..7ecdb98ea 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1261,13 +1261,13 @@ func TestCommand_OwnerForm(t *testing.T) { err = cmd.manageOwnersForm(fake.NewSnapshot(), makeStep(t, FormArg, "dummy")) require.EqualError(t, err, unmarshalTransactionErr) - // Checking that given a Blockchain that always returns an error with an Add cmd, - // it will not be able to retrieve the Form on the store. + // Checking that given a Blockchain that always returns an error with + // an Add cmd, it will not be able to retrieve the Form on the store. err = cmd.manageOwnersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataAdd))) require.ErrorContains(t, err, "failed to get key") - // Checking that given a Blockchain that always returns an error with an Remove cmd, - // it will not be able to retrieve the Form on the store. + // Checking that given a Blockchain that always returns an error with + // a Remove cmd, it will not be able to retrieve the Form on the store. err = cmd.manageOwnersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataRemove))) require.ErrorContains(t, err, "failed to get key") @@ -1422,13 +1422,13 @@ func TestCommand_VoterForm(t *testing.T) { err = cmd.manageVotersForm(fake.NewSnapshot(), makeStep(t, FormArg, "dummy")) require.EqualError(t, err, unmarshalTransactionErr) - // Checking that given a Blockchain that always returns an error with an Add cmd, - // it will not be able to retrieve the Form on the store. + // Checking that given a Blockchain that always returns an error with + // an Add cmd, it will not be able to retrieve the Form on the store. err = cmd.manageVotersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataAdd))) require.ErrorContains(t, err, "failed to get key") - // Checking that given a Blockchain that always returns an error with an Remove cmd, - // it will not be able to retrieve the Form on the store. + // Checking that given a Blockchain that always returns an error with + // a Remove cmd, it will not be able to retrieve the Form on the store. err = cmd.manageVotersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataRemove))) require.ErrorContains(t, err, "failed to get key") From 42bab3f732dd8c63355b127f9b3123860985d713 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Tue, 30 Apr 2024 14:11:01 +0200 Subject: [PATCH 048/114] merge manager voters and owners --- contracts/evoting/evoting.go | 41 +++++------------------------------ contracts/evoting/mod.go | 11 +++++----- contracts/evoting/mod_test.go | 38 +++++++++++++++----------------- 3 files changed, 28 insertions(+), 62 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index f8d55c3db..423a90130 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -834,9 +834,9 @@ func (e evotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step return nil } -// TODO modify -// manageVotersForm implements commands. It performs the ADD or REMOVE VOTERS command -func (e evotingCommand) manageVotersForm(snap store.Snapshot, step execution.Step) error { +// manageVotersForm implements commands. +// It performs the ADD or REMOVE VOTERS/OWNERS command +func (e evotingCommand) manageOwnersVotersForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { return xerrors.Errorf(errGetTransaction, err) @@ -847,6 +847,8 @@ func (e evotingCommand) manageVotersForm(snap store.Snapshot, step execution.Ste txAddVoter, okAddVoter := msg.(types.AddVoter) txRemoveVoter, okRemoveVoter := msg.(types.RemoveVoter) + txAddOwner, okAddOwner := msg.(types.AddOwner) + txRemoveOwner, okRemoveOwner := msg.(types.RemoveOwner) if okAddVoter { form, formID, err = e.getForm(txAddVoter.FormID, snap) @@ -868,38 +870,7 @@ func (e evotingCommand) manageVotersForm(snap store.Snapshot, step execution.Ste if err != nil { return xerrors.Errorf("couldn't remove voter: %v", err) } - } else { - return xerrors.Errorf(errWrongTx, msg) - } - - formBuf, err := form.Serialize(e.context) - if err != nil { - return xerrors.Errorf("failed to marshal Form : %v", err) - } - - err = snap.Set(formID, formBuf) - if err != nil { - return xerrors.Errorf("failed to set value: %v", err) - } - - return nil -} - -// TODO modify -// manageOwnersForm implements commands. It performs the ADD or REMOVE Owners command -func (e evotingCommand) manageOwnersForm(snap store.Snapshot, step execution.Step) error { - msg, err := e.getTransaction(step.Current) - if err != nil { - return xerrors.Errorf(errGetTransaction, err) - } - - var form types.Form - var formID []byte - - txAddOwner, okAddOwner := msg.(types.AddOwner) - txRemoveOwner, okRemoveOwner := msg.(types.RemoveOwner) - - if okAddOwner { + } else if okAddOwner { form, formID, err = e.getForm(txAddOwner.FormID, snap) if err != nil { return xerrors.Errorf(errGetForm, err) diff --git a/contracts/evoting/mod.go b/contracts/evoting/mod.go index f42c599d0..fd930c289 100644 --- a/contracts/evoting/mod.go +++ b/contracts/evoting/mod.go @@ -99,8 +99,7 @@ type commands interface { cancelForm(snap store.Snapshot, step execution.Step) error deleteForm(snap store.Snapshot, step execution.Step) error manageAdminForm(snap store.Snapshot, step execution.Step) error - manageOwnersForm(snap store.Snapshot, step execution.Step) error - manageVotersForm(snap store.Snapshot, step execution.Step) error + manageOwnersVotersForm(snap store.Snapshot, step execution.Step) error } // Command defines a type of command for the value contract @@ -276,22 +275,22 @@ func (c Contract) Execute(snap store.Snapshot, step execution.Step) error { return xerrors.Errorf("failed to remove admin: %v", err) } case CmdAddOwnerForm: - err := c.cmd.manageOwnersForm(snap, step) + err := c.cmd.manageOwnersVotersForm(snap, step) if err != nil { return xerrors.Errorf("failed to add owner: %v", err) } case CmdRemoveOwnerForm: - err := c.cmd.manageOwnersForm(snap, step) + err := c.cmd.manageOwnersVotersForm(snap, step) if err != nil { return xerrors.Errorf("failed to remove owner: %v", err) } case CmdAddVoterForm: - err := c.cmd.manageVotersForm(snap, step) + err := c.cmd.manageOwnersVotersForm(snap, step) if err != nil { return xerrors.Errorf("failed to add voter: %v", err) } case CmdRemoveVoterForm: - err := c.cmd.manageVotersForm(snap, step) + err := c.cmd.manageOwnersVotersForm(snap, step) if err != nil { return xerrors.Errorf("failed to remove voter: %v", err) } diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 7ecdb98ea..3c8aec592 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1253,22 +1253,22 @@ func TestCommand_OwnerForm(t *testing.T) { // Checking that if no AdminForm is on the blockchain, // It won't be able to find the transaction. - err = cmd.manageOwnersForm(fake.NewSnapshot(), makeStep(t)) + err = cmd.manageOwnersVotersForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) // Checking that providing a dummy data as argument, the form will not // recognize it and won't be able to unmarshal it. - err = cmd.manageOwnersForm(fake.NewSnapshot(), makeStep(t, FormArg, "dummy")) + err = cmd.manageOwnersVotersForm(fake.NewSnapshot(), makeStep(t, FormArg, "dummy")) require.EqualError(t, err, unmarshalTransactionErr) // Checking that given a Blockchain that always returns an error with // an Add cmd, it will not be able to retrieve the Form on the store. - err = cmd.manageOwnersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataAdd))) + err = cmd.manageOwnersVotersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataAdd))) require.ErrorContains(t, err, "failed to get key") // Checking that given a Blockchain that always returns an error with // a Remove cmd, it will not be able to retrieve the Form on the store. - err = cmd.manageOwnersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataRemove))) + err = cmd.manageOwnersVotersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataRemove))) require.ErrorContains(t, err, "failed to get key") snap := fake.NewSnapshot() @@ -1277,7 +1277,7 @@ func TestCommand_OwnerForm(t *testing.T) { // will not be able to deserialize the Form to perform the command. err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) - err = cmd.manageOwnersForm(snap, makeStep(t, FormArg, string(dataAdd))) + err = cmd.manageOwnersVotersForm(snap, makeStep(t, FormArg, string(dataAdd))) require.ErrorContains(t, err, deserializeErr) // ==== @@ -1302,7 +1302,7 @@ func TestCommand_OwnerForm(t *testing.T) { require.True(t, form.GetOwnerIndex(dummyUserID) == -1) // We perform the Add command on the ledger - err = cmd.manageOwnersForm(snap, makeStep(t, FormArg, string(dataAdd))) + err = cmd.manageOwnersVotersForm(snap, makeStep(t, FormArg, string(dataAdd))) require.NoError(t, err) // Let's see if it added the owner successfully @@ -1322,7 +1322,7 @@ func TestCommand_OwnerForm(t *testing.T) { // We perform the Remove command on the ledger // but it fails because it is the only owner. - err = cmd.manageOwnersForm(snap, makeStep(t, FormArg, string(dataRemove))) + err = cmd.manageOwnersVotersForm(snap, makeStep(t, FormArg, string(dataRemove))) require.ErrorContains(t, err, "cannot remove this owner because it is the only one remaining for this form") // So first let's add a second owner @@ -1336,7 +1336,7 @@ func TestCommand_OwnerForm(t *testing.T) { require.NoError(t, err) // We perform below the command on the ledger - err = cmd.manageOwnersForm(snap, makeStep(t, FormArg, string(dataAdd2))) + err = cmd.manageOwnersVotersForm(snap, makeStep(t, FormArg, string(dataAdd2))) require.NoError(t, err) res, err = snap.Get(dummyFormIDBuff) @@ -1352,7 +1352,7 @@ func TestCommand_OwnerForm(t *testing.T) { require.True(t, form.GetOwnerIndex("234567") == 1) // Now remove successfully the first one. - err = cmd.manageOwnersForm(snap, makeStep(t, FormArg, string(dataRemove))) + err = cmd.manageOwnersVotersForm(snap, makeStep(t, FormArg, string(dataRemove))) require.NoError(t, err) // Let's retrieve the form to check whether it worked @@ -1414,22 +1414,22 @@ func TestCommand_VoterForm(t *testing.T) { // Checking that if no AdminForm is on the blockchain, // It won't be able to find the transaction. - err = cmd.manageVotersForm(fake.NewSnapshot(), makeStep(t)) + err = cmd.manageOwnersVotersForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) // Checking that providing a dummy data as argument, the form will not // recognize it and won't be able to unmarshal it. - err = cmd.manageVotersForm(fake.NewSnapshot(), makeStep(t, FormArg, "dummy")) + err = cmd.manageOwnersVotersForm(fake.NewSnapshot(), makeStep(t, FormArg, "dummy")) require.EqualError(t, err, unmarshalTransactionErr) // Checking that given a Blockchain that always returns an error with // an Add cmd, it will not be able to retrieve the Form on the store. - err = cmd.manageVotersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataAdd))) + err = cmd.manageOwnersVotersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataAdd))) require.ErrorContains(t, err, "failed to get key") // Checking that given a Blockchain that always returns an error with // a Remove cmd, it will not be able to retrieve the Form on the store. - err = cmd.manageVotersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataRemove))) + err = cmd.manageOwnersVotersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataRemove))) require.ErrorContains(t, err, "failed to get key") snap := fake.NewSnapshot() @@ -1438,7 +1438,7 @@ func TestCommand_VoterForm(t *testing.T) { // will not be able to deserialize the Form to perform the command. err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) - err = cmd.manageVotersForm(snap, makeStep(t, FormArg, string(dataAdd))) + err = cmd.manageOwnersVotersForm(snap, makeStep(t, FormArg, string(dataAdd))) require.ErrorContains(t, err, deserializeErr) // ==== @@ -1463,7 +1463,7 @@ func TestCommand_VoterForm(t *testing.T) { require.True(t, form.GetVoterIndex(dummyUserID) == -1) // We perform the Add command on the ledger - err = cmd.manageVotersForm(snap, makeStep(t, FormArg, string(dataAdd))) + err = cmd.manageOwnersVotersForm(snap, makeStep(t, FormArg, string(dataAdd))) require.NoError(t, err) // We then check that the Add command was a success @@ -1482,7 +1482,7 @@ func TestCommand_VoterForm(t *testing.T) { // Now let's remove it // We perform below the command on the ledger - err = cmd.manageVotersForm(snap, makeStep(t, FormArg, string(dataRemove))) + err = cmd.manageOwnersVotersForm(snap, makeStep(t, FormArg, string(dataRemove))) require.NoError(t, err) res, err = snap.Get(dummyFormIDBuff) @@ -1757,11 +1757,7 @@ func (c fakeCmd) manageAdminForm(snap store.Snapshot, step execution.Step) error return c.err } -func (c fakeCmd) manageOwnersForm(snap store.Snapshot, step execution.Step) error { - return c.err -} - -func (c fakeCmd) manageVotersForm(snap store.Snapshot, step execution.Step) error { +func (c fakeCmd) manageOwnersVotersForm(snap store.Snapshot, step execution.Step) error { return c.err } From ea3f62a51a24c40b58a2172fa0fdf508b7be6795 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Tue, 30 Apr 2024 23:36:32 +0200 Subject: [PATCH 049/114] improve code --- contracts/evoting/mod_test.go | 24 +++++++++----- contracts/evoting/types/election.go | 49 +++++++++++++++++------------ 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 3c8aec592..902f21a47 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1299,7 +1299,8 @@ func TestCommand_OwnerForm(t *testing.T) { require.True(t, ok) // We check that now our dummy user is not owner yet (return -1) - require.True(t, form.GetOwnerIndex(dummyUserID) == -1) + dummyUserOwnerIndex, _ := form.GetOwnerIndex(dummyUserID) + require.True(t, dummyUserOwnerIndex == -1) // We perform the Add command on the ledger err = cmd.manageOwnersVotersForm(snap, makeStep(t, FormArg, string(dataAdd))) @@ -1316,7 +1317,8 @@ func TestCommand_OwnerForm(t *testing.T) { require.True(t, ok) // We check that now our dummy user is an owner (return 0) - require.True(t, form.GetOwnerIndex(dummyUserID) == 0) + dummyUserOwnerIndex, _ = form.GetOwnerIndex(dummyUserID) + require.True(t, dummyUserOwnerIndex == 0) // Now let's remove it @@ -1349,7 +1351,8 @@ func TestCommand_OwnerForm(t *testing.T) { require.True(t, ok) // We check that now our second dummy user is also an owner (return 0). - require.True(t, form.GetOwnerIndex("234567") == 1) + secondDummyUserOwnerIndex, _ := form.GetOwnerIndex("234567") + require.True(t, secondDummyUserOwnerIndex == 1) // Now remove successfully the first one. err = cmd.manageOwnersVotersForm(snap, makeStep(t, FormArg, string(dataRemove))) @@ -1366,9 +1369,11 @@ func TestCommand_OwnerForm(t *testing.T) { require.True(t, ok) // We check that now our first dummy user is not an owner anymore (return -1) - require.True(t, form.GetOwnerIndex(dummyUserID) == -1) + dummyUserOwnerIndex, _ = form.GetOwnerIndex(dummyUserID) + require.True(t, dummyUserOwnerIndex == -1) // But that the second one is still an admin (return != -1) - require.True(t, form.GetOwnerIndex("234567") != -1) + secondDummyUserOwnerIndex, _ = form.GetOwnerIndex("234567") + require.True(t, secondDummyUserOwnerIndex != -1) } /* @@ -1460,7 +1465,8 @@ func TestCommand_VoterForm(t *testing.T) { require.True(t, ok) // We check that now our dummy user is not a voter yet (return -1) - require.True(t, form.GetVoterIndex(dummyUserID) == -1) + dummyUserVoterIndex, _ := form.GetVoterIndex(dummyUserID) + require.True(t, dummyUserVoterIndex == -1) // We perform the Add command on the ledger err = cmd.manageOwnersVotersForm(snap, makeStep(t, FormArg, string(dataAdd))) @@ -1477,7 +1483,8 @@ func TestCommand_VoterForm(t *testing.T) { require.True(t, ok) // We check that now our dummy user is an owner (return 0) - require.True(t, form.GetVoterIndex(dummyUserID) == 0) + dummyUserVoterIndex, _ = form.GetVoterIndex(dummyUserID) + require.True(t, dummyUserVoterIndex == 0) // Now let's remove it @@ -1495,7 +1502,8 @@ func TestCommand_VoterForm(t *testing.T) { require.True(t, ok) // We check that now our dummy user is an owner (return 0) - require.True(t, form.GetVoterIndex(dummyUserID) == -1) + dummyUserVoterIndex, _ = form.GetVoterIndex(dummyUserID) + require.True(t, dummyUserVoterIndex == -1) } // ----------------------------------------------------------------------------- diff --git a/contracts/evoting/types/election.go b/contracts/evoting/types/election.go index 5b488bf4d..3ba863b42 100644 --- a/contracts/evoting/types/election.go +++ b/contracts/evoting/types/election.go @@ -430,30 +430,28 @@ func (form *Form) AddVoter(userID string) error { } // GetVoterIndex return the index of admin if userID is one, else return -1 -func (form *Form) GetVoterIndex(userID string) int { - sciperInt, err := strconv.Atoi(userID) +func (form *Form) GetVoterIndex(userID string) (int, error) { + sciperInt, err := SciperToInt(userID) if err != nil { - return -1 + return -1, xerrors.Errorf("Failed SciperToInt: %v", err) } for i := 0; i < len(form.Voters); i++ { if form.Voters[i] == sciperInt { - return i + return i, nil } } - return -1 + return -1, nil } // RemoveVoter add a new admin to the system. func (form *Form) RemoveVoter(userID string) error { - _, err := strconv.Atoi(userID) + index, err := form.GetVoterIndex(userID) if err != nil { - return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) + return xerrors.Errorf("Failed GetVoterIndex: %v", err) } - index := form.GetVoterIndex(userID) - if index < 0 { return xerrors.Errorf("Error while retrieving the index of the element.") } @@ -464,9 +462,9 @@ func (form *Form) RemoveVoter(userID string) error { // AddOwner add a new admin to the system. func (form *Form) AddOwner(userID string) error { - sciperInt, err := strconv.Atoi(userID) + sciperInt, err := SciperToInt(userID) if err != nil { - return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) + return xerrors.Errorf("Failed SciperToInt: %v", err) } // TODO need to check that the new user is admin ! @@ -476,30 +474,28 @@ func (form *Form) AddOwner(userID string) error { } // GetOwnerIndex return the index of admin if userID is one, else return -1 -func (form *Form) GetOwnerIndex(userID string) int { - sciperInt, err := strconv.Atoi(userID) +func (form *Form) GetOwnerIndex(userID string) (int, error) { + sciperInt, err := SciperToInt(userID) if err != nil { - return -1 + return -1, xerrors.Errorf("Failed SciperToInt: %v", err) } for i := 0; i < len(form.Owners); i++ { if form.Owners[i] == sciperInt { - return i + return i, nil } } - return -1 + return -1, nil } // RemoveOwner add a new admin to the system. func (form *Form) RemoveOwner(userID string) error { - _, err := strconv.Atoi(userID) + index, err := form.GetOwnerIndex(userID) if err != nil { - return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) + return xerrors.Errorf("Failed GetOwnerIndex: %v", err) } - index := form.GetOwnerIndex(userID) - if index < 0 { return xerrors.Errorf("Error while retrieving the index of the element.") } @@ -513,3 +509,16 @@ func (form *Form) RemoveOwner(userID string) error { form.Owners = append(form.Owners[:index], form.Owners[index+1:]...) return nil } + +func SciperToInt(userID string) (int, error) { + sciperInt, err := strconv.Atoi(userID) + if err != nil { + return 0, xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) + } + + if sciperInt < 100000 || sciperInt > 999999 { + return 0, xerrors.Errorf("SCIPER %v is out of range.", sciperInt) + } + + return sciperInt, nil +} From 4fa972ba6ab8b21f15116d219db73ddb59ee1333 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 1 May 2024 00:14:24 +0200 Subject: [PATCH 050/114] apply SciperToInt method to admin --- contracts/evoting/mod_test.go | 6 ++++-- contracts/evoting/types/admin.go | 24 +++++++++++------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 902f21a47..41c3cba8f 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1182,7 +1182,8 @@ func TestCommand_AdminForm(t *testing.T) { // We check that our dummy User is now admin // (if not admin return -1; else return admin index in AdminForm). - require.True(t, adminForm.GetAdminIndex(dummyUID) > -1) + dummyUserIDIndex, _ := adminForm.GetAdminIndex(dummyUID) + require.True(t, dummyUserIDIndex > -1) // Now we want to remove its admin privilege. // Initialization of the command @@ -1205,7 +1206,8 @@ func TestCommand_AdminForm(t *testing.T) { require.True(t, ok) // We check that now our dummy user is not admin anymore (return -1) - require.True(t, adminForm.GetAdminIndex(dummyUID) == -1) + dummyUserIDIndex, _ = adminForm.GetAdminIndex(dummyUID) + require.True(t, dummyUserIDIndex == -1) } /* diff --git a/contracts/evoting/types/admin.go b/contracts/evoting/types/admin.go index 46af6f087..92ad2f03a 100644 --- a/contracts/evoting/types/admin.go +++ b/contracts/evoting/types/admin.go @@ -6,7 +6,6 @@ import ( "go.dedis.ch/dela/serde" "go.dedis.ch/dela/serde/registry" "golang.org/x/xerrors" - "strconv" ) var adminFormFormat = registry.NewSimpleRegistry() @@ -47,13 +46,9 @@ func (adminForm AdminForm) Deserialize(ctx serde.Context, data []byte) (serde.Me // AddAdmin add a new admin to the system. func (adminForm *AdminForm) AddAdmin(userID string) error { - sciperInt, err := strconv.Atoi(userID) + sciperInt, err := SciperToInt(userID) if err != nil { - return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) - } - - if sciperInt < 100000 || sciperInt > 999999 { - return xerrors.Errorf("SCIPER %v is out of range.", sciperInt) + return xerrors.Errorf("Failed SciperToInt: %v", err) } adminForm.AdminList = append(adminForm.AdminList, sciperInt) @@ -62,24 +57,27 @@ func (adminForm *AdminForm) AddAdmin(userID string) error { } // GetAdminIndex return the index of admin if userID is one, else return -1 -func (adminForm *AdminForm) GetAdminIndex(userID string) int { - sciperInt, err := strconv.Atoi(userID) +func (adminForm *AdminForm) GetAdminIndex(userID string) (int, error) { + sciperInt, err := SciperToInt(userID) if err != nil { - return -1 + return -1, xerrors.Errorf("Failed SciperToInt: %v", err) } for i := 0; i < len(adminForm.AdminList); i++ { if adminForm.AdminList[i] == sciperInt { - return i + return i, nil } } - return -1 + return -1, nil } // RemoveAdmin add a new admin to the system. func (adminForm *AdminForm) RemoveAdmin(userID string) error { - index := adminForm.GetAdminIndex(userID) + index, err := adminForm.GetAdminIndex(userID) + if err != nil { + return xerrors.Errorf("Failed GetAdnubIndex: %v", err) + } if index < 0 { return xerrors.Errorf("Error while retrieving the index of the element.") From aff482dbc4ebaff77912f0ee2fa1b9bd517de732 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 1 May 2024 00:20:01 +0200 Subject: [PATCH 051/114] patch broken test --- contracts/evoting/admin_test.go | 11 +++++++---- contracts/evoting/types/election.go | 12 ++++++------ 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/contracts/evoting/admin_test.go b/contracts/evoting/admin_test.go index d0fe8e419..c9dac4196 100644 --- a/contracts/evoting/admin_test.go +++ b/contracts/evoting/admin_test.go @@ -55,16 +55,19 @@ func TestAdmin_AddAdminAndRemoveAdmin(t *testing.T) { adminForm := types.AdminForm{FormID: adminFormID, AdminList: adminFormList} - res := adminForm.GetAdminIndex(myTestID) + res, err := adminForm.GetAdminIndex(myTestID) require.Equal(t, -1, res) + require.NoError(t, err) - err := adminForm.AddAdmin(myTestID) + err = adminForm.AddAdmin(myTestID) require.NoError(t, err) - res = adminForm.GetAdminIndex(myTestID) + res, err = adminForm.GetAdminIndex(myTestID) require.Equal(t, 0, res) + require.NoError(t, err) err = adminForm.RemoveAdmin(myTestID) require.NoError(t, err) - res = adminForm.GetAdminIndex(myTestID) + res, err = adminForm.GetAdminIndex(myTestID) require.Equal(t, -1, res) + require.NoError(t, err) } diff --git a/contracts/evoting/types/election.go b/contracts/evoting/types/election.go index 3ba863b42..98db2cd0c 100644 --- a/contracts/evoting/types/election.go +++ b/contracts/evoting/types/election.go @@ -417,7 +417,7 @@ type PubsharesUnits struct { Indexes []int } -// AddVoter add a new admin to the system. +// AddVoter add a new voter to the form. func (form *Form) AddVoter(userID string) error { sciperInt, err := strconv.Atoi(userID) if err != nil { @@ -429,7 +429,7 @@ func (form *Form) AddVoter(userID string) error { return nil } -// GetVoterIndex return the index of admin if userID is one, else return -1 +// GetVoterIndex return the index of voter if userID is one, else return -1 func (form *Form) GetVoterIndex(userID string) (int, error) { sciperInt, err := SciperToInt(userID) if err != nil { @@ -445,7 +445,7 @@ func (form *Form) GetVoterIndex(userID string) (int, error) { return -1, nil } -// RemoveVoter add a new admin to the system. +// RemoveVoter remove a voter to the form. func (form *Form) RemoveVoter(userID string) error { index, err := form.GetVoterIndex(userID) if err != nil { @@ -460,7 +460,7 @@ func (form *Form) RemoveVoter(userID string) error { return nil } -// AddOwner add a new admin to the system. +// AddOwner add a new owner to the form. func (form *Form) AddOwner(userID string) error { sciperInt, err := SciperToInt(userID) if err != nil { @@ -473,7 +473,7 @@ func (form *Form) AddOwner(userID string) error { return nil } -// GetOwnerIndex return the index of admin if userID is one, else return -1 +// GetOwnerIndex return the index of owner if userID is one, else return -1 func (form *Form) GetOwnerIndex(userID string) (int, error) { sciperInt, err := SciperToInt(userID) if err != nil { @@ -489,7 +489,7 @@ func (form *Form) GetOwnerIndex(userID string) (int, error) { return -1, nil } -// RemoveOwner add a new admin to the system. +// RemoveOwner remove an owner from the form. func (form *Form) RemoveOwner(userID string) error { index, err := form.GetOwnerIndex(userID) if err != nil { From fa17b8e1f949de7d27e268f859aa9c0feef1a5cf Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 2 May 2024 00:11:14 +0200 Subject: [PATCH 052/114] start implement is admin logic --- contracts/evoting/evoting.go | 59 ++++++++++++++++++++++++++++- contracts/evoting/types/election.go | 3 +- 2 files changed, 60 insertions(+), 2 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 423a90130..acb64fd38 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -834,6 +834,63 @@ func (e evotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step return nil } +func (e evotingCommand) initializeAdminForm(snap store.Snapshot, step execution.Step, initialAdmin []int) error { + // Get the formID, which is the SHA256 of the transaction ID + h := sha256.New() + h.Write(step.Current.GetID()) + formIDBuf := h.Sum(nil) + + adminForm := types.AdminForm{ + FormID: hex.EncodeToString(formIDBuf), + AdminList: initialAdmin, + } + + formBuf, err := adminForm.Serialize(e.context) + if err != nil { + return xerrors.Errorf("failed to marshal Admin Form : %v", err) + } + + err = snap.Set(formIDBuf, formBuf) + if err != nil { + return xerrors.Errorf("failed to set value: %v", err) + } + + // Update the form metadata store + + formsMetadataBuf, err := snap.Get([]byte(FormsMetadataKey)) + if err != nil { + return xerrors.Errorf("failed to get key '%s': %v", formsMetadataBuf, err) + } + + formsMetadata := &types.FormsMetadata{ + FormsIDs: types.FormIDs{}, + } + + if len(formsMetadataBuf) != 0 { + err := json.Unmarshal(formsMetadataBuf, formsMetadata) + if err != nil { + return xerrors.Errorf("failed to unmarshal FormsMetadata: %v", err) + } + } + + err = formsMetadata.FormsIDs.Add(adminForm.FormID) + if err != nil { + return xerrors.Errorf("couldn't add new form: %v", err) + } + + formMetadataJSON, err := json.Marshal(formsMetadata) + if err != nil { + return xerrors.Errorf("failed to marshal FormsMetadata: %v", err) + } + + err = snap.Set([]byte(FormsMetadataKey), formMetadataJSON) + if err != nil { + return xerrors.Errorf("failed to set value: %v", err) + } + + return nil +} + // manageVotersForm implements commands. // It performs the ADD or REMOVE VOTERS/OWNERS command func (e evotingCommand) manageOwnersVotersForm(snap store.Snapshot, step execution.Step) error { @@ -876,7 +933,7 @@ func (e evotingCommand) manageOwnersVotersForm(snap store.Snapshot, step executi return xerrors.Errorf(errGetForm, err) } - err = form.AddOwner(txAddOwner.UserID) + err = form.AddOwner(e.context, txAddOwner.UserID) if err != nil { return xerrors.Errorf("couldn't add owner: %v", err) } diff --git a/contracts/evoting/types/election.go b/contracts/evoting/types/election.go index 98db2cd0c..8693bb35c 100644 --- a/contracts/evoting/types/election.go +++ b/contracts/evoting/types/election.go @@ -461,13 +461,14 @@ func (form *Form) RemoveVoter(userID string) error { } // AddOwner add a new owner to the form. -func (form *Form) AddOwner(userID string) error { +func (form *Form) AddOwner(ctx serde.Context, userID string) error { sciperInt, err := SciperToInt(userID) if err != nil { return xerrors.Errorf("Failed SciperToInt: %v", err) } // TODO need to check that the new user is admin ! + //adminForm, err := AdminFormFromStore(ctx) form.Owners = append(form.Owners, sciperInt) return nil From 218128b99a5a138b137c177ed3b14ad2e28202e6 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 2 May 2024 12:54:15 +0200 Subject: [PATCH 053/114] ongoing implem --- contracts/evoting/evoting.go | 49 ++++++++++++++++++----------- contracts/evoting/mod.go | 2 +- contracts/evoting/mod_test.go | 24 +++++++------- contracts/evoting/types/election.go | 4 +-- 4 files changed, 46 insertions(+), 33 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index acb64fd38..746296ae5 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -37,19 +37,30 @@ const ( errWrongTx = "wrong type of transaction: %T" ) -// evotingCommand implements the commands of the Evoting contract. +// EvotingCommand implements the commands of the Evoting contract. // // - implements commands -type evotingCommand struct { +type EvotingCommand struct { *Contract prover prover } +func NewEvotingCommand(contract *Contract, prover prover, snap store.Snapshot, step execution.Step, initialAdmin []int) EvotingCommand { + evotingCommand := EvotingCommand{ + Contract: contract, + prover: prover, + } + + evotingCommand.initializeAdminForm(snap, step, initialAdmin) + + return evotingCommand +} + type prover func(suite proof.Suite, protocolName string, verifier proof.Verifier, proof []byte) error // createForm implements commands. It performs the CREATE_FORM command -func (e evotingCommand) createForm(snap store.Snapshot, step execution.Step) error { +func (e EvotingCommand) createForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -163,7 +174,7 @@ func (e evotingCommand) createForm(snap store.Snapshot, step execution.Step) err // openForm set the public key on the form. The public key is fetched // from the DKG actor. It works only if DKG is set up. -func (e evotingCommand) openForm(snap store.Snapshot, step execution.Step) error { +func (e EvotingCommand) openForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -217,7 +228,7 @@ func (e evotingCommand) openForm(snap store.Snapshot, step execution.Step) error } // castVote implements commands. It performs the CAST_VOTE command -func (e evotingCommand) castVote(snap store.Snapshot, step execution.Step) error { +func (e EvotingCommand) castVote(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -264,7 +275,7 @@ func (e evotingCommand) castVote(snap store.Snapshot, step execution.Step) error } // shuffleBallots implements commands. It performs the SHUFFLE_BALLOTS command -func (e evotingCommand) shuffleBallots(snap store.Snapshot, step execution.Step) error { +func (e EvotingCommand) shuffleBallots(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -436,7 +447,7 @@ func (e evotingCommand) shuffleBallots(snap store.Snapshot, step execution.Step) // checkPreviousTransactions checks if a ShuffleBallotsTransaction has already // been accepted and executed for a specific round. -func (e evotingCommand) checkPreviousTransactions(step execution.Step, round int) error { +func (e EvotingCommand) checkPreviousTransactions(step execution.Step, round int) error { for _, tx := range step.Previous { // skip tx not concerning the evoting contract if string(tx.GetArg(native.ContractArg)) != ContractName { @@ -468,7 +479,7 @@ func (e evotingCommand) checkPreviousTransactions(step execution.Step, round int } // closeForm implements commands. It performs the CLOSE_FORM command -func (e evotingCommand) closeForm(snap store.Snapshot, step execution.Step) error { +func (e EvotingCommand) closeForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -511,7 +522,7 @@ func (e evotingCommand) closeForm(snap store.Snapshot, step execution.Step) erro // registerPubshares implements commands. It performs the // REGISTER_PUB_SHARES command -func (e evotingCommand) registerPubshares(snap store.Snapshot, step execution.Step) error { +func (e EvotingCommand) registerPubshares(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { return xerrors.Errorf(errGetTransaction, err) @@ -622,7 +633,7 @@ func (e evotingCommand) registerPubshares(snap store.Snapshot, step execution.St } // combineShares implements commands. It performs the COMBINE_SHARES command -func (e evotingCommand) combineShares(snap store.Snapshot, step execution.Step) error { +func (e EvotingCommand) combineShares(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -695,7 +706,7 @@ func (e evotingCommand) combineShares(snap store.Snapshot, step execution.Step) } // cancelForm implements commands. It performs the CANCEL_FORM command -func (e evotingCommand) cancelForm(snap store.Snapshot, step execution.Step) error { +func (e EvotingCommand) cancelForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -729,7 +740,7 @@ func (e evotingCommand) cancelForm(snap store.Snapshot, step execution.Step) err } // deleteForm implements commands. It performs the DELETE_FORM command -func (e evotingCommand) deleteForm(snap store.Snapshot, step execution.Step) error { +func (e EvotingCommand) deleteForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -785,7 +796,7 @@ func (e evotingCommand) deleteForm(snap store.Snapshot, step execution.Step) err } // manageAdminForm implements commands. It performs the ADD or REMOVE ADMIN command -func (e evotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step) error { +func (e EvotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { return xerrors.Errorf(errGetTransaction, err) @@ -834,7 +845,7 @@ func (e evotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step return nil } -func (e evotingCommand) initializeAdminForm(snap store.Snapshot, step execution.Step, initialAdmin []int) error { +func (e EvotingCommand) initializeAdminForm(snap store.Snapshot, step execution.Step, initialAdmin []int) error { // Get the formID, which is the SHA256 of the transaction ID h := sha256.New() h.Write(step.Current.GetID()) @@ -893,7 +904,7 @@ func (e evotingCommand) initializeAdminForm(snap store.Snapshot, step execution. // manageVotersForm implements commands. // It performs the ADD or REMOVE VOTERS/OWNERS command -func (e evotingCommand) manageOwnersVotersForm(snap store.Snapshot, step execution.Step) error { +func (e EvotingCommand) manageOwnersVotersForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { return xerrors.Errorf(errGetTransaction, err) @@ -933,6 +944,8 @@ func (e evotingCommand) manageOwnersVotersForm(snap store.Snapshot, step executi return xerrors.Errorf(errGetForm, err) } + adminForm, err := e.getAdminForm("id", snap) + err = form.AddOwner(e.context, txAddOwner.UserID) if err != nil { return xerrors.Errorf("couldn't add owner: %v", err) @@ -1031,7 +1044,7 @@ func (s SemiRandomStream) XORKeyStream(dst, src []byte) { // getForm gets the form from the snap. Returns the form ID NOT hex // encoded. -func (e evotingCommand) getForm(formIDHex string, +func (e EvotingCommand) getForm(formIDHex string, snap store.Snapshot) (types.Form, []byte, error) { var form types.Form @@ -1051,7 +1064,7 @@ func (e evotingCommand) getForm(formIDHex string, // getAdminForm gets the AdminForm from the snap. Returns the form ID NOT hex // encoded. -func (e evotingCommand) getAdminForm(formIDHex string, +func (e EvotingCommand) getAdminForm(formIDHex string, snap store.Snapshot) (types.AdminForm, []byte, error) { var form types.AdminForm @@ -1070,7 +1083,7 @@ func (e evotingCommand) getAdminForm(formIDHex string, } // getTransaction extracts the argument from the transaction. -func (e evotingCommand) getTransaction(tx txn.Transaction) (serde.Message, error) { +func (e EvotingCommand) getTransaction(tx txn.Transaction) (serde.Message, error) { buff := tx.GetArg(FormArg) if len(buff) == 0 { return nil, xerrors.Errorf("%q not found in tx arg", FormArg) diff --git a/contracts/evoting/mod.go b/contracts/evoting/mod.go index fd930c289..acfe2c54c 100644 --- a/contracts/evoting/mod.go +++ b/contracts/evoting/mod.go @@ -198,7 +198,7 @@ func NewContract(srvc access.Service, transactionFac: transactionFac, } - contract.cmd = evotingCommand{Contract: &contract, prover: proof.HashVerify} + contract.cmd = EvotingCommand{Contract: &contract, prover: proof.HashVerify} return contract } diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 41c3cba8f..c55afbe17 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -142,7 +142,7 @@ func TestCommand_CreateForm(t *testing.T) { contract := NewContract(service, fakeDkg, rosterFac) - cmd := evotingCommand{ + cmd := EvotingCommand{ Contract: &contract, } @@ -202,7 +202,7 @@ func TestCommand_CastVote(t *testing.T) { formBuf, err := dummyForm.Serialize(ctx) require.NoError(t, err) - cmd := evotingCommand{ + cmd := EvotingCommand{ Contract: &contract, } @@ -332,7 +332,7 @@ func TestCommand_CloseForm(t *testing.T) { formBuf, err := dummyForm.Serialize(ctx) require.NoError(t, err) - cmd := evotingCommand{ + cmd := EvotingCommand{ Contract: &contract, } @@ -408,7 +408,7 @@ func TestCommand_ShuffleBallotsCannotShuffleTwice(t *testing.T) { snap, form, shuffleBallots, contract := initGoodShuffleBallot(t, k) - cmd := evotingCommand{ + cmd := EvotingCommand{ Contract: &contract, prover: fakeProver, } @@ -452,7 +452,7 @@ func TestCommand_ShuffleBallotsValidScenarios(t *testing.T) { // Simple Shuffle from round 0 : snap, form, shuffleBallots, contract := initGoodShuffleBallot(t, k) - cmd := evotingCommand{ + cmd := EvotingCommand{ Contract: &contract, prover: fakeProver, } @@ -530,7 +530,7 @@ func TestCommand_ShuffleBallotsFormatErrors(t *testing.T) { formBuf, err := form.Serialize(ctx) require.NoError(t, err) - cmd := evotingCommand{ + cmd := EvotingCommand{ Contract: &contract, prover: fakeProver, } @@ -756,7 +756,7 @@ func TestCommand_RegisterPubShares(t *testing.T) { formBuf, err := form.Serialize(ctx) require.NoError(t, err) - cmd := evotingCommand{ + cmd := EvotingCommand{ Contract: &contract, } @@ -957,7 +957,7 @@ func TestCommand_DecryptBallots(t *testing.T) { formBuf, err := dummyForm.Serialize(ctx) require.NoError(t, err) - cmd := evotingCommand{ + cmd := EvotingCommand{ Contract: &contract, } @@ -1057,7 +1057,7 @@ func TestCommand_CancelForm(t *testing.T) { formBuf, err := dummyForm.Serialize(ctx) require.NoError(t, err) - cmd := evotingCommand{ + cmd := EvotingCommand{ Contract: &contract, } @@ -1118,7 +1118,7 @@ func TestCommand_AdminForm(t *testing.T) { require.NoError(t, err) // Initialize the command handler to post on the ledger - cmd := evotingCommand{ + cmd := EvotingCommand{ Contract: &contract, } @@ -1247,7 +1247,7 @@ func TestCommand_OwnerForm(t *testing.T) { require.NoError(t, err) // Create an evoting command. - cmd := evotingCommand{ + cmd := EvotingCommand{ Contract: &contract, } @@ -1413,7 +1413,7 @@ func TestCommand_VoterForm(t *testing.T) { require.NoError(t, err) // Create an evoting command. - cmd := evotingCommand{ + cmd := EvotingCommand{ Contract: &contract, } diff --git a/contracts/evoting/types/election.go b/contracts/evoting/types/election.go index 8693bb35c..1a0309a53 100644 --- a/contracts/evoting/types/election.go +++ b/contracts/evoting/types/election.go @@ -461,14 +461,14 @@ func (form *Form) RemoveVoter(userID string) error { } // AddOwner add a new owner to the form. -func (form *Form) AddOwner(ctx serde.Context, userID string) error { +func (form *Form) AddOwner(userID string) error { sciperInt, err := SciperToInt(userID) if err != nil { return xerrors.Errorf("Failed SciperToInt: %v", err) } // TODO need to check that the new user is admin ! - //adminForm, err := AdminFormFromStore(ctx) + form.Owners = append(form.Owners, sciperInt) return nil From 03606e16f7216e00e567db773a963dc9db1be165 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 2 May 2024 13:18:08 +0200 Subject: [PATCH 054/114] add SciperToInt to AddVoter --- contracts/evoting/types/election.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/evoting/types/election.go b/contracts/evoting/types/election.go index 98db2cd0c..588769260 100644 --- a/contracts/evoting/types/election.go +++ b/contracts/evoting/types/election.go @@ -419,9 +419,9 @@ type PubsharesUnits struct { // AddVoter add a new voter to the form. func (form *Form) AddVoter(userID string) error { - sciperInt, err := strconv.Atoi(userID) + sciperInt, err := SciperToInt(userID) if err != nil { - return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) + return xerrors.Errorf("Failed SciperToInt: %v", err) } form.Voters = append(form.Voters, sciperInt) From 64f7dbb4b5c6a7a6e05fcb52dfcf365bb373b26f Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 2 May 2024 13:48:13 +0200 Subject: [PATCH 055/114] change error message to make them more clear --- contracts/evoting/types/admin.go | 4 ++-- contracts/evoting/types/election.go | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/evoting/types/admin.go b/contracts/evoting/types/admin.go index 92ad2f03a..cc4b9e91d 100644 --- a/contracts/evoting/types/admin.go +++ b/contracts/evoting/types/admin.go @@ -48,7 +48,7 @@ func (adminForm AdminForm) Deserialize(ctx serde.Context, data []byte) (serde.Me func (adminForm *AdminForm) AddAdmin(userID string) error { sciperInt, err := SciperToInt(userID) if err != nil { - return xerrors.Errorf("Failed SciperToInt: %v", err) + return xerrors.Errorf("failed to convert SCIPER to integer: %v", err) } adminForm.AdminList = append(adminForm.AdminList, sciperInt) @@ -60,7 +60,7 @@ func (adminForm *AdminForm) AddAdmin(userID string) error { func (adminForm *AdminForm) GetAdminIndex(userID string) (int, error) { sciperInt, err := SciperToInt(userID) if err != nil { - return -1, xerrors.Errorf("Failed SciperToInt: %v", err) + return -1, xerrors.Errorf("failed to convert SCIPER to integer: %v", err) } for i := 0; i < len(adminForm.AdminList); i++ { diff --git a/contracts/evoting/types/election.go b/contracts/evoting/types/election.go index 588769260..947b03038 100644 --- a/contracts/evoting/types/election.go +++ b/contracts/evoting/types/election.go @@ -421,7 +421,7 @@ type PubsharesUnits struct { func (form *Form) AddVoter(userID string) error { sciperInt, err := SciperToInt(userID) if err != nil { - return xerrors.Errorf("Failed SciperToInt: %v", err) + return xerrors.Errorf("failed to convert SCIPER to integer: %v", err) } form.Voters = append(form.Voters, sciperInt) @@ -433,7 +433,7 @@ func (form *Form) AddVoter(userID string) error { func (form *Form) GetVoterIndex(userID string) (int, error) { sciperInt, err := SciperToInt(userID) if err != nil { - return -1, xerrors.Errorf("Failed SciperToInt: %v", err) + return -1, xerrors.Errorf("failed to convert SCIPER to integer: %v", err) } for i := 0; i < len(form.Voters); i++ { @@ -464,7 +464,7 @@ func (form *Form) RemoveVoter(userID string) error { func (form *Form) AddOwner(userID string) error { sciperInt, err := SciperToInt(userID) if err != nil { - return xerrors.Errorf("Failed SciperToInt: %v", err) + return xerrors.Errorf("failed to convert SCIPER to integer: %v", err) } // TODO need to check that the new user is admin ! @@ -477,7 +477,7 @@ func (form *Form) AddOwner(userID string) error { func (form *Form) GetOwnerIndex(userID string) (int, error) { sciperInt, err := SciperToInt(userID) if err != nil { - return -1, xerrors.Errorf("Failed SciperToInt: %v", err) + return -1, xerrors.Errorf("failed to convert SCIPER to integer: %v", err) } for i := 0; i < len(form.Owners); i++ { From 4d48f2bcdf11838c326796a31bda1130344a1958 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 2 May 2024 14:04:36 +0200 Subject: [PATCH 056/114] change error message to make them more clear part 2 --- contracts/evoting/types/admin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/evoting/types/admin.go b/contracts/evoting/types/admin.go index cc4b9e91d..ad40615ca 100644 --- a/contracts/evoting/types/admin.go +++ b/contracts/evoting/types/admin.go @@ -76,7 +76,7 @@ func (adminForm *AdminForm) GetAdminIndex(userID string) (int, error) { func (adminForm *AdminForm) RemoveAdmin(userID string) error { index, err := adminForm.GetAdminIndex(userID) if err != nil { - return xerrors.Errorf("Failed GetAdnubIndex: %v", err) + return xerrors.Errorf("Failed to retrieve the Admin permission: %v", err) } if index < 0 { From d75c5d16a94becfc2231c9eb2ea64dee2e0ac394 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 2 May 2024 14:15:51 +0200 Subject: [PATCH 057/114] add an additional SciperToInt Method --- contracts/evoting/evoting.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 423a90130..baceecc12 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -9,7 +9,6 @@ import ( "encoding/hex" "encoding/json" "math/rand" - "strconv" "strings" "go.dedis.ch/dela" @@ -89,9 +88,9 @@ func (e evotingCommand) createForm(snap store.Snapshot, step execution.Step) err // Initial owner is the creator owners := make([]int, 1) - sciperInt, err := strconv.Atoi(tx.UserID) + sciperInt, err := types.SciperToInt(tx.UserID) if err != nil { - return xerrors.Errorf("Failed to convert SCIPER to an INT: %v", err) + return xerrors.Errorf("failed to convert SCIPER to integer: %v", err) } owners[0] = sciperInt From 445c009d7610ca926ff095d73f824991cbae6b92 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 2 May 2024 14:24:13 +0200 Subject: [PATCH 058/114] patched unvalid userid in test --- contracts/evoting/mod_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 41c3cba8f..dccbcb44e 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -356,7 +356,7 @@ func TestCommand_CloseForm(t *testing.T) { err = snap.Set(dummyFormIDBuff, formBuf) require.NoError(t, err) - closeForm.UserID = hex.EncodeToString([]byte("dummyAdminID")) + closeForm.UserID = hex.EncodeToString([]byte("123456")) data, err = closeForm.Serialize(ctx) require.NoError(t, err) @@ -377,8 +377,8 @@ func TestCommand_CloseForm(t *testing.T) { err = cmd.closeForm(snap, makeStep(t, FormArg, string(data))) require.EqualError(t, err, "at least two ballots are required") - require.NoError(t, dummyForm.CastVote(ctx, snap, "dummyUser1", types.Ciphervote{})) - require.NoError(t, dummyForm.CastVote(ctx, snap, "dummyUser2", types.Ciphervote{})) + require.NoError(t, dummyForm.CastVote(ctx, snap, "123456", types.Ciphervote{})) + require.NoError(t, dummyForm.CastVote(ctx, snap, "654321", types.Ciphervote{})) formBuf, err = dummyForm.Serialize(ctx) require.NoError(t, err) From b54e0f4af4e8be0e8dc0d51f1af2b328fa364a00 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 2 May 2024 14:25:59 +0200 Subject: [PATCH 059/114] update a comment in the test --- contracts/evoting/mod_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index dccbcb44e..cc0d5cc71 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1503,7 +1503,7 @@ func TestCommand_VoterForm(t *testing.T) { form, ok = message.(types.Form) require.True(t, ok) - // We check that now our dummy user is an owner (return 0) + // We check that now our dummy user is a voter (return 0) dummyUserVoterIndex, _ = form.GetVoterIndex(dummyUserID) require.True(t, dummyUserVoterIndex == -1) } From 0f440cc9c5b49b9a3ff25a9928851c85a80b5f43 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 2 May 2024 15:13:55 +0200 Subject: [PATCH 060/114] update a comment in the test 2 --- contracts/evoting/mod_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index cc0d5cc71..113865f8e 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1484,7 +1484,7 @@ func TestCommand_VoterForm(t *testing.T) { form, ok = message.(types.Form) require.True(t, ok) - // We check that now our dummy user is an owner (return 0) + // We check that now our dummy user is a voter (return 0) dummyUserVoterIndex, _ = form.GetVoterIndex(dummyUserID) require.True(t, dummyUserVoterIndex == 0) From 6a4dffa500883761d38257f77ec19087215b77c3 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Sat, 11 May 2024 16:23:53 +0200 Subject: [PATCH 061/114] patch changes --- contracts/evoting/evoting.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 746296ae5..d90659b7c 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -944,9 +944,18 @@ func (e EvotingCommand) manageOwnersVotersForm(snap store.Snapshot, step executi return xerrors.Errorf(errGetForm, err) } - adminForm, err := e.getAdminForm("id", snap) + adminForm, _, err := e.getAdminForm("id", snap) + adminIndex, err := adminForm.GetAdminIndex(txAddOwner.UserID) + if err != nil { + return xerrors.Errorf("Couldn't retrieve the admin right of the user: %v", err) + } + + if adminIndex < 0 { + return xerrors.Errorf("The user is not admin: %v", err) + } - err = form.AddOwner(e.context, txAddOwner.UserID) + // TODO mettre le adminForm en argument du AddOwner et faire la verif dedans + err = form.AddOwner(txAddOwner.UserID) if err != nil { return xerrors.Errorf("couldn't add owner: %v", err) } From 44bab356e3031fe1e92cbdeb24b633c9a0f2794a Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Sat, 11 May 2024 16:27:11 +0200 Subject: [PATCH 062/114] patch changes 2 --- contracts/evoting/evoting.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index d90659b7c..b9758ae7f 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -945,6 +945,9 @@ func (e EvotingCommand) manageOwnersVotersForm(snap store.Snapshot, step executi } adminForm, _, err := e.getAdminForm("id", snap) + if err != nil { + return xerrors.Errorf("failed to get AdminForm: %v", err) + } adminIndex, err := adminForm.GetAdminIndex(txAddOwner.UserID) if err != nil { return xerrors.Errorf("Couldn't retrieve the admin right of the user: %v", err) From 26fd7075321036603406e19ee5e1ebb0b71f93bc Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Sat, 11 May 2024 16:59:54 +0200 Subject: [PATCH 063/114] Init AdminForm method --- contracts/evoting/evoting.go | 42 ++++++++++++++++++++--------------- contracts/evoting/mod_test.go | 12 ++++++---- 2 files changed, 32 insertions(+), 22 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index b9758ae7f..5d3286b6d 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -43,18 +43,24 @@ const ( type EvotingCommand struct { *Contract - prover prover + prover prover + adminFormID string } -func NewEvotingCommand(contract *Contract, prover prover, snap store.Snapshot, step execution.Step, initialAdmin []int) EvotingCommand { - evotingCommand := EvotingCommand{ - Contract: contract, - prover: prover, +func NewEvotingCommand(contract *Contract, prover prover, snap store.Snapshot, step execution.Step, initialAdmin []int) (EvotingCommand, error) { + // TODO add error handling + adminFormID, err := initializeAdminForm(snap, step, initialAdmin, contract.context) + if err != nil { + return EvotingCommand{}, xerrors.Errorf("failed to create an Admin Form: %v", err) } - evotingCommand.initializeAdminForm(snap, step, initialAdmin) + evotingCommand := EvotingCommand{ + Contract: contract, + prover: prover, + adminFormID: hex.EncodeToString(adminFormID), + } - return evotingCommand + return evotingCommand, nil } type prover func(suite proof.Suite, protocolName string, verifier proof.Verifier, proof []byte) error @@ -845,7 +851,7 @@ func (e EvotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step return nil } -func (e EvotingCommand) initializeAdminForm(snap store.Snapshot, step execution.Step, initialAdmin []int) error { +func initializeAdminForm(snap store.Snapshot, step execution.Step, initialAdmin []int, ctx serde.Context) ([]byte, error) { // Get the formID, which is the SHA256 of the transaction ID h := sha256.New() h.Write(step.Current.GetID()) @@ -856,21 +862,21 @@ func (e EvotingCommand) initializeAdminForm(snap store.Snapshot, step execution. AdminList: initialAdmin, } - formBuf, err := adminForm.Serialize(e.context) + formBuf, err := adminForm.Serialize(ctx) if err != nil { - return xerrors.Errorf("failed to marshal Admin Form : %v", err) + return nil, xerrors.Errorf("failed to marshal Admin Form : %v", err) } err = snap.Set(formIDBuf, formBuf) if err != nil { - return xerrors.Errorf("failed to set value: %v", err) + return nil, xerrors.Errorf("failed to set value: %v", err) } // Update the form metadata store formsMetadataBuf, err := snap.Get([]byte(FormsMetadataKey)) if err != nil { - return xerrors.Errorf("failed to get key '%s': %v", formsMetadataBuf, err) + return nil, xerrors.Errorf("failed to get key '%s': %v", formsMetadataBuf, err) } formsMetadata := &types.FormsMetadata{ @@ -880,26 +886,26 @@ func (e EvotingCommand) initializeAdminForm(snap store.Snapshot, step execution. if len(formsMetadataBuf) != 0 { err := json.Unmarshal(formsMetadataBuf, formsMetadata) if err != nil { - return xerrors.Errorf("failed to unmarshal FormsMetadata: %v", err) + return nil, xerrors.Errorf("failed to unmarshal FormsMetadata: %v", err) } } err = formsMetadata.FormsIDs.Add(adminForm.FormID) if err != nil { - return xerrors.Errorf("couldn't add new form: %v", err) + return nil, xerrors.Errorf("couldn't add new form: %v", err) } formMetadataJSON, err := json.Marshal(formsMetadata) if err != nil { - return xerrors.Errorf("failed to marshal FormsMetadata: %v", err) + return nil, xerrors.Errorf("failed to marshal FormsMetadata: %v", err) } err = snap.Set([]byte(FormsMetadataKey), formMetadataJSON) if err != nil { - return xerrors.Errorf("failed to set value: %v", err) + return nil, xerrors.Errorf("failed to set value: %v", err) } - return nil + return formIDBuf, nil } // manageVotersForm implements commands. @@ -944,7 +950,7 @@ func (e EvotingCommand) manageOwnersVotersForm(snap store.Snapshot, step executi return xerrors.Errorf(errGetForm, err) } - adminForm, _, err := e.getAdminForm("id", snap) + adminForm, _, err := e.getAdminForm(e.adminFormID, snap) if err != nil { return xerrors.Errorf("failed to get AdminForm: %v", err) } diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index c55afbe17..8b31e519c 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1246,11 +1246,17 @@ func TestCommand_OwnerForm(t *testing.T) { formBuf, err := dummyForm.Serialize(ctx) require.NoError(t, err) + snap := fake.NewSnapshot() + initialAdmin := []int{123456, 234567} // Create an evoting command. - cmd := EvotingCommand{ - Contract: &contract, + cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) + require.NoError(t, err) + /* EvotingCommand{ + Contract: &contract, } + */ + // The following test are there to check error handling // Checking that if no AdminForm is on the blockchain, @@ -1273,8 +1279,6 @@ func TestCommand_OwnerForm(t *testing.T) { err = cmd.manageOwnersVotersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataRemove))) require.ErrorContains(t, err, "failed to get key") - snap := fake.NewSnapshot() - // Checking that given the form set in the Snapshot which is invalid, then it // will not be able to deserialize the Form to perform the command. err = snap.Set(dummyFormIDBuff, invalidForm) From f3aed814c2aede7b032f38e6ed232b27d2b6ca4f Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Sat, 11 May 2024 17:58:04 +0200 Subject: [PATCH 064/114] now need an admin perm on blockchain to create form --- contracts/evoting/evoting.go | 28 +++++----- contracts/evoting/mod_test.go | 97 +++++++++++++++++------------------ 2 files changed, 61 insertions(+), 64 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 5d3286b6d..f5aef98b3 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -83,6 +83,20 @@ func (e EvotingCommand) createForm(snap store.Snapshot, step execution.Step) err return xerrors.Errorf("failed to get roster") } + // Check if has Admin Right to create a form + adminForm, _, err := e.getAdminForm(e.adminFormID, snap) + if err != nil { + return xerrors.Errorf("failed to get AdminForm: %v", err) + } + adminIndex, err := adminForm.GetAdminIndex(tx.UserID) + if err != nil { + return xerrors.Errorf("Couldn't retrieve the admin right of the user: %v", err) + } + + if adminIndex < 0 { + return xerrors.Errorf("The user is not admin: %v", err) + } + roster, err := e.rosterFac.AuthorityOf(e.context, rosterBuf) if err != nil { return xerrors.Errorf("failed to get roster: %v", err) @@ -950,20 +964,6 @@ func (e EvotingCommand) manageOwnersVotersForm(snap store.Snapshot, step executi return xerrors.Errorf(errGetForm, err) } - adminForm, _, err := e.getAdminForm(e.adminFormID, snap) - if err != nil { - return xerrors.Errorf("failed to get AdminForm: %v", err) - } - adminIndex, err := adminForm.GetAdminIndex(txAddOwner.UserID) - if err != nil { - return xerrors.Errorf("Couldn't retrieve the admin right of the user: %v", err) - } - - if adminIndex < 0 { - return xerrors.Errorf("The user is not admin: %v", err) - } - - // TODO mettre le adminForm en argument du AddOwner et faire la verif dedans err = form.AddOwner(txAddOwner.UserID) if err != nil { return xerrors.Errorf("couldn't add owner: %v", err) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 8b31e519c..ab1ceb4cb 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -34,7 +34,8 @@ var dummyAdminFormIDBuff = []byte("dummyAdminID") var fakeFormID = hex.EncodeToString(dummyFormIDBuff) var fakeAdminFormID = hex.EncodeToString(dummyAdminFormIDBuff) var fakeCommonSigner = bls.NewSigner() -var dummyUserID = "123456" +var dummyUserAdminID = "123456" +var dummyUserAdminIDInt = 123456 const getTransactionErr = "failed to get transaction: \"evoting:arg\" not found in tx arg" const unmarshalTransactionErr = "failed to get transaction: failed to deserialize " + @@ -131,7 +132,7 @@ func TestCommand_CreateForm(t *testing.T) { } createForm := types.CreateForm{ - UserID: dummyUserID, + UserID: dummyUserAdminID, } data, err := createForm.Serialize(ctx) @@ -142,9 +143,11 @@ func TestCommand_CreateForm(t *testing.T) { contract := NewContract(service, fakeDkg, rosterFac) - cmd := EvotingCommand{ - Contract: &contract, - } + snap := fake.NewSnapshot() + initialAdmin := []int{dummyUserAdminIDInt} + // Create an evoting command. + cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) + require.NoError(t, err) err = cmd.createForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -155,7 +158,6 @@ func TestCommand_CreateForm(t *testing.T) { err = cmd.createForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.EqualError(t, err, "failed to get roster") - snap := fake.NewSnapshot() step := makeStep(t, FormArg, string(data)) err = cmd.createForm(snap, step) require.NoError(t, err) @@ -202,9 +204,11 @@ func TestCommand_CastVote(t *testing.T) { formBuf, err := dummyForm.Serialize(ctx) require.NoError(t, err) - cmd := EvotingCommand{ - Contract: &contract, - } + snap := fake.NewSnapshot() + initialAdmin := []int{dummyUserAdminIDInt} + // Create an evoting command. + cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) + require.NoError(t, err) err = cmd.castVote(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -215,8 +219,6 @@ func TestCommand_CastVote(t *testing.T) { err = cmd.castVote(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to get key") - snap := fake.NewSnapshot() - err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) @@ -320,7 +322,7 @@ func TestCommand_CloseForm(t *testing.T) { closeForm := types.CloseForm{ FormID: fakeFormID, - UserID: dummyUserID, + UserID: dummyUserAdminID, } data, err := closeForm.Serialize(ctx) @@ -332,9 +334,11 @@ func TestCommand_CloseForm(t *testing.T) { formBuf, err := dummyForm.Serialize(ctx) require.NoError(t, err) - cmd := EvotingCommand{ - Contract: &contract, - } + snap := fake.NewSnapshot() + initialAdmin := []int{dummyUserAdminIDInt} + // Create an evoting command. + cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) + require.NoError(t, err) err = cmd.closeForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -345,8 +349,6 @@ func TestCommand_CloseForm(t *testing.T) { err = cmd.closeForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to get key") - snap := fake.NewSnapshot() - err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) @@ -756,9 +758,11 @@ func TestCommand_RegisterPubShares(t *testing.T) { formBuf, err := form.Serialize(ctx) require.NoError(t, err) - cmd := EvotingCommand{ - Contract: &contract, - } + snap := fake.NewSnapshot() + initialAdmin := []int{dummyUserAdminIDInt} + // Create an evoting command. + cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) + require.NoError(t, err) err = cmd.registerPubshares(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -769,8 +773,6 @@ func TestCommand_RegisterPubShares(t *testing.T) { err = cmd.registerPubshares(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to get key") - snap := fake.NewSnapshot() - err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) @@ -946,7 +948,7 @@ func TestCommand_RegisterPubShares(t *testing.T) { func TestCommand_DecryptBallots(t *testing.T) { decryptBallot := types.CombineShares{ FormID: fakeFormID, - UserID: dummyUserID, + UserID: dummyUserAdminID, } data, err := decryptBallot.Serialize(ctx) @@ -957,9 +959,11 @@ func TestCommand_DecryptBallots(t *testing.T) { formBuf, err := dummyForm.Serialize(ctx) require.NoError(t, err) - cmd := EvotingCommand{ - Contract: &contract, - } + snap := fake.NewSnapshot() + initialAdmin := []int{dummyUserAdminIDInt} + // Create an evoting command. + cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) + require.NoError(t, err) err = cmd.combineShares(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -970,8 +974,6 @@ func TestCommand_DecryptBallots(t *testing.T) { err = cmd.combineShares(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to get key") - snap := fake.NewSnapshot() - err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) @@ -1045,7 +1047,7 @@ func TestCommand_DecryptBallots(t *testing.T) { func TestCommand_CancelForm(t *testing.T) { cancelForm := types.CancelForm{ FormID: fakeFormID, - UserID: dummyUserID, + UserID: dummyUserAdminID, } data, err := cancelForm.Serialize(ctx) @@ -1057,9 +1059,11 @@ func TestCommand_CancelForm(t *testing.T) { formBuf, err := dummyForm.Serialize(ctx) require.NoError(t, err) - cmd := EvotingCommand{ - Contract: &contract, - } + snap := fake.NewSnapshot() + initialAdmin := []int{dummyUserAdminIDInt} + // Create an evoting command. + cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) + require.NoError(t, err) err = cmd.cancelForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -1070,8 +1074,6 @@ func TestCommand_CancelForm(t *testing.T) { err = cmd.cancelForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to get key") - snap := fake.NewSnapshot() - err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) @@ -1222,7 +1224,7 @@ func TestCommand_AdminForm(t *testing.T) { func TestCommand_OwnerForm(t *testing.T) { addOwner := types.AddOwner{ FormID: fakeFormID, - UserID: dummyUserID, + UserID: dummyUserAdminID, } // Test Serialization of AddOwner command @@ -1231,7 +1233,7 @@ func TestCommand_OwnerForm(t *testing.T) { removeOwner := types.RemoveOwner{ FormID: fakeFormID, - UserID: dummyUserID, + UserID: dummyUserAdminID, } // Test Serialization of RemoveOwner command @@ -1247,15 +1249,10 @@ func TestCommand_OwnerForm(t *testing.T) { require.NoError(t, err) snap := fake.NewSnapshot() - initialAdmin := []int{123456, 234567} + initialAdmin := []int{123456} // Create an evoting command. cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) require.NoError(t, err) - /* EvotingCommand{ - Contract: &contract, - } - - */ // The following test are there to check error handling @@ -1305,7 +1302,7 @@ func TestCommand_OwnerForm(t *testing.T) { require.True(t, ok) // We check that now our dummy user is not owner yet (return -1) - dummyUserOwnerIndex, _ := form.GetOwnerIndex(dummyUserID) + dummyUserOwnerIndex, _ := form.GetOwnerIndex(dummyUserAdminID) require.True(t, dummyUserOwnerIndex == -1) // We perform the Add command on the ledger @@ -1323,7 +1320,7 @@ func TestCommand_OwnerForm(t *testing.T) { require.True(t, ok) // We check that now our dummy user is an owner (return 0) - dummyUserOwnerIndex, _ = form.GetOwnerIndex(dummyUserID) + dummyUserOwnerIndex, _ = form.GetOwnerIndex(dummyUserAdminID) require.True(t, dummyUserOwnerIndex == 0) // Now let's remove it @@ -1375,7 +1372,7 @@ func TestCommand_OwnerForm(t *testing.T) { require.True(t, ok) // We check that now our first dummy user is not an owner anymore (return -1) - dummyUserOwnerIndex, _ = form.GetOwnerIndex(dummyUserID) + dummyUserOwnerIndex, _ = form.GetOwnerIndex(dummyUserAdminID) require.True(t, dummyUserOwnerIndex == -1) // But that the second one is still an admin (return != -1) secondDummyUserOwnerIndex, _ = form.GetOwnerIndex("234567") @@ -1392,7 +1389,7 @@ func TestCommand_OwnerForm(t *testing.T) { func TestCommand_VoterForm(t *testing.T) { addVoter := types.AddVoter{ FormID: fakeFormID, - UserID: dummyUserID, + UserID: dummyUserAdminID, } // Test Serialization of AddVoter command @@ -1401,7 +1398,7 @@ func TestCommand_VoterForm(t *testing.T) { removeVoter := types.RemoveVoter{ FormID: fakeFormID, - UserID: dummyUserID, + UserID: dummyUserAdminID, } // Test Serialization of RemoveVoter command @@ -1471,7 +1468,7 @@ func TestCommand_VoterForm(t *testing.T) { require.True(t, ok) // We check that now our dummy user is not a voter yet (return -1) - dummyUserVoterIndex, _ := form.GetVoterIndex(dummyUserID) + dummyUserVoterIndex, _ := form.GetVoterIndex(dummyUserAdminID) require.True(t, dummyUserVoterIndex == -1) // We perform the Add command on the ledger @@ -1489,7 +1486,7 @@ func TestCommand_VoterForm(t *testing.T) { require.True(t, ok) // We check that now our dummy user is an owner (return 0) - dummyUserVoterIndex, _ = form.GetVoterIndex(dummyUserID) + dummyUserVoterIndex, _ = form.GetVoterIndex(dummyUserAdminID) require.True(t, dummyUserVoterIndex == 0) // Now let's remove it @@ -1508,7 +1505,7 @@ func TestCommand_VoterForm(t *testing.T) { require.True(t, ok) // We check that now our dummy user is an owner (return 0) - dummyUserVoterIndex, _ = form.GetVoterIndex(dummyUserID) + dummyUserVoterIndex, _ = form.GetVoterIndex(dummyUserAdminID) require.True(t, dummyUserVoterIndex == -1) } From a3cb44314975b98d5429e5f2e68f1a283a9fc609 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 15 May 2024 00:38:36 +0200 Subject: [PATCH 065/114] evening work refactor part 1 --- contracts/evoting/admin_test.go | 13 +- contracts/evoting/evoting.go | 134 +++++++------- .../json/{adminForm.go => adminList.go} | 9 +- contracts/evoting/json/transaction.go | 6 +- contracts/evoting/mod.go | 4 +- contracts/evoting/mod_test.go | 174 +++++++++--------- contracts/evoting/types/admin.go | 56 +++--- contracts/evoting/types/transactions.go | 4 - integration/form.go | 23 +++ integration/integration_test.go | 9 + 10 files changed, 221 insertions(+), 211 deletions(-) rename contracts/evoting/json/{adminForm.go => adminList.go} (80%) diff --git a/contracts/evoting/admin_test.go b/contracts/evoting/admin_test.go index c9dac4196..4f0441e16 100644 --- a/contracts/evoting/admin_test.go +++ b/contracts/evoting/admin_test.go @@ -23,37 +23,34 @@ func init() { // This test create an Admin Form structure which is then serialized and // deserialized to check whether these operations work as intended. -// Serialization/Deserialization of an AdminForm should not change its values. +// Serialization/Deserialization of an AdminList should not change its values. func TestAdmin_Serde(t *testing.T) { - adminFormID := "myID" adminFormList := []int{111111, 222222, 333333, 123456} - adminForm := types.AdminForm{FormID: adminFormID, AdminList: adminFormList} + adminForm := types.AdminList{AdminList: adminFormList} value, err := adminForm.Serialize(ctxAdminTest) require.NoError(t, err) // deserialization - newAdminForm := types.AdminForm{} + newAdminForm := types.AdminList{} msgs, err := newAdminForm.Deserialize(ctxAdminTest, value) require.NoError(t, err) - updatedAdminForm := msgs.(types.AdminForm) + updatedAdminForm := msgs.(types.AdminList) - require.Equal(t, adminFormID, updatedAdminForm.FormID) require.Equal(t, adminFormList, updatedAdminForm.AdminList) } func TestAdmin_AddAdminAndRemoveAdmin(t *testing.T) { - adminFormID := "myID" adminFormList := []int{} myTestID := "123456" - adminForm := types.AdminForm{FormID: adminFormID, AdminList: adminFormList} + adminForm := types.AdminList{AdminList: adminFormList} res, err := adminForm.GetAdminIndex(myTestID) require.Equal(t, -1, res) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index f5aef98b3..20e9646ae 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -37,36 +37,19 @@ const ( errWrongTx = "wrong type of transaction: %T" ) -// EvotingCommand implements the commands of the Evoting contract. +// evotingCommand implements the commands of the Evoting contract. // // - implements commands -type EvotingCommand struct { +type evotingCommand struct { *Contract - prover prover - adminFormID string -} - -func NewEvotingCommand(contract *Contract, prover prover, snap store.Snapshot, step execution.Step, initialAdmin []int) (EvotingCommand, error) { - // TODO add error handling - adminFormID, err := initializeAdminForm(snap, step, initialAdmin, contract.context) - if err != nil { - return EvotingCommand{}, xerrors.Errorf("failed to create an Admin Form: %v", err) - } - - evotingCommand := EvotingCommand{ - Contract: contract, - prover: prover, - adminFormID: hex.EncodeToString(adminFormID), - } - - return evotingCommand, nil + prover prover } type prover func(suite proof.Suite, protocolName string, verifier proof.Verifier, proof []byte) error // createForm implements commands. It performs the CREATE_FORM command -func (e EvotingCommand) createForm(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) createForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -84,9 +67,9 @@ func (e EvotingCommand) createForm(snap store.Snapshot, step execution.Step) err } // Check if has Admin Right to create a form - adminForm, _, err := e.getAdminForm(e.adminFormID, snap) + adminForm, err := e.getAdminForm(snap) if err != nil { - return xerrors.Errorf("failed to get AdminForm: %v", err) + return xerrors.Errorf("failed to get AdminList: %v", err) } adminIndex, err := adminForm.GetAdminIndex(tx.UserID) if err != nil { @@ -194,7 +177,7 @@ func (e EvotingCommand) createForm(snap store.Snapshot, step execution.Step) err // openForm set the public key on the form. The public key is fetched // from the DKG actor. It works only if DKG is set up. -func (e EvotingCommand) openForm(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) openForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -248,7 +231,7 @@ func (e EvotingCommand) openForm(snap store.Snapshot, step execution.Step) error } // castVote implements commands. It performs the CAST_VOTE command -func (e EvotingCommand) castVote(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) castVote(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -295,7 +278,7 @@ func (e EvotingCommand) castVote(snap store.Snapshot, step execution.Step) error } // shuffleBallots implements commands. It performs the SHUFFLE_BALLOTS command -func (e EvotingCommand) shuffleBallots(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) shuffleBallots(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -467,7 +450,7 @@ func (e EvotingCommand) shuffleBallots(snap store.Snapshot, step execution.Step) // checkPreviousTransactions checks if a ShuffleBallotsTransaction has already // been accepted and executed for a specific round. -func (e EvotingCommand) checkPreviousTransactions(step execution.Step, round int) error { +func (e evotingCommand) checkPreviousTransactions(step execution.Step, round int) error { for _, tx := range step.Previous { // skip tx not concerning the evoting contract if string(tx.GetArg(native.ContractArg)) != ContractName { @@ -499,7 +482,7 @@ func (e EvotingCommand) checkPreviousTransactions(step execution.Step, round int } // closeForm implements commands. It performs the CLOSE_FORM command -func (e EvotingCommand) closeForm(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) closeForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -542,7 +525,7 @@ func (e EvotingCommand) closeForm(snap store.Snapshot, step execution.Step) erro // registerPubshares implements commands. It performs the // REGISTER_PUB_SHARES command -func (e EvotingCommand) registerPubshares(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) registerPubshares(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { return xerrors.Errorf(errGetTransaction, err) @@ -653,7 +636,7 @@ func (e EvotingCommand) registerPubshares(snap store.Snapshot, step execution.St } // combineShares implements commands. It performs the COMBINE_SHARES command -func (e EvotingCommand) combineShares(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) combineShares(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -726,7 +709,7 @@ func (e EvotingCommand) combineShares(snap store.Snapshot, step execution.Step) } // cancelForm implements commands. It performs the CANCEL_FORM command -func (e EvotingCommand) cancelForm(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) cancelForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -760,7 +743,7 @@ func (e EvotingCommand) cancelForm(snap store.Snapshot, step execution.Step) err } // deleteForm implements commands. It performs the DELETE_FORM command -func (e EvotingCommand) deleteForm(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) deleteForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -816,22 +799,41 @@ func (e EvotingCommand) deleteForm(snap store.Snapshot, step execution.Step) err } // manageAdminForm implements commands. It performs the ADD or REMOVE ADMIN command -func (e EvotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { return xerrors.Errorf(errGetTransaction, err) } - var form types.AdminForm - var formID []byte + var form types.AdminList + + h := sha256.New() + h.Write([]byte(AdminListId)) + formIDBuf := h.Sum(nil) txAddAdmin, okAddAdmin := msg.(types.AddAdmin) txRemoveAdmin, okRemoveAdmin := msg.(types.RemoveAdmin) if okAddAdmin { - form, formID, err = e.getAdminForm(txAddAdmin.FormID, snap) + form, err = e.getAdminForm(snap) if err != nil { - return xerrors.Errorf("failed to get AdminForm: %v", err) + if !strings.Contains(err.Error(), "No form found") { + return xerrors.Errorf("failed to get AdminList: %v", err) + } + + intSciper, err := types.SciperToInt(txAddAdmin.UserID) + if err != nil { + return xerrors.Errorf("Invalid Sciper: %v", err) + } + + err = initializeAdminList(snap, intSciper, e.context) + if err != nil { + return xerrors.Errorf("Failed to initialize admin list: %v", err) + } + + // Adding the initial admin is performed by the initialize Admin List + // Therefore return + return nil } err = form.AddAdmin(txAddAdmin.UserID) @@ -839,9 +841,9 @@ func (e EvotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step return xerrors.Errorf("couldn't add admin: %v", err) } } else if okRemoveAdmin { - form, formID, err = e.getAdminForm(txRemoveAdmin.FormID, snap) + form, err = e.getAdminForm(snap) if err != nil { - return xerrors.Errorf("failed to get AdminForm: %v", err) + return xerrors.Errorf("failed to get AdminList: %v", err) } err = form.RemoveAdmin(txRemoveAdmin.UserID) @@ -857,7 +859,7 @@ func (e EvotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step return xerrors.Errorf("failed to marshal Form : %v", err) } - err = snap.Set(formID, formBuf) + err = snap.Set(formIDBuf, formBuf) if err != nil { return xerrors.Errorf("failed to set value: %v", err) } @@ -865,32 +867,30 @@ func (e EvotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step return nil } -func initializeAdminForm(snap store.Snapshot, step execution.Step, initialAdmin []int, ctx serde.Context) ([]byte, error) { - // Get the formID, which is the SHA256 of the transaction ID +func initializeAdminList(snap store.Snapshot, initialAdmin int, ctx serde.Context) error { h := sha256.New() - h.Write(step.Current.GetID()) + h.Write([]byte(AdminListId)) formIDBuf := h.Sum(nil) - adminForm := types.AdminForm{ - FormID: hex.EncodeToString(formIDBuf), - AdminList: initialAdmin, + adminForm := types.AdminList{ + AdminList: []int{initialAdmin}, } formBuf, err := adminForm.Serialize(ctx) if err != nil { - return nil, xerrors.Errorf("failed to marshal Admin Form : %v", err) + return xerrors.Errorf("failed to marshal Admin Form : %v", err) } err = snap.Set(formIDBuf, formBuf) if err != nil { - return nil, xerrors.Errorf("failed to set value: %v", err) + return xerrors.Errorf("failed to set value: %v", err) } // Update the form metadata store formsMetadataBuf, err := snap.Get([]byte(FormsMetadataKey)) if err != nil { - return nil, xerrors.Errorf("failed to get key '%s': %v", formsMetadataBuf, err) + return xerrors.Errorf("failed to get key '%s': %v", formsMetadataBuf, err) } formsMetadata := &types.FormsMetadata{ @@ -900,31 +900,31 @@ func initializeAdminForm(snap store.Snapshot, step execution.Step, initialAdmin if len(formsMetadataBuf) != 0 { err := json.Unmarshal(formsMetadataBuf, formsMetadata) if err != nil { - return nil, xerrors.Errorf("failed to unmarshal FormsMetadata: %v", err) + return xerrors.Errorf("failed to unmarshal FormsMetadata: %v", err) } } - err = formsMetadata.FormsIDs.Add(adminForm.FormID) + err = formsMetadata.FormsIDs.Add(hex.EncodeToString(formIDBuf)) if err != nil { - return nil, xerrors.Errorf("couldn't add new form: %v", err) + return xerrors.Errorf("couldn't add new form: %v", err) } formMetadataJSON, err := json.Marshal(formsMetadata) if err != nil { - return nil, xerrors.Errorf("failed to marshal FormsMetadata: %v", err) + return xerrors.Errorf("failed to marshal FormsMetadata: %v", err) } err = snap.Set([]byte(FormsMetadataKey), formMetadataJSON) if err != nil { - return nil, xerrors.Errorf("failed to set value: %v", err) + return xerrors.Errorf("failed to set value: %v", err) } - return formIDBuf, nil + return nil } // manageVotersForm implements commands. // It performs the ADD or REMOVE VOTERS/OWNERS command -func (e EvotingCommand) manageOwnersVotersForm(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) manageOwnersVotersForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { return xerrors.Errorf(errGetTransaction, err) @@ -1062,7 +1062,7 @@ func (s SemiRandomStream) XORKeyStream(dst, src []byte) { // getForm gets the form from the snap. Returns the form ID NOT hex // encoded. -func (e EvotingCommand) getForm(formIDHex string, +func (e evotingCommand) getForm(formIDHex string, snap store.Snapshot) (types.Form, []byte, error) { var form types.Form @@ -1080,28 +1080,22 @@ func (e EvotingCommand) getForm(formIDHex string, return form, formIDBuf, nil } -// getAdminForm gets the AdminForm from the snap. Returns the form ID NOT hex +// getAdminForm gets the AdminList from the snap. Returns the form ID NOT hex // encoded. -func (e EvotingCommand) getAdminForm(formIDHex string, - snap store.Snapshot) (types.AdminForm, []byte, error) { +func (e evotingCommand) getAdminForm(snap store.Snapshot) (types.AdminList, error) { - var form types.AdminForm + var form types.AdminList - formIDBuf, err := hex.DecodeString(formIDHex) + form, err := types.AdminFormFromStore(e.context, e.adminFormFac, snap, AdminListId) if err != nil { - return form, nil, xerrors.Errorf("failed to decode adminFormIDHex: %v", err) + return form, xerrors.Errorf("failed to get the AdminList: %v", err) } - form, err = types.AdminFormFromStore(e.context, e.adminFormFac, formIDHex, snap) - if err != nil { - return form, nil, xerrors.Errorf("failed to get key %q: %v", formIDBuf, err) - } - - return form, formIDBuf, nil + return form, nil } // getTransaction extracts the argument from the transaction. -func (e EvotingCommand) getTransaction(tx txn.Transaction) (serde.Message, error) { +func (e evotingCommand) getTransaction(tx txn.Transaction) (serde.Message, error) { buff := tx.GetArg(FormArg) if len(buff) == 0 { return nil, xerrors.Errorf("%q not found in tx arg", FormArg) diff --git a/contracts/evoting/json/adminForm.go b/contracts/evoting/json/adminList.go similarity index 80% rename from contracts/evoting/json/adminForm.go rename to contracts/evoting/json/adminList.go index 29255548b..f2d5c489d 100644 --- a/contracts/evoting/json/adminForm.go +++ b/contracts/evoting/json/adminList.go @@ -9,13 +9,12 @@ import ( type adminFormFormat struct{} func (adminFormFormat) Encode(ctx serde.Context, message serde.Message) ([]byte, error) { - adminForm, ok := message.(types.AdminForm) + adminForm, ok := message.(types.AdminList) if !ok { return nil, xerrors.Errorf("Unknown format: %T", message) } adminFormJSON := AdminFormJSON{ - FormID: adminForm.FormID, AdminList: adminForm.AdminList, } @@ -35,16 +34,12 @@ func (adminFormFormat) Decode(ctx serde.Context, data []byte) (serde.Message, er return nil, xerrors.Errorf("failed to unmarshal form: %v", err) } - return types.AdminForm{ - FormID: adminFormJSON.FormID, + return types.AdminList{ AdminList: adminFormJSON.AdminList, }, nil } type AdminFormJSON struct { - // FormID is the hex-encoded SHA265 of the Tx ID that creates the form - FormID string - // List of SCIPER with admin rights AdminList []int } diff --git a/contracts/evoting/json/transaction.go b/contracts/evoting/json/transaction.go index 22642f641..47feccb79 100644 --- a/contracts/evoting/json/transaction.go +++ b/contracts/evoting/json/transaction.go @@ -120,14 +120,12 @@ func (transactionFormat) Encode(ctx serde.Context, msg serde.Message) ([]byte, e m = TransactionJSON{DeleteForm: &de} case types.AddAdmin: aa := AddAdminJSON{ - FormID: t.FormID, UserID: t.UserID, } m = TransactionJSON{AddAdmin: &aa} case types.RemoveAdmin: ra := RemoveAdminJSON{ - FormID: t.FormID, UserID: t.UserID, } @@ -233,12 +231,10 @@ func (transactionFormat) Decode(ctx serde.Context, data []byte) (serde.Message, }, nil case m.AddAdmin != nil: return types.AddAdmin{ - FormID: m.AddAdmin.FormID, UserID: m.AddAdmin.UserID, }, nil case m.RemoveAdmin != nil: return types.RemoveAdmin{ - FormID: m.RemoveAdmin.FormID, UserID: m.RemoveAdmin.UserID, }, nil case m.AddOwner != nil: @@ -346,7 +342,7 @@ type DeleteFormJSON struct { FormID string } -// AdminForm +// AdminList // AddAdminJSON is the JSON representation of a AddAdmin transaction type AddAdminJSON struct { diff --git a/contracts/evoting/mod.go b/contracts/evoting/mod.go index acfe2c54c..dc3059656 100644 --- a/contracts/evoting/mod.go +++ b/contracts/evoting/mod.go @@ -84,6 +84,8 @@ const ( // credentialAllCommand defines the credential command that is allowed to // perform all commands. credentialAllCommand = "all" + + AdminListId = ContractUID + "AdminList" ) // commands defines the commands of the evoting contract. Using an interface @@ -198,7 +200,7 @@ func NewContract(srvc access.Service, transactionFac: transactionFac, } - contract.cmd = EvotingCommand{Contract: &contract, prover: proof.HashVerify} + contract.cmd = evotingCommand{Contract: &contract, prover: proof.HashVerify} return contract } diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index ab1ceb4cb..4ad3907d7 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -30,9 +30,7 @@ import ( ) var dummyFormIDBuff = []byte("dummyID") -var dummyAdminFormIDBuff = []byte("dummyAdminID") var fakeFormID = hex.EncodeToString(dummyFormIDBuff) -var fakeAdminFormID = hex.EncodeToString(dummyAdminFormIDBuff) var fakeCommonSigner = bls.NewSigner() var dummyUserAdminID = "123456" var dummyUserAdminIDInt = 123456 @@ -131,6 +129,10 @@ func TestCommand_CreateForm(t *testing.T) { err: nil, } + addAdmin := types.AddAdmin{dummyUserAdminID} + dataAddAdmin, err := addAdmin.Serialize(ctx) + require.NoError(t, err) + createForm := types.CreateForm{ UserID: dummyUserAdminID, } @@ -143,11 +145,9 @@ func TestCommand_CreateForm(t *testing.T) { contract := NewContract(service, fakeDkg, rosterFac) - snap := fake.NewSnapshot() - initialAdmin := []int{dummyUserAdminIDInt} - // Create an evoting command. - cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) - require.NoError(t, err) + cmd := evotingCommand{ + Contract: &contract, + } err = cmd.createForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -158,7 +158,12 @@ func TestCommand_CreateForm(t *testing.T) { err = cmd.createForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.EqualError(t, err, "failed to get roster") - step := makeStep(t, FormArg, string(data)) + snap := fake.NewSnapshot() + step := makeStep(t, FormArg, string(dataAddAdmin)) + err = cmd.manageAdminForm(snap, step) + require.NoError(t, err) + + step = makeStep(t, FormArg, string(data)) err = cmd.createForm(snap, step) require.NoError(t, err) @@ -204,11 +209,9 @@ func TestCommand_CastVote(t *testing.T) { formBuf, err := dummyForm.Serialize(ctx) require.NoError(t, err) - snap := fake.NewSnapshot() - initialAdmin := []int{dummyUserAdminIDInt} - // Create an evoting command. - cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) - require.NoError(t, err) + cmd := evotingCommand{ + Contract: &contract, + } err = cmd.castVote(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -219,6 +222,7 @@ func TestCommand_CastVote(t *testing.T) { err = cmd.castVote(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to get key") + snap := fake.NewSnapshot() err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) @@ -334,11 +338,9 @@ func TestCommand_CloseForm(t *testing.T) { formBuf, err := dummyForm.Serialize(ctx) require.NoError(t, err) - snap := fake.NewSnapshot() - initialAdmin := []int{dummyUserAdminIDInt} - // Create an evoting command. - cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) - require.NoError(t, err) + cmd := evotingCommand{ + Contract: &contract, + } err = cmd.closeForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -349,6 +351,7 @@ func TestCommand_CloseForm(t *testing.T) { err = cmd.closeForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to get key") + snap := fake.NewSnapshot() err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) @@ -410,7 +413,7 @@ func TestCommand_ShuffleBallotsCannotShuffleTwice(t *testing.T) { snap, form, shuffleBallots, contract := initGoodShuffleBallot(t, k) - cmd := EvotingCommand{ + cmd := evotingCommand{ Contract: &contract, prover: fakeProver, } @@ -454,7 +457,7 @@ func TestCommand_ShuffleBallotsValidScenarios(t *testing.T) { // Simple Shuffle from round 0 : snap, form, shuffleBallots, contract := initGoodShuffleBallot(t, k) - cmd := EvotingCommand{ + cmd := evotingCommand{ Contract: &contract, prover: fakeProver, } @@ -532,7 +535,7 @@ func TestCommand_ShuffleBallotsFormatErrors(t *testing.T) { formBuf, err := form.Serialize(ctx) require.NoError(t, err) - cmd := EvotingCommand{ + cmd := evotingCommand{ Contract: &contract, prover: fakeProver, } @@ -758,11 +761,9 @@ func TestCommand_RegisterPubShares(t *testing.T) { formBuf, err := form.Serialize(ctx) require.NoError(t, err) - snap := fake.NewSnapshot() - initialAdmin := []int{dummyUserAdminIDInt} - // Create an evoting command. - cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) - require.NoError(t, err) + cmd := evotingCommand{ + Contract: &contract, + } err = cmd.registerPubshares(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -773,6 +774,7 @@ func TestCommand_RegisterPubShares(t *testing.T) { err = cmd.registerPubshares(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to get key") + snap := fake.NewSnapshot() err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) @@ -959,11 +961,9 @@ func TestCommand_DecryptBallots(t *testing.T) { formBuf, err := dummyForm.Serialize(ctx) require.NoError(t, err) - snap := fake.NewSnapshot() - initialAdmin := []int{dummyUserAdminIDInt} - // Create an evoting command. - cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) - require.NoError(t, err) + cmd := evotingCommand{ + Contract: &contract, + } err = cmd.combineShares(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -974,6 +974,7 @@ func TestCommand_DecryptBallots(t *testing.T) { err = cmd.combineShares(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to get key") + snap := fake.NewSnapshot() err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) @@ -1059,11 +1060,9 @@ func TestCommand_CancelForm(t *testing.T) { formBuf, err := dummyForm.Serialize(ctx) require.NoError(t, err) - snap := fake.NewSnapshot() - initialAdmin := []int{dummyUserAdminIDInt} - // Create an evoting command. - cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) - require.NoError(t, err) + cmd := evotingCommand{ + Contract: &contract, + } err = cmd.cancelForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -1074,6 +1073,7 @@ func TestCommand_CancelForm(t *testing.T) { err = cmd.cancelForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to get key") + snap := fake.NewSnapshot() err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) @@ -1114,13 +1114,11 @@ func TestRegisterContract(t *testing.T) { func TestCommand_AdminForm(t *testing.T) { initMetrics() - // Initialize a contract and an AdminForm - adminForm, contract := initAdminFormAndContract() - _, err := adminForm.Serialize(ctx) - require.NoError(t, err) + dummyForm, contract := initFormAndContract() + dummyForm.FormID = fakeFormID // Initialize the command handler to post on the ledger - cmd := EvotingCommand{ + cmd := evotingCommand{ Contract: &contract, } @@ -1128,13 +1126,13 @@ func TestCommand_AdminForm(t *testing.T) { dummyUID := "123456" // We initialize the command to add permission. - addAdmin := types.AddAdmin{FormID: fakeAdminFormID, UserID: dummyUID} + addAdmin := types.AddAdmin{UserID: "123455"} data, err := addAdmin.Serialize(ctx) require.NoError(t, err) // The following test are there to check error handling - // Checking that if no AdminForm is on the blockchain, + // Checking that if no AdminList is on the blockchain, // It won't be able to find the transaction. err = cmd.manageAdminForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -1145,26 +1143,25 @@ func TestCommand_AdminForm(t *testing.T) { require.EqualError(t, err, unmarshalTransactionErr) // Checking that given a Blockchain that always returns an error, - // it will not be able to retrieve the AdminForm on the store. + // it will not be able to create the AdminList on the store. err = cmd.manageAdminForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) - require.ErrorContains(t, err, "failed to get key") + require.ErrorContains(t, err, "failed to get AdminList") snap := fake.NewSnapshot() - // Checking that given the form set in the Snapshot which is invalid, then it - // will not be able to deserialize the AdminForm to perform the command. - err = snap.Set(dummyAdminFormIDBuff, invalidForm) - require.NoError(t, err) - err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data))) - require.ErrorContains(t, err, "failed to deserialize AdminForm") + // General ID for AdminList + h := sha256.New() + h.Write([]byte(AdminListId)) + formIDBuf := h.Sum(nil) - // We reset everything to perform the real test - adminFormBuf, err := adminForm.Serialize(ctx) + // before adding admin lets check the AdminList does not exist + res, err := snap.Get(formIDBuf) require.NoError(t, err) - err = snap.Set(dummyAdminFormIDBuff, adminFormBuf) - require.NoError(t, err) + message, err := adminFormFac.Deserialize(ctx, res) + require.ErrorContains(t, err, "failed to unmarshal form") + // Now Let's add our admin data, err = addAdmin.Serialize(ctx) require.NoError(t, err) @@ -1172,24 +1169,42 @@ func TestCommand_AdminForm(t *testing.T) { err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data))) require.NoError(t, err) + // Now we want to remove its admin privilege. + // Will be a failure cause only one left + // Initialization of the command + removeAdmin := types.RemoveAdmin{UserID: dummyUID} + data, err = removeAdmin.Serialize(ctx) + require.NoError(t, err) + + // Publish the command on the ledger. + err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data))) + require.ErrorContains(t, err, "couldn't remove admin") + + addAdmin2 := types.AddAdmin{UserID: dummyUID} + data2, err := addAdmin2.Serialize(ctx) + require.NoError(t, err) + + err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data2))) + require.NoError(t, err) + // We retrieve the form on the ledger - res, err := snap.Get(dummyAdminFormIDBuff) + res, err = snap.Get(formIDBuf) require.NoError(t, err) - message, err := adminFormFac.Deserialize(ctx, res) + message, err = adminFormFac.Deserialize(ctx, res) require.NoError(t, err) - adminForm, ok := message.(types.AdminForm) + adminForm, ok := message.(types.AdminList) require.True(t, ok) // We check that our dummy User is now admin - // (if not admin return -1; else return admin index in AdminForm). + // (if not admin return -1; else return admin index in AdminList). dummyUserIDIndex, _ := adminForm.GetAdminIndex(dummyUID) require.True(t, dummyUserIDIndex > -1) // Now we want to remove its admin privilege. // Initialization of the command - removeAdmin := types.RemoveAdmin{FormID: fakeAdminFormID, UserID: dummyUID} + removeAdmin = types.RemoveAdmin{UserID: dummyUID} data, err = removeAdmin.Serialize(ctx) require.NoError(t, err) @@ -1198,17 +1213,18 @@ func TestCommand_AdminForm(t *testing.T) { require.NoError(t, err) // We retrieve the Admin Form from the ledger. - res, err = snap.Get(dummyAdminFormIDBuff) + res, err = snap.Get(formIDBuf) require.NoError(t, err) message, err = adminFormFac.Deserialize(ctx, res) require.NoError(t, err) - adminForm, ok = message.(types.AdminForm) + adminForm, ok = message.(types.AdminList) require.True(t, ok) // We check that now our dummy user is not admin anymore (return -1) dummyUserIDIndex, _ = adminForm.GetAdminIndex(dummyUID) + require.True(t, dummyUserIDIndex == -1) } @@ -1248,15 +1264,13 @@ func TestCommand_OwnerForm(t *testing.T) { formBuf, err := dummyForm.Serialize(ctx) require.NoError(t, err) - snap := fake.NewSnapshot() - initialAdmin := []int{123456} - // Create an evoting command. - cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) - require.NoError(t, err) + cmd := evotingCommand{ + Contract: &contract, + } // The following test are there to check error handling - // Checking that if no AdminForm is on the blockchain, + // Checking that if no AdminList is on the blockchain, // It won't be able to find the transaction. err = cmd.manageOwnersVotersForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -1278,6 +1292,7 @@ func TestCommand_OwnerForm(t *testing.T) { // Checking that given the form set in the Snapshot which is invalid, then it // will not be able to deserialize the Form to perform the command. + snap := fake.NewSnapshot() err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) err = cmd.manageOwnersVotersForm(snap, makeStep(t, FormArg, string(dataAdd))) @@ -1414,13 +1429,13 @@ func TestCommand_VoterForm(t *testing.T) { require.NoError(t, err) // Create an evoting command. - cmd := EvotingCommand{ + cmd := evotingCommand{ Contract: &contract, } // The following test are there to check error handling - // Checking that if no AdminForm is on the blockchain, + // Checking that if no AdminList is on the blockchain, // It won't be able to find the transaction. err = cmd.manageOwnersVotersForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -1543,25 +1558,6 @@ func initFormAndContract() (types.Form, Contract) { return dummyForm, contract } -func initAdminFormAndContract() (types.AdminForm, Contract) { - fakeDkg := fakeDKG{ - actor: fakeDkgActor{}, - err: nil, - } - - dummyForm := types.AdminForm{ - FormID: fakeAdminFormID, - AdminList: make([]int, 0), - } - - service := fakeAccess{err: fake.GetError()} - rosterFac := fakeAuthorityFactory{} - - contract := NewContract(service, fakeDkg, rosterFac) - - return dummyForm, contract -} - func initGoodShuffleBallot(t *testing.T, k int) (store.Snapshot, types.Form, types.ShuffleBallots, Contract) { form, shuffleBallots, contract := initBadShuffleBallot(3) form.Status = types.Closed diff --git a/contracts/evoting/types/admin.go b/contracts/evoting/types/admin.go index 92ad2f03a..2ea6fdc8e 100644 --- a/contracts/evoting/types/admin.go +++ b/contracts/evoting/types/admin.go @@ -1,7 +1,7 @@ package types import ( - "encoding/hex" + "crypto/sha256" "go.dedis.ch/dela/core/store" "go.dedis.ch/dela/serde" "go.dedis.ch/dela/serde/registry" @@ -14,26 +14,23 @@ func RegisterAdminFormFormat(format serde.Format, engine serde.FormatEngine) { adminFormFormat.Register(format, engine) } -type AdminForm struct { - // FormID is the hex-encoded SHA265 of the Tx ID that creates the form - FormID string - +type AdminList struct { // List of SCIPER with admin rights AdminList []int } -func (adminForm AdminForm) Serialize(ctx serde.Context) ([]byte, error) { +func (adminList AdminList) Serialize(ctx serde.Context) ([]byte, error) { format := adminFormFormat.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, adminForm) + data, err := format.Encode(ctx, adminList) if err != nil { - return nil, xerrors.Errorf("Failed to encode AdminForm: %v", err) + return nil, xerrors.Errorf("Failed to encode AdminList: %v", err) } return data, nil } -func (adminForm AdminForm) Deserialize(ctx serde.Context, data []byte) (serde.Message, error) { +func (adminList AdminList) Deserialize(ctx serde.Context, data []byte) (serde.Message, error) { format := adminFormFormat.Get(ctx.GetFormat()) message, err := format.Decode(ctx, data) @@ -45,26 +42,26 @@ func (adminForm AdminForm) Deserialize(ctx serde.Context, data []byte) (serde.Me } // AddAdmin add a new admin to the system. -func (adminForm *AdminForm) AddAdmin(userID string) error { +func (adminList *AdminList) AddAdmin(userID string) error { sciperInt, err := SciperToInt(userID) if err != nil { return xerrors.Errorf("Failed SciperToInt: %v", err) } - adminForm.AdminList = append(adminForm.AdminList, sciperInt) + adminList.AdminList = append(adminList.AdminList, sciperInt) return nil } // GetAdminIndex return the index of admin if userID is one, else return -1 -func (adminForm *AdminForm) GetAdminIndex(userID string) (int, error) { +func (adminList *AdminList) GetAdminIndex(userID string) (int, error) { sciperInt, err := SciperToInt(userID) if err != nil { return -1, xerrors.Errorf("Failed SciperToInt: %v", err) } - for i := 0; i < len(adminForm.AdminList); i++ { - if adminForm.AdminList[i] == sciperInt { + for i := 0; i < len(adminList.AdminList); i++ { + if adminList.AdminList[i] == sciperInt { return i, nil } } @@ -73,27 +70,32 @@ func (adminForm *AdminForm) GetAdminIndex(userID string) (int, error) { } // RemoveAdmin add a new admin to the system. -func (adminForm *AdminForm) RemoveAdmin(userID string) error { - index, err := adminForm.GetAdminIndex(userID) +func (adminList *AdminList) RemoveAdmin(userID string) error { + index, err := adminList.GetAdminIndex(userID) if err != nil { - return xerrors.Errorf("Failed GetAdnubIndex: %v", err) + return xerrors.Errorf("Failed GetAdminIndex: %v", err) } if index < 0 { return xerrors.Errorf("Error while retrieving the index of the element.") } - adminForm.AdminList = append(adminForm.AdminList[:index], adminForm.AdminList[index+1:]...) + // We don't want to have a form without any Owners. + if len(adminList.AdminList) <= 1 { + return xerrors.Errorf("Error, cannot remove this Admin because it is the " + + "only one remaining.") + } + + adminList.AdminList = append(adminList.AdminList[:index], adminList.AdminList[index+1:]...) return nil } -func AdminFormFromStore(ctx serde.Context, adminFormFac serde.Factory, adminFormIDHex string, store store.Readable) (AdminForm, error) { - adminForm := AdminForm{} +func AdminFormFromStore(ctx serde.Context, adminFormFac serde.Factory, store store.Readable, adminListId string) (AdminList, error) { + adminForm := AdminList{} - adminFormIDBuf, err := hex.DecodeString(adminFormIDHex) - if err != nil { - return adminForm, xerrors.Errorf("Failed to decode adminFormIDHex: %v", err) - } + h := sha256.New() + h.Write([]byte(adminListId)) + adminFormIDBuf := h.Sum(nil) adminFormBuf, err := store.Get(adminFormIDBuf) if err != nil { @@ -105,10 +107,10 @@ func AdminFormFromStore(ctx serde.Context, adminFormFac serde.Factory, adminForm message, err := adminFormFac.Deserialize(ctx, adminFormBuf) if err != nil { - return adminForm, xerrors.Errorf("failed to deserialize AdminForm: %v", err) + return adminForm, xerrors.Errorf("failed to deserialize AdminList: %v", err) } - adminForm, ok := message.(AdminForm) + adminForm, ok := message.(AdminList) if !ok { return adminForm, xerrors.Errorf("Wrong message type: %T", message) } @@ -116,7 +118,7 @@ func AdminFormFromStore(ctx serde.Context, adminFormFac serde.Factory, adminForm return adminForm, nil } -// AdminFormFactory provides the mean to deserialize a AdminForm. It naturally +// AdminFormFactory provides the mean to deserialize a AdminList. It naturally // uses the formFormat. // // - implements serde.Factory diff --git a/contracts/evoting/types/transactions.go b/contracts/evoting/types/transactions.go index aca85057d..77221d126 100644 --- a/contracts/evoting/types/transactions.go +++ b/contracts/evoting/types/transactions.go @@ -348,8 +348,6 @@ func (registerPubShares RegisterPubShares) Fingerprint(writer io.Writer) error { // // - implements serde.Message type AddAdmin struct { - // FormID is hex-encoded - FormID string UserID string } @@ -369,8 +367,6 @@ func (addAdmin AddAdmin) Serialize(ctx serde.Context) ([]byte, error) { // // - implements serde.Message type RemoveAdmin struct { - // FormID is hex-encoded - FormID string UserID string } diff --git a/integration/form.go b/integration/form.go index ee8301865..946f4f5a6 100644 --- a/integration/form.go +++ b/integration/form.go @@ -33,6 +33,29 @@ func encodeID(ID string) types.ID { return types.ID(base64.StdEncoding.EncodeToString([]byte(ID))) } +// for integration tests +func addAdmin(m txManager, admin string) error { + addAdmin := types.AddAdmin{UserID: admin} + + data, err := addAdmin.Serialize(serdecontext) + if err != nil { + return xerrors.Errorf("failed to serialize: %v", err) + } + + args := []txn.Arg{ + {Key: native.ContractArg, Value: []byte(evoting.ContractName)}, + {Key: evoting.FormArg, Value: data}, + {Key: evoting.CmdArg, Value: []byte(evoting.CmdAddAdminForm)}, + } + + _, err = m.addAndWait(args...) + if err != nil { + return xerrors.Errorf(addAndWaitErr, err) + } + + return nil +} + // for integration tests func createForm(m txManager, title string, admin string) ([]byte, error) { // Define the configuration : diff --git a/integration/integration_test.go b/integration/integration_test.go index 6b8489126..2310460ad 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -64,6 +64,9 @@ func getIntegrationTest(numNodes, numVotes int) func(*testing.T) { } // ##### CREATE FORM ##### + err = addAdmin(m, adminID) + require.NoError(t, err) + formID, err := createForm(m, "Three votes form", adminID) require.NoError(t, err) @@ -204,6 +207,9 @@ func getIntegrationTestCrash(numNodes, numVotes, failingNodes int) func(*testing } // ##### CREATE FORM ##### + err = addAdmin(m, adminID) + require.NoError(t, err) + formID, err := createForm(m, "Three votes form", adminID) require.NoError(t, err) @@ -351,6 +357,9 @@ func getIntegrationBenchmark(numNodes, numVotes int) func(*testing.B) { } // ##### CREATE FORM ##### + err = addAdmin(m, adminID) + require.NoError(b, err) + formID, err := createForm(m, "Three votes form", adminID) require.NoError(b, err) From 483d41730db1040106af3c8730bcbbac378a11cb Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 15 May 2024 00:43:06 +0200 Subject: [PATCH 066/114] merge rebase --- contracts/evoting/admin_test.go | 13 +- contracts/evoting/evoting.go | 134 +++++++------- .../json/{adminForm.go => adminList.go} | 9 +- contracts/evoting/json/transaction.go | 6 +- contracts/evoting/mod.go | 4 +- contracts/evoting/mod_test.go | 174 +++++++++--------- contracts/evoting/types/admin.go | 60 +++--- contracts/evoting/types/transactions.go | 4 - integration/form.go | 23 +++ integration/integration_test.go | 9 + 10 files changed, 223 insertions(+), 213 deletions(-) rename contracts/evoting/json/{adminForm.go => adminList.go} (80%) diff --git a/contracts/evoting/admin_test.go b/contracts/evoting/admin_test.go index c9dac4196..4f0441e16 100644 --- a/contracts/evoting/admin_test.go +++ b/contracts/evoting/admin_test.go @@ -23,37 +23,34 @@ func init() { // This test create an Admin Form structure which is then serialized and // deserialized to check whether these operations work as intended. -// Serialization/Deserialization of an AdminForm should not change its values. +// Serialization/Deserialization of an AdminList should not change its values. func TestAdmin_Serde(t *testing.T) { - adminFormID := "myID" adminFormList := []int{111111, 222222, 333333, 123456} - adminForm := types.AdminForm{FormID: adminFormID, AdminList: adminFormList} + adminForm := types.AdminList{AdminList: adminFormList} value, err := adminForm.Serialize(ctxAdminTest) require.NoError(t, err) // deserialization - newAdminForm := types.AdminForm{} + newAdminForm := types.AdminList{} msgs, err := newAdminForm.Deserialize(ctxAdminTest, value) require.NoError(t, err) - updatedAdminForm := msgs.(types.AdminForm) + updatedAdminForm := msgs.(types.AdminList) - require.Equal(t, adminFormID, updatedAdminForm.FormID) require.Equal(t, adminFormList, updatedAdminForm.AdminList) } func TestAdmin_AddAdminAndRemoveAdmin(t *testing.T) { - adminFormID := "myID" adminFormList := []int{} myTestID := "123456" - adminForm := types.AdminForm{FormID: adminFormID, AdminList: adminFormList} + adminForm := types.AdminList{AdminList: adminFormList} res, err := adminForm.GetAdminIndex(myTestID) require.Equal(t, -1, res) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 215c8e6ef..ec8dddc7d 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -36,36 +36,19 @@ const ( errWrongTx = "wrong type of transaction: %T" ) -// EvotingCommand implements the commands of the Evoting contract. +// evotingCommand implements the commands of the Evoting contract. // // - implements commands -type EvotingCommand struct { +type evotingCommand struct { *Contract - prover prover - adminFormID string -} - -func NewEvotingCommand(contract *Contract, prover prover, snap store.Snapshot, step execution.Step, initialAdmin []int) (EvotingCommand, error) { - // TODO add error handling - adminFormID, err := initializeAdminForm(snap, step, initialAdmin, contract.context) - if err != nil { - return EvotingCommand{}, xerrors.Errorf("failed to create an Admin Form: %v", err) - } - - evotingCommand := EvotingCommand{ - Contract: contract, - prover: prover, - adminFormID: hex.EncodeToString(adminFormID), - } - - return evotingCommand, nil + prover prover } type prover func(suite proof.Suite, protocolName string, verifier proof.Verifier, proof []byte) error // createForm implements commands. It performs the CREATE_FORM command -func (e EvotingCommand) createForm(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) createForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -83,9 +66,9 @@ func (e EvotingCommand) createForm(snap store.Snapshot, step execution.Step) err } // Check if has Admin Right to create a form - adminForm, _, err := e.getAdminForm(e.adminFormID, snap) + adminForm, err := e.getAdminForm(snap) if err != nil { - return xerrors.Errorf("failed to get AdminForm: %v", err) + return xerrors.Errorf("failed to get AdminList: %v", err) } adminIndex, err := adminForm.GetAdminIndex(tx.UserID) if err != nil { @@ -193,7 +176,7 @@ func (e EvotingCommand) createForm(snap store.Snapshot, step execution.Step) err // openForm set the public key on the form. The public key is fetched // from the DKG actor. It works only if DKG is set up. -func (e EvotingCommand) openForm(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) openForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -247,7 +230,7 @@ func (e EvotingCommand) openForm(snap store.Snapshot, step execution.Step) error } // castVote implements commands. It performs the CAST_VOTE command -func (e EvotingCommand) castVote(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) castVote(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -294,7 +277,7 @@ func (e EvotingCommand) castVote(snap store.Snapshot, step execution.Step) error } // shuffleBallots implements commands. It performs the SHUFFLE_BALLOTS command -func (e EvotingCommand) shuffleBallots(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) shuffleBallots(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -466,7 +449,7 @@ func (e EvotingCommand) shuffleBallots(snap store.Snapshot, step execution.Step) // checkPreviousTransactions checks if a ShuffleBallotsTransaction has already // been accepted and executed for a specific round. -func (e EvotingCommand) checkPreviousTransactions(step execution.Step, round int) error { +func (e evotingCommand) checkPreviousTransactions(step execution.Step, round int) error { for _, tx := range step.Previous { // skip tx not concerning the evoting contract if string(tx.GetArg(native.ContractArg)) != ContractName { @@ -498,7 +481,7 @@ func (e EvotingCommand) checkPreviousTransactions(step execution.Step, round int } // closeForm implements commands. It performs the CLOSE_FORM command -func (e EvotingCommand) closeForm(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) closeForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -541,7 +524,7 @@ func (e EvotingCommand) closeForm(snap store.Snapshot, step execution.Step) erro // registerPubshares implements commands. It performs the // REGISTER_PUB_SHARES command -func (e EvotingCommand) registerPubshares(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) registerPubshares(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { return xerrors.Errorf(errGetTransaction, err) @@ -652,7 +635,7 @@ func (e EvotingCommand) registerPubshares(snap store.Snapshot, step execution.St } // combineShares implements commands. It performs the COMBINE_SHARES command -func (e EvotingCommand) combineShares(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) combineShares(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -725,7 +708,7 @@ func (e EvotingCommand) combineShares(snap store.Snapshot, step execution.Step) } // cancelForm implements commands. It performs the CANCEL_FORM command -func (e EvotingCommand) cancelForm(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) cancelForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -759,7 +742,7 @@ func (e EvotingCommand) cancelForm(snap store.Snapshot, step execution.Step) err } // deleteForm implements commands. It performs the DELETE_FORM command -func (e EvotingCommand) deleteForm(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) deleteForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { @@ -815,22 +798,41 @@ func (e EvotingCommand) deleteForm(snap store.Snapshot, step execution.Step) err } // manageAdminForm implements commands. It performs the ADD or REMOVE ADMIN command -func (e EvotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { return xerrors.Errorf(errGetTransaction, err) } - var form types.AdminForm - var formID []byte + var form types.AdminList + + h := sha256.New() + h.Write([]byte(AdminListId)) + formIDBuf := h.Sum(nil) txAddAdmin, okAddAdmin := msg.(types.AddAdmin) txRemoveAdmin, okRemoveAdmin := msg.(types.RemoveAdmin) if okAddAdmin { - form, formID, err = e.getAdminForm(txAddAdmin.FormID, snap) + form, err = e.getAdminForm(snap) if err != nil { - return xerrors.Errorf("failed to get AdminForm: %v", err) + if !strings.Contains(err.Error(), "No form found") { + return xerrors.Errorf("failed to get AdminList: %v", err) + } + + intSciper, err := types.SciperToInt(txAddAdmin.UserID) + if err != nil { + return xerrors.Errorf("Invalid Sciper: %v", err) + } + + err = initializeAdminList(snap, intSciper, e.context) + if err != nil { + return xerrors.Errorf("Failed to initialize admin list: %v", err) + } + + // Adding the initial admin is performed by the initialize Admin List + // Therefore return + return nil } err = form.AddAdmin(txAddAdmin.UserID) @@ -838,9 +840,9 @@ func (e EvotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step return xerrors.Errorf("couldn't add admin: %v", err) } } else if okRemoveAdmin { - form, formID, err = e.getAdminForm(txRemoveAdmin.FormID, snap) + form, err = e.getAdminForm(snap) if err != nil { - return xerrors.Errorf("failed to get AdminForm: %v", err) + return xerrors.Errorf("failed to get AdminList: %v", err) } err = form.RemoveAdmin(txRemoveAdmin.UserID) @@ -856,7 +858,7 @@ func (e EvotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step return xerrors.Errorf("failed to marshal Form : %v", err) } - err = snap.Set(formID, formBuf) + err = snap.Set(formIDBuf, formBuf) if err != nil { return xerrors.Errorf("failed to set value: %v", err) } @@ -864,32 +866,30 @@ func (e EvotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step return nil } -func initializeAdminForm(snap store.Snapshot, step execution.Step, initialAdmin []int, ctx serde.Context) ([]byte, error) { - // Get the formID, which is the SHA256 of the transaction ID +func initializeAdminList(snap store.Snapshot, initialAdmin int, ctx serde.Context) error { h := sha256.New() - h.Write(step.Current.GetID()) + h.Write([]byte(AdminListId)) formIDBuf := h.Sum(nil) - adminForm := types.AdminForm{ - FormID: hex.EncodeToString(formIDBuf), - AdminList: initialAdmin, + adminForm := types.AdminList{ + AdminList: []int{initialAdmin}, } formBuf, err := adminForm.Serialize(ctx) if err != nil { - return nil, xerrors.Errorf("failed to marshal Admin Form : %v", err) + return xerrors.Errorf("failed to marshal Admin Form : %v", err) } err = snap.Set(formIDBuf, formBuf) if err != nil { - return nil, xerrors.Errorf("failed to set value: %v", err) + return xerrors.Errorf("failed to set value: %v", err) } // Update the form metadata store formsMetadataBuf, err := snap.Get([]byte(FormsMetadataKey)) if err != nil { - return nil, xerrors.Errorf("failed to get key '%s': %v", formsMetadataBuf, err) + return xerrors.Errorf("failed to get key '%s': %v", formsMetadataBuf, err) } formsMetadata := &types.FormsMetadata{ @@ -899,31 +899,31 @@ func initializeAdminForm(snap store.Snapshot, step execution.Step, initialAdmin if len(formsMetadataBuf) != 0 { err := json.Unmarshal(formsMetadataBuf, formsMetadata) if err != nil { - return nil, xerrors.Errorf("failed to unmarshal FormsMetadata: %v", err) + return xerrors.Errorf("failed to unmarshal FormsMetadata: %v", err) } } - err = formsMetadata.FormsIDs.Add(adminForm.FormID) + err = formsMetadata.FormsIDs.Add(hex.EncodeToString(formIDBuf)) if err != nil { - return nil, xerrors.Errorf("couldn't add new form: %v", err) + return xerrors.Errorf("couldn't add new form: %v", err) } formMetadataJSON, err := json.Marshal(formsMetadata) if err != nil { - return nil, xerrors.Errorf("failed to marshal FormsMetadata: %v", err) + return xerrors.Errorf("failed to marshal FormsMetadata: %v", err) } err = snap.Set([]byte(FormsMetadataKey), formMetadataJSON) if err != nil { - return nil, xerrors.Errorf("failed to set value: %v", err) + return xerrors.Errorf("failed to set value: %v", err) } - return formIDBuf, nil + return nil } // manageVotersForm implements commands. // It performs the ADD or REMOVE VOTERS/OWNERS command -func (e EvotingCommand) manageOwnersVotersForm(snap store.Snapshot, step execution.Step) error { +func (e evotingCommand) manageOwnersVotersForm(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { return xerrors.Errorf(errGetTransaction, err) @@ -1061,7 +1061,7 @@ func (s SemiRandomStream) XORKeyStream(dst, src []byte) { // getForm gets the form from the snap. Returns the form ID NOT hex // encoded. -func (e EvotingCommand) getForm(formIDHex string, +func (e evotingCommand) getForm(formIDHex string, snap store.Snapshot) (types.Form, []byte, error) { var form types.Form @@ -1079,28 +1079,22 @@ func (e EvotingCommand) getForm(formIDHex string, return form, formIDBuf, nil } -// getAdminForm gets the AdminForm from the snap. Returns the form ID NOT hex +// getAdminForm gets the AdminList from the snap. Returns the form ID NOT hex // encoded. -func (e EvotingCommand) getAdminForm(formIDHex string, - snap store.Snapshot) (types.AdminForm, []byte, error) { +func (e evotingCommand) getAdminForm(snap store.Snapshot) (types.AdminList, error) { - var form types.AdminForm + var form types.AdminList - formIDBuf, err := hex.DecodeString(formIDHex) + form, err := types.AdminFormFromStore(e.context, e.adminFormFac, snap, AdminListId) if err != nil { - return form, nil, xerrors.Errorf("failed to decode adminFormIDHex: %v", err) + return form, xerrors.Errorf("failed to get the AdminList: %v", err) } - form, err = types.AdminFormFromStore(e.context, e.adminFormFac, formIDHex, snap) - if err != nil { - return form, nil, xerrors.Errorf("failed to get key %q: %v", formIDBuf, err) - } - - return form, formIDBuf, nil + return form, nil } // getTransaction extracts the argument from the transaction. -func (e EvotingCommand) getTransaction(tx txn.Transaction) (serde.Message, error) { +func (e evotingCommand) getTransaction(tx txn.Transaction) (serde.Message, error) { buff := tx.GetArg(FormArg) if len(buff) == 0 { return nil, xerrors.Errorf("%q not found in tx arg", FormArg) diff --git a/contracts/evoting/json/adminForm.go b/contracts/evoting/json/adminList.go similarity index 80% rename from contracts/evoting/json/adminForm.go rename to contracts/evoting/json/adminList.go index 29255548b..f2d5c489d 100644 --- a/contracts/evoting/json/adminForm.go +++ b/contracts/evoting/json/adminList.go @@ -9,13 +9,12 @@ import ( type adminFormFormat struct{} func (adminFormFormat) Encode(ctx serde.Context, message serde.Message) ([]byte, error) { - adminForm, ok := message.(types.AdminForm) + adminForm, ok := message.(types.AdminList) if !ok { return nil, xerrors.Errorf("Unknown format: %T", message) } adminFormJSON := AdminFormJSON{ - FormID: adminForm.FormID, AdminList: adminForm.AdminList, } @@ -35,16 +34,12 @@ func (adminFormFormat) Decode(ctx serde.Context, data []byte) (serde.Message, er return nil, xerrors.Errorf("failed to unmarshal form: %v", err) } - return types.AdminForm{ - FormID: adminFormJSON.FormID, + return types.AdminList{ AdminList: adminFormJSON.AdminList, }, nil } type AdminFormJSON struct { - // FormID is the hex-encoded SHA265 of the Tx ID that creates the form - FormID string - // List of SCIPER with admin rights AdminList []int } diff --git a/contracts/evoting/json/transaction.go b/contracts/evoting/json/transaction.go index 22642f641..47feccb79 100644 --- a/contracts/evoting/json/transaction.go +++ b/contracts/evoting/json/transaction.go @@ -120,14 +120,12 @@ func (transactionFormat) Encode(ctx serde.Context, msg serde.Message) ([]byte, e m = TransactionJSON{DeleteForm: &de} case types.AddAdmin: aa := AddAdminJSON{ - FormID: t.FormID, UserID: t.UserID, } m = TransactionJSON{AddAdmin: &aa} case types.RemoveAdmin: ra := RemoveAdminJSON{ - FormID: t.FormID, UserID: t.UserID, } @@ -233,12 +231,10 @@ func (transactionFormat) Decode(ctx serde.Context, data []byte) (serde.Message, }, nil case m.AddAdmin != nil: return types.AddAdmin{ - FormID: m.AddAdmin.FormID, UserID: m.AddAdmin.UserID, }, nil case m.RemoveAdmin != nil: return types.RemoveAdmin{ - FormID: m.RemoveAdmin.FormID, UserID: m.RemoveAdmin.UserID, }, nil case m.AddOwner != nil: @@ -346,7 +342,7 @@ type DeleteFormJSON struct { FormID string } -// AdminForm +// AdminList // AddAdminJSON is the JSON representation of a AddAdmin transaction type AddAdminJSON struct { diff --git a/contracts/evoting/mod.go b/contracts/evoting/mod.go index acfe2c54c..dc3059656 100644 --- a/contracts/evoting/mod.go +++ b/contracts/evoting/mod.go @@ -84,6 +84,8 @@ const ( // credentialAllCommand defines the credential command that is allowed to // perform all commands. credentialAllCommand = "all" + + AdminListId = ContractUID + "AdminList" ) // commands defines the commands of the evoting contract. Using an interface @@ -198,7 +200,7 @@ func NewContract(srvc access.Service, transactionFac: transactionFac, } - contract.cmd = EvotingCommand{Contract: &contract, prover: proof.HashVerify} + contract.cmd = evotingCommand{Contract: &contract, prover: proof.HashVerify} return contract } diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index a7413372e..f3a059826 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -30,9 +30,7 @@ import ( ) var dummyFormIDBuff = []byte("dummyID") -var dummyAdminFormIDBuff = []byte("dummyAdminID") var fakeFormID = hex.EncodeToString(dummyFormIDBuff) -var fakeAdminFormID = hex.EncodeToString(dummyAdminFormIDBuff) var fakeCommonSigner = bls.NewSigner() var dummyUserAdminID = "123456" var dummyUserAdminIDInt = 123456 @@ -131,6 +129,10 @@ func TestCommand_CreateForm(t *testing.T) { err: nil, } + addAdmin := types.AddAdmin{dummyUserAdminID} + dataAddAdmin, err := addAdmin.Serialize(ctx) + require.NoError(t, err) + createForm := types.CreateForm{ UserID: dummyUserAdminID, } @@ -143,11 +145,9 @@ func TestCommand_CreateForm(t *testing.T) { contract := NewContract(service, fakeDkg, rosterFac) - snap := fake.NewSnapshot() - initialAdmin := []int{dummyUserAdminIDInt} - // Create an evoting command. - cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) - require.NoError(t, err) + cmd := evotingCommand{ + Contract: &contract, + } err = cmd.createForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -158,7 +158,12 @@ func TestCommand_CreateForm(t *testing.T) { err = cmd.createForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.EqualError(t, err, "failed to get roster") - step := makeStep(t, FormArg, string(data)) + snap := fake.NewSnapshot() + step := makeStep(t, FormArg, string(dataAddAdmin)) + err = cmd.manageAdminForm(snap, step) + require.NoError(t, err) + + step = makeStep(t, FormArg, string(data)) err = cmd.createForm(snap, step) require.NoError(t, err) @@ -204,11 +209,9 @@ func TestCommand_CastVote(t *testing.T) { formBuf, err := dummyForm.Serialize(ctx) require.NoError(t, err) - snap := fake.NewSnapshot() - initialAdmin := []int{dummyUserAdminIDInt} - // Create an evoting command. - cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) - require.NoError(t, err) + cmd := evotingCommand{ + Contract: &contract, + } err = cmd.castVote(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -219,6 +222,7 @@ func TestCommand_CastVote(t *testing.T) { err = cmd.castVote(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to get key") + snap := fake.NewSnapshot() err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) @@ -334,11 +338,9 @@ func TestCommand_CloseForm(t *testing.T) { formBuf, err := dummyForm.Serialize(ctx) require.NoError(t, err) - snap := fake.NewSnapshot() - initialAdmin := []int{dummyUserAdminIDInt} - // Create an evoting command. - cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) - require.NoError(t, err) + cmd := evotingCommand{ + Contract: &contract, + } err = cmd.closeForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -349,6 +351,7 @@ func TestCommand_CloseForm(t *testing.T) { err = cmd.closeForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to get key") + snap := fake.NewSnapshot() err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) @@ -410,7 +413,7 @@ func TestCommand_ShuffleBallotsCannotShuffleTwice(t *testing.T) { snap, form, shuffleBallots, contract := initGoodShuffleBallot(t, k) - cmd := EvotingCommand{ + cmd := evotingCommand{ Contract: &contract, prover: fakeProver, } @@ -454,7 +457,7 @@ func TestCommand_ShuffleBallotsValidScenarios(t *testing.T) { // Simple Shuffle from round 0 : snap, form, shuffleBallots, contract := initGoodShuffleBallot(t, k) - cmd := EvotingCommand{ + cmd := evotingCommand{ Contract: &contract, prover: fakeProver, } @@ -532,7 +535,7 @@ func TestCommand_ShuffleBallotsFormatErrors(t *testing.T) { formBuf, err := form.Serialize(ctx) require.NoError(t, err) - cmd := EvotingCommand{ + cmd := evotingCommand{ Contract: &contract, prover: fakeProver, } @@ -758,11 +761,9 @@ func TestCommand_RegisterPubShares(t *testing.T) { formBuf, err := form.Serialize(ctx) require.NoError(t, err) - snap := fake.NewSnapshot() - initialAdmin := []int{dummyUserAdminIDInt} - // Create an evoting command. - cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) - require.NoError(t, err) + cmd := evotingCommand{ + Contract: &contract, + } err = cmd.registerPubshares(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -773,6 +774,7 @@ func TestCommand_RegisterPubShares(t *testing.T) { err = cmd.registerPubshares(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to get key") + snap := fake.NewSnapshot() err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) @@ -959,11 +961,9 @@ func TestCommand_DecryptBallots(t *testing.T) { formBuf, err := dummyForm.Serialize(ctx) require.NoError(t, err) - snap := fake.NewSnapshot() - initialAdmin := []int{dummyUserAdminIDInt} - // Create an evoting command. - cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) - require.NoError(t, err) + cmd := evotingCommand{ + Contract: &contract, + } err = cmd.combineShares(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -974,6 +974,7 @@ func TestCommand_DecryptBallots(t *testing.T) { err = cmd.combineShares(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to get key") + snap := fake.NewSnapshot() err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) @@ -1059,11 +1060,9 @@ func TestCommand_CancelForm(t *testing.T) { formBuf, err := dummyForm.Serialize(ctx) require.NoError(t, err) - snap := fake.NewSnapshot() - initialAdmin := []int{dummyUserAdminIDInt} - // Create an evoting command. - cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) - require.NoError(t, err) + cmd := evotingCommand{ + Contract: &contract, + } err = cmd.cancelForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -1074,6 +1073,7 @@ func TestCommand_CancelForm(t *testing.T) { err = cmd.cancelForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to get key") + snap := fake.NewSnapshot() err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) @@ -1114,13 +1114,11 @@ func TestRegisterContract(t *testing.T) { func TestCommand_AdminForm(t *testing.T) { initMetrics() - // Initialize a contract and an AdminForm - adminForm, contract := initAdminFormAndContract() - _, err := adminForm.Serialize(ctx) - require.NoError(t, err) + dummyForm, contract := initFormAndContract() + dummyForm.FormID = fakeFormID // Initialize the command handler to post on the ledger - cmd := EvotingCommand{ + cmd := evotingCommand{ Contract: &contract, } @@ -1128,13 +1126,13 @@ func TestCommand_AdminForm(t *testing.T) { dummyUID := "123456" // We initialize the command to add permission. - addAdmin := types.AddAdmin{FormID: fakeAdminFormID, UserID: dummyUID} + addAdmin := types.AddAdmin{UserID: "123455"} data, err := addAdmin.Serialize(ctx) require.NoError(t, err) // The following test are there to check error handling - // Checking that if no AdminForm is on the blockchain, + // Checking that if no AdminList is on the blockchain, // It won't be able to find the transaction. err = cmd.manageAdminForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -1145,26 +1143,25 @@ func TestCommand_AdminForm(t *testing.T) { require.EqualError(t, err, unmarshalTransactionErr) // Checking that given a Blockchain that always returns an error, - // it will not be able to retrieve the AdminForm on the store. + // it will not be able to create the AdminList on the store. err = cmd.manageAdminForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) - require.ErrorContains(t, err, "failed to get key") + require.ErrorContains(t, err, "failed to get AdminList") snap := fake.NewSnapshot() - // Checking that given the form set in the Snapshot which is invalid, then it - // will not be able to deserialize the AdminForm to perform the command. - err = snap.Set(dummyAdminFormIDBuff, invalidForm) - require.NoError(t, err) - err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data))) - require.ErrorContains(t, err, "failed to deserialize AdminForm") + // General ID for AdminList + h := sha256.New() + h.Write([]byte(AdminListId)) + formIDBuf := h.Sum(nil) - // We reset everything to perform the real test - adminFormBuf, err := adminForm.Serialize(ctx) + // before adding admin lets check the AdminList does not exist + res, err := snap.Get(formIDBuf) require.NoError(t, err) - err = snap.Set(dummyAdminFormIDBuff, adminFormBuf) - require.NoError(t, err) + message, err := adminFormFac.Deserialize(ctx, res) + require.ErrorContains(t, err, "failed to unmarshal form") + // Now Let's add our admin data, err = addAdmin.Serialize(ctx) require.NoError(t, err) @@ -1172,24 +1169,42 @@ func TestCommand_AdminForm(t *testing.T) { err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data))) require.NoError(t, err) + // Now we want to remove its admin privilege. + // Will be a failure cause only one left + // Initialization of the command + removeAdmin := types.RemoveAdmin{UserID: dummyUID} + data, err = removeAdmin.Serialize(ctx) + require.NoError(t, err) + + // Publish the command on the ledger. + err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data))) + require.ErrorContains(t, err, "couldn't remove admin") + + addAdmin2 := types.AddAdmin{UserID: dummyUID} + data2, err := addAdmin2.Serialize(ctx) + require.NoError(t, err) + + err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data2))) + require.NoError(t, err) + // We retrieve the form on the ledger - res, err := snap.Get(dummyAdminFormIDBuff) + res, err = snap.Get(formIDBuf) require.NoError(t, err) - message, err := adminFormFac.Deserialize(ctx, res) + message, err = adminFormFac.Deserialize(ctx, res) require.NoError(t, err) - adminForm, ok := message.(types.AdminForm) + adminForm, ok := message.(types.AdminList) require.True(t, ok) // We check that our dummy User is now admin - // (if not admin return -1; else return admin index in AdminForm). + // (if not admin return -1; else return admin index in AdminList). dummyUserIDIndex, _ := adminForm.GetAdminIndex(dummyUID) require.True(t, dummyUserIDIndex > -1) // Now we want to remove its admin privilege. // Initialization of the command - removeAdmin := types.RemoveAdmin{FormID: fakeAdminFormID, UserID: dummyUID} + removeAdmin = types.RemoveAdmin{UserID: dummyUID} data, err = removeAdmin.Serialize(ctx) require.NoError(t, err) @@ -1198,17 +1213,18 @@ func TestCommand_AdminForm(t *testing.T) { require.NoError(t, err) // We retrieve the Admin Form from the ledger. - res, err = snap.Get(dummyAdminFormIDBuff) + res, err = snap.Get(formIDBuf) require.NoError(t, err) message, err = adminFormFac.Deserialize(ctx, res) require.NoError(t, err) - adminForm, ok = message.(types.AdminForm) + adminForm, ok = message.(types.AdminList) require.True(t, ok) // We check that now our dummy user is not admin anymore (return -1) dummyUserIDIndex, _ = adminForm.GetAdminIndex(dummyUID) + require.True(t, dummyUserIDIndex == -1) } @@ -1248,15 +1264,13 @@ func TestCommand_OwnerForm(t *testing.T) { formBuf, err := dummyForm.Serialize(ctx) require.NoError(t, err) - snap := fake.NewSnapshot() - initialAdmin := []int{123456} - // Create an evoting command. - cmd, err := NewEvotingCommand(&contract, proof.HashVerify, snap, makeStep(t, FormArg, "dummy"), initialAdmin) - require.NoError(t, err) + cmd := evotingCommand{ + Contract: &contract, + } // The following test are there to check error handling - // Checking that if no AdminForm is on the blockchain, + // Checking that if no AdminList is on the blockchain, // It won't be able to find the transaction. err = cmd.manageOwnersVotersForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -1278,6 +1292,7 @@ func TestCommand_OwnerForm(t *testing.T) { // Checking that given the form set in the Snapshot which is invalid, then it // will not be able to deserialize the Form to perform the command. + snap := fake.NewSnapshot() err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) err = cmd.manageOwnersVotersForm(snap, makeStep(t, FormArg, string(dataAdd))) @@ -1414,13 +1429,13 @@ func TestCommand_VoterForm(t *testing.T) { require.NoError(t, err) // Create an evoting command. - cmd := EvotingCommand{ + cmd := evotingCommand{ Contract: &contract, } // The following test are there to check error handling - // Checking that if no AdminForm is on the blockchain, + // Checking that if no AdminList is on the blockchain, // It won't be able to find the transaction. err = cmd.manageOwnersVotersForm(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) @@ -1545,25 +1560,6 @@ func initFormAndContract() (types.Form, Contract) { return dummyForm, contract } -func initAdminFormAndContract() (types.AdminForm, Contract) { - fakeDkg := fakeDKG{ - actor: fakeDkgActor{}, - err: nil, - } - - dummyForm := types.AdminForm{ - FormID: fakeAdminFormID, - AdminList: make([]int, 0), - } - - service := fakeAccess{err: fake.GetError()} - rosterFac := fakeAuthorityFactory{} - - contract := NewContract(service, fakeDkg, rosterFac) - - return dummyForm, contract -} - func initGoodShuffleBallot(t *testing.T, k int) (store.Snapshot, types.Form, types.ShuffleBallots, Contract) { form, shuffleBallots, contract := initBadShuffleBallot(3) form.Status = types.Closed diff --git a/contracts/evoting/types/admin.go b/contracts/evoting/types/admin.go index ad40615ca..2ea6fdc8e 100644 --- a/contracts/evoting/types/admin.go +++ b/contracts/evoting/types/admin.go @@ -1,7 +1,7 @@ package types import ( - "encoding/hex" + "crypto/sha256" "go.dedis.ch/dela/core/store" "go.dedis.ch/dela/serde" "go.dedis.ch/dela/serde/registry" @@ -14,26 +14,23 @@ func RegisterAdminFormFormat(format serde.Format, engine serde.FormatEngine) { adminFormFormat.Register(format, engine) } -type AdminForm struct { - // FormID is the hex-encoded SHA265 of the Tx ID that creates the form - FormID string - +type AdminList struct { // List of SCIPER with admin rights AdminList []int } -func (adminForm AdminForm) Serialize(ctx serde.Context) ([]byte, error) { +func (adminList AdminList) Serialize(ctx serde.Context) ([]byte, error) { format := adminFormFormat.Get(ctx.GetFormat()) - data, err := format.Encode(ctx, adminForm) + data, err := format.Encode(ctx, adminList) if err != nil { - return nil, xerrors.Errorf("Failed to encode AdminForm: %v", err) + return nil, xerrors.Errorf("Failed to encode AdminList: %v", err) } return data, nil } -func (adminForm AdminForm) Deserialize(ctx serde.Context, data []byte) (serde.Message, error) { +func (adminList AdminList) Deserialize(ctx serde.Context, data []byte) (serde.Message, error) { format := adminFormFormat.Get(ctx.GetFormat()) message, err := format.Decode(ctx, data) @@ -45,26 +42,26 @@ func (adminForm AdminForm) Deserialize(ctx serde.Context, data []byte) (serde.Me } // AddAdmin add a new admin to the system. -func (adminForm *AdminForm) AddAdmin(userID string) error { +func (adminList *AdminList) AddAdmin(userID string) error { sciperInt, err := SciperToInt(userID) if err != nil { - return xerrors.Errorf("failed to convert SCIPER to integer: %v", err) + return xerrors.Errorf("Failed SciperToInt: %v", err) } - adminForm.AdminList = append(adminForm.AdminList, sciperInt) + adminList.AdminList = append(adminList.AdminList, sciperInt) return nil } // GetAdminIndex return the index of admin if userID is one, else return -1 -func (adminForm *AdminForm) GetAdminIndex(userID string) (int, error) { +func (adminList *AdminList) GetAdminIndex(userID string) (int, error) { sciperInt, err := SciperToInt(userID) if err != nil { - return -1, xerrors.Errorf("failed to convert SCIPER to integer: %v", err) + return -1, xerrors.Errorf("Failed SciperToInt: %v", err) } - for i := 0; i < len(adminForm.AdminList); i++ { - if adminForm.AdminList[i] == sciperInt { + for i := 0; i < len(adminList.AdminList); i++ { + if adminList.AdminList[i] == sciperInt { return i, nil } } @@ -73,27 +70,32 @@ func (adminForm *AdminForm) GetAdminIndex(userID string) (int, error) { } // RemoveAdmin add a new admin to the system. -func (adminForm *AdminForm) RemoveAdmin(userID string) error { - index, err := adminForm.GetAdminIndex(userID) +func (adminList *AdminList) RemoveAdmin(userID string) error { + index, err := adminList.GetAdminIndex(userID) if err != nil { - return xerrors.Errorf("Failed to retrieve the Admin permission: %v", err) + return xerrors.Errorf("Failed GetAdminIndex: %v", err) } if index < 0 { return xerrors.Errorf("Error while retrieving the index of the element.") } - adminForm.AdminList = append(adminForm.AdminList[:index], adminForm.AdminList[index+1:]...) + // We don't want to have a form without any Owners. + if len(adminList.AdminList) <= 1 { + return xerrors.Errorf("Error, cannot remove this Admin because it is the " + + "only one remaining.") + } + + adminList.AdminList = append(adminList.AdminList[:index], adminList.AdminList[index+1:]...) return nil } -func AdminFormFromStore(ctx serde.Context, adminFormFac serde.Factory, adminFormIDHex string, store store.Readable) (AdminForm, error) { - adminForm := AdminForm{} +func AdminFormFromStore(ctx serde.Context, adminFormFac serde.Factory, store store.Readable, adminListId string) (AdminList, error) { + adminForm := AdminList{} - adminFormIDBuf, err := hex.DecodeString(adminFormIDHex) - if err != nil { - return adminForm, xerrors.Errorf("Failed to decode adminFormIDHex: %v", err) - } + h := sha256.New() + h.Write([]byte(adminListId)) + adminFormIDBuf := h.Sum(nil) adminFormBuf, err := store.Get(adminFormIDBuf) if err != nil { @@ -105,10 +107,10 @@ func AdminFormFromStore(ctx serde.Context, adminFormFac serde.Factory, adminForm message, err := adminFormFac.Deserialize(ctx, adminFormBuf) if err != nil { - return adminForm, xerrors.Errorf("failed to deserialize AdminForm: %v", err) + return adminForm, xerrors.Errorf("failed to deserialize AdminList: %v", err) } - adminForm, ok := message.(AdminForm) + adminForm, ok := message.(AdminList) if !ok { return adminForm, xerrors.Errorf("Wrong message type: %T", message) } @@ -116,7 +118,7 @@ func AdminFormFromStore(ctx serde.Context, adminFormFac serde.Factory, adminForm return adminForm, nil } -// AdminFormFactory provides the mean to deserialize a AdminForm. It naturally +// AdminFormFactory provides the mean to deserialize a AdminList. It naturally // uses the formFormat. // // - implements serde.Factory diff --git a/contracts/evoting/types/transactions.go b/contracts/evoting/types/transactions.go index aca85057d..77221d126 100644 --- a/contracts/evoting/types/transactions.go +++ b/contracts/evoting/types/transactions.go @@ -348,8 +348,6 @@ func (registerPubShares RegisterPubShares) Fingerprint(writer io.Writer) error { // // - implements serde.Message type AddAdmin struct { - // FormID is hex-encoded - FormID string UserID string } @@ -369,8 +367,6 @@ func (addAdmin AddAdmin) Serialize(ctx serde.Context) ([]byte, error) { // // - implements serde.Message type RemoveAdmin struct { - // FormID is hex-encoded - FormID string UserID string } diff --git a/integration/form.go b/integration/form.go index ee8301865..946f4f5a6 100644 --- a/integration/form.go +++ b/integration/form.go @@ -33,6 +33,29 @@ func encodeID(ID string) types.ID { return types.ID(base64.StdEncoding.EncodeToString([]byte(ID))) } +// for integration tests +func addAdmin(m txManager, admin string) error { + addAdmin := types.AddAdmin{UserID: admin} + + data, err := addAdmin.Serialize(serdecontext) + if err != nil { + return xerrors.Errorf("failed to serialize: %v", err) + } + + args := []txn.Arg{ + {Key: native.ContractArg, Value: []byte(evoting.ContractName)}, + {Key: evoting.FormArg, Value: data}, + {Key: evoting.CmdArg, Value: []byte(evoting.CmdAddAdminForm)}, + } + + _, err = m.addAndWait(args...) + if err != nil { + return xerrors.Errorf(addAndWaitErr, err) + } + + return nil +} + // for integration tests func createForm(m txManager, title string, admin string) ([]byte, error) { // Define the configuration : diff --git a/integration/integration_test.go b/integration/integration_test.go index 6b8489126..2310460ad 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -64,6 +64,9 @@ func getIntegrationTest(numNodes, numVotes int) func(*testing.T) { } // ##### CREATE FORM ##### + err = addAdmin(m, adminID) + require.NoError(t, err) + formID, err := createForm(m, "Three votes form", adminID) require.NoError(t, err) @@ -204,6 +207,9 @@ func getIntegrationTestCrash(numNodes, numVotes, failingNodes int) func(*testing } // ##### CREATE FORM ##### + err = addAdmin(m, adminID) + require.NoError(t, err) + formID, err := createForm(m, "Three votes form", adminID) require.NoError(t, err) @@ -351,6 +357,9 @@ func getIntegrationBenchmark(numNodes, numVotes int) func(*testing.B) { } // ##### CREATE FORM ##### + err = addAdmin(m, adminID) + require.NoError(b, err) + formID, err := createForm(m, "Three votes form", adminID) require.NoError(b, err) From 4b47701795420854c82e014ba53368d434a2dfd6 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 15 May 2024 00:44:42 +0200 Subject: [PATCH 067/114] patch one test --- contracts/evoting/admin_test.go | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/contracts/evoting/admin_test.go b/contracts/evoting/admin_test.go index 4f0441e16..4ad6c4a66 100644 --- a/contracts/evoting/admin_test.go +++ b/contracts/evoting/admin_test.go @@ -62,6 +62,12 @@ func TestAdmin_AddAdminAndRemoveAdmin(t *testing.T) { require.Equal(t, 0, res) require.NoError(t, err) + err = adminForm.RemoveAdmin(myTestID) + require.ErrorContains(t, err, "cannot remove this Admin because it is the only one remaining") + + err = adminForm.AddAdmin("654321") + require.NoError(t, err) + err = adminForm.RemoveAdmin(myTestID) require.NoError(t, err) res, err = adminForm.GetAdminIndex(myTestID) From d1074cc40c01608bf0538ec9961a66645fd82656 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 15 May 2024 00:51:00 +0200 Subject: [PATCH 068/114] patch vet --- contracts/evoting/mod_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index f3a059826..946bc05c2 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -33,7 +33,6 @@ var dummyFormIDBuff = []byte("dummyID") var fakeFormID = hex.EncodeToString(dummyFormIDBuff) var fakeCommonSigner = bls.NewSigner() var dummyUserAdminID = "123456" -var dummyUserAdminIDInt = 123456 const getTransactionErr = "failed to get transaction: \"evoting:arg\" not found in tx arg" const unmarshalTransactionErr = "failed to get transaction: failed to deserialize " + @@ -1158,7 +1157,7 @@ func TestCommand_AdminForm(t *testing.T) { res, err := snap.Get(formIDBuf) require.NoError(t, err) - message, err := adminFormFac.Deserialize(ctx, res) + _, err = adminFormFac.Deserialize(ctx, res) require.ErrorContains(t, err, "failed to unmarshal form") // Now Let's add our admin @@ -1191,7 +1190,7 @@ func TestCommand_AdminForm(t *testing.T) { res, err = snap.Get(formIDBuf) require.NoError(t, err) - message, err = adminFormFac.Deserialize(ctx, res) + message, err := adminFormFac.Deserialize(ctx, res) require.NoError(t, err) adminForm, ok := message.(types.AdminList) From 3a64006b20cec5118f03e3749e924ebf12694918 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 15 May 2024 16:09:00 +0200 Subject: [PATCH 069/114] patch even more adminform to adminlist --- contracts/evoting/admin_test.go | 14 ++++++------- contracts/evoting/evoting.go | 2 +- contracts/evoting/json/mod.go | 2 +- contracts/evoting/mod.go | 2 +- contracts/evoting/mod_test.go | 10 +++++----- contracts/evoting/types/admin.go | 34 ++++++++++++++++---------------- 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/contracts/evoting/admin_test.go b/contracts/evoting/admin_test.go index 4ad6c4a66..922bf271f 100644 --- a/contracts/evoting/admin_test.go +++ b/contracts/evoting/admin_test.go @@ -25,24 +25,24 @@ func init() { // deserialized to check whether these operations work as intended. // Serialization/Deserialization of an AdminList should not change its values. func TestAdmin_Serde(t *testing.T) { - adminFormList := []int{111111, 222222, 333333, 123456} + initialAdminList := []int{111111, 222222, 333333, 123456} - adminForm := types.AdminList{AdminList: adminFormList} + adminList := types.AdminList{AdminList: initialAdminList} - value, err := adminForm.Serialize(ctxAdminTest) + value, err := adminList.Serialize(ctxAdminTest) require.NoError(t, err) // deserialization - newAdminForm := types.AdminList{} + deserializedAdminList := types.AdminList{} - msgs, err := newAdminForm.Deserialize(ctxAdminTest, value) + msgs, err := deserializedAdminList.Deserialize(ctxAdminTest, value) require.NoError(t, err) - updatedAdminForm := msgs.(types.AdminList) + updatedAdminList := msgs.(types.AdminList) - require.Equal(t, adminFormList, updatedAdminForm.AdminList) + require.Equal(t, initialAdminList, updatedAdminList.AdminList) } func TestAdmin_AddAdminAndRemoveAdmin(t *testing.T) { diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index ec8dddc7d..b3933ef62 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -1085,7 +1085,7 @@ func (e evotingCommand) getAdminForm(snap store.Snapshot) (types.AdminList, erro var form types.AdminList - form, err := types.AdminFormFromStore(e.context, e.adminFormFac, snap, AdminListId) + form, err := types.AdminListFromStore(e.context, e.adminFormFac, snap, AdminListId) if err != nil { return form, xerrors.Errorf("failed to get the AdminList: %v", err) } diff --git a/contracts/evoting/json/mod.go b/contracts/evoting/json/mod.go index be6023adc..e05053f89 100644 --- a/contracts/evoting/json/mod.go +++ b/contracts/evoting/json/mod.go @@ -12,5 +12,5 @@ func init() { types.RegisterSuffragiaFormat(serde.FormatJSON, suffragiaFormat{}) types.RegisterCiphervoteFormat(serde.FormatJSON, ciphervoteFormat{}) types.RegisterTransactionFormat(serde.FormatJSON, transactionFormat{}) - types.RegisterAdminFormFormat(serde.FormatJSON, adminFormFormat{}) + types.RegisterAdminListFormat(serde.FormatJSON, adminFormFormat{}) } diff --git a/contracts/evoting/mod.go b/contracts/evoting/mod.go index dc3059656..df2153c92 100644 --- a/contracts/evoting/mod.go +++ b/contracts/evoting/mod.go @@ -186,7 +186,7 @@ func NewContract(srvc access.Service, ciphervoteFac := types.CiphervoteFactory{} formFac := types.NewFormFactory(ciphervoteFac, rosterFac) transactionFac := types.NewTransactionFactory(ciphervoteFac) - adminFormFac := types.AdminFormFactory{} + adminFormFac := types.AdminListFactory{} contract := Contract{ access: srvc, diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 946bc05c2..f740c68a7 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -45,13 +45,13 @@ var invalidForm = []byte("fake form") var ctx serde.Context var formFac serde.Factory -var adminFormFac serde.Factory +var adminListFac serde.Factory var transactionFac serde.Factory func init() { ciphervoteFac := types.CiphervoteFactory{} formFac = types.NewFormFactory(ciphervoteFac, fakeAuthorityFactory{}) - adminFormFac = types.AdminFormFactory{} + adminListFac = types.AdminListFactory{} transactionFac = types.NewTransactionFactory(ciphervoteFac) ctx = sjson.NewContext() @@ -1157,7 +1157,7 @@ func TestCommand_AdminForm(t *testing.T) { res, err := snap.Get(formIDBuf) require.NoError(t, err) - _, err = adminFormFac.Deserialize(ctx, res) + _, err = adminListFac.Deserialize(ctx, res) require.ErrorContains(t, err, "failed to unmarshal form") // Now Let's add our admin @@ -1190,7 +1190,7 @@ func TestCommand_AdminForm(t *testing.T) { res, err = snap.Get(formIDBuf) require.NoError(t, err) - message, err := adminFormFac.Deserialize(ctx, res) + message, err := adminListFac.Deserialize(ctx, res) require.NoError(t, err) adminForm, ok := message.(types.AdminList) @@ -1215,7 +1215,7 @@ func TestCommand_AdminForm(t *testing.T) { res, err = snap.Get(formIDBuf) require.NoError(t, err) - message, err = adminFormFac.Deserialize(ctx, res) + message, err = adminListFac.Deserialize(ctx, res) require.NoError(t, err) adminForm, ok = message.(types.AdminList) diff --git a/contracts/evoting/types/admin.go b/contracts/evoting/types/admin.go index 2ea6fdc8e..cef691a87 100644 --- a/contracts/evoting/types/admin.go +++ b/contracts/evoting/types/admin.go @@ -8,10 +8,10 @@ import ( "golang.org/x/xerrors" ) -var adminFormFormat = registry.NewSimpleRegistry() +var adminListFormat = registry.NewSimpleRegistry() -func RegisterAdminFormFormat(format serde.Format, engine serde.FormatEngine) { - adminFormFormat.Register(format, engine) +func RegisterAdminListFormat(format serde.Format, engine serde.FormatEngine) { + adminListFormat.Register(format, engine) } type AdminList struct { @@ -20,7 +20,7 @@ type AdminList struct { } func (adminList AdminList) Serialize(ctx serde.Context) ([]byte, error) { - format := adminFormFormat.Get(ctx.GetFormat()) + format := adminListFormat.Get(ctx.GetFormat()) data, err := format.Encode(ctx, adminList) if err != nil { @@ -31,7 +31,7 @@ func (adminList AdminList) Serialize(ctx serde.Context) ([]byte, error) { } func (adminList AdminList) Deserialize(ctx serde.Context, data []byte) (serde.Message, error) { - format := adminFormFormat.Get(ctx.GetFormat()) + format := adminListFormat.Get(ctx.GetFormat()) message, err := format.Decode(ctx, data) if err != nil { @@ -90,8 +90,8 @@ func (adminList *AdminList) RemoveAdmin(userID string) error { return nil } -func AdminFormFromStore(ctx serde.Context, adminFormFac serde.Factory, store store.Readable, adminListId string) (AdminList, error) { - adminForm := AdminList{} +func AdminListFromStore(ctx serde.Context, adminFormFac serde.Factory, store store.Readable, adminListId string) (AdminList, error) { + adminList := AdminList{} h := sha256.New() h.Write([]byte(adminListId)) @@ -99,34 +99,34 @@ func AdminFormFromStore(ctx serde.Context, adminFormFac serde.Factory, store sto adminFormBuf, err := store.Get(adminFormIDBuf) if err != nil { - return adminForm, xerrors.Errorf("While getting data for form: %v", err) + return adminList, xerrors.Errorf("While getting data for form: %v", err) } if len(adminFormBuf) == 0 { - return adminForm, xerrors.Errorf("No form found") + return adminList, xerrors.Errorf("No form found") } message, err := adminFormFac.Deserialize(ctx, adminFormBuf) if err != nil { - return adminForm, xerrors.Errorf("failed to deserialize AdminList: %v", err) + return adminList, xerrors.Errorf("failed to deserialize AdminList: %v", err) } - adminForm, ok := message.(AdminList) + adminList, ok := message.(AdminList) if !ok { - return adminForm, xerrors.Errorf("Wrong message type: %T", message) + return adminList, xerrors.Errorf("Wrong message type: %T", message) } - return adminForm, nil + return adminList, nil } -// AdminFormFactory provides the mean to deserialize a AdminList. It naturally +// AdminListFactory provides the mean to deserialize a AdminList. It naturally // uses the formFormat. // // - implements serde.Factory -type AdminFormFactory struct{} +type AdminListFactory struct{} // Deserialize implements serde.Factory -func (AdminFormFactory) Deserialize(ctx serde.Context, data []byte) (serde.Message, error) { - format := adminFormFormat.Get(ctx.GetFormat()) +func (AdminListFactory) Deserialize(ctx serde.Context, data []byte) (serde.Message, error) { + format := adminListFormat.Get(ctx.GetFormat()) message, err := format.Decode(ctx, data) if err != nil { From 6a346c07532bf3cea1e1061ff921c4b93c004174 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 15 May 2024 16:45:37 +0200 Subject: [PATCH 070/114] getting rid of adminform --- contracts/evoting/admin_test.go | 18 ++++++++-------- contracts/evoting/evoting.go | 28 +++++++++++++++---------- contracts/evoting/json/adminList.go | 22 ++++++++++---------- contracts/evoting/json/mod.go | 2 +- contracts/evoting/mod.go | 24 +++++++++++----------- contracts/evoting/mod_test.go | 32 ++++++++++++++--------------- contracts/evoting/types/admin.go | 10 ++++----- integration/form.go | 2 +- 8 files changed, 72 insertions(+), 66 deletions(-) diff --git a/contracts/evoting/admin_test.go b/contracts/evoting/admin_test.go index 922bf271f..425da2fc4 100644 --- a/contracts/evoting/admin_test.go +++ b/contracts/evoting/admin_test.go @@ -46,31 +46,31 @@ func TestAdmin_Serde(t *testing.T) { } func TestAdmin_AddAdminAndRemoveAdmin(t *testing.T) { - adminFormList := []int{} + initialAdminList := []int{} myTestID := "123456" - adminForm := types.AdminList{AdminList: adminFormList} + adminList := types.AdminList{AdminList: initialAdminList} - res, err := adminForm.GetAdminIndex(myTestID) + res, err := adminList.GetAdminIndex(myTestID) require.Equal(t, -1, res) require.NoError(t, err) - err = adminForm.AddAdmin(myTestID) + err = adminList.AddAdmin(myTestID) require.NoError(t, err) - res, err = adminForm.GetAdminIndex(myTestID) + res, err = adminList.GetAdminIndex(myTestID) require.Equal(t, 0, res) require.NoError(t, err) - err = adminForm.RemoveAdmin(myTestID) + err = adminList.RemoveAdmin(myTestID) require.ErrorContains(t, err, "cannot remove this Admin because it is the only one remaining") - err = adminForm.AddAdmin("654321") + err = adminList.AddAdmin("654321") require.NoError(t, err) - err = adminForm.RemoveAdmin(myTestID) + err = adminList.RemoveAdmin(myTestID) require.NoError(t, err) - res, err = adminForm.GetAdminIndex(myTestID) + res, err = adminList.GetAdminIndex(myTestID) require.Equal(t, -1, res) require.NoError(t, err) } diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index b3933ef62..9d169e91c 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -66,11 +66,11 @@ func (e evotingCommand) createForm(snap store.Snapshot, step execution.Step) err } // Check if has Admin Right to create a form - adminForm, err := e.getAdminForm(snap) + adminList, err := e.getAdminList(snap) if err != nil { return xerrors.Errorf("failed to get AdminList: %v", err) } - adminIndex, err := adminForm.GetAdminIndex(tx.UserID) + adminIndex, err := adminList.GetAdminIndex(tx.UserID) if err != nil { return xerrors.Errorf("Couldn't retrieve the admin right of the user: %v", err) } @@ -797,8 +797,8 @@ func (e evotingCommand) deleteForm(snap store.Snapshot, step execution.Step) err return nil } -// manageAdminForm implements commands. It performs the ADD or REMOVE ADMIN command -func (e evotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step) error { +// manageAdminList implements commands. It performs the ADD or REMOVE ADMIN command +func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step) error { msg, err := e.getTransaction(step.Current) if err != nil { return xerrors.Errorf(errGetTransaction, err) @@ -814,12 +814,14 @@ func (e evotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step txRemoveAdmin, okRemoveAdmin := msg.(types.RemoveAdmin) if okAddAdmin { - form, err = e.getAdminForm(snap) + form, err = e.getAdminList(snap) if err != nil { if !strings.Contains(err.Error(), "No form found") { return xerrors.Errorf("failed to get AdminList: %v", err) } + // Trust On First Use System -> if no AdminList, will create one by default. + intSciper, err := types.SciperToInt(txAddAdmin.UserID) if err != nil { return xerrors.Errorf("Invalid Sciper: %v", err) @@ -835,12 +837,16 @@ func (e evotingCommand) manageAdminForm(snap store.Snapshot, step execution.Step return nil } + // TODO Check if admin + //form.GetAdminIndex() + err = form.AddAdmin(txAddAdmin.UserID) if err != nil { return xerrors.Errorf("couldn't add admin: %v", err) } } else if okRemoveAdmin { - form, err = e.getAdminForm(snap) + // TODO Check if admin + form, err = e.getAdminList(snap) if err != nil { return xerrors.Errorf("failed to get AdminList: %v", err) } @@ -871,11 +877,11 @@ func initializeAdminList(snap store.Snapshot, initialAdmin int, ctx serde.Contex h.Write([]byte(AdminListId)) formIDBuf := h.Sum(nil) - adminForm := types.AdminList{ + adminList := types.AdminList{ AdminList: []int{initialAdmin}, } - formBuf, err := adminForm.Serialize(ctx) + formBuf, err := adminList.Serialize(ctx) if err != nil { return xerrors.Errorf("failed to marshal Admin Form : %v", err) } @@ -1079,13 +1085,13 @@ func (e evotingCommand) getForm(formIDHex string, return form, formIDBuf, nil } -// getAdminForm gets the AdminList from the snap. Returns the form ID NOT hex +// getAdminList gets the AdminList from the snap. Returns the form ID NOT hex // encoded. -func (e evotingCommand) getAdminForm(snap store.Snapshot) (types.AdminList, error) { +func (e evotingCommand) getAdminList(snap store.Snapshot) (types.AdminList, error) { var form types.AdminList - form, err := types.AdminListFromStore(e.context, e.adminFormFac, snap, AdminListId) + form, err := types.AdminListFromStore(e.context, e.adminListFac, snap, AdminListId) if err != nil { return form, xerrors.Errorf("failed to get the AdminList: %v", err) } diff --git a/contracts/evoting/json/adminList.go b/contracts/evoting/json/adminList.go index f2d5c489d..e74981d6f 100644 --- a/contracts/evoting/json/adminList.go +++ b/contracts/evoting/json/adminList.go @@ -6,19 +6,19 @@ import ( "golang.org/x/xerrors" ) -type adminFormFormat struct{} +type adminListFormat struct{} -func (adminFormFormat) Encode(ctx serde.Context, message serde.Message) ([]byte, error) { - adminForm, ok := message.(types.AdminList) +func (adminListFormat) Encode(ctx serde.Context, message serde.Message) ([]byte, error) { + adminList, ok := message.(types.AdminList) if !ok { return nil, xerrors.Errorf("Unknown format: %T", message) } - adminFormJSON := AdminFormJSON{ - AdminList: adminForm.AdminList, + adminListJSON := AdminListJSON{ + AdminList: adminList.AdminList, } - buff, err := ctx.Marshal(&adminFormJSON) + buff, err := ctx.Marshal(&adminListJSON) if err != nil { return nil, xerrors.Errorf("failed to marshal form: %v", err) } @@ -26,20 +26,20 @@ func (adminFormFormat) Encode(ctx serde.Context, message serde.Message) ([]byte, return buff, nil } -func (adminFormFormat) Decode(ctx serde.Context, data []byte) (serde.Message, error) { - var adminFormJSON AdminFormJSON +func (adminListFormat) Decode(ctx serde.Context, data []byte) (serde.Message, error) { + var adminListJSON AdminListJSON - err := ctx.Unmarshal(data, &adminFormJSON) + err := ctx.Unmarshal(data, &adminListJSON) if err != nil { return nil, xerrors.Errorf("failed to unmarshal form: %v", err) } return types.AdminList{ - AdminList: adminFormJSON.AdminList, + AdminList: adminListJSON.AdminList, }, nil } -type AdminFormJSON struct { +type AdminListJSON struct { // List of SCIPER with admin rights AdminList []int } diff --git a/contracts/evoting/json/mod.go b/contracts/evoting/json/mod.go index e05053f89..6dc23f385 100644 --- a/contracts/evoting/json/mod.go +++ b/contracts/evoting/json/mod.go @@ -12,5 +12,5 @@ func init() { types.RegisterSuffragiaFormat(serde.FormatJSON, suffragiaFormat{}) types.RegisterCiphervoteFormat(serde.FormatJSON, ciphervoteFormat{}) types.RegisterTransactionFormat(serde.FormatJSON, transactionFormat{}) - types.RegisterAdminListFormat(serde.FormatJSON, adminFormFormat{}) + types.RegisterAdminListFormat(serde.FormatJSON, adminListFormat{}) } diff --git a/contracts/evoting/mod.go b/contracts/evoting/mod.go index df2153c92..f9aeb87b1 100644 --- a/contracts/evoting/mod.go +++ b/contracts/evoting/mod.go @@ -100,7 +100,7 @@ type commands interface { combineShares(snap store.Snapshot, step execution.Step) error cancelForm(snap store.Snapshot, step execution.Step) error deleteForm(snap store.Snapshot, step execution.Step) error - manageAdminForm(snap store.Snapshot, step execution.Step) error + manageAdminList(snap store.Snapshot, step execution.Step) error manageOwnersVotersForm(snap store.Snapshot, step execution.Step) error } @@ -130,10 +130,10 @@ const ( // CmdDeleteForm is the command to delete a form CmdDeleteForm Command = "DELETE_FORM" - // CmdAddAdminForm is the command to delete a form - CmdAddAdminForm Command = "ADD_ADMIN" - // CmdRemoveAdminForm is the command to delete a form - CmdRemoveAdminForm Command = "REMOVE_ADMIN" + // CmdAddAdmin is the command to add an admin to the system + CmdAddAdmin Command = "ADD_ADMIN" + // CmdRemoveAdmin is the command to remove an admin to the system + CmdRemoveAdmin Command = "REMOVE_ADMIN" // CmdAddOwnerForm is the command to add an Owner to a form CmdAddOwnerForm Command = "ADD_OWNER" @@ -172,7 +172,7 @@ type Contract struct { context serde.Context formFac serde.Factory - adminFormFac serde.Factory + adminListFac serde.Factory rosterFac authority.Factory transactionFac serde.Factory } @@ -186,7 +186,7 @@ func NewContract(srvc access.Service, ciphervoteFac := types.CiphervoteFactory{} formFac := types.NewFormFactory(ciphervoteFac, rosterFac) transactionFac := types.NewTransactionFactory(ciphervoteFac) - adminFormFac := types.AdminListFactory{} + adminListFac := types.AdminListFactory{} contract := Contract{ access: srvc, @@ -195,7 +195,7 @@ func NewContract(srvc access.Service, context: ctx, formFac: formFac, - adminFormFac: adminFormFac, + adminListFac: adminListFac, rosterFac: rosterFac, transactionFac: transactionFac, } @@ -266,13 +266,13 @@ func (c Contract) Execute(snap store.Snapshot, step execution.Step) error { if err != nil { return xerrors.Errorf("failed to delete form: %v", err) } - case CmdAddAdminForm: - err := c.cmd.manageAdminForm(snap, step) + case CmdAddAdmin: + err := c.cmd.manageAdminList(snap, step) if err != nil { return xerrors.Errorf("failed to add admin: %v", err) } - case CmdRemoveAdminForm: - err := c.cmd.manageAdminForm(snap, step) + case CmdRemoveAdmin: + err := c.cmd.manageAdminList(snap, step) if err != nil { return xerrors.Errorf("failed to remove admin: %v", err) } diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index f740c68a7..029b6e62f 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -100,10 +100,10 @@ func TestExecute(t *testing.T) { err = contract.Execute(fakeStore{}, makeStep(t, CmdArg, string(CmdCancelForm))) require.EqualError(t, err, fake.Err("failed to cancel form")) - err = contract.Execute(fakeStore{}, makeStep(t, CmdArg, string(CmdAddAdminForm))) + err = contract.Execute(fakeStore{}, makeStep(t, CmdArg, string(CmdAddAdmin))) require.EqualError(t, err, fake.Err("failed to add admin")) - err = contract.Execute(fakeStore{}, makeStep(t, CmdArg, string(CmdRemoveAdminForm))) + err = contract.Execute(fakeStore{}, makeStep(t, CmdArg, string(CmdRemoveAdmin))) require.EqualError(t, err, fake.Err("failed to remove admin")) err = contract.Execute(fakeStore{}, makeStep(t, CmdArg, "fake")) @@ -159,7 +159,7 @@ func TestCommand_CreateForm(t *testing.T) { snap := fake.NewSnapshot() step := makeStep(t, FormArg, string(dataAddAdmin)) - err = cmd.manageAdminForm(snap, step) + err = cmd.manageAdminList(snap, step) require.NoError(t, err) step = makeStep(t, FormArg, string(data)) @@ -1110,7 +1110,7 @@ func TestRegisterContract(t *testing.T) { // =============== // Admin Form Test -func TestCommand_AdminForm(t *testing.T) { +func TestCommand_AdminList(t *testing.T) { initMetrics() dummyForm, contract := initFormAndContract() @@ -1133,17 +1133,17 @@ func TestCommand_AdminForm(t *testing.T) { // Checking that if no AdminList is on the blockchain, // It won't be able to find the transaction. - err = cmd.manageAdminForm(fake.NewSnapshot(), makeStep(t)) + err = cmd.manageAdminList(fake.NewSnapshot(), makeStep(t)) require.EqualError(t, err, getTransactionErr) // Checking that providing a dummy data as argument, the form will not // recognize it and won't be able to unmarshal it. - err = cmd.manageAdminForm(fake.NewSnapshot(), makeStep(t, FormArg, "dummy")) + err = cmd.manageAdminList(fake.NewSnapshot(), makeStep(t, FormArg, "dummy")) require.EqualError(t, err, unmarshalTransactionErr) // Checking that given a Blockchain that always returns an error, // it will not be able to create the AdminList on the store. - err = cmd.manageAdminForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) + err = cmd.manageAdminList(fake.NewBadSnapshot(), makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "failed to get AdminList") snap := fake.NewSnapshot() @@ -1165,7 +1165,7 @@ func TestCommand_AdminForm(t *testing.T) { require.NoError(t, err) // We perform below the command on the ledger - err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data))) + err = cmd.manageAdminList(snap, makeStep(t, FormArg, string(data))) require.NoError(t, err) // Now we want to remove its admin privilege. @@ -1176,14 +1176,14 @@ func TestCommand_AdminForm(t *testing.T) { require.NoError(t, err) // Publish the command on the ledger. - err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data))) + err = cmd.manageAdminList(snap, makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "couldn't remove admin") addAdmin2 := types.AddAdmin{UserID: dummyUID} data2, err := addAdmin2.Serialize(ctx) require.NoError(t, err) - err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data2))) + err = cmd.manageAdminList(snap, makeStep(t, FormArg, string(data2))) require.NoError(t, err) // We retrieve the form on the ledger @@ -1193,12 +1193,12 @@ func TestCommand_AdminForm(t *testing.T) { message, err := adminListFac.Deserialize(ctx, res) require.NoError(t, err) - adminForm, ok := message.(types.AdminList) + adminList, ok := message.(types.AdminList) require.True(t, ok) // We check that our dummy User is now admin // (if not admin return -1; else return admin index in AdminList). - dummyUserIDIndex, _ := adminForm.GetAdminIndex(dummyUID) + dummyUserIDIndex, _ := adminList.GetAdminIndex(dummyUID) require.True(t, dummyUserIDIndex > -1) // Now we want to remove its admin privilege. @@ -1208,7 +1208,7 @@ func TestCommand_AdminForm(t *testing.T) { require.NoError(t, err) // Publish the command on the ledger. - err = cmd.manageAdminForm(snap, makeStep(t, FormArg, string(data))) + err = cmd.manageAdminList(snap, makeStep(t, FormArg, string(data))) require.NoError(t, err) // We retrieve the Admin Form from the ledger. @@ -1218,11 +1218,11 @@ func TestCommand_AdminForm(t *testing.T) { message, err = adminListFac.Deserialize(ctx, res) require.NoError(t, err) - adminForm, ok = message.(types.AdminList) + adminList, ok = message.(types.AdminList) require.True(t, ok) // We check that now our dummy user is not admin anymore (return -1) - dummyUserIDIndex, _ = adminForm.GetAdminIndex(dummyUID) + dummyUserIDIndex, _ = adminList.GetAdminIndex(dummyUID) require.True(t, dummyUserIDIndex == -1) } @@ -1761,7 +1761,7 @@ type fakeCmd struct { err error } -func (c fakeCmd) manageAdminForm(snap store.Snapshot, step execution.Step) error { +func (c fakeCmd) manageAdminList(snap store.Snapshot, step execution.Step) error { return c.err } diff --git a/contracts/evoting/types/admin.go b/contracts/evoting/types/admin.go index cef691a87..2715bac23 100644 --- a/contracts/evoting/types/admin.go +++ b/contracts/evoting/types/admin.go @@ -90,22 +90,22 @@ func (adminList *AdminList) RemoveAdmin(userID string) error { return nil } -func AdminListFromStore(ctx serde.Context, adminFormFac serde.Factory, store store.Readable, adminListId string) (AdminList, error) { +func AdminListFromStore(ctx serde.Context, adminListFac serde.Factory, store store.Readable, adminListId string) (AdminList, error) { adminList := AdminList{} h := sha256.New() h.Write([]byte(adminListId)) - adminFormIDBuf := h.Sum(nil) + adminListIDBuf := h.Sum(nil) - adminFormBuf, err := store.Get(adminFormIDBuf) + adminListBuf, err := store.Get(adminListIDBuf) if err != nil { return adminList, xerrors.Errorf("While getting data for form: %v", err) } - if len(adminFormBuf) == 0 { + if len(adminListBuf) == 0 { return adminList, xerrors.Errorf("No form found") } - message, err := adminFormFac.Deserialize(ctx, adminFormBuf) + message, err := adminListFac.Deserialize(ctx, adminListBuf) if err != nil { return adminList, xerrors.Errorf("failed to deserialize AdminList: %v", err) } diff --git a/integration/form.go b/integration/form.go index 946f4f5a6..700d66bb3 100644 --- a/integration/form.go +++ b/integration/form.go @@ -45,7 +45,7 @@ func addAdmin(m txManager, admin string) error { args := []txn.Arg{ {Key: native.ContractArg, Value: []byte(evoting.ContractName)}, {Key: evoting.FormArg, Value: data}, - {Key: evoting.CmdArg, Value: []byte(evoting.CmdAddAdminForm)}, + {Key: evoting.CmdArg, Value: []byte(evoting.CmdAddAdmin)}, } _, err = m.addAndWait(args...) From cdde2db0712cd4f5823eb20e926676fe31549a02 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 16 May 2024 11:19:29 +0200 Subject: [PATCH 071/114] add performing and target field --- contracts/evoting/evoting.go | 6 +++--- contracts/evoting/json/transaction.go | 20 ++++++++++++-------- contracts/evoting/mod_test.go | 10 +++++----- contracts/evoting/types/transactions.go | 6 ++++-- integration/form.go | 2 +- 5 files changed, 25 insertions(+), 19 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 9d169e91c..4f6fc0dce 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -822,7 +822,7 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step // Trust On First Use System -> if no AdminList, will create one by default. - intSciper, err := types.SciperToInt(txAddAdmin.UserID) + intSciper, err := types.SciperToInt(txAddAdmin.TargetUserID) if err != nil { return xerrors.Errorf("Invalid Sciper: %v", err) } @@ -840,7 +840,7 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step // TODO Check if admin //form.GetAdminIndex() - err = form.AddAdmin(txAddAdmin.UserID) + err = form.AddAdmin(txAddAdmin.TargetUserID) if err != nil { return xerrors.Errorf("couldn't add admin: %v", err) } @@ -851,7 +851,7 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step return xerrors.Errorf("failed to get AdminList: %v", err) } - err = form.RemoveAdmin(txRemoveAdmin.UserID) + err = form.RemoveAdmin(txRemoveAdmin.TargetUserID) if err != nil { return xerrors.Errorf("couldn't remove admin: %v", err) } diff --git a/contracts/evoting/json/transaction.go b/contracts/evoting/json/transaction.go index 47feccb79..ee0fe0121 100644 --- a/contracts/evoting/json/transaction.go +++ b/contracts/evoting/json/transaction.go @@ -120,13 +120,15 @@ func (transactionFormat) Encode(ctx serde.Context, msg serde.Message) ([]byte, e m = TransactionJSON{DeleteForm: &de} case types.AddAdmin: aa := AddAdminJSON{ - UserID: t.UserID, + PerformingUserID: t.PerformingUserID, + TargetUserID: t.TargetUserID, } m = TransactionJSON{AddAdmin: &aa} case types.RemoveAdmin: ra := RemoveAdminJSON{ - UserID: t.UserID, + PerformingUserID: t.PerformingUserID, + TargetUserID: t.TargetUserID, } m = TransactionJSON{RemoveAdmin: &ra} @@ -231,11 +233,13 @@ func (transactionFormat) Decode(ctx serde.Context, data []byte) (serde.Message, }, nil case m.AddAdmin != nil: return types.AddAdmin{ - UserID: m.AddAdmin.UserID, + TargetUserID: m.AddAdmin.TargetUserID, + PerformingUserID: m.AddAdmin.PerformingUserID, }, nil case m.RemoveAdmin != nil: return types.RemoveAdmin{ - UserID: m.RemoveAdmin.UserID, + TargetUserID: m.RemoveAdmin.TargetUserID, + PerformingUserID: m.RemoveAdmin.PerformingUserID, }, nil case m.AddOwner != nil: return types.AddOwner{ @@ -346,14 +350,14 @@ type DeleteFormJSON struct { // AddAdminJSON is the JSON representation of a AddAdmin transaction type AddAdminJSON struct { - FormID string - UserID string + TargetUserID string + PerformingUserID string } // RemoveAdminJSON is the JSON representation of a RemoveAdmin transaction type RemoveAdminJSON struct { - FormID string - UserID string + TargetUserID string + PerformingUserID string } // OwnerForm diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 029b6e62f..58ce1424c 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -128,7 +128,7 @@ func TestCommand_CreateForm(t *testing.T) { err: nil, } - addAdmin := types.AddAdmin{dummyUserAdminID} + addAdmin := types.AddAdmin{dummyUserAdminID, dummyUserAdminID} dataAddAdmin, err := addAdmin.Serialize(ctx) require.NoError(t, err) @@ -1125,7 +1125,7 @@ func TestCommand_AdminList(t *testing.T) { dummyUID := "123456" // We initialize the command to add permission. - addAdmin := types.AddAdmin{UserID: "123455"} + addAdmin := types.AddAdmin{"123455", "123455"} data, err := addAdmin.Serialize(ctx) require.NoError(t, err) @@ -1171,7 +1171,7 @@ func TestCommand_AdminList(t *testing.T) { // Now we want to remove its admin privilege. // Will be a failure cause only one left // Initialization of the command - removeAdmin := types.RemoveAdmin{UserID: dummyUID} + removeAdmin := types.RemoveAdmin{dummyUID, dummyUID} data, err = removeAdmin.Serialize(ctx) require.NoError(t, err) @@ -1179,7 +1179,7 @@ func TestCommand_AdminList(t *testing.T) { err = cmd.manageAdminList(snap, makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "couldn't remove admin") - addAdmin2 := types.AddAdmin{UserID: dummyUID} + addAdmin2 := types.AddAdmin{dummyUID, dummyUID} data2, err := addAdmin2.Serialize(ctx) require.NoError(t, err) @@ -1203,7 +1203,7 @@ func TestCommand_AdminList(t *testing.T) { // Now we want to remove its admin privilege. // Initialization of the command - removeAdmin = types.RemoveAdmin{UserID: dummyUID} + removeAdmin = types.RemoveAdmin{dummyUID, dummyUID} data, err = removeAdmin.Serialize(ctx) require.NoError(t, err) diff --git a/contracts/evoting/types/transactions.go b/contracts/evoting/types/transactions.go index 77221d126..2a8aeabb0 100644 --- a/contracts/evoting/types/transactions.go +++ b/contracts/evoting/types/transactions.go @@ -348,7 +348,8 @@ func (registerPubShares RegisterPubShares) Fingerprint(writer io.Writer) error { // // - implements serde.Message type AddAdmin struct { - UserID string + TargetUserID string + PerformingUserID string } // Serialize implements serde.Message @@ -367,7 +368,8 @@ func (addAdmin AddAdmin) Serialize(ctx serde.Context) ([]byte, error) { // // - implements serde.Message type RemoveAdmin struct { - UserID string + TargetUserID string + PerformingUserID string } // Serialize implements serde.Message diff --git a/integration/form.go b/integration/form.go index 700d66bb3..839aa08dc 100644 --- a/integration/form.go +++ b/integration/form.go @@ -35,7 +35,7 @@ func encodeID(ID string) types.ID { // for integration tests func addAdmin(m txManager, admin string) error { - addAdmin := types.AddAdmin{UserID: admin} + addAdmin := types.AddAdmin{admin, admin} data, err := addAdmin.Serialize(serdecontext) if err != nil { From ab8faaca6813f74e813b92b2459fa4d33e18ff40 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 16 May 2024 12:56:11 +0200 Subject: [PATCH 072/114] patch error and test --- contracts/evoting/evoting.go | 22 +++++++++++++++++++--- contracts/evoting/mod_test.go | 30 +++++++++++++++++++++++++++--- 2 files changed, 46 insertions(+), 6 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 4f6fc0dce..86b33c733 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -837,20 +837,36 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step return nil } - // TODO Check if admin - //form.GetAdminIndex() + // Check that the performing user is Admin + performingUserPerm, err := form.GetAdminIndex(txAddAdmin.PerformingUserID) + if err != nil { + return xerrors.Errorf("couldn't retrieve admin permission of the performing user: %v", err) + } + + if performingUserPerm < 0 { + return xerrors.Errorf("the performing user %v doesn't have the permission to add admin", txAddAdmin.PerformingUserID) + } err = form.AddAdmin(txAddAdmin.TargetUserID) if err != nil { return xerrors.Errorf("couldn't add admin: %v", err) } } else if okRemoveAdmin { - // TODO Check if admin form, err = e.getAdminList(snap) if err != nil { return xerrors.Errorf("failed to get AdminList: %v", err) } + // Check that the performing user is Admin + performingUserPerm, err := form.GetAdminIndex(txRemoveAdmin.PerformingUserID) + if err != nil { + return xerrors.Errorf("couldn't retrieve admin permission of the performing user: %v", err) + } + + if performingUserPerm < 0 { + return xerrors.Errorf("the performing user %v doesn't have the permission to remove admin", txRemoveAdmin.PerformingUserID) + } + err = form.RemoveAdmin(txRemoveAdmin.TargetUserID) if err != nil { return xerrors.Errorf("couldn't remove admin: %v", err) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 58ce1424c..299943a43 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1110,6 +1110,16 @@ func TestRegisterContract(t *testing.T) { // =============== // Admin Form Test +/* + Testing Scenario: + - Initialize Contract & Form + - Perform error handling test + - 123456 add admin 123456 + - 123456 remove admin 123456 -> error cause only one left + - 777777 add admin 777777 -> error cause not an admin + - 123456 add admin 777777 + - 123456 remove admin 123456 +*/ func TestCommand_AdminList(t *testing.T) { initMetrics() @@ -1123,9 +1133,10 @@ func TestCommand_AdminList(t *testing.T) { // We define a dummy userID which we are going to add admin permission. dummyUID := "123456" + dummyUID2 := "777777" // We initialize the command to add permission. - addAdmin := types.AddAdmin{"123455", "123455"} + addAdmin := types.AddAdmin{dummyUID, dummyUID} data, err := addAdmin.Serialize(ctx) require.NoError(t, err) @@ -1171,7 +1182,10 @@ func TestCommand_AdminList(t *testing.T) { // Now we want to remove its admin privilege. // Will be a failure cause only one left // Initialization of the command - removeAdmin := types.RemoveAdmin{dummyUID, dummyUID} + removeAdmin := types.RemoveAdmin{ + TargetUserID: dummyUID, + PerformingUserID: dummyUID, + } data, err = removeAdmin.Serialize(ctx) require.NoError(t, err) @@ -1179,10 +1193,20 @@ func TestCommand_AdminList(t *testing.T) { err = cmd.manageAdminList(snap, makeStep(t, FormArg, string(data))) require.ErrorContains(t, err, "couldn't remove admin") - addAdmin2 := types.AddAdmin{dummyUID, dummyUID} + // We try to add a second admin but the performing user + // does not have the permission + addAdmin2 := types.AddAdmin{dummyUID2, dummyUID2} data2, err := addAdmin2.Serialize(ctx) require.NoError(t, err) + err = cmd.manageAdminList(snap, makeStep(t, FormArg, string(data2))) + require.ErrorContains(t, err, "doesn't have the permission to add admin") + + // Now we add another admin but with a performing user that is already admin + addAdmin2 = types.AddAdmin{dummyUID2, dummyUID} + data2, err = addAdmin2.Serialize(ctx) + require.NoError(t, err) + err = cmd.manageAdminList(snap, makeStep(t, FormArg, string(data2))) require.NoError(t, err) From 357e4ac6a0e898f1f5a4842ad8a488d28dbcf995 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 16 May 2024 14:35:10 +0200 Subject: [PATCH 073/114] some minor changes --- contracts/evoting/evoting.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 86b33c733..e2cfa537e 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -814,6 +814,7 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step txRemoveAdmin, okRemoveAdmin := msg.(types.RemoveAdmin) if okAddAdmin { + // Recover the AdminList stored on the blockchain form, err = e.getAdminList(snap) if err != nil { if !strings.Contains(err.Error(), "No form found") { @@ -837,6 +838,7 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step return nil } + // If it found the AdminList // Check that the performing user is Admin performingUserPerm, err := form.GetAdminIndex(txAddAdmin.PerformingUserID) if err != nil { From 45b5ab45a7153752e9e93a1df8310b8cea240afa Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Tue, 21 May 2024 09:27:54 +0200 Subject: [PATCH 074/114] small code cleaning --- contracts/evoting/evoting.go | 2 ++ contracts/evoting/types/election.go | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index e2cfa537e..610d95ca4 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -890,6 +890,8 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step return nil } +// initializeAdminList initialize an AdminList on the blockchain. It is called the first time that +// we attempt to add an admin. func initializeAdminList(snap store.Snapshot, initialAdmin int, ctx serde.Context) error { h := sha256.New() h.Write([]byte(AdminListId)) diff --git a/contracts/evoting/types/election.go b/contracts/evoting/types/election.go index 35309dda6..43f3294f9 100644 --- a/contracts/evoting/types/election.go +++ b/contracts/evoting/types/election.go @@ -467,8 +467,6 @@ func (form *Form) AddOwner(userID string) error { return xerrors.Errorf("failed to convert SCIPER to integer: %v", err) } - // TODO need to check that the new user is admin ! - form.Owners = append(form.Owners, sciperInt) return nil From 78977de792cd243566fcd76ab53cf90e8917d4da Mon Sep 17 00:00:00 2001 From: Maxime <61186830+MaximeZmt@users.noreply.github.com> Date: Thu, 23 May 2024 09:33:01 +0200 Subject: [PATCH 075/114] Update contracts/evoting/evoting.go Co-authored-by: Carine Dengler --- contracts/evoting/evoting.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 610d95ca4..d18093b32 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -903,7 +903,7 @@ func initializeAdminList(snap store.Snapshot, initialAdmin int, ctx serde.Contex formBuf, err := adminList.Serialize(ctx) if err != nil { - return xerrors.Errorf("failed to marshal Admin Form : %v", err) + return xerrors.Errorf("failed to marshal AdminList : %v", err) } err = snap.Set(formIDBuf, formBuf) From 18e73252d46733c1b0d682d60fdd18ad7ca4b8e1 Mon Sep 17 00:00:00 2001 From: Maxime <61186830+MaximeZmt@users.noreply.github.com> Date: Thu, 23 May 2024 09:33:18 +0200 Subject: [PATCH 076/114] Update contracts/evoting/mod_test.go Co-authored-by: Carine Dengler --- contracts/evoting/mod_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 299943a43..452291ccd 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1115,8 +1115,8 @@ func TestRegisterContract(t *testing.T) { - Initialize Contract & Form - Perform error handling test - 123456 add admin 123456 - - 123456 remove admin 123456 -> error cause only one left - - 777777 add admin 777777 -> error cause not an admin + - 123456 remove admin 123456 -> error because only one left + - 777777 add admin 777777 -> error because not an admin - 123456 add admin 777777 - 123456 remove admin 123456 */ From 22661a28af3426edf30e2ee8aeca619867cdd14f Mon Sep 17 00:00:00 2001 From: Maxime <61186830+MaximeZmt@users.noreply.github.com> Date: Thu, 23 May 2024 09:33:25 +0200 Subject: [PATCH 077/114] Update contracts/evoting/types/admin.go Co-authored-by: Carine Dengler --- contracts/evoting/types/admin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/evoting/types/admin.go b/contracts/evoting/types/admin.go index 2715bac23..f7d8d69cf 100644 --- a/contracts/evoting/types/admin.go +++ b/contracts/evoting/types/admin.go @@ -45,7 +45,7 @@ func (adminList AdminList) Deserialize(ctx serde.Context, data []byte) (serde.Me func (adminList *AdminList) AddAdmin(userID string) error { sciperInt, err := SciperToInt(userID) if err != nil { - return xerrors.Errorf("Failed SciperToInt: %v", err) + return xerrors.Errorf("Failed to convert SCIPER to int: %v", err) } adminList.AdminList = append(adminList.AdminList, sciperInt) From 10e8080c0849b542314f3402529febbdfbd79714 Mon Sep 17 00:00:00 2001 From: Maxime <61186830+MaximeZmt@users.noreply.github.com> Date: Thu, 23 May 2024 09:33:34 +0200 Subject: [PATCH 078/114] Update contracts/evoting/types/admin.go Co-authored-by: Carine Dengler --- contracts/evoting/types/admin.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/evoting/types/admin.go b/contracts/evoting/types/admin.go index f7d8d69cf..faf77f70b 100644 --- a/contracts/evoting/types/admin.go +++ b/contracts/evoting/types/admin.go @@ -57,7 +57,7 @@ func (adminList *AdminList) AddAdmin(userID string) error { func (adminList *AdminList) GetAdminIndex(userID string) (int, error) { sciperInt, err := SciperToInt(userID) if err != nil { - return -1, xerrors.Errorf("Failed SciperToInt: %v", err) + return -1, xerrors.Errorf("Failed to convert SCIPER to int: %v", err) } for i := 0; i < len(adminList.AdminList); i++ { From ef2af91a09e0eb42cb4ecfba60ae5c558cff554c Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 23 May 2024 09:35:26 +0200 Subject: [PATCH 079/114] address partial review --- contracts/evoting/evoting.go | 11 ++--- contracts/evoting/json/transaction.go | 60 +++++++++++++++---------- contracts/evoting/mod_test.go | 25 ++++++----- contracts/evoting/types/transactions.go | 38 +++++++++++----- 4 files changed, 85 insertions(+), 49 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index d18093b32..ed5f6d740 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -817,7 +817,8 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step // Recover the AdminList stored on the blockchain form, err = e.getAdminList(snap) if err != nil { - if !strings.Contains(err.Error(), "No form found") { + // Exact string matching of the error + if !strings.Contains(err.Error(), "failed to get the AdminList: No form found") { return xerrors.Errorf("failed to get AdminList: %v", err) } @@ -969,7 +970,7 @@ func (e evotingCommand) manageOwnersVotersForm(snap store.Snapshot, step executi return xerrors.Errorf(errGetForm, err) } - err = form.AddVoter(txAddVoter.UserID) + err = form.AddVoter(txAddVoter.TargetUserID) if err != nil { return xerrors.Errorf("couldn't add voter: %v", err) } @@ -979,7 +980,7 @@ func (e evotingCommand) manageOwnersVotersForm(snap store.Snapshot, step executi return xerrors.Errorf(errGetForm, err) } - err = form.RemoveVoter(txRemoveVoter.UserID) + err = form.RemoveVoter(txRemoveVoter.TargetUserID) if err != nil { return xerrors.Errorf("couldn't remove voter: %v", err) } @@ -989,7 +990,7 @@ func (e evotingCommand) manageOwnersVotersForm(snap store.Snapshot, step executi return xerrors.Errorf(errGetForm, err) } - err = form.AddOwner(txAddOwner.UserID) + err = form.AddOwner(txAddOwner.TargetUserID) if err != nil { return xerrors.Errorf("couldn't add owner: %v", err) } @@ -999,7 +1000,7 @@ func (e evotingCommand) manageOwnersVotersForm(snap store.Snapshot, step executi return xerrors.Errorf(errGetForm, err) } - err = form.RemoveOwner(txRemoveOwner.UserID) + err = form.RemoveOwner(txRemoveOwner.TargetUserID) if err != nil { return xerrors.Errorf("couldn't remove owner: %v", err) } diff --git a/contracts/evoting/json/transaction.go b/contracts/evoting/json/transaction.go index ee0fe0121..fdc29e60e 100644 --- a/contracts/evoting/json/transaction.go +++ b/contracts/evoting/json/transaction.go @@ -134,29 +134,33 @@ func (transactionFormat) Encode(ctx serde.Context, msg serde.Message) ([]byte, e m = TransactionJSON{RemoveAdmin: &ra} case types.AddOwner: addOwner := AddOwnerJSON{ - FormID: t.FormID, - UserID: t.UserID, + FormID: t.FormID, + TargetUserID: t.TargetUserID, + PerformingUserID: t.PerformingUserID, } m = TransactionJSON{AddOwner: &addOwner} case types.RemoveOwner: removeOwner := RemoveOwnerJSON{ - FormID: t.FormID, - UserID: t.UserID, + FormID: t.FormID, + TargetUserID: t.TargetUserID, + PerformingUserID: t.PerformingUserID, } m = TransactionJSON{RemoveOwner: &removeOwner} case types.AddVoter: addVoter := AddVoterJSON{ - FormID: t.FormID, - UserID: t.UserID, + FormID: t.FormID, + TargetUserID: t.TargetUserID, + PerformingUserID: t.PerformingUserID, } m = TransactionJSON{AddVoter: &addVoter} case types.RemoveVoter: removeVoter := RemoveVoterJSON{ - FormID: t.FormID, - UserID: t.UserID, + FormID: t.FormID, + TargetUserID: t.TargetUserID, + PerformingUserID: t.PerformingUserID, } m = TransactionJSON{RemoveVoter: &removeVoter} @@ -243,23 +247,27 @@ func (transactionFormat) Decode(ctx serde.Context, data []byte) (serde.Message, }, nil case m.AddOwner != nil: return types.AddOwner{ - FormID: m.AddOwner.FormID, - UserID: m.AddOwner.UserID, + FormID: m.AddOwner.FormID, + TargetUserID: m.AddOwner.TargetUserID, + PerformingUserID: m.AddOwner.PerformingUserID, }, nil case m.RemoveOwner != nil: return types.RemoveOwner{ - FormID: m.RemoveOwner.FormID, - UserID: m.RemoveOwner.UserID, + FormID: m.RemoveOwner.FormID, + TargetUserID: m.AddOwner.TargetUserID, + PerformingUserID: m.AddOwner.PerformingUserID, }, nil case m.AddVoter != nil: return types.AddVoter{ - FormID: m.AddVoter.FormID, - UserID: m.AddVoter.UserID, + FormID: m.AddVoter.FormID, + TargetUserID: m.AddOwner.TargetUserID, + PerformingUserID: m.AddOwner.PerformingUserID, }, nil case m.RemoveVoter != nil: return types.RemoveVoter{ - FormID: m.RemoveVoter.FormID, - UserID: m.RemoveVoter.UserID, + FormID: m.RemoveVoter.FormID, + TargetUserID: m.AddOwner.TargetUserID, + PerformingUserID: m.AddOwner.PerformingUserID, }, nil } @@ -364,28 +372,32 @@ type RemoveAdminJSON struct { // AddOwnerJSON is the JSON representation of a AddOwner transaction type AddOwnerJSON struct { - FormID string - UserID string + FormID string + TargetUserID string + PerformingUserID string } // RemoveOwnerJSON is the JSON representation of a RemoveOwner transaction type RemoveOwnerJSON struct { - FormID string - UserID string + FormID string + TargetUserID string + PerformingUserID string } // VoterForm // AddVoterJSON is the JSON representation of a AddVoter transaction type AddVoterJSON struct { - FormID string - UserID string + FormID string + TargetUserID string + PerformingUserID string } // RemoveVoterJSON is the JSON representation of a RemoveVoter transaction type RemoveVoterJSON struct { - FormID string - UserID string + FormID string + TargetUserID string + PerformingUserID string } func decodeCastVote(ctx serde.Context, m CastVoteJSON) (serde.Message, error) { diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 452291ccd..37ef7c4de 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1262,8 +1262,9 @@ func TestCommand_AdminList(t *testing.T) { */ func TestCommand_OwnerForm(t *testing.T) { addOwner := types.AddOwner{ - FormID: fakeFormID, - UserID: dummyUserAdminID, + FormID: fakeFormID, + TargetUserID: dummyUserAdminID, + PerformingUserID: dummyUserAdminID, } // Test Serialization of AddOwner command @@ -1271,8 +1272,9 @@ func TestCommand_OwnerForm(t *testing.T) { require.NoError(t, err) removeOwner := types.RemoveOwner{ - FormID: fakeFormID, - UserID: dummyUserAdminID, + FormID: fakeFormID, + TargetUserID: dummyUserAdminID, + PerformingUserID: dummyUserAdminID, } // Test Serialization of RemoveOwner command @@ -1370,8 +1372,9 @@ func TestCommand_OwnerForm(t *testing.T) { // So first let's add a second owner addOwner2 := types.AddOwner{ - FormID: fakeFormID, - UserID: "234567", + FormID: fakeFormID, + TargetUserID: "234567", + PerformingUserID: "234567", } // Test Serialization of AddOwner command @@ -1426,8 +1429,9 @@ func TestCommand_OwnerForm(t *testing.T) { */ func TestCommand_VoterForm(t *testing.T) { addVoter := types.AddVoter{ - FormID: fakeFormID, - UserID: dummyUserAdminID, + FormID: fakeFormID, + TargetUserID: dummyUserAdminID, + PerformingUserID: dummyUserAdminID, } // Test Serialization of AddVoter command @@ -1435,8 +1439,9 @@ func TestCommand_VoterForm(t *testing.T) { require.NoError(t, err) removeVoter := types.RemoveVoter{ - FormID: fakeFormID, - UserID: dummyUserAdminID, + FormID: fakeFormID, + TargetUserID: dummyUserAdminID, + PerformingUserID: dummyUserAdminID, } // Test Serialization of RemoveVoter command diff --git a/contracts/evoting/types/transactions.go b/contracts/evoting/types/transactions.go index 2a8aeabb0..97a462d51 100644 --- a/contracts/evoting/types/transactions.go +++ b/contracts/evoting/types/transactions.go @@ -92,7 +92,8 @@ func (transactionFactory TransactionFactory) Deserialize(ctx serde.Context, data // - implements serde.Message type CreateForm struct { Configuration Configuration - UserID string + // UserID of the owner that is performing the action + UserID string } // Serialize implements serde.Message @@ -113,6 +114,8 @@ func (createForm CreateForm) Serialize(ctx serde.Context) ([]byte, error) { type OpenForm struct { // FormID is hex-encoded FormID string + // UserID of the owner that is performing the action + UserID string } // Serialize implements serde.Message @@ -155,6 +158,7 @@ func (castVote CastVote) Serialize(ctx serde.Context) ([]byte, error) { type CloseForm struct { // FormID is hex-encoded FormID string + // UserID of the owner that is performing the action UserID string } @@ -186,8 +190,10 @@ type ShuffleBallots struct { // Signature is the signature of the result of HashShuffle() with the private // key corresponding to PublicKey Signature []byte - //PublicKey is the public key of the signer. + // PublicKey is the public key of the signer. PublicKey []byte + // UserID of the owner that is performing the action + UserID string } // Serialize implements serde.Message @@ -218,6 +224,10 @@ type RegisterPubShares struct { Signature []byte // PublicKey is the public key of the signer PublicKey []byte + + // TODO Is is needed + // UserID of the owner that is performing the action + // UserID string } // Serialize implements serde.Message @@ -239,6 +249,7 @@ func (registerPubShares RegisterPubShares) Serialize(ctx serde.Context) ([]byte, type CombineShares struct { // FormID is hex-encoded FormID string + // UserID of the owner that is performing the action UserID string } @@ -260,6 +271,7 @@ func (combineShares CombineShares) Serialize(ctx serde.Context) ([]byte, error) type CancelForm struct { // FormID is hex-encoded FormID string + // UserID of the owner that is performing the action UserID string } @@ -281,6 +293,8 @@ func (cancelForm CancelForm) Serialize(ctx serde.Context) ([]byte, error) { type DeleteForm struct { // FormID is hex-encoded FormID string + // UserID of the owner that is performing the action + UserID string } // Serialize implements serde.Message @@ -389,8 +403,9 @@ func (removeAdmin RemoveAdmin) Serialize(ctx serde.Context) ([]byte, error) { // - implements serde.Message type AddVoter struct { // FormID is hex-encoded - FormID string - UserID string + FormID string + TargetUserID string + PerformingUserID string } // Serialize implements serde.Message @@ -410,8 +425,9 @@ func (addVoter AddVoter) Serialize(ctx serde.Context) ([]byte, error) { // - implements serde.Message type RemoveVoter struct { // FormID is hex-encoded - FormID string - UserID string + FormID string + TargetUserID string + PerformingUserID string } // Serialize implements serde.Message @@ -431,8 +447,9 @@ func (removeVoter RemoveVoter) Serialize(ctx serde.Context) ([]byte, error) { // - implements serde.Message type AddOwner struct { // FormID is hex-encoded - FormID string - UserID string + FormID string + TargetUserID string + PerformingUserID string } // Serialize implements serde.Message @@ -452,8 +469,9 @@ func (addOwner AddOwner) Serialize(ctx serde.Context) ([]byte, error) { // - implements serde.Message type RemoveOwner struct { // FormID is hex-encoded - FormID string - UserID string + FormID string + TargetUserID string + PerformingUserID string } // Serialize implements serde.Message From 5b22dad5172524b1e05451750023cca1ab98507f Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 23 May 2024 09:42:42 +0200 Subject: [PATCH 080/114] isAdmin function --- contracts/evoting/evoting.go | 38 ++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 17 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index ed5f6d740..e99b9f94e 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -839,15 +839,9 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step return nil } - // If it found the AdminList - // Check that the performing user is Admin - performingUserPerm, err := form.GetAdminIndex(txAddAdmin.PerformingUserID) - if err != nil { - return xerrors.Errorf("couldn't retrieve admin permission of the performing user: %v", err) - } - - if performingUserPerm < 0 { - return xerrors.Errorf("the performing user %v doesn't have the permission to add admin", txAddAdmin.PerformingUserID) + isAdmin, err := e.isAdmin(form, txAddAdmin) + if err != nil || !isAdmin { + return xerrors.Errorf("The performing user is not an admin: %v", err) } err = form.AddAdmin(txAddAdmin.TargetUserID) @@ -860,14 +854,9 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step return xerrors.Errorf("failed to get AdminList: %v", err) } - // Check that the performing user is Admin - performingUserPerm, err := form.GetAdminIndex(txRemoveAdmin.PerformingUserID) - if err != nil { - return xerrors.Errorf("couldn't retrieve admin permission of the performing user: %v", err) - } - - if performingUserPerm < 0 { - return xerrors.Errorf("the performing user %v doesn't have the permission to remove admin", txRemoveAdmin.PerformingUserID) + isAdmin, err := e.isAdmin(form, txAddAdmin) + if err != nil || !isAdmin { + return xerrors.Errorf("The performing user is not an admin: %v", err) } err = form.RemoveAdmin(txRemoveAdmin.TargetUserID) @@ -891,6 +880,21 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step return nil } +// isAdmin Check whether a user is in an Admin List +func (e evotingCommand) isAdmin(form types.AdminList, txAddAdmin types.AddAdmin) (bool, error) { + // If it found the AdminList + // Check that the performing user is Admin + performingUserPerm, err := form.GetAdminIndex(txAddAdmin.PerformingUserID) + if err != nil { + return false, xerrors.Errorf("couldn't retrieve admin permission of the performing user: %v", err) + } + + if performingUserPerm < 0 { + return false, xerrors.Errorf("the performing user %v doesn't have the permission to add admin", txAddAdmin.PerformingUserID) + } + return true, nil +} + // initializeAdminList initialize an AdminList on the blockchain. It is called the first time that // we attempt to add an admin. func initializeAdminList(snap store.Snapshot, initialAdmin int, ctx serde.Context) error { From 302a4b0f73cfd820620274b5e1b9fbe7838ced38 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 23 May 2024 10:45:05 +0200 Subject: [PATCH 081/114] patch updatemetadata review --- contracts/evoting/evoting.go | 84 ++++++++------------------------ contracts/evoting/types/admin.go | 4 +- 2 files changed, 21 insertions(+), 67 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index e99b9f94e..9025a99cd 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -138,8 +138,16 @@ func (e evotingCommand) createForm(snap store.Snapshot, step execution.Step) err return xerrors.Errorf("failed to set value: %v", err) } - // Update the form metadata store + err = updateFormMetadataStore(snap, form.FormID) + if err != nil { + return xerrors.Errorf("failed to update the metadata in the store: %v", err) + } + return nil +} + +// updateFormMetadataStore Update the form metadata store +func updateFormMetadataStore(snap store.Snapshot, formID string) error { formsMetadataBuf, err := snap.Get([]byte(FormsMetadataKey)) if err != nil { return xerrors.Errorf("failed to get key '%s': %v", formsMetadataBuf, err) @@ -156,7 +164,7 @@ func (e evotingCommand) createForm(snap store.Snapshot, step execution.Step) err } } - err = formsMetadata.FormsIDs.Add(form.FormID) + err = formsMetadata.FormsIDs.Add(formID) if err != nil { return xerrors.Errorf("couldn't add new form: %v", err) } @@ -170,7 +178,6 @@ func (e evotingCommand) createForm(snap store.Snapshot, step execution.Step) err if err != nil { return xerrors.Errorf("failed to set value: %v", err) } - return nil } @@ -764,34 +771,9 @@ func (e evotingCommand) deleteForm(snap store.Snapshot, step execution.Step) err return xerrors.Errorf("failed to delete form: %v", err) } - // Update the form metadata store - - formsMetadataBuf, err := snap.Get([]byte(FormsMetadataKey)) + err = updateFormMetadataStore(snap, form.FormID) if err != nil { - return xerrors.Errorf("failed to get key '%s': %v", formsMetadataBuf, err) - } - - if len(formsMetadataBuf) == 0 { - return nil - } - - var formsMetadata types.FormsMetadata - - err = json.Unmarshal(formsMetadataBuf, &formsMetadata) - if err != nil { - return xerrors.Errorf("failed to unmarshal FormsMetadata: %v", err) - } - - formsMetadata.FormsIDs.Remove(form.FormID) - - formMetadataJSON, err := json.Marshal(formsMetadata) - if err != nil { - return xerrors.Errorf("failed to marshal FormsMetadata: %v", err) - } - - err = snap.Set([]byte(FormsMetadataKey), formMetadataJSON) - if err != nil { - return xerrors.Errorf("failed to set value: %v", err) + return xerrors.Errorf("failed to update the metadata in the store: %v", err) } return nil @@ -839,7 +821,7 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step return nil } - isAdmin, err := e.isAdmin(form, txAddAdmin) + isAdmin, err := e.isAdmin(form, txAddAdmin.PerformingUserID) if err != nil || !isAdmin { return xerrors.Errorf("The performing user is not an admin: %v", err) } @@ -854,7 +836,7 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step return xerrors.Errorf("failed to get AdminList: %v", err) } - isAdmin, err := e.isAdmin(form, txAddAdmin) + isAdmin, err := e.isAdmin(form, txRemoveAdmin.PerformingUserID) if err != nil || !isAdmin { return xerrors.Errorf("The performing user is not an admin: %v", err) } @@ -881,16 +863,16 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step } // isAdmin Check whether a user is in an Admin List -func (e evotingCommand) isAdmin(form types.AdminList, txAddAdmin types.AddAdmin) (bool, error) { +func (e evotingCommand) isAdmin(form types.AdminList, txPerformingUser string) (bool, error) { // If it found the AdminList // Check that the performing user is Admin - performingUserPerm, err := form.GetAdminIndex(txAddAdmin.PerformingUserID) + performingUserPerm, err := form.GetAdminIndex(txPerformingUser) if err != nil { return false, xerrors.Errorf("couldn't retrieve admin permission of the performing user: %v", err) } if performingUserPerm < 0 { - return false, xerrors.Errorf("the performing user %v doesn't have the permission to add admin", txAddAdmin.PerformingUserID) + return false, xerrors.Errorf("the performing user %v doesn't have the permission to add admin", txPerformingUser) } return true, nil } @@ -916,37 +898,9 @@ func initializeAdminList(snap store.Snapshot, initialAdmin int, ctx serde.Contex return xerrors.Errorf("failed to set value: %v", err) } - // Update the form metadata store - - formsMetadataBuf, err := snap.Get([]byte(FormsMetadataKey)) - if err != nil { - return xerrors.Errorf("failed to get key '%s': %v", formsMetadataBuf, err) - } - - formsMetadata := &types.FormsMetadata{ - FormsIDs: types.FormIDs{}, - } - - if len(formsMetadataBuf) != 0 { - err := json.Unmarshal(formsMetadataBuf, formsMetadata) - if err != nil { - return xerrors.Errorf("failed to unmarshal FormsMetadata: %v", err) - } - } - - err = formsMetadata.FormsIDs.Add(hex.EncodeToString(formIDBuf)) - if err != nil { - return xerrors.Errorf("couldn't add new form: %v", err) - } - - formMetadataJSON, err := json.Marshal(formsMetadata) + err = updateFormMetadataStore(snap, hex.EncodeToString(formIDBuf)) if err != nil { - return xerrors.Errorf("failed to marshal FormsMetadata: %v", err) - } - - err = snap.Set([]byte(FormsMetadataKey), formMetadataJSON) - if err != nil { - return xerrors.Errorf("failed to set value: %v", err) + return xerrors.Errorf("failed to update the metadata in the store: %v", err) } return nil diff --git a/contracts/evoting/types/admin.go b/contracts/evoting/types/admin.go index faf77f70b..7bdcbffd1 100644 --- a/contracts/evoting/types/admin.go +++ b/contracts/evoting/types/admin.go @@ -73,14 +73,14 @@ func (adminList *AdminList) GetAdminIndex(userID string) (int, error) { func (adminList *AdminList) RemoveAdmin(userID string) error { index, err := adminList.GetAdminIndex(userID) if err != nil { - return xerrors.Errorf("Failed GetAdminIndex: %v", err) + return xerrors.Errorf("Failed to retrieve the admin from the Admin List: %v", err) } if index < 0 { return xerrors.Errorf("Error while retrieving the index of the element.") } - // We don't want to have a form without any Owners. + // We don't want to have a form without any Admin. if len(adminList.AdminList) <= 1 { return xerrors.Errorf("Error, cannot remove this Admin because it is the " + "only one remaining.") From df96a91239a57a382d3e70d0585b4f590d959dad Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Thu, 23 May 2024 10:52:25 +0200 Subject: [PATCH 082/114] patch ownervoter test --- contracts/evoting/json/transaction.go | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/evoting/json/transaction.go b/contracts/evoting/json/transaction.go index fdc29e60e..f56a67627 100644 --- a/contracts/evoting/json/transaction.go +++ b/contracts/evoting/json/transaction.go @@ -254,20 +254,20 @@ func (transactionFormat) Decode(ctx serde.Context, data []byte) (serde.Message, case m.RemoveOwner != nil: return types.RemoveOwner{ FormID: m.RemoveOwner.FormID, - TargetUserID: m.AddOwner.TargetUserID, - PerformingUserID: m.AddOwner.PerformingUserID, + TargetUserID: m.RemoveOwner.TargetUserID, + PerformingUserID: m.RemoveOwner.PerformingUserID, }, nil case m.AddVoter != nil: return types.AddVoter{ FormID: m.AddVoter.FormID, - TargetUserID: m.AddOwner.TargetUserID, - PerformingUserID: m.AddOwner.PerformingUserID, + TargetUserID: m.AddVoter.TargetUserID, + PerformingUserID: m.AddVoter.PerformingUserID, }, nil case m.RemoveVoter != nil: return types.RemoveVoter{ FormID: m.RemoveVoter.FormID, - TargetUserID: m.AddOwner.TargetUserID, - PerformingUserID: m.AddOwner.PerformingUserID, + TargetUserID: m.RemoveVoter.TargetUserID, + PerformingUserID: m.RemoveVoter.PerformingUserID, }, nil } From a6d8e8d7540901c9de81b4433569d1a64a6d8d88 Mon Sep 17 00:00:00 2001 From: Maxime <61186830+MaximeZmt@users.noreply.github.com> Date: Thu, 23 May 2024 11:02:55 +0200 Subject: [PATCH 083/114] Update evoting.go exact error comparison update --- contracts/evoting/evoting.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 9025a99cd..4f3718218 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -800,7 +800,7 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step form, err = e.getAdminList(snap) if err != nil { // Exact string matching of the error - if !strings.Contains(err.Error(), "failed to get the AdminList: No form found") { + if err.Error() != "failed to get the AdminList: No form found" { return xerrors.Errorf("failed to get AdminList: %v", err) } From 36ebc0ba922e74a7d205bd099f3e1670f6fc83a3 Mon Sep 17 00:00:00 2001 From: Maxime Date: Thu, 23 May 2024 12:43:36 +0200 Subject: [PATCH 084/114] patch is admin error mgmt --- contracts/evoting/evoting.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 4f3718218..6100f73a7 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -872,7 +872,7 @@ func (e evotingCommand) isAdmin(form types.AdminList, txPerformingUser string) ( } if performingUserPerm < 0 { - return false, xerrors.Errorf("the performing user %v doesn't have the permission to add admin", txPerformingUser) + return false, nil } return true, nil } From 645a08f6d3bafb0c033ff364f7e6341a34b710b4 Mon Sep 17 00:00:00 2001 From: Maxime Date: Thu, 23 May 2024 12:48:43 +0200 Subject: [PATCH 085/114] patch test --- contracts/evoting/evoting.go | 14 ++++++++++---- contracts/evoting/mod_test.go | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 6100f73a7..e7298fa8a 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -822,8 +822,11 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step } isAdmin, err := e.isAdmin(form, txAddAdmin.PerformingUserID) - if err != nil || !isAdmin { - return xerrors.Errorf("The performing user is not an admin: %v", err) + if err != nil { + return err + } + if !isAdmin { + return xerrors.Errorf("The performing user is not an admin.") } err = form.AddAdmin(txAddAdmin.TargetUserID) @@ -837,8 +840,11 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step } isAdmin, err := e.isAdmin(form, txRemoveAdmin.PerformingUserID) - if err != nil || !isAdmin { - return xerrors.Errorf("The performing user is not an admin: %v", err) + if err != nil { + return err + } + if !isAdmin { + return xerrors.Errorf("The performing user is not an admin.") } err = form.RemoveAdmin(txRemoveAdmin.TargetUserID) diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 37ef7c4de..54f1d5aa3 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -1200,7 +1200,7 @@ func TestCommand_AdminList(t *testing.T) { require.NoError(t, err) err = cmd.manageAdminList(snap, makeStep(t, FormArg, string(data2))) - require.ErrorContains(t, err, "doesn't have the permission to add admin") + require.ErrorContains(t, err, "The performing user is not an admin") // Now we add another admin but with a performing user that is already admin addAdmin2 = types.AddAdmin{dummyUID2, dummyUID} From bf030a2f5c8e7697b55f765aa7474a59d4221f8b Mon Sep 17 00:00:00 2001 From: Maxime Date: Thu, 23 May 2024 14:35:09 +0200 Subject: [PATCH 086/114] patch isAdmin structure --- contracts/evoting/evoting.go | 51 +++++++++++++++----------------- contracts/evoting/types/admin.go | 4 +-- 2 files changed, 26 insertions(+), 29 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index e7298fa8a..84cd0ffd0 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -66,17 +66,12 @@ func (e evotingCommand) createForm(snap store.Snapshot, step execution.Step) err } // Check if has Admin Right to create a form - adminList, err := e.getAdminList(snap) + isAdmin, _, err := e.isAdmin(snap, tx.UserID) if err != nil { - return xerrors.Errorf("failed to get AdminList: %v", err) + return err } - adminIndex, err := adminList.GetAdminIndex(tx.UserID) - if err != nil { - return xerrors.Errorf("Couldn't retrieve the admin right of the user: %v", err) - } - - if adminIndex < 0 { - return xerrors.Errorf("The user is not admin: %v", err) + if !isAdmin { + return xerrors.Errorf("The performing user is not an admin.") } roster, err := e.rosterFac.AuthorityOf(e.context, rosterBuf) @@ -786,7 +781,7 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step return xerrors.Errorf(errGetTransaction, err) } - var form types.AdminList + var list types.AdminList h := sha256.New() h.Write([]byte(AdminListId)) @@ -796,11 +791,12 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step txRemoveAdmin, okRemoveAdmin := msg.(types.RemoveAdmin) if okAddAdmin { - // Recover the AdminList stored on the blockchain - form, err = e.getAdminList(snap) + isAdmin, listRetrieved, err := e.isAdmin(snap, txAddAdmin.PerformingUserID) + list = listRetrieved if err != nil { // Exact string matching of the error - if err.Error() != "failed to get the AdminList: No form found" { + println("HEYO: " + err.Error()) + if err.Error() != "failed to get the AdminList: No list found" { return xerrors.Errorf("failed to get AdminList: %v", err) } @@ -820,26 +816,22 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step // Therefore return return nil } - - isAdmin, err := e.isAdmin(form, txAddAdmin.PerformingUserID) - if err != nil { - return err - } if !isAdmin { return xerrors.Errorf("The performing user is not an admin.") } - err = form.AddAdmin(txAddAdmin.TargetUserID) + err = list.AddAdmin(txAddAdmin.TargetUserID) if err != nil { return xerrors.Errorf("couldn't add admin: %v", err) } } else if okRemoveAdmin { - form, err = e.getAdminList(snap) + list, err = e.getAdminList(snap) if err != nil { return xerrors.Errorf("failed to get AdminList: %v", err) } - isAdmin, err := e.isAdmin(form, txRemoveAdmin.PerformingUserID) + isAdmin, listRetrieved, err := e.isAdmin(snap, txRemoveAdmin.PerformingUserID) + list = listRetrieved if err != nil { return err } @@ -847,7 +839,7 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step return xerrors.Errorf("The performing user is not an admin.") } - err = form.RemoveAdmin(txRemoveAdmin.TargetUserID) + err = list.RemoveAdmin(txRemoveAdmin.TargetUserID) if err != nil { return xerrors.Errorf("couldn't remove admin: %v", err) } @@ -855,7 +847,7 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step return xerrors.Errorf(errWrongTx, msg) } - formBuf, err := form.Serialize(e.context) + formBuf, err := list.Serialize(e.context) if err != nil { return xerrors.Errorf("failed to marshal Form : %v", err) } @@ -869,18 +861,23 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step } // isAdmin Check whether a user is in an Admin List -func (e evotingCommand) isAdmin(form types.AdminList, txPerformingUser string) (bool, error) { +func (e evotingCommand) isAdmin(snap store.Snapshot, txPerformingUser string) (bool, types.AdminList, error) { // If it found the AdminList // Check that the performing user is Admin + form, err := e.getAdminList(snap) + if err != nil { + return false, types.AdminList{}, err + } + performingUserPerm, err := form.GetAdminIndex(txPerformingUser) if err != nil { - return false, xerrors.Errorf("couldn't retrieve admin permission of the performing user: %v", err) + return false, form, xerrors.Errorf("couldn't retrieve admin permission of the performing user: %v", err) } if performingUserPerm < 0 { - return false, nil + return false, form, nil } - return true, nil + return true, form, nil } // initializeAdminList initialize an AdminList on the blockchain. It is called the first time that diff --git a/contracts/evoting/types/admin.go b/contracts/evoting/types/admin.go index 7bdcbffd1..8ebd96f32 100644 --- a/contracts/evoting/types/admin.go +++ b/contracts/evoting/types/admin.go @@ -99,10 +99,10 @@ func AdminListFromStore(ctx serde.Context, adminListFac serde.Factory, store sto adminListBuf, err := store.Get(adminListIDBuf) if err != nil { - return adminList, xerrors.Errorf("While getting data for form: %v", err) + return adminList, xerrors.Errorf("While getting data for list: %v", err) } if len(adminListBuf) == 0 { - return adminList, xerrors.Errorf("No form found") + return adminList, xerrors.Errorf("No list found") } message, err := adminListFac.Deserialize(ctx, adminListBuf) From c014c6ea96049c360742dc12c8537787d4077d8a Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Fri, 24 May 2024 15:18:37 +0200 Subject: [PATCH 087/114] Address review fixed comment change isAdmin to fetchAdmin remove useless getAdminList in manageAdminList cmd --- contracts/evoting/evoting.go | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 84cd0ffd0..dab60bb40 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -66,7 +66,7 @@ func (e evotingCommand) createForm(snap store.Snapshot, step execution.Step) err } // Check if has Admin Right to create a form - isAdmin, _, err := e.isAdmin(snap, tx.UserID) + isAdmin, _, err := e.fetchAdmin(snap, tx.UserID) if err != nil { return err } @@ -791,11 +791,10 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step txRemoveAdmin, okRemoveAdmin := msg.(types.RemoveAdmin) if okAddAdmin { - isAdmin, listRetrieved, err := e.isAdmin(snap, txAddAdmin.PerformingUserID) + isAdmin, listRetrieved, err := e.fetchAdmin(snap, txAddAdmin.PerformingUserID) list = listRetrieved if err != nil { // Exact string matching of the error - println("HEYO: " + err.Error()) if err.Error() != "failed to get the AdminList: No list found" { return xerrors.Errorf("failed to get AdminList: %v", err) } @@ -825,12 +824,7 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step return xerrors.Errorf("couldn't add admin: %v", err) } } else if okRemoveAdmin { - list, err = e.getAdminList(snap) - if err != nil { - return xerrors.Errorf("failed to get AdminList: %v", err) - } - - isAdmin, listRetrieved, err := e.isAdmin(snap, txRemoveAdmin.PerformingUserID) + isAdmin, listRetrieved, err := e.fetchAdmin(snap, txRemoveAdmin.PerformingUserID) list = listRetrieved if err != nil { return err @@ -860,8 +854,8 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step return nil } -// isAdmin Check whether a user is in an Admin List -func (e evotingCommand) isAdmin(snap store.Snapshot, txPerformingUser string) (bool, types.AdminList, error) { +// fetchAdmin Check whether a user is in an Admin List +func (e evotingCommand) fetchAdmin(snap store.Snapshot, txPerformingUser string) (bool, types.AdminList, error) { // If it found the AdminList // Check that the performing user is Admin form, err := e.getAdminList(snap) From 7f070acb6d3c2c330c79c6e2d85996c7f2ad2562 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Mon, 27 May 2024 23:18:26 +0200 Subject: [PATCH 088/114] first version of ownersvoters logic --- contracts/evoting/evoting.go | 126 ++++++++++++++++++++++++++ contracts/evoting/json/transaction.go | 3 + contracts/evoting/mod_test.go | 96 ++++++++------------ 3 files changed, 167 insertions(+), 58 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index dab60bb40..8a58195f3 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -9,6 +9,7 @@ import ( "encoding/hex" "encoding/json" "math/rand" + "slices" "strings" "go.dedis.ch/dela" @@ -33,6 +34,9 @@ const ( shufflingProtocolName = "PairShuffle" errGetTransaction = "failed to get transaction: %v" errGetForm = "failed to get form: %v" + errIsRole = "failed check the permission: %v" + errNoOwnerPerms = "The user %v doesn't have the Owner permission on the form." + errNoVoterPerms = "The user %v doesn't have the Voter permission on the form." errWrongTx = "wrong type of transaction: %T" ) @@ -45,6 +49,13 @@ type evotingCommand struct { prover prover } +type Role int + +const ( + Voters Role = iota + 1 + Owners +) + type prover func(suite proof.Suite, protocolName string, verifier proof.Verifier, proof []byte) error // createForm implements commands. It performs the CREATE_FORM command @@ -195,6 +206,15 @@ func (e evotingCommand) openForm(snap store.Snapshot, step execution.Step) error return xerrors.Errorf(errGetForm, err) } + isOwner, err := e.isRole(form, tx.UserID, Owners) + if err != nil { + return xerrors.Errorf(errIsRole, err) + } + + if !isOwner { + return xerrors.Errorf(errNoOwnerPerms, tx.UserID) + } + if form.Status != types.Initial { return xerrors.Errorf("the form was opened before, current status: %d", form.Status) } @@ -253,6 +273,15 @@ func (e evotingCommand) castVote(snap store.Snapshot, step execution.Step) error return xerrors.Errorf("the form is not open, current status: %d", form.Status) } + isOwner, err := e.isRole(form, tx.VoterID, Voters) + if err != nil { + return xerrors.Errorf(errIsRole, err) + } + + if !isOwner { + return xerrors.Errorf(errNoVoterPerms, tx.VoterID) + } + if len(tx.Ballot) != form.ChunksPerBallot() { return xerrors.Errorf("the ballot has unexpected length: %d != %d", len(tx.Ballot), form.ChunksPerBallot()) @@ -306,6 +335,15 @@ func (e evotingCommand) shuffleBallots(snap store.Snapshot, step execution.Step) form.Status, types.Closed) } + isOwner, err := e.isRole(form, tx.UserID, Owners) + if err != nil { + return xerrors.Errorf(errIsRole, err) + } + + if !isOwner { + return xerrors.Errorf(errNoOwnerPerms, tx.UserID) + } + // Round starts at 0 expectedRound := len(form.ShuffleInstances) @@ -504,6 +542,15 @@ func (e evotingCommand) closeForm(snap store.Snapshot, step execution.Step) erro return xerrors.Errorf("the form is not open, current status: %d", form.Status) } + isOwner, err := e.isRole(form, tx.UserID, Owners) + if err != nil { + return xerrors.Errorf(errIsRole, err) + } + + if !isOwner { + return xerrors.Errorf(errNoOwnerPerms, tx.UserID) + } + if form.BallotCount <= 1 { return xerrors.Errorf("at least two ballots are required") } @@ -659,6 +706,15 @@ func (e evotingCommand) combineShares(snap store.Snapshot, step execution.Step) " current status: %d", form.Status) } + isOwner, err := e.isRole(form, tx.UserID, Owners) + if err != nil { + return xerrors.Errorf(errIsRole, err) + } + + if !isOwner { + return xerrors.Errorf(errNoOwnerPerms, tx.UserID) + } + allPubShares := form.PubsharesUnits.Pubshares shufflesSize := len(form.ShuffleInstances) @@ -727,6 +783,15 @@ func (e evotingCommand) cancelForm(snap store.Snapshot, step execution.Step) err return xerrors.Errorf(errGetForm, err) } + isOwner, err := e.isRole(form, tx.UserID, Owners) + if err != nil { + return xerrors.Errorf(errIsRole, err) + } + + if !isOwner { + return xerrors.Errorf(errNoOwnerPerms, tx.UserID) + } + form.Status = types.Canceled PromFormStatus.WithLabelValues(form.FormID).Set(float64(form.Status)) @@ -761,6 +826,15 @@ func (e evotingCommand) deleteForm(snap store.Snapshot, step execution.Step) err return xerrors.Errorf(errGetForm, err) } + isOwner, err := e.isRole(form, tx.UserID, Owners) + if err != nil { + return xerrors.Errorf(errIsRole, err) + } + + if !isOwner { + return xerrors.Errorf(errNoOwnerPerms, tx.UserID) + } + err = snap.Delete(formID) if err != nil { return xerrors.Errorf("failed to delete form: %v", err) @@ -854,6 +928,22 @@ func (e evotingCommand) manageAdminList(snap store.Snapshot, step execution.Step return nil } +// isRole check whether the txPerformingUser has the role in the provided form +func (e evotingCommand) isRole(form types.Form, txPerformingUser string, role Role) (bool, error) { + sciperInt, err := types.SciperToInt(txPerformingUser) + if err != nil { + return false, xerrors.Errorf("Failed to convert SCIPER to int: %v", err) + } + + if role == Voters && slices.Contains(form.Voters, sciperInt) { + return true, nil + } else if role == Owners && slices.Contains(form.Owners, sciperInt) { + return true, nil + } + + return false, nil +} + // fetchAdmin Check whether a user is in an Admin List func (e evotingCommand) fetchAdmin(snap store.Snapshot, txPerformingUser string) (bool, types.AdminList, error) { // If it found the AdminList @@ -925,6 +1015,15 @@ func (e evotingCommand) manageOwnersVotersForm(snap store.Snapshot, step executi return xerrors.Errorf(errGetForm, err) } + isOwner, err := e.isRole(form, txAddVoter.PerformingUserID, Owners) + if err != nil { + return xerrors.Errorf(errIsRole, err) + } + + if !isOwner { + return xerrors.Errorf(errNoOwnerPerms, txAddVoter.PerformingUserID) + } + err = form.AddVoter(txAddVoter.TargetUserID) if err != nil { return xerrors.Errorf("couldn't add voter: %v", err) @@ -935,6 +1034,15 @@ func (e evotingCommand) manageOwnersVotersForm(snap store.Snapshot, step executi return xerrors.Errorf(errGetForm, err) } + isOwner, err := e.isRole(form, txRemoveVoter.PerformingUserID, Owners) + if err != nil { + return xerrors.Errorf(errIsRole, err) + } + + if !isOwner { + return xerrors.Errorf(errNoOwnerPerms, txRemoveVoter.PerformingUserID) + } + err = form.RemoveVoter(txRemoveVoter.TargetUserID) if err != nil { return xerrors.Errorf("couldn't remove voter: %v", err) @@ -945,6 +1053,15 @@ func (e evotingCommand) manageOwnersVotersForm(snap store.Snapshot, step executi return xerrors.Errorf(errGetForm, err) } + isOwner, err := e.isRole(form, txAddOwner.PerformingUserID, Owners) + if err != nil { + return xerrors.Errorf(errIsRole, err) + } + + if !isOwner { + return xerrors.Errorf(errNoOwnerPerms, txAddOwner.PerformingUserID) + } + err = form.AddOwner(txAddOwner.TargetUserID) if err != nil { return xerrors.Errorf("couldn't add owner: %v", err) @@ -955,6 +1072,15 @@ func (e evotingCommand) manageOwnersVotersForm(snap store.Snapshot, step executi return xerrors.Errorf(errGetForm, err) } + isOwner, err := e.isRole(form, txRemoveOwner.PerformingUserID, Owners) + if err != nil { + return xerrors.Errorf(errIsRole, err) + } + + if !isOwner { + return xerrors.Errorf(errNoOwnerPerms, txRemoveOwner.PerformingUserID) + } + err = form.RemoveOwner(txRemoveOwner.TargetUserID) if err != nil { return xerrors.Errorf("couldn't remove owner: %v", err) diff --git a/contracts/evoting/json/transaction.go b/contracts/evoting/json/transaction.go index f56a67627..792369bdf 100644 --- a/contracts/evoting/json/transaction.go +++ b/contracts/evoting/json/transaction.go @@ -71,6 +71,7 @@ func (transactionFormat) Encode(ctx serde.Context, msg serde.Message) ([]byte, e Proof: t.Proof, Signature: t.Signature, PublicKey: t.PublicKey, + UserID: t.UserID, } m = TransactionJSON{ShuffleBallots: &sb} @@ -327,6 +328,7 @@ type ShuffleBallotsJSON struct { Proof []byte Signature []byte PublicKey []byte + UserID string } type RegisterPubSharesJSON struct { @@ -453,6 +455,7 @@ func decodeShuffleBallots(ctx serde.Context, m ShuffleBallotsJSON) (serde.Messag Proof: m.Proof, Signature: m.Signature, PublicKey: m.PublicKey, + UserID: m.UserID, }, nil } diff --git a/contracts/evoting/mod_test.go b/contracts/evoting/mod_test.go index 54f1d5aa3..8c4d80df8 100644 --- a/contracts/evoting/mod_test.go +++ b/contracts/evoting/mod_test.go @@ -188,12 +188,16 @@ func TestCommand_OpenForm(t *testing.T) { // TODO } +/* + Testing Scenario: + - TODO +*/ func TestCommand_CastVote(t *testing.T) { initMetrics() castVote := types.CastVote{ FormID: fakeFormID, - VoterID: "dummyVoterId", + VoterID: dummyUserAdminID, Ballot: types.Ciphervote{types.EGPair{ K: suite.Point(), C: suite.Point(), @@ -203,7 +207,7 @@ func TestCommand_CastVote(t *testing.T) { data, err := castVote.Serialize(ctx) require.NoError(t, err) - dummyForm, contract := initFormAndContract() + dummyForm, contract := initFormAndContract(123456) formBuf, err := dummyForm.Serialize(ctx) require.NoError(t, err) @@ -243,6 +247,15 @@ func TestCommand_CastVote(t *testing.T) { err = snap.Set(dummyFormIDBuff, formBuf) require.NoError(t, err) + err = cmd.castVote(snap, makeStep(t, FormArg, string(data))) + require.EqualError(t, err, "The user 123456 doesn't have the Voter permission on the form.") + + addVoter := types.AddVoter{FormID: fakeFormID, TargetUserID: dummyUserAdminID, PerformingUserID: dummyUserAdminID} + dataAddVoter, err := addVoter.Serialize(ctx) + require.NoError(t, err) + err = cmd.manageOwnersVotersForm(snap, makeStep(t, FormArg, string(dataAddVoter))) + require.NoError(t, err) + err = cmd.castVote(snap, makeStep(t, FormArg, string(data))) require.EqualError(t, err, "the ballot has unexpected length: 1 != 0") @@ -299,6 +312,9 @@ func TestCommand_CastVote(t *testing.T) { data, err = castVote.Serialize(ctx) require.NoError(t, err) + err = cmd.manageOwnersVotersForm(snap, makeStep(t, FormArg, string(dataAddVoter))) + require.NoError(t, err) + err = cmd.castVote(snap, makeStep(t, FormArg, string(data))) require.NoError(t, err) @@ -331,7 +347,7 @@ func TestCommand_CloseForm(t *testing.T) { data, err := closeForm.Serialize(ctx) require.NoError(t, err) - dummyForm, contract := initFormAndContract() + dummyForm, contract := initFormAndContract(123456) dummyForm.FormID = fakeFormID formBuf, err := dummyForm.Serialize(ctx) @@ -360,8 +376,6 @@ func TestCommand_CloseForm(t *testing.T) { err = snap.Set(dummyFormIDBuff, formBuf) require.NoError(t, err) - closeForm.UserID = hex.EncodeToString([]byte("123456")) - data, err = closeForm.Serialize(ctx) require.NoError(t, err) @@ -754,7 +768,7 @@ func TestCommand_RegisterPubShares(t *testing.T) { data, err := registerPubShares.Serialize(ctx) require.NoError(t, err) - form, contract := initFormAndContract() + form, contract := initFormAndContract(123456) form.FormID = fakeFormID formBuf, err := form.Serialize(ctx) @@ -955,7 +969,7 @@ func TestCommand_DecryptBallots(t *testing.T) { data, err := decryptBallot.Serialize(ctx) require.NoError(t, err) - dummyForm, contract := initFormAndContract() + dummyForm, contract := initFormAndContract(123456) formBuf, err := dummyForm.Serialize(ctx) require.NoError(t, err) @@ -983,8 +997,6 @@ func TestCommand_DecryptBallots(t *testing.T) { err = snap.Set(dummyFormIDBuff, formBuf) require.NoError(t, err) - decryptBallot.UserID = hex.EncodeToString([]byte("dummyAdminID")) - data, err = decryptBallot.Serialize(ctx) require.NoError(t, err) @@ -1053,7 +1065,7 @@ func TestCommand_CancelForm(t *testing.T) { data, err := cancelForm.Serialize(ctx) require.NoError(t, err) - dummyForm, contract := initFormAndContract() + dummyForm, contract := initFormAndContract(123456) dummyForm.FormID = fakeFormID formBuf, err := dummyForm.Serialize(ctx) @@ -1082,8 +1094,6 @@ func TestCommand_CancelForm(t *testing.T) { err = snap.Set(dummyFormIDBuff, formBuf) require.NoError(t, err) - cancelForm.UserID = hex.EncodeToString([]byte("dummyAdminID")) - data, err = cancelForm.Serialize(ctx) require.NoError(t, err) @@ -1123,7 +1133,7 @@ func TestRegisterContract(t *testing.T) { func TestCommand_AdminList(t *testing.T) { initMetrics() - dummyForm, contract := initFormAndContract() + dummyForm, contract := initFormAndContract(123456) dummyForm.FormID = fakeFormID // Initialize the command handler to post on the ledger @@ -1253,23 +1263,14 @@ func TestCommand_AdminList(t *testing.T) { /* Testing Scenario: - - We check that the owner field is empty - - We add user: 123456 + - We initialize a form with user 123456 as owner - We check that 123456 is owner - We try to remove it. -> failure cause is the only owner. - We add a second user: 234567 - Now we can remove ownership to: 123456 */ func TestCommand_OwnerForm(t *testing.T) { - addOwner := types.AddOwner{ - FormID: fakeFormID, - TargetUserID: dummyUserAdminID, - PerformingUserID: dummyUserAdminID, - } - - // Test Serialization of AddOwner command - dataAdd, err := addOwner.Serialize(ctx) - require.NoError(t, err) + dummyUser := 654321 removeOwner := types.RemoveOwner{ FormID: fakeFormID, @@ -1282,7 +1283,7 @@ func TestCommand_OwnerForm(t *testing.T) { require.NoError(t, err) // Initialize the form and contract chain - dummyForm, contract := initFormAndContract() + dummyForm, contract := initFormAndContract(123456) dummyForm.FormID = fakeFormID // Test the serialization of the Ledger @@ -1305,11 +1306,6 @@ func TestCommand_OwnerForm(t *testing.T) { err = cmd.manageOwnersVotersForm(fake.NewSnapshot(), makeStep(t, FormArg, "dummy")) require.EqualError(t, err, unmarshalTransactionErr) - // Checking that given a Blockchain that always returns an error with - // an Add cmd, it will not be able to retrieve the Form on the store. - err = cmd.manageOwnersVotersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataAdd))) - require.ErrorContains(t, err, "failed to get key") - // Checking that given a Blockchain that always returns an error with // a Remove cmd, it will not be able to retrieve the Form on the store. err = cmd.manageOwnersVotersForm(fake.NewBadSnapshot(), makeStep(t, FormArg, string(dataRemove))) @@ -1320,7 +1316,7 @@ func TestCommand_OwnerForm(t *testing.T) { snap := fake.NewSnapshot() err = snap.Set(dummyFormIDBuff, invalidForm) require.NoError(t, err) - err = cmd.manageOwnersVotersForm(snap, makeStep(t, FormArg, string(dataAdd))) + err = cmd.manageOwnersVotersForm(snap, makeStep(t, FormArg, string(dataRemove))) require.ErrorContains(t, err, deserializeErr) // ==== @@ -1331,7 +1327,7 @@ func TestCommand_OwnerForm(t *testing.T) { err = snap.Set(dummyFormIDBuff, formBuf) require.NoError(t, err) - // We retrieve the Admin Form from the ledger. + // Let's see if the owner was set successfully at the form creation res, err := snap.Get(dummyFormIDBuff) require.NoError(t, err) @@ -1341,26 +1337,8 @@ func TestCommand_OwnerForm(t *testing.T) { form, ok := message.(types.Form) require.True(t, ok) - // We check that now our dummy user is not owner yet (return -1) - dummyUserOwnerIndex, _ := form.GetOwnerIndex(dummyUserAdminID) - require.True(t, dummyUserOwnerIndex == -1) - - // We perform the Add command on the ledger - err = cmd.manageOwnersVotersForm(snap, makeStep(t, FormArg, string(dataAdd))) - require.NoError(t, err) - - // Let's see if it added the owner successfully - res, err = snap.Get(dummyFormIDBuff) - require.NoError(t, err) - - message, err = formFac.Deserialize(ctx, res) - require.NoError(t, err) - - form, ok = message.(types.Form) - require.True(t, ok) - // We check that now our dummy user is an owner (return 0) - dummyUserOwnerIndex, _ = form.GetOwnerIndex(dummyUserAdminID) + dummyUserOwnerIndex, _ := form.GetOwnerIndex(dummyUserAdminID) require.True(t, dummyUserOwnerIndex == 0) // Now let's remove it @@ -1373,8 +1351,8 @@ func TestCommand_OwnerForm(t *testing.T) { // So first let's add a second owner addOwner2 := types.AddOwner{ FormID: fakeFormID, - TargetUserID: "234567", - PerformingUserID: "234567", + TargetUserID: strconv.Itoa(dummyUser), + PerformingUserID: dummyUserAdminID, } // Test Serialization of AddOwner command @@ -1395,7 +1373,7 @@ func TestCommand_OwnerForm(t *testing.T) { require.True(t, ok) // We check that now our second dummy user is also an owner (return 0). - secondDummyUserOwnerIndex, _ := form.GetOwnerIndex("234567") + secondDummyUserOwnerIndex, _ := form.GetOwnerIndex(strconv.Itoa(dummyUser)) require.True(t, secondDummyUserOwnerIndex == 1) // Now remove successfully the first one. @@ -1416,7 +1394,7 @@ func TestCommand_OwnerForm(t *testing.T) { dummyUserOwnerIndex, _ = form.GetOwnerIndex(dummyUserAdminID) require.True(t, dummyUserOwnerIndex == -1) // But that the second one is still an admin (return != -1) - secondDummyUserOwnerIndex, _ = form.GetOwnerIndex("234567") + secondDummyUserOwnerIndex, _ = form.GetOwnerIndex(strconv.Itoa(dummyUser)) require.True(t, secondDummyUserOwnerIndex != -1) } @@ -1449,7 +1427,7 @@ func TestCommand_VoterForm(t *testing.T) { require.NoError(t, err) // Initialize the form and contract chain - dummyForm, contract := initFormAndContract() + dummyForm, contract := initFormAndContract(123456) dummyForm.FormID = fakeFormID // Test the serialization of the Ledger @@ -1564,7 +1542,7 @@ func initMetrics() { PromFormPubShares.Reset() } -func initFormAndContract() (types.Form, Contract) { +func initFormAndContract(initialOwner int) (types.Form, Contract) { fakeDkg := fakeDKG{ actor: fakeDkgActor{}, err: nil, @@ -1578,6 +1556,7 @@ func initFormAndContract() (types.Form, Contract) { DecryptedBallots: nil, ShuffleThreshold: 0, Roster: fake.Authority{}, + Owners: []int{initialOwner}, } service := fakeAccess{err: fake.GetError()} @@ -1659,9 +1638,10 @@ func initBadShuffleBallot(sizeOfForm int) (types.Form, types.ShuffleBallots, Con ShuffledBallots: shuffledBallots, Proof: nil, PublicKey: FakePubKeyMarshalled, + UserID: dummyUserAdminID, } - form, contract := initFormAndContract() + form, contract := initFormAndContract(123456) return form, shuffleBallots, contract } From b291e3783820c45daecad0c141976ee6ac7e4246 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Mon, 27 May 2024 23:25:33 +0200 Subject: [PATCH 089/114] remove slices package and replace it by hand implemented method --- contracts/evoting/evoting.go | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/contracts/evoting/evoting.go b/contracts/evoting/evoting.go index 8a58195f3..5ac952d30 100644 --- a/contracts/evoting/evoting.go +++ b/contracts/evoting/evoting.go @@ -9,7 +9,6 @@ import ( "encoding/hex" "encoding/json" "math/rand" - "slices" "strings" "go.dedis.ch/dela" @@ -935,10 +934,18 @@ func (e evotingCommand) isRole(form types.Form, txPerformingUser string, role Ro return false, xerrors.Errorf("Failed to convert SCIPER to int: %v", err) } - if role == Voters && slices.Contains(form.Voters, sciperInt) { - return true, nil - } else if role == Owners && slices.Contains(form.Owners, sciperInt) { - return true, nil + if role == Voters { + for i := 0; i < len(form.Voters); i++ { + if form.Voters[i] == sciperInt { + return true, nil + } + } + } else if role == Owners { + for i := 0; i < len(form.Owners); i++ { + if form.Owners[i] == sciperInt { + return true, nil + } + } } return false, nil From fbbed41bff9486d193673fdfe667aa82e0973688 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Tue, 28 May 2024 10:28:44 +0200 Subject: [PATCH 090/114] patch integration test for createform and openform --- contracts/evoting/json/transaction.go | 3 +++ integration/ballot.go | 29 +++++++++++++++++++++++++-- integration/form.go | 3 ++- integration/integration_test.go | 13 ++++++------ integration/performance_test.go | 2 +- integration/votes_test.go | 10 ++++----- 6 files changed, 44 insertions(+), 16 deletions(-) diff --git a/contracts/evoting/json/transaction.go b/contracts/evoting/json/transaction.go index 792369bdf..495da3cec 100644 --- a/contracts/evoting/json/transaction.go +++ b/contracts/evoting/json/transaction.go @@ -28,6 +28,7 @@ func (transactionFormat) Encode(ctx serde.Context, msg serde.Message) ([]byte, e case types.OpenForm: oe := OpenFormJSON{ FormID: t.FormID, + UserID: t.UserID, } m = TransactionJSON{OpenForm: &oe} @@ -195,6 +196,7 @@ func (transactionFormat) Decode(ctx serde.Context, data []byte) (serde.Message, case m.OpenForm != nil: return types.OpenForm{ FormID: m.OpenForm.FormID, + UserID: m.OpenForm.UserID, }, nil case m.CastVote != nil: msg, err := decodeCastVote(ctx, *m.CastVote) @@ -304,6 +306,7 @@ type CreateFormJSON struct { // OpenFormJSON is the JSON representation of a OpenForm transaction type OpenFormJSON struct { FormID string + UserID string } // CastVoteJSON is the JSON representation of a CastVote transaction diff --git a/integration/ballot.go b/integration/ballot.go index 3fec5d5bb..e90cae3c9 100644 --- a/integration/ballot.go +++ b/integration/ballot.go @@ -44,7 +44,7 @@ func ballotIsNull(ballot types.Ballot) bool { // castVotesRandomly chooses numberOfVotes predefined ballots randomly // and cast them func castVotesRandomly(m txManager, actor dkg.Actor, form types.Form, - numberOfVotes int) ([]types.Ballot, error) { + numberOfVotes int, ownerID string) ([]types.Ballot, error) { possibleBallots := []string{ string("select:" + encodeID("bb") + ":0,0,1,0\n" + @@ -57,6 +57,31 @@ func castVotesRandomly(m txManager, actor dkg.Actor, form types.Form, votes := make([]types.Ballot, numberOfVotes) + for i := 0; i < numberOfVotes; i++ { + voterID := "11111" + strconv.Itoa(i) + addVoter := types.AddVoter{ + FormID: form.FormID, + TargetUserID: voterID, + PerformingUserID: ownerID, + } + + data, err := addVoter.Serialize(serdecontext) + if err != nil { + return nil, xerrors.Errorf("failed to serialize add voter: %v", err) + } + + args := []txn.Arg{ + {Key: native.ContractArg, Value: []byte(evoting.ContractName)}, + {Key: evoting.FormArg, Value: data}, + {Key: evoting.CmdArg, Value: []byte(evoting.CmdAddVoterForm)}, + } + + _, err = m.addAndWait(args...) + if err != nil { + return nil, xerrors.Errorf(addAndWaitErr, err) + } + } + for i := 0; i < numberOfVotes; i++ { randomIndex := rand.Intn(len(possibleBallots)) vote := possibleBallots[randomIndex] @@ -66,7 +91,7 @@ func castVotesRandomly(m txManager, actor dkg.Actor, form types.Form, return nil, xerrors.Errorf("failed to marshallBallot: %v", err) } - voterID := "user " + strconv.Itoa(i) + voterID := "11111" + strconv.Itoa(i) castVote := types.CastVote{ FormID: form.FormID, diff --git a/integration/form.go b/integration/form.go index 839aa08dc..090b54335 100644 --- a/integration/form.go +++ b/integration/form.go @@ -133,9 +133,10 @@ func createFormScenario(contentType, proxy string, secret kyber.Scalar, t *testi } // for integration tests -func openForm(m txManager, formID []byte) error { +func openForm(m txManager, formID []byte, userID string) error { openForm := &types.OpenForm{ FormID: hex.EncodeToString(formID), + UserID: userID, } data, err := openForm.Serialize(serdecontext) diff --git a/integration/integration_test.go b/integration/integration_test.go index 2310460ad..ad18f8f03 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -75,9 +75,8 @@ func getIntegrationTest(numNodes, numVotes int) func(*testing.T) { // ##### SETUP DKG ##### actor, err := initDkg(nodes, formID, m.m) require.NoError(t, err) - // ##### OPEN FORM ##### - err = openForm(m, formID) + err = openForm(m, formID, adminID) require.NoError(t, err) formFac := types.NewFormFactory(types.CiphervoteFactory{}, nodes[0].GetRosterFac()) @@ -86,7 +85,7 @@ func getIntegrationTest(numNodes, numVotes int) func(*testing.T) { form, err := getForm(formFac, formID, nodes[0].GetOrdering()) require.NoError(t, err) - castedVotes, err := castVotesRandomly(m, actor, form, numVotes) + castedVotes, err := castVotesRandomly(m, actor, form, numVotes, adminID) require.NoError(t, err) fmt.Println("casted votes:", castedVotes) @@ -220,7 +219,7 @@ func getIntegrationTestCrash(numNodes, numVotes, failingNodes int) func(*testing require.NoError(t, err) // ##### OPEN FORM ##### - err = openForm(m, formID) + err = openForm(m, formID, adminID) require.NoError(t, err) formFac := types.NewFormFactory(types.CiphervoteFactory{}, nodes[0].GetRosterFac()) @@ -241,7 +240,7 @@ func getIntegrationTestCrash(numNodes, numVotes, failingNodes int) func(*testing err = closeNodes(crashNodeList) require.NoError(t, err) - castedVotes, err := castVotesRandomly(m, actor, form, numVotes) + castedVotes, err := castVotesRandomly(m, actor, form, numVotes, adminID) require.NoError(t, err) fmt.Println("casted votes:", castedVotes) @@ -370,7 +369,7 @@ func getIntegrationBenchmark(numNodes, numVotes int) func(*testing.B) { require.NoError(b, err) // ##### OPEN FORM ##### - err = openForm(m, formID) + err = openForm(m, formID, adminID) require.NoError(b, err) formFac := types.NewFormFactory(types.CiphervoteFactory{}, nodes[0].GetRosterFac()) @@ -379,7 +378,7 @@ func getIntegrationBenchmark(numNodes, numVotes int) func(*testing.B) { form, err := getForm(formFac, formID, nodes[0].GetOrdering()) require.NoError(b, err) - castedVotes, err := castVotesRandomly(m, actor, form, numVotes) + castedVotes, err := castVotesRandomly(m, actor, form, numVotes, adminID) require.NoError(b, err) fmt.Println("casted votes:", castedVotes) diff --git a/integration/performance_test.go b/integration/performance_test.go index b8839d342..e933eff2e 100644 --- a/integration/performance_test.go +++ b/integration/performance_test.go @@ -87,7 +87,7 @@ func customVotesScenario(b *testing.B, stuffing bool) { require.NoError(b, err) // ##### OPEN FORM ##### - err = openForm(m, formID) + err = openForm(m, formID, adminID) require.NoError(b, err) formFac := types.NewFormFactory(types.CiphervoteFactory{}, nodes[0].GetRosterFac()) diff --git a/integration/votes_test.go b/integration/votes_test.go index 207798f18..621550634 100644 --- a/integration/votes_test.go +++ b/integration/votes_test.go @@ -69,7 +69,7 @@ func getIntegrationTestBadVote(numNodes, numVotes, numBadVotes int) func(*testin require.NoError(t, err) // ##### OPEN FORM ##### - err = openForm(m, formID) + err = openForm(m, formID, adminID) require.NoError(t, err) formFac := types.NewFormFactory(types.CiphervoteFactory{}, nodes[0].GetRosterFac()) @@ -80,7 +80,7 @@ func getIntegrationTestBadVote(numNodes, numVotes, numBadVotes int) func(*testin // cast a vote with wrong answers: Should not be taken into account - _, err = castVotesRandomly(m, actor, form, numVotes-numBadVotes) + _, err = castVotesRandomly(m, actor, form, numVotes-numBadVotes, adminID) require.NoError(t, err) err = castBadVote(m, actor, form, numBadVotes) @@ -207,7 +207,7 @@ func getIntegrationTestRevote(numNodes, numVotes, numRevotes int) func(*testing. require.NoError(t, err) // ##### OPEN FORM ##### - err = openForm(m, formID) + err = openForm(m, formID, adminID) require.NoError(t, err) formFac := types.NewFormFactory(types.CiphervoteFactory{}, nodes[0].GetRosterFac()) @@ -216,10 +216,10 @@ func getIntegrationTestRevote(numNodes, numVotes, numRevotes int) func(*testing. form, err := getForm(formFac, formID, nodes[0].GetOrdering()) require.NoError(t, err) - _, err = castVotesRandomly(m, actor, form, numVotes) + _, err = castVotesRandomly(m, actor, form, numVotes, adminID) require.NoError(t, err) - castedVotes, err := castVotesRandomly(m, actor, form, numRevotes) + castedVotes, err := castVotesRandomly(m, actor, form, numRevotes, adminID) require.NoError(t, err) fmt.Println("casted votes:", castedVotes) From c256b9e7d3b3ded8e405d79de9560013f9b5b870 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Tue, 28 May 2024 11:31:48 +0200 Subject: [PATCH 091/114] patch shuffle intergration test --- integration/ballot.go | 3 ++- integration/integration_test.go | 13 ++++++----- integration/performance_test.go | 4 ++-- integration/votes_test.go | 8 +++---- proxy/election.go | 23 +++++++++++++------- proxy/shuffle.go | 3 ++- services/shuffle/mod.go | 2 +- services/shuffle/neff/handler.go | 9 ++++---- services/shuffle/neff/json/mod.go | 8 ++++--- services/shuffle/neff/json/mod_test.go | 2 +- services/shuffle/neff/mod.go | 6 ++--- services/shuffle/neff/types/messages.go | 19 +++++++++++----- services/shuffle/neff/types/messages_test.go | 2 +- 13 files changed, 61 insertions(+), 41 deletions(-) diff --git a/integration/ballot.go b/integration/ballot.go index e90cae3c9..928e4cda8 100644 --- a/integration/ballot.go +++ b/integration/ballot.go @@ -208,13 +208,14 @@ func marshallBallot(vote io.Reader, actor dkg.Actor, chunks int) (types.Ciphervo return ballot, nil } -func decryptBallots(m txManager, actor dkg.Actor, form types.Form) error { +func decryptBallots(m txManager, actor dkg.Actor, form types.Form, userID string) error { if form.Status != types.PubSharesSubmitted { return xerrors.Errorf("cannot decrypt: not all pubShares submitted") } decryptBallots := types.CombineShares{ FormID: form.FormID, + UserID: userID, } data, err := decryptBallots.Serialize(serdecontext) diff --git a/integration/integration_test.go b/integration/integration_test.go index ad18f8f03..73877fc87 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -106,7 +106,7 @@ func getIntegrationTest(numNodes, numVotes int) func(*testing.T) { time.Sleep(time.Second * 1) t.Logf("shuffling") - err = sActor.Shuffle(formID) + err = sActor.Shuffle(formID, adminID) require.NoError(t, err) err = waitForStatus(types.ShuffledBallots, formFac, formID, nodes, @@ -131,7 +131,7 @@ func getIntegrationTest(numNodes, numVotes int) func(*testing.T) { form, err = getForm(formFac, formID, nodes[0].GetOrdering()) t.Logf("PubsharesUnit: %v", form.PubsharesUnits) require.NoError(t, err) - err = decryptBallots(m, actor, form) + err = decryptBallots(m, actor, form, adminID) require.NoError(t, err) err = waitForStatus(types.ResultAvailable, formFac, formID, nodes, @@ -170,6 +170,7 @@ func getIntegrationTest(numNodes, numVotes int) func(*testing.T) { fmt.Println("test done") } + } func getIntegrationTestCrash(numNodes, numVotes, failingNodes int) func(*testing.T) { @@ -261,7 +262,7 @@ func getIntegrationTestCrash(numNodes, numVotes, failingNodes int) func(*testing time.Sleep(time.Second * 1) t.Logf("shuffling") - err = sActor.Shuffle(formID) + err = sActor.Shuffle(formID, adminID) // If the number of failing nodes is greater // than the threshold, the shuffle will fail @@ -298,7 +299,7 @@ func getIntegrationTestCrash(numNodes, numVotes, failingNodes int) func(*testing t.Logf("PubsharesUnit: %v", form.PubsharesUnits) require.NoError(t, err) // Heisenbug: https://github.com/c4dt/d-voting/issues/90 - err = decryptBallots(m, actor, form) + err = decryptBallots(m, actor, form, adminID) require.NoError(t, err) err = waitForStatus(types.ResultAvailable, formFac, formID, nodes, @@ -397,7 +398,7 @@ func getIntegrationBenchmark(numNodes, numVotes int) func(*testing.B) { time.Sleep(time.Second * 1) - err = sActor.Shuffle(formID) + err = sActor.Shuffle(formID, adminID) require.NoError(b, err) err = waitForStatus(types.ShuffledBallots, formFac, formID, nodes, @@ -421,7 +422,7 @@ func getIntegrationBenchmark(numNodes, numVotes int) func(*testing.B) { form, err = getForm(formFac, formID, nodes[0].GetOrdering()) b.Logf("PubsharesUnit: %v", form.PubsharesUnits) require.NoError(b, err) - err = decryptBallots(m, actor, form) + err = decryptBallots(m, actor, form, adminID) require.NoError(b, err) err = waitForStatus(types.ResultAvailable, formFac, formID, nodes, diff --git a/integration/performance_test.go b/integration/performance_test.go index e933eff2e..1c8a294c8 100644 --- a/integration/performance_test.go +++ b/integration/performance_test.go @@ -117,7 +117,7 @@ func customVotesScenario(b *testing.B, stuffing bool) { require.NoError(b, err) b.Logf("shuffling") - err = sActor.Shuffle(formID) + err = sActor.Shuffle(formID, adminID) require.NoError(b, err) durationShuffling := b.Elapsed() @@ -146,7 +146,7 @@ func customVotesScenario(b *testing.B, stuffing bool) { require.NoError(b, err) b.ResetTimer() - err = decryptBallots(m, actor, form) + err = decryptBallots(m, actor, form, adminID) require.NoError(b, err) durationDecrypt := b.Elapsed() diff --git a/integration/votes_test.go b/integration/votes_test.go index 621550634..fe151a9e9 100644 --- a/integration/votes_test.go +++ b/integration/votes_test.go @@ -102,7 +102,7 @@ func getIntegrationTestBadVote(numNodes, numVotes, numBadVotes int) func(*testin time.Sleep(time.Second * 1) t.Logf("shuffling") - err = sActor.Shuffle(formID) + err = sActor.Shuffle(formID, adminID) require.NoError(t, err) err = waitForStatus(types.ShuffledBallots, formFac, formID, nodes, @@ -127,7 +127,7 @@ func getIntegrationTestBadVote(numNodes, numVotes, numBadVotes int) func(*testin form, err = getForm(formFac, formID, nodes[0].GetOrdering()) t.Logf("PubsharesUnit: %v", form.PubsharesUnits) require.NoError(t, err) - err = decryptBallots(m, actor, form) + err = decryptBallots(m, actor, form, adminID) require.NoError(t, err) err = waitForStatus(types.ResultAvailable, formFac, formID, nodes, @@ -240,7 +240,7 @@ func getIntegrationTestRevote(numNodes, numVotes, numRevotes int) func(*testing. time.Sleep(time.Second * 1) t.Logf("shuffling") - err = sActor.Shuffle(formID) + err = sActor.Shuffle(formID, adminID) require.NoError(t, err) err = waitForStatus(types.ShuffledBallots, formFac, formID, nodes, @@ -265,7 +265,7 @@ func getIntegrationTestRevote(numNodes, numVotes, numRevotes int) func(*testing. form, err = getForm(formFac, formID, nodes[0].GetOrdering()) t.Logf("PubsharesUnit: %v", form.PubsharesUnits) require.NoError(t, err) - err = decryptBallots(m, actor, form) + err = decryptBallots(m, actor, form, adminID) require.NoError(t, err) err = waitForStatus(types.ResultAvailable, formFac, formID, nodes, diff --git a/proxy/election.go b/proxy/election.go index 842766c4f..caf019185 100644 --- a/proxy/election.go +++ b/proxy/election.go @@ -248,6 +248,7 @@ func (h *form) EditForm(w http.ResponseWriter, r *http.Request) { } formID := vars["formID"] + userID := vars["userID"] elecMD, err := h.getFormsMetadata() if err != nil { @@ -263,13 +264,13 @@ func (h *form) EditForm(w http.ResponseWriter, r *http.Request) { switch req.Action { case "open": - h.openForm(formID, w, r) + h.openForm(formID, userID, w, r) case "close": - h.closeForm(formID, w, r) + h.closeForm(formID, userID, w, r) case "combineShares": - h.combineShares(formID, w, r) + h.combineShares(formID, userID, w, r) case "cancel": - h.cancelForm(formID, w, r) + h.cancelForm(formID, userID, w, r) default: BadRequestError(w, r, xerrors.Errorf("invalid action: %s", req.Action), nil) return @@ -278,9 +279,10 @@ func (h *form) EditForm(w http.ResponseWriter, r *http.Request) { // openForm allows opening a form, which sets the public key based on // the DKG actor. -func (h *form) openForm(formID string, w http.ResponseWriter, r *http.Request) { +func (h *form) openForm(formID string, userID string, w http.ResponseWriter, r *http.Request) { openForm := types.OpenForm{ FormID: formID, + UserID: userID, } // serialize the transaction @@ -303,10 +305,11 @@ func (h *form) openForm(formID string, w http.ResponseWriter, r *http.Request) { } // closeForm closes a form. -func (h *form) closeForm(formIDHex string, w http.ResponseWriter, r *http.Request) { +func (h *form) closeForm(formIDHex string, userID string, w http.ResponseWriter, r *http.Request) { closeForm := types.CloseForm{ FormID: formIDHex, + UserID: userID, } // serialize the transaction @@ -330,7 +333,7 @@ func (h *form) closeForm(formIDHex string, w http.ResponseWriter, r *http.Reques } // combineShares decrypts the shuffled ballots in a form. -func (h *form) combineShares(formIDHex string, w http.ResponseWriter, r *http.Request) { +func (h *form) combineShares(formIDHex string, userID string, w http.ResponseWriter, r *http.Request) { form, err := types.FormFromStore(h.context, h.formFac, formIDHex, h.orderingSvc.GetStore()) if err != nil { @@ -346,6 +349,7 @@ func (h *form) combineShares(formIDHex string, w http.ResponseWriter, r *http.Re decryptBallots := types.CombineShares{ FormID: formIDHex, + UserID: userID, } // serialize the transaction @@ -368,10 +372,11 @@ func (h *form) combineShares(formIDHex string, w http.ResponseWriter, r *http.Re } // cancelForm cancels a form. -func (h *form) cancelForm(formIDHex string, w http.ResponseWriter, r *http.Request) { +func (h *form) cancelForm(formIDHex string, userID string, w http.ResponseWriter, r *http.Request) { cancelForm := types.CancelForm{ FormID: formIDHex, + UserID: userID, } // serialize the transaction @@ -517,6 +522,7 @@ func (h *form) DeleteForm(w http.ResponseWriter, r *http.Request) { } formID := vars["formID"] + userID := vars["userID"] elecMD, err := h.getFormsMetadata() if err != nil { @@ -549,6 +555,7 @@ func (h *form) DeleteForm(w http.ResponseWriter, r *http.Request) { deleteForm := types.DeleteForm{ FormID: formID, + UserID: userID, } data, err := deleteForm.Serialize(h.context) diff --git a/proxy/shuffle.go b/proxy/shuffle.go index ef9466890..9554cae13 100644 --- a/proxy/shuffle.go +++ b/proxy/shuffle.go @@ -57,6 +57,7 @@ func (s shuffle) EditShuffle(w http.ResponseWriter, r *http.Request) { } formID := vars["formID"] + userID := vars["userID"] formIDBuf, err := hex.DecodeString(formID) if err != nil { @@ -67,7 +68,7 @@ func (s shuffle) EditShuffle(w http.ResponseWriter, r *http.Request) { switch req.Action { // shuffle the ballots case "shuffle": - err = s.actor.Shuffle(formIDBuf) + err = s.actor.Shuffle(formIDBuf, userID) if err != nil { http.Error(w, "failed to shuffle: "+err.Error(), http.StatusInternalServerError) return diff --git a/services/shuffle/mod.go b/services/shuffle/mod.go index f06f0254b..9ed31ab76 100644 --- a/services/shuffle/mod.go +++ b/services/shuffle/mod.go @@ -15,5 +15,5 @@ type Shuffle interface { type Actor interface { // Shuffle must be called by ONE of the actor to shuffle the list of ElGamal // pairs. Each node represented by a player must first execute Listen(). - Shuffle(formID []byte) (err error) + Shuffle(formID []byte, userID string) (err error) } diff --git a/services/shuffle/neff/handler.go b/services/shuffle/neff/handler.go index b7382a7b8..7412a728c 100644 --- a/services/shuffle/neff/handler.go +++ b/services/shuffle/neff/handler.go @@ -70,7 +70,7 @@ func (h *Handler) Stream(out mino.Sender, in mino.Receiver) error { switch msg := msg.(type) { case types.StartShuffle: - err := h.handleStartShuffle(msg.GetFormId()) + err := h.handleStartShuffle(msg.GetFormID(), msg.GetUserID()) if err != nil { return xerrors.Errorf("failed to handle StartShuffle message: %v", err) } @@ -81,7 +81,7 @@ func (h *Handler) Stream(out mino.Sender, in mino.Receiver) error { return nil } -func (h *Handler) handleStartShuffle(formID string) error { +func (h *Handler) handleStartShuffle(formID string, userID string) error { dela.Logger.Info().Msg("Starting the neff shuffle protocol ...") err := h.txmngr.Sync() @@ -108,7 +108,7 @@ func (h *Handler) handleStartShuffle(formID string) error { return xerrors.Errorf("the form must be closed: (%v)", form.Status) } - tx, err := h.makeTx(&form) + tx, err := h.makeTx(&form, userID) if err != nil { return xerrors.Errorf("failed to make tx: %v", err) } @@ -149,7 +149,7 @@ func (h *Handler) handleStartShuffle(formID string) error { } } -func (h *Handler) makeTx(form *etypes.Form) (txn.Transaction, error) { +func (h *Handler) makeTx(form *etypes.Form, userID string) (txn.Transaction, error) { shuffledBallots, getProver, err := h.getShuffledBallots(form) if err != nil { @@ -158,6 +158,7 @@ func (h *Handler) makeTx(form *etypes.Form) (txn.Transaction, error) { shuffleBallots := etypes.ShuffleBallots{ FormID: form.FormID, + UserID: userID, Round: len(form.ShuffleInstances), ShuffledBallots: shuffledBallots, } diff --git a/services/shuffle/neff/json/mod.go b/services/shuffle/neff/json/mod.go index bc973c358..d03fa55e0 100644 --- a/services/shuffle/neff/json/mod.go +++ b/services/shuffle/neff/json/mod.go @@ -15,7 +15,8 @@ func init() { type Address []byte type StartShuffle struct { - FormId string + FormID string + UserID string Addresses []Address } @@ -60,7 +61,8 @@ func (f MsgFormat) Encode(ctx serde.Context, msg serde.Message) ([]byte, error) } startShuffle := StartShuffle{ - FormId: in.GetFormId(), + FormID: in.GetFormID(), + UserID: in.GetUserID(), Addresses: addrs, } m = Message{StartShuffle: &startShuffle} @@ -114,7 +116,7 @@ func (f MsgFormat) decodeStartShuffle(ctx serde.Context, startShuffle *StartShuf addrs[i] = fac.FromText(addr) } - s := types.NewStartShuffle(startShuffle.FormId, addrs) + s := types.NewStartShuffle(startShuffle.FormID, startShuffle.UserID, addrs) return s, nil } diff --git a/services/shuffle/neff/json/mod_test.go b/services/shuffle/neff/json/mod_test.go index 6f5bddc2a..94741cdb8 100644 --- a/services/shuffle/neff/json/mod_test.go +++ b/services/shuffle/neff/json/mod_test.go @@ -72,7 +72,7 @@ func TestMessageFormat_StartShuffle_Decode(t *testing.T) { startShuffle, err := format.Decode(ctx, data) require.NoError(t, err) - require.Equal(t, expected.GetFormId(), startShuffle.(types.StartShuffle).GetFormId()) + require.Equal(t, expected.GetFormID(), startShuffle.(types.StartShuffle).GetFormID()) require.Len(t, startShuffle.(types.StartShuffle).GetAddresses(), len(expected.GetAddresses())) } diff --git a/services/shuffle/neff/mod.go b/services/shuffle/neff/mod.go index 3ac3220f2..9b29766a2 100644 --- a/services/shuffle/neff/mod.go +++ b/services/shuffle/neff/mod.go @@ -98,7 +98,7 @@ type Actor struct { // 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 { +func (a *Actor) Shuffle(formID []byte, userID string) error { a.Lock() defer a.Unlock() @@ -133,7 +133,7 @@ func (a *Actor) Shuffle(formID []byte) error { dela.Logger.Info().Msgf("sending start shuffle to: %v", addrs) - message := types.NewStartShuffle(formIDHex, addrs) + message := types.NewStartShuffle(formIDHex, userID, addrs) errs := sender.Send(message, addrs...) err = <-errs @@ -142,7 +142,7 @@ func (a *Actor) Shuffle(formID []byte) error { //return xerrors.Errorf("failed to start shuffle: %v", err) } - err = a.waitAndCheckShuffling(message.GetFormId(), form.Roster.Len()) + err = a.waitAndCheckShuffling(message.GetFormID(), form.Roster.Len()) if err != nil { return xerrors.Errorf("failed to wait and check shuffling: %v", err) } diff --git a/services/shuffle/neff/types/messages.go b/services/shuffle/neff/types/messages.go index 9e7abbed6..635d7be8b 100644 --- a/services/shuffle/neff/types/messages.go +++ b/services/shuffle/neff/types/messages.go @@ -19,21 +19,28 @@ func RegisterMessageFormat(c serde.Format, f serde.FormatEngine) { // // - implements serde.Message type StartShuffle struct { - formId string + formID string + userID string addresses []mino.Address } // NewStartShuffle creates a new StartShuffle message. -func NewStartShuffle(formId string, addresses []mino.Address) StartShuffle { +func NewStartShuffle(formID string, userID string, addresses []mino.Address) StartShuffle { return StartShuffle{ - formId: formId, + formID: formID, + userID: userID, addresses: addresses, } } -// GetFormId returns the formId. -func (s StartShuffle) GetFormId() string { - return s.formId +// GetFormID returns the formId. +func (s StartShuffle) GetFormID() string { + return s.formID +} + +// GetUserID returns the formId. +func (s StartShuffle) GetUserID() string { + return s.userID } // GetAddresses returns the list of addresses. diff --git a/services/shuffle/neff/types/messages_test.go b/services/shuffle/neff/types/messages_test.go index e76dd6a73..570efd53c 100644 --- a/services/shuffle/neff/types/messages_test.go +++ b/services/shuffle/neff/types/messages_test.go @@ -19,7 +19,7 @@ func init() { func TestStartShuffle_GetFormId(t *testing.T) { startShuffle := NewStartShuffle("dummyId", nil) - require.Equal(t, "dummyId", startShuffle.GetFormId()) + require.Equal(t, "dummyId", startShuffle.GetFormID()) } func TestStartShuffle_GetAddresses(t *testing.T) { From 2dc4a7c0905e72e879de3f49142625edf76d9dca Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Tue, 28 May 2024 11:45:18 +0200 Subject: [PATCH 092/114] patch neff test --- integration/ballot.go | 6 ++++-- integration/integration_test.go | 2 +- services/shuffle/neff/handler_test.go | 24 ++++++++++++------------ services/shuffle/neff/mod_test.go | 8 ++++---- 4 files changed, 21 insertions(+), 19 deletions(-) diff --git a/integration/ballot.go b/integration/ballot.go index 928e4cda8..c11104e0b 100644 --- a/integration/ballot.go +++ b/integration/ballot.go @@ -58,7 +58,8 @@ func castVotesRandomly(m txManager, actor dkg.Actor, form types.Form, votes := make([]types.Ballot, numberOfVotes) for i := 0; i < numberOfVotes; i++ { - voterID := "11111" + strconv.Itoa(i) + voterID := strconv.Itoa(i+1) + "11111" + voterID = voterID[:6] addVoter := types.AddVoter{ FormID: form.FormID, TargetUserID: voterID, @@ -91,7 +92,8 @@ func castVotesRandomly(m txManager, actor dkg.Actor, form types.Form, return nil, xerrors.Errorf("failed to marshallBallot: %v", err) } - voterID := "11111" + strconv.Itoa(i) + voterID := strconv.Itoa(i+1) + "11111" + voterID = voterID[:6] castVote := types.CastVote{ FormID: form.FormID, diff --git a/integration/integration_test.go b/integration/integration_test.go index 73877fc87..d77000224 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -391,7 +391,7 @@ func getIntegrationBenchmark(numNodes, numVotes int) func(*testing.B) { err = waitForStatus(types.Closed, formFac, formID, nodes, numNodes, 5*time.Second) require.NoError(b, err) - + time.Sleep(time.Second * 5) // ##### SHUFFLE BALLOTS ##### sActor, err := initShuffle(nodes) require.NoError(b, err) diff --git a/services/shuffle/neff/handler_test.go b/services/shuffle/neff/handler_test.go index 154b7a6f4..2ebe27e52 100644 --- a/services/shuffle/neff/handler_test.go +++ b/services/shuffle/neff/handler_test.go @@ -37,7 +37,7 @@ func TestHandler_Stream(t *testing.T) { require.EqualError(t, err, "expected StartShuffle message, got: fake.Message") receiver = fake.NewReceiver(fake.NewRecvMsg(fake.NewAddress(0), - types.NewStartShuffle("dummyID", make([]mino.Address, 0)))) + types.NewStartShuffle("dummyID", "123456", make([]mino.Address, 0)))) handler.txmngr = fake.Manager{} handler.service = &fake.Service{Forms: make(map[string]etypes.Form), BallotSnap: fake.NewSnapshot()} @@ -50,7 +50,7 @@ func TestHandler_Stream(t *testing.T) { dummyID := hex.EncodeToString([]byte("dummyId")) handler = initValidHandler(dummyID) - receiver = fake.NewReceiver(fake.NewRecvMsg(fake.NewAddress(0), types.NewStartShuffle(dummyID, make([]mino.Address, 0)))) + receiver = fake.NewReceiver(fake.NewRecvMsg(fake.NewAddress(0), types.NewStartShuffle(dummyID, "123456", make([]mino.Address, 0)))) err = handler.Stream(fake.Sender{}, receiver) require.NoError(t, err) @@ -76,7 +76,7 @@ func TestHandler_StartShuffle(t *testing.T) { handler.service = &badService handler.txmngr = fake.Manager{} - err := handler.handleStartShuffle(dummyID) + err := handler.handleStartShuffle(dummyID, "123456") require.EqualError(t, err, "failed to get form: while getting data for form: this key doesn't exist") // Form does not exist @@ -87,7 +87,7 @@ func TestHandler_StartShuffle(t *testing.T) { } handler.service = &service - err = handler.handleStartShuffle(dummyID) + err = handler.handleStartShuffle(dummyID, "123456") require.EqualError(t, err, "failed to get form: while getting data for form: this key doesn't exist") // Form still opened: @@ -107,7 +107,7 @@ func TestHandler_StartShuffle(t *testing.T) { handler.context = serdecontext handler.formFac = formFac - err = handler.handleStartShuffle(dummyID) + err = handler.handleStartShuffle(dummyID, "123456") require.EqualError(t, err, "the form must be closed: (0)") t.Skip("Doesn't work with new form because of snap needed by Form") @@ -140,7 +140,7 @@ func TestHandler_StartShuffle(t *testing.T) { C: Cs[i], }, } - form.CastVote(service.Context, snap, "dummyUser"+strconv.Itoa(i), ballot) + form.CastVote(service.Context, snap, "123456", ballot) } service = updateService(form, dummyID) @@ -155,7 +155,7 @@ func TestHandler_StartShuffle(t *testing.T) { handler.shuffleSigner = fake.NewBadSigner() - err = handler.handleStartShuffle(dummyID) + err = handler.handleStartShuffle(dummyID, "123456") require.EqualError(t, err, fake.Err("failed to make tx: could not sign the shuffle ")) // Bad common signer : @@ -168,7 +168,7 @@ func TestHandler_StartShuffle(t *testing.T) { handler.txmngr = fake.Manager{} - err = handler.handleStartShuffle(dummyID) + err = handler.handleStartShuffle(dummyID, "123456") require.EqualError(t, err, fake.Err("failed to make tx: failed to use manager")) manager := signed.NewManager(fake.NewSigner(), fakeClient{}) @@ -181,7 +181,7 @@ func TestHandler_StartShuffle(t *testing.T) { handler.service = &service handler.p = &fakePool - err = handler.handleStartShuffle(dummyID) + err = handler.handleStartShuffle(dummyID, "123456") require.NoError(t, err) // Threshold is reached : @@ -190,7 +190,7 @@ func TestHandler_StartShuffle(t *testing.T) { fakePool = fake.Pool{Service: &service} handler.service = &service - err = handler.handleStartShuffle(dummyID) + err = handler.handleStartShuffle(dummyID, "123456") require.NoError(t, err) // Service not working : @@ -200,7 +200,7 @@ func TestHandler_StartShuffle(t *testing.T) { fakePool = fake.Pool{Service: &service} handler.service = &service - err = handler.handleStartShuffle(dummyID) + err = handler.handleStartShuffle(dummyID, "123456") // all transactions got denied require.NoError(t, err) @@ -219,7 +219,7 @@ func TestHandler_StartShuffle(t *testing.T) { handler = *NewHandler(handler.me, &service, &fakePool, manager, handler.shuffleSigner, serdecontext, formFac) - err = handler.handleStartShuffle(dummyID) + err = handler.handleStartShuffle(dummyID, "123456") require.NoError(t, err) } diff --git a/services/shuffle/neff/mod_test.go b/services/shuffle/neff/mod_test.go index a21812e8d..eaa67e7d0 100644 --- a/services/shuffle/neff/mod_test.go +++ b/services/shuffle/neff/mod_test.go @@ -74,7 +74,7 @@ func TestNeffShuffle_Shuffle(t *testing.T) { formFac: etypes.NewFormFactory(etypes.CiphervoteFactory{}, fake.NewRosterFac(roster)), } - err = actor.Shuffle(formIDBuf) + err = actor.Shuffle(formIDBuf, "123456") require.EqualError(t, err, fake.Err("failed to stream")) rpc := fake.NewStreamRPC(fake.NewReceiver(), fake.NewBadSender()) @@ -89,7 +89,7 @@ func TestNeffShuffle_Shuffle(t *testing.T) { dela.Logger = zerolog.New(out) // should only output a warning - err = actor.Shuffle(formIDBuf) + err = actor.Shuffle(formIDBuf, "123456") require.NoError(t, err) require.True(t, strings.Contains(out.String(), "failed to start shuffle"), out.String()) @@ -97,7 +97,7 @@ func TestNeffShuffle_Shuffle(t *testing.T) { actor.rpc = rpc // we no longer use the receiver: - err = actor.Shuffle(formIDBuf) + err = actor.Shuffle(formIDBuf, "123456") require.NoError(t, err) recv := fake.NewReceiver(fake.NewRecvMsg(fake.NewAddress(0), types.NewEndShuffle())) @@ -105,7 +105,7 @@ func TestNeffShuffle_Shuffle(t *testing.T) { rpc = fake.NewStreamRPC(recv, fake.Sender{}) actor.rpc = rpc - err = actor.Shuffle(formIDBuf) + err = actor.Shuffle(formIDBuf, "123456") require.NoError(t, err) } From 98c0f461868d85f3e766045bef01dd6b1d8fb02b Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Tue, 28 May 2024 12:07:25 +0200 Subject: [PATCH 093/114] patch neff test round 2 --- services/shuffle/neff/json/mod_test.go | 5 +++-- services/shuffle/neff/types/messages_test.go | 4 ++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/services/shuffle/neff/json/mod_test.go b/services/shuffle/neff/json/mod_test.go index 94741cdb8..6a675edd7 100644 --- a/services/shuffle/neff/json/mod_test.go +++ b/services/shuffle/neff/json/mod_test.go @@ -20,12 +20,12 @@ func TestMessageFormat_StartShuffle_Encode(t *testing.T) { _, err = format.Encode(ctx, fake.Message{}) require.EqualError(t, err, "unsupported message of type 'fake.Message'") - startShuffle := types.NewStartShuffle("", []mino.Address{fake.NewBadAddress()}) + startShuffle := types.NewStartShuffle("", "123456", []mino.Address{fake.NewBadAddress()}) _, err = format.Encode(ctx, startShuffle) require.EqualError(t, err, fake.Err("couldn't marshal address")) - startShuffle = types.NewStartShuffle("dummyId", []mino.Address{fake.NewAddress(0)}) + startShuffle = types.NewStartShuffle("dummyId", "123456", []mino.Address{fake.NewAddress(0)}) data, err := format.Encode(ctx, startShuffle) require.NoError(t, err) @@ -64,6 +64,7 @@ func TestMessageFormat_StartShuffle_Decode(t *testing.T) { expected := types.NewStartShuffle( "dummyId", + "123456", []mino.Address{fake.NewAddress(0)}, ) diff --git a/services/shuffle/neff/types/messages_test.go b/services/shuffle/neff/types/messages_test.go index 570efd53c..454b296c2 100644 --- a/services/shuffle/neff/types/messages_test.go +++ b/services/shuffle/neff/types/messages_test.go @@ -17,13 +17,13 @@ func init() { } func TestStartShuffle_GetFormId(t *testing.T) { - startShuffle := NewStartShuffle("dummyId", nil) + startShuffle := NewStartShuffle("dummyId", "123456", nil) require.Equal(t, "dummyId", startShuffle.GetFormID()) } func TestStartShuffle_GetAddresses(t *testing.T) { - startShuffle := NewStartShuffle("", []mino.Address{fake.NewAddress(0)}) + startShuffle := NewStartShuffle("", "123456", []mino.Address{fake.NewAddress(0)}) require.Len(t, startShuffle.GetAddresses(), 1) } From 4a40e99c16315b2a3424fa52a07ef8e015471f93 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Tue, 28 May 2024 12:16:55 +0200 Subject: [PATCH 094/114] patch weird neff test --- services/shuffle/neff/json/mod_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/shuffle/neff/json/mod_test.go b/services/shuffle/neff/json/mod_test.go index 6a675edd7..6981bbae4 100644 --- a/services/shuffle/neff/json/mod_test.go +++ b/services/shuffle/neff/json/mod_test.go @@ -30,8 +30,8 @@ func TestMessageFormat_StartShuffle_Encode(t *testing.T) { data, err := format.Encode(ctx, startShuffle) require.NoError(t, err) - regexp := `{"StartShuffle":{"FormId":"dummyId","Addresses":\["AAAAAA=="\]` - require.Regexp(t, regexp, string(data)) + regexp := `{"StartShuffle":{"FormID":"dummyId","UserID":"123456","Addresses":["AAAAAA=="]}}` + require.Equal(t, regexp, string(data)) } func TestMessageFormat_EndShuffle_Encode(t *testing.T) { From e48be783710304ad13a44feea11f2108c1ba4e06 Mon Sep 17 00:00:00 2001 From: Maxime Date: Tue, 28 May 2024 16:32:43 +0200 Subject: [PATCH 095/114] remove useless time.sleep --- integration/integration_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/integration/integration_test.go b/integration/integration_test.go index d77000224..73877fc87 100644 --- a/integration/integration_test.go +++ b/integration/integration_test.go @@ -391,7 +391,7 @@ func getIntegrationBenchmark(numNodes, numVotes int) func(*testing.B) { err = waitForStatus(types.Closed, formFac, formID, nodes, numNodes, 5*time.Second) require.NoError(b, err) - time.Sleep(time.Second * 5) + // ##### SHUFFLE BALLOTS ##### sActor, err := initShuffle(nodes) require.NoError(b, err) From 1eb028f4617e8e3e7b3d8d64d569540d2503fd18 Mon Sep 17 00:00:00 2001 From: Maxime Date: Tue, 28 May 2024 16:37:17 +0200 Subject: [PATCH 096/114] add explanation for voterid --- integration/ballot.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/integration/ballot.go b/integration/ballot.go index c11104e0b..939bb65ac 100644 --- a/integration/ballot.go +++ b/integration/ballot.go @@ -92,6 +92,30 @@ func castVotesRandomly(m txManager, actor dkg.Actor, form types.Form, return nil, xerrors.Errorf("failed to marshallBallot: %v", err) } + /* + For the voters permission verification, we need a voter id. As this method + does not use a fix number of voters, we need a way to generate these voters' id. + We decided to use the ith voter as an id. + As the sciper range from 100000 to 999999 and as we don't know how many voters + they will be created in the method, we pad the ith number with 1's, + and then we truncate to take the first six number. + + example run + if it generates 10 voters, i is going to vary from 0 to 9 + with the +1 + from 1 to 10 + we are going to get id: + 1 11111 + 2 11111 + 3 11111 + 4 11111 + 5 11111 + 6 11111 + 7 11111 + 8 11111 + 9 11111 + 10 11111 -> truncate to 6 digits: 101111 + */ voterID := strconv.Itoa(i+1) + "11111" voterID = voterID[:6] From 93cdd3b18ded3fceb8d58c2b0f6ec54ac12ae38f Mon Sep 17 00:00:00 2001 From: Maxime Date: Tue, 28 May 2024 16:39:57 +0200 Subject: [PATCH 097/114] vet reformat --- integration/ballot.go | 44 +++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/integration/ballot.go b/integration/ballot.go index 939bb65ac..23c6012ec 100644 --- a/integration/ballot.go +++ b/integration/ballot.go @@ -93,28 +93,28 @@ func castVotesRandomly(m txManager, actor dkg.Actor, form types.Form, } /* - For the voters permission verification, we need a voter id. As this method - does not use a fix number of voters, we need a way to generate these voters' id. - We decided to use the ith voter as an id. - As the sciper range from 100000 to 999999 and as we don't know how many voters - they will be created in the method, we pad the ith number with 1's, - and then we truncate to take the first six number. - - example run - if it generates 10 voters, i is going to vary from 0 to 9 - with the +1 - from 1 to 10 - we are going to get id: - 1 11111 - 2 11111 - 3 11111 - 4 11111 - 5 11111 - 6 11111 - 7 11111 - 8 11111 - 9 11111 - 10 11111 -> truncate to 6 digits: 101111 + For the voters permission verification, we need a voter id. As this method + does not use a fix number of voters, we need a way to generate these voters' + id. We decided to use the ith voter as an id. + As the sciper range from 100000 to 999999 and as we don't know how many + voters they will be created in the method, we pad the ith number with + 1's, and then we truncate to take the first six number. + + example run + if it generates 10 voters, i is going to vary from 0 to 9 + with the +1 + from 1 to 10 + we are going to get id: + 1 11111 + 2 11111 + 3 11111 + 4 11111 + 5 11111 + 6 11111 + 7 11111 + 8 11111 + 9 11111 + 10 11111 -> truncate to 6 digits: 101111 */ voterID := strconv.Itoa(i+1) + "11111" voterID = voterID[:6] From b7cf44beb9b4e213195b83b819922c565cc49eb3 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 29 May 2024 16:32:18 +0200 Subject: [PATCH 098/114] feat: added new interface to the proxy (part 1) --- proxy/election.go | 143 ++++++++++++++++++++++++++-------------------- proxy/mod.go | 13 +++++ 2 files changed, 95 insertions(+), 61 deletions(-) diff --git a/proxy/election.go b/proxy/election.go index caf019185..9d9441674 100644 --- a/proxy/election.go +++ b/proxy/election.go @@ -64,7 +64,7 @@ type form struct { } // NewForm implements proxy.Proxy -func (h *form) NewForm(w http.ResponseWriter, r *http.Request) { +func (form *form) NewForm(w http.ResponseWriter, r *http.Request) { var req ptypes.CreateFormRequest // get the signed request @@ -75,7 +75,7 @@ func (h *form) NewForm(w http.ResponseWriter, r *http.Request) { } // get the request and verify the signature - err = signed.GetAndVerify(h.pk, &req) + err = signed.GetAndVerify(form.pk, &req) if err != nil { InternalError(w, r, getSignedErr(err), nil) return @@ -87,7 +87,7 @@ func (h *form) NewForm(w http.ResponseWriter, r *http.Request) { } // serialize the transaction - data, err := createForm.Serialize(h.context) + data, err := createForm.Serialize(form.context) if err != nil { http.Error(w, "failed to marshal CreateFormTransaction: "+err.Error(), http.StatusInternalServerError) @@ -95,7 +95,7 @@ func (h *form) NewForm(w http.ResponseWriter, r *http.Request) { } // create the transaction and add it to the pool - txnID, blockIdx, err := h.mngr.SubmitTxn(r.Context(), evoting.CmdCreateForm, evoting.FormArg, data) + txnID, blockIdx, err := form.mngr.SubmitTxn(r.Context(), evoting.CmdCreateForm, evoting.FormArg, data) if err != nil { http.Error(w, "failed to submit txn: "+err.Error(), http.StatusInternalServerError) return @@ -107,7 +107,7 @@ func (h *form) NewForm(w http.ResponseWriter, r *http.Request) { formID := hash.Sum(nil) // create it to get the token - transactionClientInfo, err := h.mngr.CreateTransactionResult(txnID, blockIdx, txnmanager.UnknownTransactionStatus) + transactionClientInfo, err := form.mngr.CreateTransactionResult(txnID, blockIdx, txnmanager.UnknownTransactionStatus) if err != nil { http.Error(w, "failed to create transaction info: "+err.Error(), http.StatusInternalServerError) return @@ -126,7 +126,7 @@ func (h *form) NewForm(w http.ResponseWriter, r *http.Request) { } // NewFormVote implements proxy.Proxy -func (h *form) NewFormVote(w http.ResponseWriter, r *http.Request) { +func (form *form) NewFormVote(w http.ResponseWriter, r *http.Request) { var req ptypes.CastVoteRequest // get the signed request @@ -137,7 +137,7 @@ func (h *form) NewFormVote(w http.ResponseWriter, r *http.Request) { } // get the request and verify the signature - err = signed.GetAndVerify(h.pk, &req) + err = signed.GetAndVerify(form.pk, &req) if err != nil { InternalError(w, r, getSignedErr(err), nil) return @@ -153,7 +153,7 @@ func (h *form) NewFormVote(w http.ResponseWriter, r *http.Request) { formID := vars["formID"] - elecMD, err := h.getFormsMetadata() + elecMD, err := form.getFormsMetadata() if err != nil { http.Error(w, "failed to get form metadata", http.StatusNotFound) return @@ -198,7 +198,7 @@ func (h *form) NewFormVote(w http.ResponseWriter, r *http.Request) { } // serialize the vote - data, err := castVote.Serialize(h.context) + data, err := castVote.Serialize(form.context) if err != nil { http.Error(w, "failed to marshal CastVoteTransaction: "+err.Error(), http.StatusInternalServerError) @@ -206,15 +206,15 @@ func (h *form) NewFormVote(w http.ResponseWriter, r *http.Request) { } // create the transaction and add it to the pool - txnID, lastBlock, err := h.mngr.SubmitTxn(r.Context(), evoting.CmdCastVote, evoting.FormArg, data) + txnID, lastBlock, err := form.mngr.SubmitTxn(r.Context(), evoting.CmdCastVote, evoting.FormArg, data) if err != nil { - h.logger.Err(err).Msg("failed to submit txn") + form.logger.Err(err).Msg("failed to submit txn") http.Error(w, "failed to submit txn: "+err.Error(), http.StatusInternalServerError) return } // send the transaction's information - err = h.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) + err = form.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) if err != nil { http.Error(w, "couldn't send transaction info: "+err.Error(), http.StatusInternalServerError) return @@ -222,7 +222,7 @@ func (h *form) NewFormVote(w http.ResponseWriter, r *http.Request) { } // EditForm implements proxy.Proxy -func (h *form) EditForm(w http.ResponseWriter, r *http.Request) { +func (form *form) EditForm(w http.ResponseWriter, r *http.Request) { var req ptypes.UpdateFormRequest // get the signed request @@ -233,7 +233,7 @@ func (h *form) EditForm(w http.ResponseWriter, r *http.Request) { } // get the request and verify the signature - err = signed.GetAndVerify(h.pk, &req) + err = signed.GetAndVerify(form.pk, &req) if err != nil { InternalError(w, r, getSignedErr(err), nil) return @@ -250,7 +250,7 @@ func (h *form) EditForm(w http.ResponseWriter, r *http.Request) { formID := vars["formID"] userID := vars["userID"] - elecMD, err := h.getFormsMetadata() + elecMD, err := form.getFormsMetadata() if err != nil { http.Error(w, "failed to get form metadata", http.StatusNotFound) return @@ -264,13 +264,13 @@ func (h *form) EditForm(w http.ResponseWriter, r *http.Request) { switch req.Action { case "open": - h.openForm(formID, userID, w, r) + form.openForm(formID, userID, w, r) case "close": - h.closeForm(formID, userID, w, r) + form.closeForm(formID, userID, w, r) case "combineShares": - h.combineShares(formID, userID, w, r) + form.combineShares(formID, userID, w, r) case "cancel": - h.cancelForm(formID, userID, w, r) + form.cancelForm(formID, userID, w, r) default: BadRequestError(w, r, xerrors.Errorf("invalid action: %s", req.Action), nil) return @@ -279,14 +279,14 @@ func (h *form) EditForm(w http.ResponseWriter, r *http.Request) { // openForm allows opening a form, which sets the public key based on // the DKG actor. -func (h *form) openForm(formID string, userID string, w http.ResponseWriter, r *http.Request) { +func (form *form) openForm(formID string, userID string, w http.ResponseWriter, r *http.Request) { openForm := types.OpenForm{ FormID: formID, UserID: userID, } // serialize the transaction - data, err := openForm.Serialize(h.context) + data, err := openForm.Serialize(form.context) if err != nil { http.Error(w, "failed to marshal OpenFormTransaction: "+err.Error(), http.StatusInternalServerError) @@ -294,18 +294,18 @@ func (h *form) openForm(formID string, userID string, w http.ResponseWriter, r * } // create the transaction and add it to the pool - txnID, lastBlock, err := h.mngr.SubmitTxn(r.Context(), evoting.CmdOpenForm, evoting.FormArg, data) + txnID, lastBlock, err := form.mngr.SubmitTxn(r.Context(), evoting.CmdOpenForm, evoting.FormArg, data) if err != nil { http.Error(w, "failed to submit txn: "+err.Error(), http.StatusInternalServerError) return } // send the transaction's informations - h.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) + form.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) } // closeForm closes a form. -func (h *form) closeForm(formIDHex string, userID string, w http.ResponseWriter, r *http.Request) { +func (form *form) closeForm(formIDHex string, userID string, w http.ResponseWriter, r *http.Request) { closeForm := types.CloseForm{ FormID: formIDHex, @@ -313,7 +313,7 @@ func (h *form) closeForm(formIDHex string, userID string, w http.ResponseWriter, } // serialize the transaction - data, err := closeForm.Serialize(h.context) + data, err := closeForm.Serialize(form.context) if err != nil { http.Error(w, "failed to marshal CloseFormTransaction: "+err.Error(), http.StatusInternalServerError) @@ -321,27 +321,27 @@ func (h *form) closeForm(formIDHex string, userID string, w http.ResponseWriter, } // create the transaction and add it to the pool - txnID, lastBlock, err := h.mngr.SubmitTxn(r.Context(), evoting.CmdCloseForm, evoting.FormArg, data) + txnID, lastBlock, err := form.mngr.SubmitTxn(r.Context(), evoting.CmdCloseForm, evoting.FormArg, data) if err != nil { http.Error(w, "failed to submit txn: "+err.Error(), http.StatusInternalServerError) return } // send the transaction's informations - h.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) + form.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) } // combineShares decrypts the shuffled ballots in a form. -func (h *form) combineShares(formIDHex string, userID string, w http.ResponseWriter, r *http.Request) { +func (form *form) combineShares(formIDHex string, userID string, w http.ResponseWriter, r *http.Request) { - form, err := types.FormFromStore(h.context, h.formFac, formIDHex, h.orderingSvc.GetStore()) + formFromStore, err := types.FormFromStore(form.context, form.formFac, formIDHex, form.orderingSvc.GetStore()) if err != nil { http.Error(w, "failed to get form: "+err.Error(), http.StatusInternalServerError) return } - if form.Status != types.PubSharesSubmitted { + if formFromStore.Status != types.PubSharesSubmitted { http.Error(w, "the submission of public shares must be over!", http.StatusUnauthorized) return @@ -353,7 +353,7 @@ func (h *form) combineShares(formIDHex string, userID string, w http.ResponseWri } // serialize the transaction - data, err := decryptBallots.Serialize(h.context) + data, err := decryptBallots.Serialize(form.context) if err != nil { http.Error(w, "failed to marshal decryptBallots: "+err.Error(), http.StatusInternalServerError) @@ -361,18 +361,18 @@ func (h *form) combineShares(formIDHex string, userID string, w http.ResponseWri } // create the transaction and add it to the pool - txnID, lastBlock, err := h.mngr.SubmitTxn(r.Context(), evoting.CmdCombineShares, evoting.FormArg, data) + txnID, lastBlock, err := form.mngr.SubmitTxn(r.Context(), evoting.CmdCombineShares, evoting.FormArg, data) if err != nil { http.Error(w, "failed to submit txn: "+err.Error(), http.StatusInternalServerError) return } // send the transaction's informations - h.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) + form.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) } // cancelForm cancels a form. -func (h *form) cancelForm(formIDHex string, userID string, w http.ResponseWriter, r *http.Request) { +func (form *form) cancelForm(formIDHex string, userID string, w http.ResponseWriter, r *http.Request) { cancelForm := types.CancelForm{ FormID: formIDHex, @@ -380,7 +380,7 @@ func (h *form) cancelForm(formIDHex string, userID string, w http.ResponseWriter } // serialize the transaction - data, err := cancelForm.Serialize(h.context) + data, err := cancelForm.Serialize(form.context) if err != nil { http.Error(w, "failed to marshal CancelForm: "+err.Error(), http.StatusInternalServerError) @@ -388,19 +388,19 @@ func (h *form) cancelForm(formIDHex string, userID string, w http.ResponseWriter } // create the transaction and add it to the pool - txnID, lastBlock, err := h.mngr.SubmitTxn(r.Context(), evoting.CmdCancelForm, evoting.FormArg, data) + txnID, lastBlock, err := form.mngr.SubmitTxn(r.Context(), evoting.CmdCancelForm, evoting.FormArg, data) if err != nil { http.Error(w, "failed to submit txn: "+err.Error(), http.StatusInternalServerError) return } // send the transaction's informations - h.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) + form.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) } // Form implements proxy.Proxy. The request should not be signed because it // is fetching public data. -func (h *form) Form(w http.ResponseWriter, r *http.Request) { +func (form *form) Form(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Headers", "*") @@ -415,7 +415,7 @@ func (h *form) Form(w http.ResponseWriter, r *http.Request) { formID := vars["formID"] // get the form - form, err := types.FormFromStore(h.context, h.formFac, formID, h.orderingSvc.GetStore()) + formFromStore, err := types.FormFromStore(form.context, form.formFac, formID, form.orderingSvc.GetStore()) if err != nil { http.Error(w, xerrors.Errorf("failed to get form: %v", err).Error(), http.StatusInternalServerError) return @@ -424,8 +424,8 @@ func (h *form) Form(w http.ResponseWriter, r *http.Request) { var pubkeyBuf []byte // get the public key - if form.Pubkey != nil { - pubkeyBuf, err = form.Pubkey.MarshalBinary() + if formFromStore.Pubkey != nil { + pubkeyBuf, err = formFromStore.Pubkey.MarshalBinary() if err != nil { http.Error(w, "failed to marshal pubkey: "+err.Error(), http.StatusInternalServerError) @@ -433,14 +433,14 @@ func (h *form) Form(w http.ResponseWriter, r *http.Request) { } } - roster := make([]string, 0, form.Roster.Len()) + roster := make([]string, 0, formFromStore.Roster.Len()) - iter := form.Roster.AddressIterator() + iter := formFromStore.Roster.AddressIterator() for iter.HasNext() { roster = append(roster, iter.GetNext().String()) } - suff, err := form.Suffragia(h.context, h.orderingSvc.GetStore()) + suff, err := formFromStore.Suffragia(form.context, form.orderingSvc.GetStore()) if err != nil { http.Error(w, "couldn't get ballots: "+err.Error(), http.StatusInternalServerError) @@ -448,14 +448,14 @@ func (h *form) Form(w http.ResponseWriter, r *http.Request) { } response := ptypes.GetFormResponse{ - FormID: string(form.FormID), - Configuration: form.Configuration, - Status: uint16(form.Status), + FormID: string(formFromStore.FormID), + Configuration: formFromStore.Configuration, + Status: uint16(formFromStore.Status), Pubkey: hex.EncodeToString(pubkeyBuf), - Result: form.DecryptedBallots, + Result: formFromStore.DecryptedBallots, Roster: roster, - ChunksPerBallot: form.ChunksPerBallot(), - BallotSize: form.BallotSize, + ChunksPerBallot: formFromStore.ChunksPerBallot(), + BallotSize: formFromStore.BallotSize, Voters: suff.VoterIDs, } @@ -465,11 +465,11 @@ func (h *form) Form(w http.ResponseWriter, r *http.Request) { // Forms implements proxy.Proxy. The request should not be signed because it // is fecthing public data. -func (h *form) Forms(w http.ResponseWriter, r *http.Request) { +func (form *form) Forms(w http.ResponseWriter, r *http.Request) { w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Access-Control-Allow-Headers", "*") - elecMD, err := h.getFormsMetadata() + elecMD, err := form.getFormsMetadata() if err != nil { InternalError(w, r, xerrors.Errorf("failed to get form metadata: %v", err), nil) return @@ -479,7 +479,7 @@ func (h *form) Forms(w http.ResponseWriter, r *http.Request) { // get the forms for i, id := range elecMD.FormsIDs { - form, err := types.FormFromStore(h.context, h.formFac, id, h.orderingSvc.GetStore()) + form, err := types.FormFromStore(form.context, form.formFac, id, form.orderingSvc.GetStore()) if err != nil { InternalError(w, r, xerrors.Errorf("failed to get form: %v", err), nil) return @@ -512,7 +512,7 @@ func (h *form) Forms(w http.ResponseWriter, r *http.Request) { } // DeleteForm implements proxy.Proxy -func (h *form) DeleteForm(w http.ResponseWriter, r *http.Request) { +func (form *form) DeleteForm(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) // check if the formID is valid @@ -524,7 +524,7 @@ func (h *form) DeleteForm(w http.ResponseWriter, r *http.Request) { formID := vars["formID"] userID := vars["userID"] - elecMD, err := h.getFormsMetadata() + elecMD, err := form.getFormsMetadata() if err != nil { http.Error(w, "failed to get form metadata", http.StatusNotFound) return @@ -547,7 +547,7 @@ func (h *form) DeleteForm(w http.ResponseWriter, r *http.Request) { } // check if the signature is valid - err = schnorr.Verify(suite, h.pk, []byte(formID), signature) + err = schnorr.Verify(suite, form.pk, []byte(formID), signature) if err != nil { ForbiddenError(w, r, xerrors.Errorf("signature verification failed: %v", err), nil) return @@ -558,27 +558,48 @@ func (h *form) DeleteForm(w http.ResponseWriter, r *http.Request) { UserID: userID, } - data, err := deleteForm.Serialize(h.context) + data, err := deleteForm.Serialize(form.context) if err != nil { InternalError(w, r, xerrors.Errorf("failed to marshal DeleteForm: %v", err), nil) return } // create the transaction and add it to the pool - txnID, lastBlock, err := h.mngr.SubmitTxn(r.Context(), evoting.CmdDeleteForm, evoting.FormArg, data) + txnID, lastBlock, err := form.mngr.SubmitTxn(r.Context(), evoting.CmdDeleteForm, evoting.FormArg, data) if err != nil { http.Error(w, "failed to submit txn: "+err.Error(), http.StatusInternalServerError) return } // send the transaction's information - h.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) + form.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) } -func (h *form) getFormsMetadata() (types.FormsMetadata, error) { +// TODO CHECK CAUSE NEW +// POST /addtoadminlist +func (form *form) AddToAdminList(http.ResponseWriter, *http.Request) {} + +// POST /removetoadminlist +func (form *form) RemoveToAdminList(http.ResponseWriter, *http.Request) {} + +// POST /forms/{formID}/addowner +func (form *form) AddOwnerToForm(http.ResponseWriter, *http.Request) {} + +// POST /forms/{formID}/removeowner +func (form *form) RemoveOwnerToForm(http.ResponseWriter, *http.Request) {} + +// POST /forms/{formID}/addvoter +func (form *form) AddVoterToForm(http.ResponseWriter, *http.Request) {} + +// POST /forms/{formID}/removevoter +func (form *form) RemoveVoterToForm(http.ResponseWriter, *http.Request) {} + +// ===== HELPER ===== + +func (form *form) getFormsMetadata() (types.FormsMetadata, error) { var md types.FormsMetadata - store, err := h.orderingSvc.GetStore().Get([]byte(evoting.FormsMetadataKey)) + store, err := form.orderingSvc.GetStore().Get([]byte(evoting.FormsMetadataKey)) if err != nil { return md, nil } diff --git a/proxy/mod.go b/proxy/mod.go index dbd1cb9cb..dd26e10f3 100644 --- a/proxy/mod.go +++ b/proxy/mod.go @@ -31,6 +31,19 @@ type Form interface { Form(http.ResponseWriter, *http.Request) // DELETE /forms/{formID} DeleteForm(http.ResponseWriter, *http.Request) + // TODO CHECK CAUSE NEW + // POST /addtoadminlist + AddToAdminList(http.ResponseWriter, *http.Request) + // POST /removetoadminlist + RemoveToAdminList(http.ResponseWriter, *http.Request) + // POST /forms/{formID}/addowner + AddOwnerToForm(http.ResponseWriter, *http.Request) + // POST /forms/{formID}/removeowner + RemoveOwnerToForm(http.ResponseWriter, *http.Request) + // POST /forms/{formID}/addvoter + AddVoterToForm(http.ResponseWriter, *http.Request) + // POST /forms/{formID}/removevoter + RemoveVoterToForm(http.ResponseWriter, *http.Request) } // DKG defines the public HTTP API of the DKG service From a4d96fbd239488b7cb5dac295466505a5285b0c0 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 29 May 2024 16:48:35 +0200 Subject: [PATCH 099/114] feat: AddToAdminList first implem --- proxy/election.go | 43 ++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-) diff --git a/proxy/election.go b/proxy/election.go index 9d9441674..d698e5f58 100644 --- a/proxy/election.go +++ b/proxy/election.go @@ -245,6 +245,9 @@ func (form *form) EditForm(w http.ResponseWriter, r *http.Request) { if vars == nil || vars["formID"] == "" { http.Error(w, fmt.Sprintf("formID not found: %v", vars), http.StatusInternalServerError) return + } else if vars["userID"] == "" { + http.Error(w, fmt.Sprintf("userID not found: %v", vars), http.StatusInternalServerError) + return } formID := vars["formID"] @@ -519,6 +522,9 @@ func (form *form) DeleteForm(w http.ResponseWriter, r *http.Request) { if vars == nil || vars["formID"] == "" { http.Error(w, fmt.Sprintf("formID not found: %v", vars), http.StatusInternalServerError) return + } else if vars["userID"] == "" { + http.Error(w, fmt.Sprintf("userID not found: %v", vars), http.StatusInternalServerError) + return } formID := vars["formID"] @@ -577,7 +583,42 @@ func (form *form) DeleteForm(w http.ResponseWriter, r *http.Request) { // TODO CHECK CAUSE NEW // POST /addtoadminlist -func (form *form) AddToAdminList(http.ResponseWriter, *http.Request) {} +func (form *form) AddToAdminList(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + + // check if the formID is valid + if vars == nil || vars["targetUserID"] == "" { + http.Error(w, fmt.Sprintf("targetUserID not found: %v", vars), http.StatusInternalServerError) + return + } else if vars["performingUserID"] == "" { + http.Error(w, fmt.Sprintf("performingUserID not found: %v", vars), http.StatusInternalServerError) + return + } + + targetUserID := vars["targetUserID"] + performingUserID := vars["performingUserID"] + + addAdmin := types.AddAdmin{ + TargetUserID: targetUserID, + PerformingUserID: performingUserID, + } + + data, err := addAdmin.Serialize(form.context) + if err != nil { + InternalError(w, r, xerrors.Errorf("failed to marshal AddAdmin: %v", err), nil) + return + } + + // create the transaction and add it to the pool + txnID, lastBlock, err := form.mngr.SubmitTxn(r.Context(), evoting.CmdAddAdmin, evoting.FormArg, data) + if err != nil { + http.Error(w, "failed to submit txn: "+err.Error(), http.StatusInternalServerError) + return + } + + // send the transaction's information + form.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) +} // POST /removetoadminlist func (form *form) RemoveToAdminList(http.ResponseWriter, *http.Request) {} From b6d4d25bb4dc26cc0dc06346397d33b82049abcc Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 29 May 2024 17:14:56 +0200 Subject: [PATCH 100/114] temp: add info --- proxy/mod.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/proxy/mod.go b/proxy/mod.go index dd26e10f3..be72b639a 100644 --- a/proxy/mod.go +++ b/proxy/mod.go @@ -31,11 +31,11 @@ type Form interface { Form(http.ResponseWriter, *http.Request) // DELETE /forms/{formID} DeleteForm(http.ResponseWriter, *http.Request) - // TODO CHECK CAUSE NEW - // POST /addtoadminlist - AddToAdminList(http.ResponseWriter, *http.Request) - // POST /removetoadminlist - RemoveToAdminList(http.ResponseWriter, *http.Request) + // TODO CHECK CAUSE NEW -> modif according to blockchain + // POST /addadmin + AddAdmin(http.ResponseWriter, *http.Request) + // POST /removeadmin + RemoveAdmin(http.ResponseWriter, *http.Request) // POST /forms/{formID}/addowner AddOwnerToForm(http.ResponseWriter, *http.Request) // POST /forms/{formID}/removeowner From e3454c4a1ebf542e83c2b772d16436471a8875f3 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 29 May 2024 17:19:51 +0200 Subject: [PATCH 101/114] fix: do reinsert existing admin --- contracts/evoting/types/admin.go | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/contracts/evoting/types/admin.go b/contracts/evoting/types/admin.go index 8ebd96f32..c520c4be7 100644 --- a/contracts/evoting/types/admin.go +++ b/contracts/evoting/types/admin.go @@ -48,6 +48,15 @@ func (adminList *AdminList) AddAdmin(userID string) error { return xerrors.Errorf("Failed to convert SCIPER to int: %v", err) } + index, err := adminList.GetAdminIndex(userID) + if err != nil { + return err + } + + if index > -1 { + return xerrors.Errorf("The user %v is already an admin", userID) + } + adminList.AdminList = append(adminList.AdminList, sciperInt) return nil From 36cd87dba4b9bd89fe82e0552a8a316e3365d239 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Mon, 3 Jun 2024 14:23:41 +0200 Subject: [PATCH 102/114] feat: update the signature verification on proxy --- proxy/election.go | 57 +++++++++++++++++++++++++++++++++-------- proxy/mod.go | 2 ++ proxy/types/election.go | 12 +++++++++ 3 files changed, 60 insertions(+), 11 deletions(-) diff --git a/proxy/election.go b/proxy/election.go index d698e5f58..184c1aab2 100644 --- a/proxy/election.go +++ b/proxy/election.go @@ -19,7 +19,6 @@ import ( "go.dedis.ch/dela/core/txn/pool" "go.dedis.ch/dela/serde" "go.dedis.ch/kyber/v3" - "go.dedis.ch/kyber/v3/sign/schnorr" "golang.org/x/xerrors" ) @@ -516,6 +515,8 @@ func (form *form) Forms(w http.ResponseWriter, r *http.Request) { // DeleteForm implements proxy.Proxy func (form *form) DeleteForm(w http.ResponseWriter, r *http.Request) { + var req ptypes.UpdateFormRequest + vars := mux.Vars(r) // check if the formID is valid @@ -542,20 +543,38 @@ func (form *form) DeleteForm(w http.ResponseWriter, r *http.Request) { return } - // auth should contain the hex-encoded signature on the hex-encoded form - // ID - auth := r.Header.Get("Authorization") + /* + // auth should contain the hex-encoded signature on the hex-encoded form + // ID + auth := r.Header.Get("Authorization") + + signature, err := hex.DecodeString(auth) + if err != nil { + BadRequestError(w, r, xerrors.Errorf("failed to decode auth: %v", err), nil) + return + } - signature, err := hex.DecodeString(auth) + // check if the signature is valid + //TODO ADD User ID to existing + err = schnorr.Verify(suite, form.pk, []byte(formID+userID), signature) + if err != nil { + ForbiddenError(w, r, xerrors.Errorf("signature verification failed: %v", err), nil) + return + } + + */ + + // TODO double check + // get the signed request + signed, err := ptypes.NewSignedRequest(r.Body) if err != nil { - BadRequestError(w, r, xerrors.Errorf("failed to decode auth: %v", err), nil) + InternalError(w, r, newSignedErr(err), nil) return } - // check if the signature is valid - err = schnorr.Verify(suite, form.pk, []byte(formID), signature) + err = signed.GetAndVerify(form.pk, &req) if err != nil { - ForbiddenError(w, r, xerrors.Errorf("signature verification failed: %v", err), nil) + InternalError(w, r, getSignedErr(err), nil) return } @@ -583,7 +602,20 @@ func (form *form) DeleteForm(w http.ResponseWriter, r *http.Request) { // TODO CHECK CAUSE NEW // POST /addtoadminlist -func (form *form) AddToAdminList(w http.ResponseWriter, r *http.Request) { +func (form *form) AddAdmin(w http.ResponseWriter, r *http.Request) { + var req ptypes.AddAdminRequest + signed, err := ptypes.NewSignedRequest(r.Body) + if err != nil { + InternalError(w, r, newSignedErr(err), nil) + return + } + + err = signed.GetAndVerify(form.pk, &req) + if err != nil { + InternalError(w, r, getSignedErr(err), nil) + return + } + vars := mux.Vars(r) // check if the formID is valid @@ -621,7 +653,10 @@ func (form *form) AddToAdminList(w http.ResponseWriter, r *http.Request) { } // POST /removetoadminlist -func (form *form) RemoveToAdminList(http.ResponseWriter, *http.Request) {} +func (form *form) RemoveAdmin(http.ResponseWriter, *http.Request) {} + +// POST /adminlist +func (form *form) AdminList(http.ResponseWriter, *http.Request) {} // POST /forms/{formID}/addowner func (form *form) AddOwnerToForm(http.ResponseWriter, *http.Request) {} diff --git a/proxy/mod.go b/proxy/mod.go index be72b639a..b5e2be50f 100644 --- a/proxy/mod.go +++ b/proxy/mod.go @@ -36,6 +36,8 @@ type Form interface { AddAdmin(http.ResponseWriter, *http.Request) // POST /removeadmin RemoveAdmin(http.ResponseWriter, *http.Request) + // GET /adminlist + AdminList(http.ResponseWriter, *http.Request) // POST /forms/{formID}/addowner AddOwnerToForm(http.ResponseWriter, *http.Request) // POST /forms/{formID}/removeowner diff --git a/proxy/types/election.go b/proxy/types/election.go index fd8775d7b..d8720cc7d 100644 --- a/proxy/types/election.go +++ b/proxy/types/election.go @@ -10,6 +10,18 @@ type CreateFormRequest struct { Configuration etypes.Configuration } +// AddAdminRequest defines the HTTP request for adding an admin +type AddAdminRequest struct { + TargetUserID string + PerformingUserID string +} + +// RemoveAdminRequest defines the HTTP request for Removing an admin +type RemoveAdminRequest struct { + TargetUserID string + PerformingUserID string +} + // CreateFormResponse defines the HTTP response when creating a form type CreateFormResponse struct { FormID string // hex-encoded From 0d6075d52445afee673223959e1c134490ea1f83 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Tue, 4 Jun 2024 00:25:00 +0200 Subject: [PATCH 103/114] work: working on debugging the new features of the proxy --- contracts/evoting/controller/action.go | 12 ++++++-- proxy/election.go | 32 ++++++++++++-------- proxy/generate_test.go | 42 ++++++++++++++++++++++++++ proxy/types/signed.go | 3 ++ 4 files changed, 74 insertions(+), 15 deletions(-) create mode 100644 proxy/generate_test.go diff --git a/contracts/evoting/controller/action.go b/contracts/evoting/controller/action.go index b62c03f1c..50b1502f1 100644 --- a/contracts/evoting/controller/action.go +++ b/contracts/evoting/controller/action.go @@ -48,9 +48,12 @@ const ( contentType = "application/json" formPath = "/evoting/forms" // FormPathSlash is the path to the form with a trailing slash - FormPathSlash = formPath + "/" - formIDPath = FormPathSlash + "{formID}" - transactionSlash = "/evoting/transactions/" + FormPathSlash = formPath + "/" + formIDPath = FormPathSlash + "{formID}" + transactionSlash = "/evoting/transactions/" + + evotingPathSlash = "/evoting/" + transactionPath = transactionSlash + "{token}" unexpectedStatus = "unexpected status: %s, body: %s" failRetrieveDecryption = "failed to retrieve decryption key: %v" @@ -175,6 +178,8 @@ func (a *RegisterAction) Execute(ctx node.Context) error { router := mux.NewRouter() + router.HandleFunc(evotingPathSlash+"addadmin", ep.AddAdmin).Methods("POST") + router.HandleFunc(evotingPathSlash+"adminlist", ep.AdminList).Methods("GET") router.HandleFunc(formPath, ep.NewForm).Methods("POST") router.HandleFunc(formPath, ep.Forms).Methods("GET") router.HandleFunc(formPath, eproxy.AllowCORS).Methods("OPTIONS") @@ -188,6 +193,7 @@ func (a *RegisterAction) Execute(ctx node.Context) error { router.NotFoundHandler = http.HandlerFunc(eproxy.NotFoundHandler) router.MethodNotAllowedHandler = http.HandlerFunc(eproxy.NotAllowedHandler) + proxy.RegisterHandler(evotingPathSlash, router.ServeHTTP) proxy.RegisterHandler(formPath, router.ServeHTTP) proxy.RegisterHandler(FormPathSlash, router.ServeHTTP) proxy.RegisterHandler(transactionSlash, router.ServeHTTP) diff --git a/proxy/election.go b/proxy/election.go index 184c1aab2..2452d14fc 100644 --- a/proxy/election.go +++ b/proxy/election.go @@ -604,6 +604,8 @@ func (form *form) DeleteForm(w http.ResponseWriter, r *http.Request) { // POST /addtoadminlist func (form *form) AddAdmin(w http.ResponseWriter, r *http.Request) { var req ptypes.AddAdminRequest + println("plouf plouf\n\nparfois la vie fait plouf \n\n") + println(fmt.Sprintf("ploufi %v", r.Body)) signed, err := ptypes.NewSignedRequest(r.Body) if err != nil { InternalError(w, r, newSignedErr(err), nil) @@ -616,19 +618,22 @@ func (form *form) AddAdmin(w http.ResponseWriter, r *http.Request) { return } - vars := mux.Vars(r) + //vars := mux.Vars(r) - // check if the formID is valid - if vars == nil || vars["targetUserID"] == "" { - http.Error(w, fmt.Sprintf("targetUserID not found: %v", vars), http.StatusInternalServerError) - return - } else if vars["performingUserID"] == "" { - http.Error(w, fmt.Sprintf("performingUserID not found: %v", vars), http.StatusInternalServerError) - return - } + /* + // check if the formID is valid + if vars == nil || vars["TargetUserID"] == "" { + http.Error(w, fmt.Sprintf("TargetUserID not found: %v", vars), http.StatusInternalServerError) + return + } else if vars["PerformingUserID"] == "" { + http.Error(w, fmt.Sprintf("PerformingUserID not found: %v", vars), http.StatusInternalServerError) + return + } - targetUserID := vars["targetUserID"] - performingUserID := vars["performingUserID"] + */ + + targetUserID := req.TargetUserID //vars["TargetUserID"] + performingUserID := req.PerformingUserID //vars["PerformingUserID"] addAdmin := types.AddAdmin{ TargetUserID: targetUserID, @@ -656,7 +661,10 @@ func (form *form) AddAdmin(w http.ResponseWriter, r *http.Request) { func (form *form) RemoveAdmin(http.ResponseWriter, *http.Request) {} // POST /adminlist -func (form *form) AdminList(http.ResponseWriter, *http.Request) {} +func (form *form) AdminList(w http.ResponseWriter, r *http.Request) { + println("un test marche parfois\n\n mais parfois pas \n\n") + txnmanager.SendResponse(w, "hellow rodl") +} // POST /forms/{formID}/addowner func (form *form) AddOwnerToForm(http.ResponseWriter, *http.Request) {} diff --git a/proxy/generate_test.go b/proxy/generate_test.go new file mode 100644 index 000000000..669356e0e --- /dev/null +++ b/proxy/generate_test.go @@ -0,0 +1,42 @@ +package proxy + +import ( + "crypto/sha256" + "encoding/base64" + "encoding/hex" + "github.com/stretchr/testify/require" + "go.dedis.ch/kyber/v3/sign/schnorr" + "testing" +) + +func TestGenerateSignature(t *testing.T) { + msg := `{"TargetUserID" : "123456", "PerformingUserID" : "123456"}` + + payload := base64.URLEncoding.EncodeToString([]byte(msg)) + + hash := sha256.New() + hash.Write([]byte(payload)) + md := hash.Sum(nil) + + pk := "6aadf480d068ac896330b726802abd0da2a5f3824f791fe8dbd4cd555e80b809" + pkhex, err := hex.DecodeString(pk) + require.NoError(t, err) + + point := suite.Scalar() + err = point.UnmarshalBinary(pkhex) + require.NoError(t, err) + + require.NoError(t, err) + + signature, err := schnorr.Sign(suite, point, md) + require.NoError(t, err) + + println(hex.EncodeToString(signature)) + println(payload) +} + +/* +CURL to add 123456 as an admin +curl -XPOST -H "Content-type: application/json" -d '{ +"Payload":"eyJUYXJnZXRVc2VySUQiIDogIjEyMzQ1NiIsICJQZXJmb3JtaW5nVXNlcklEIiA6ICIxMjM0NTYifQ==", "Signature":"942501b9ae78b63aafcfd65b582087de93c877c53754fdb6221de0444bd6d56240882042395a79b601e6cce36e10b474c42b96b12d7a0cb5909c725025978f09"}' 'http://172.19.44.254:8080/evoting/addadmin' +*/ diff --git a/proxy/types/signed.go b/proxy/types/signed.go index 7c1402317..2cfe146d0 100644 --- a/proxy/types/signed.go +++ b/proxy/types/signed.go @@ -5,6 +5,7 @@ import ( "encoding/base64" "encoding/hex" "encoding/json" + "fmt" "io" "go.dedis.ch/kyber/v3" @@ -25,6 +26,8 @@ func NewSignedRequest(r io.Reader) (SignedRequest, error) { return req, xerrors.Errorf("failed to decode signed request: %v", err) } + println(fmt.Sprintf("helloReq: %v", req)) + return req, nil } From 032fe70b5c4c5b6db3073a3938b043ea2bc0559d Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Tue, 4 Jun 2024 11:50:36 +0200 Subject: [PATCH 104/114] work: proxy add/remove/get adminlist --- contracts/evoting/controller/action.go | 1 + proxy/election.go | 124 ++++++++++++++----------- proxy/generate_test.go | 23 ++++- proxy/types/election.go | 5 +- scripts/run_docker.sh | 2 +- 5 files changed, 95 insertions(+), 60 deletions(-) diff --git a/contracts/evoting/controller/action.go b/contracts/evoting/controller/action.go index 50b1502f1..53c0786c2 100644 --- a/contracts/evoting/controller/action.go +++ b/contracts/evoting/controller/action.go @@ -179,6 +179,7 @@ func (a *RegisterAction) Execute(ctx node.Context) error { router := mux.NewRouter() router.HandleFunc(evotingPathSlash+"addadmin", ep.AddAdmin).Methods("POST") + router.HandleFunc(evotingPathSlash+"removeadmin", ep.RemoveAdmin).Methods("POST") router.HandleFunc(evotingPathSlash+"adminlist", ep.AdminList).Methods("GET") router.HandleFunc(formPath, ep.NewForm).Methods("POST") router.HandleFunc(formPath, ep.Forms).Methods("GET") diff --git a/proxy/election.go b/proxy/election.go index 2452d14fc..2d9026978 100644 --- a/proxy/election.go +++ b/proxy/election.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "net/http" + "strconv" "sync" "github.com/c4dt/d-voting/contracts/evoting" @@ -41,6 +42,7 @@ func NewForm(srv ordering.Service, p pool.Pool, orderingSvc: srv, context: ctx, formFac: fac, + adminFac: types.AdminListFactory{}, mngr: txnManaxer, pool: p, pk: pk, @@ -57,6 +59,7 @@ type form struct { logger zerolog.Logger context serde.Context formFac serde.Factory + adminFac serde.Factory mngr txnmanager.Manager pool pool.Pool pk kyber.Point @@ -244,13 +247,9 @@ func (form *form) EditForm(w http.ResponseWriter, r *http.Request) { if vars == nil || vars["formID"] == "" { http.Error(w, fmt.Sprintf("formID not found: %v", vars), http.StatusInternalServerError) return - } else if vars["userID"] == "" { - http.Error(w, fmt.Sprintf("userID not found: %v", vars), http.StatusInternalServerError) - return } formID := vars["formID"] - userID := vars["userID"] elecMD, err := form.getFormsMetadata() if err != nil { @@ -266,13 +265,13 @@ func (form *form) EditForm(w http.ResponseWriter, r *http.Request) { switch req.Action { case "open": - form.openForm(formID, userID, w, r) + form.openForm(formID, req.UserID, w, r) case "close": - form.closeForm(formID, userID, w, r) + form.closeForm(formID, req.UserID, w, r) case "combineShares": - form.combineShares(formID, userID, w, r) + form.combineShares(formID, req.UserID, w, r) case "cancel": - form.cancelForm(formID, userID, w, r) + form.cancelForm(formID, req.UserID, w, r) default: BadRequestError(w, r, xerrors.Errorf("invalid action: %s", req.Action), nil) return @@ -523,13 +522,9 @@ func (form *form) DeleteForm(w http.ResponseWriter, r *http.Request) { if vars == nil || vars["formID"] == "" { http.Error(w, fmt.Sprintf("formID not found: %v", vars), http.StatusInternalServerError) return - } else if vars["userID"] == "" { - http.Error(w, fmt.Sprintf("userID not found: %v", vars), http.StatusInternalServerError) - return } formID := vars["formID"] - userID := vars["userID"] elecMD, err := form.getFormsMetadata() if err != nil { @@ -543,27 +538,6 @@ func (form *form) DeleteForm(w http.ResponseWriter, r *http.Request) { return } - /* - // auth should contain the hex-encoded signature on the hex-encoded form - // ID - auth := r.Header.Get("Authorization") - - signature, err := hex.DecodeString(auth) - if err != nil { - BadRequestError(w, r, xerrors.Errorf("failed to decode auth: %v", err), nil) - return - } - - // check if the signature is valid - //TODO ADD User ID to existing - err = schnorr.Verify(suite, form.pk, []byte(formID+userID), signature) - if err != nil { - ForbiddenError(w, r, xerrors.Errorf("signature verification failed: %v", err), nil) - return - } - - */ - // TODO double check // get the signed request signed, err := ptypes.NewSignedRequest(r.Body) @@ -580,7 +554,7 @@ func (form *form) DeleteForm(w http.ResponseWriter, r *http.Request) { deleteForm := types.DeleteForm{ FormID: formID, - UserID: userID, + UserID: req.UserID, } data, err := deleteForm.Serialize(form.context) @@ -603,9 +577,8 @@ func (form *form) DeleteForm(w http.ResponseWriter, r *http.Request) { // TODO CHECK CAUSE NEW // POST /addtoadminlist func (form *form) AddAdmin(w http.ResponseWriter, r *http.Request) { - var req ptypes.AddAdminRequest - println("plouf plouf\n\nparfois la vie fait plouf \n\n") - println(fmt.Sprintf("ploufi %v", r.Body)) + var req ptypes.AdminRequest + signed, err := ptypes.NewSignedRequest(r.Body) if err != nil { InternalError(w, r, newSignedErr(err), nil) @@ -618,22 +591,8 @@ func (form *form) AddAdmin(w http.ResponseWriter, r *http.Request) { return } - //vars := mux.Vars(r) - - /* - // check if the formID is valid - if vars == nil || vars["TargetUserID"] == "" { - http.Error(w, fmt.Sprintf("TargetUserID not found: %v", vars), http.StatusInternalServerError) - return - } else if vars["PerformingUserID"] == "" { - http.Error(w, fmt.Sprintf("PerformingUserID not found: %v", vars), http.StatusInternalServerError) - return - } - - */ - - targetUserID := req.TargetUserID //vars["TargetUserID"] - performingUserID := req.PerformingUserID //vars["PerformingUserID"] + targetUserID := req.TargetUserID + performingUserID := req.PerformingUserID addAdmin := types.AddAdmin{ TargetUserID: targetUserID, @@ -658,12 +617,65 @@ func (form *form) AddAdmin(w http.ResponseWriter, r *http.Request) { } // POST /removetoadminlist -func (form *form) RemoveAdmin(http.ResponseWriter, *http.Request) {} +func (form *form) RemoveAdmin(w http.ResponseWriter, r *http.Request) { + var req ptypes.AdminRequest -// POST /adminlist + signed, err := ptypes.NewSignedRequest(r.Body) + if err != nil { + InternalError(w, r, newSignedErr(err), nil) + return + } + + err = signed.GetAndVerify(form.pk, &req) + if err != nil { + InternalError(w, r, getSignedErr(err), nil) + return + } + + targetUserID := req.TargetUserID + performingUserID := req.PerformingUserID + + removeAdmin := types.RemoveAdmin{ + TargetUserID: targetUserID, + PerformingUserID: performingUserID, + } + + data, err := removeAdmin.Serialize(form.context) + if err != nil { + InternalError(w, r, xerrors.Errorf("failed to marshal RemoveAdmin: %v", err), nil) + return + } + + // create the transaction and add it to the pool + txnID, lastBlock, err := form.mngr.SubmitTxn(r.Context(), evoting.CmdRemoveAdmin, evoting.FormArg, data) + if err != nil { + http.Error(w, "failed to submit txn: "+err.Error(), http.StatusInternalServerError) + return + } + + // send the transaction's information + form.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) + +} + +// GET /adminlist func (form *form) AdminList(w http.ResponseWriter, r *http.Request) { println("un test marche parfois\n\n mais parfois pas \n\n") - txnmanager.SendResponse(w, "hellow rodl") + adminList, err := types.AdminListFromStore(form.context, form.adminFac, form.orderingSvc.GetStore(), evoting.AdminListId) + if err != nil { + InternalError(w, r, xerrors.Errorf("failed to get form: %v", err), nil) + return + } + + myAdminList := "{" + for id := range adminList.AdminList { + myAdminList += strconv.Itoa(adminList.AdminList[id]) + ", " + } + myAdminList += "}" + + println(myAdminList) + + txnmanager.SendResponse(w, myAdminList) } // POST /forms/{formID}/addowner diff --git a/proxy/generate_test.go b/proxy/generate_test.go index 669356e0e..1348207b8 100644 --- a/proxy/generate_test.go +++ b/proxy/generate_test.go @@ -10,7 +10,7 @@ import ( ) func TestGenerateSignature(t *testing.T) { - msg := `{"TargetUserID" : "123456", "PerformingUserID" : "123456"}` + msg := `{"TargetUserID" : "654321", "PerformingUserID" : "123456"}` payload := base64.URLEncoding.EncodeToString([]byte(msg)) @@ -37,6 +37,27 @@ func TestGenerateSignature(t *testing.T) { /* CURL to add 123456 as an admin +-- curl -XPOST -H "Content-type: application/json" -d '{ "Payload":"eyJUYXJnZXRVc2VySUQiIDogIjEyMzQ1NiIsICJQZXJmb3JtaW5nVXNlcklEIiA6ICIxMjM0NTYifQ==", "Signature":"942501b9ae78b63aafcfd65b582087de93c877c53754fdb6221de0444bd6d56240882042395a79b601e6cce36e10b474c42b96b12d7a0cb5909c725025978f09"}' 'http://172.19.44.254:8080/evoting/addadmin' */ + +/* +CURL to add 654321 as an admin +-- +curl -XPOST -H "Content-type: application/json" -d '{ +"Payload":"eyJUYXJnZXRVc2VySUQiIDogIjY1NDMyMSIsICJQZXJmb3JtaW5nVXNlcklEIiA6ICIxMjM0NTYifQ==", "Signature":"b02557ce9133fe945dc3dd47e53883e007f06c30031b7e42159b38623923d19a5b05f1012edc8ea580fbff233ab819bd1d6b9dc72b881c2d1c9dd9f681d07a0a"}' 'http://172.19.44.254:8080/evoting/addadmin' +*/ + +/* +CURL to remove 654321 as an admin +-- +curl -XPOST -H "Content-type: application/json" -d '{ +"Payload":"eyJUYXJnZXRVc2VySUQiIDogIjY1NDMyMSIsICJQZXJmb3JtaW5nVXNlcklEIiA6ICIxMjM0NTYifQ==", "Signature":"b02557ce9133fe945dc3dd47e53883e007f06c30031b7e42159b38623923d19a5b05f1012edc8ea580fbff233ab819bd1d6b9dc72b881c2d1c9dd9f681d07a0a"}' 'http://172.19.44.254:8080/evoting/removeadmin' +*/ + +/* +CURL to get admin list +-- +curl -XGET -H "Content-type: application/json" 'http://172.19.44.254:8080/evoting/adminlist' +*/ diff --git a/proxy/types/election.go b/proxy/types/election.go index d8720cc7d..c02d54061 100644 --- a/proxy/types/election.go +++ b/proxy/types/election.go @@ -10,8 +10,8 @@ type CreateFormRequest struct { Configuration etypes.Configuration } -// AddAdminRequest defines the HTTP request for adding an admin -type AddAdminRequest struct { +// AdminRequest defines the HTTP request for adding an admin +type AdminRequest struct { TargetUserID string PerformingUserID string } @@ -47,6 +47,7 @@ type EGPairJSON struct { // UpdateFormRequest defines the HTTP request for updating a form type UpdateFormRequest struct { Action string + UserID string } // GetFormResponse defines the HTTP response when getting the form info diff --git a/scripts/run_docker.sh b/scripts/run_docker.sh index 630af08bb..67195bf1c 100755 --- a/scripts/run_docker.sh +++ b/scripts/run_docker.sh @@ -70,7 +70,7 @@ function init_dela() { function local_admin() { echo "adding local user $REACT_APP_SCIPER_ADMIN to admins"; docker compose exec backend npx cli addAdmin --sciper "$REACT_APP_SCIPER_ADMIN"; - docker compose exec backend npx cli addAdmin --sciper 987654; + docker compose exec backend npx cli addAdmin --sciper 654321; docker compose restart backend; } From ec4fcc18f2388cf14bce6154b56e8b895f76d576 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Tue, 4 Jun 2024 12:16:35 +0200 Subject: [PATCH 105/114] fix: for display --- proxy/election.go | 49 +++++++++++++++++++++++++++++------------------ 1 file changed, 30 insertions(+), 19 deletions(-) diff --git a/proxy/election.go b/proxy/election.go index 2d9026978..3fc05ab70 100644 --- a/proxy/election.go +++ b/proxy/election.go @@ -37,6 +37,13 @@ func NewForm(srv ordering.Service, p pool.Pool, logger := dela.Logger.With().Timestamp().Str("role", "evoting-proxy").Logger() + // Compute the ID of the admin list id + // We need it to filter the send list of form + h := sha256.New() + h.Write([]byte(evoting.AdminListId)) + adminListIDBuf := h.Sum(nil) + adminListID := hex.EncodeToString(adminListIDBuf) + return &form{ logger: logger, orderingSvc: srv, @@ -46,6 +53,7 @@ func NewForm(srv ordering.Service, p pool.Pool, mngr: txnManaxer, pool: p, pk: pk, + adminListID: adminListID, } } @@ -63,6 +71,7 @@ type form struct { mngr txnmanager.Manager pool pool.Pool pk kyber.Point + adminListID string } // NewForm implements proxy.Proxy @@ -480,30 +489,32 @@ func (form *form) Forms(w http.ResponseWriter, r *http.Request) { // get the forms for i, id := range elecMD.FormsIDs { - form, err := types.FormFromStore(form.context, form.formFac, id, form.orderingSvc.GetStore()) - if err != nil { - InternalError(w, r, xerrors.Errorf("failed to get form: %v", err), nil) - return - } - - var pubkeyBuf []byte - - if form.Pubkey != nil { - pubkeyBuf, err = form.Pubkey.MarshalBinary() + if id != form.adminListID { + form, err := types.FormFromStore(form.context, form.formFac, id, form.orderingSvc.GetStore()) if err != nil { - InternalError(w, r, xerrors.Errorf("failed to marshal pubkey: %v", err), nil) + InternalError(w, r, xerrors.Errorf("failed to get form: %v", err), nil) return } - } - info := ptypes.LightForm{ - FormID: string(form.FormID), - Title: form.Configuration.Title, - Status: uint16(form.Status), - Pubkey: hex.EncodeToString(pubkeyBuf), - } + var pubkeyBuf []byte + + if form.Pubkey != nil { + pubkeyBuf, err = form.Pubkey.MarshalBinary() + if err != nil { + InternalError(w, r, xerrors.Errorf("failed to marshal pubkey: %v", err), nil) + return + } + } - allFormsInfo[i] = info + info := ptypes.LightForm{ + FormID: string(form.FormID), + Title: form.Configuration.Title, + Status: uint16(form.Status), + Pubkey: hex.EncodeToString(pubkeyBuf), + } + + allFormsInfo[i] = info + } } response := ptypes.GetFormsResponse{Forms: allFormsInfo} From d4cf486bfec98496f995003f868f8fecaa0d8ed1 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 5 Jun 2024 18:04:58 +0200 Subject: [PATCH 106/114] fix: fix bug on transaction result --- contracts/evoting/controller/action.go | 2 +- proxy/election.go | 36 ++++++++++++++++++++++---- proxy/txnmanager/transaction.go | 20 +++++++++++--- 3 files changed, 48 insertions(+), 10 deletions(-) diff --git a/contracts/evoting/controller/action.go b/contracts/evoting/controller/action.go index 53c0786c2..fcd3eb532 100644 --- a/contracts/evoting/controller/action.go +++ b/contracts/evoting/controller/action.go @@ -172,7 +172,7 @@ func (a *RegisterAction) Execute(ctx node.Context) error { return xerrors.Errorf("failed to unmarshal proxy key: %v", err) } - transactionManager := txnmanager.NewTransactionManager(mngr, p, sjson.NewContext(), proxykey, blocks, signer) + transactionManager := txnmanager.NewTransactionManager(mngr, p, sjson.NewContext(), proxykey, blocks, signer, validation) ep := eproxy.NewForm(ordering, p, sjson.NewContext(), formFac, proxykey, transactionManager) diff --git a/proxy/election.go b/proxy/election.go index 3fc05ab70..530297690 100644 --- a/proxy/election.go +++ b/proxy/election.go @@ -112,6 +112,8 @@ func (form *form) NewForm(w http.ResponseWriter, r *http.Request) { return } + println("TXNewForm ID: " + hex.EncodeToString(txnID)) + // hash the transaction hash := sha256.New() hash.Write(txnID) @@ -618,6 +620,7 @@ func (form *form) AddAdmin(w http.ResponseWriter, r *http.Request) { // create the transaction and add it to the pool txnID, lastBlock, err := form.mngr.SubmitTxn(r.Context(), evoting.CmdAddAdmin, evoting.FormArg, data) + println("TXAddAdmin ID: " + hex.EncodeToString(txnID)) if err != nil { http.Error(w, "failed to submit txn: "+err.Error(), http.StatusInternalServerError) return @@ -663,15 +666,40 @@ func (form *form) RemoveAdmin(w http.ResponseWriter, r *http.Request) { http.Error(w, "failed to submit txn: "+err.Error(), http.StatusInternalServerError) return } - + println("TXRemoveAdmin ID: " + hex.EncodeToString(txnID)) // send the transaction's information - form.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) + + // hash the transaction + hash := sha256.New() + hash.Write(txnID) + formID := hash.Sum(nil) + + // create it to get the token + transactionClientInfo, err := form.mngr.CreateTransactionResult(txnID, lastBlock, txnmanager.UnknownTransactionStatus) + if err != nil { + http.Error(w, "failed to create transaction info: "+err.Error(), http.StatusInternalServerError) + return + } + + response := ptypes.CreateFormResponse{ + FormID: hex.EncodeToString(formID), + Token: transactionClientInfo.Token, + } + + println("\n\nnew code ...\n") + + // send the response json + err = txnmanager.SendResponse(w, response) + if err != nil { + fmt.Printf("Caught unhandled error: %+v", err) + } + + //form.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) } // GET /adminlist func (form *form) AdminList(w http.ResponseWriter, r *http.Request) { - println("un test marche parfois\n\n mais parfois pas \n\n") adminList, err := types.AdminListFromStore(form.context, form.adminFac, form.orderingSvc.GetStore(), evoting.AdminListId) if err != nil { InternalError(w, r, xerrors.Errorf("failed to get form: %v", err), nil) @@ -684,8 +712,6 @@ func (form *form) AdminList(w http.ResponseWriter, r *http.Request) { } myAdminList += "}" - println(myAdminList) - txnmanager.SendResponse(w, myAdminList) } diff --git a/proxy/txnmanager/transaction.go b/proxy/txnmanager/transaction.go index 0cce21e7a..f8f189629 100644 --- a/proxy/txnmanager/transaction.go +++ b/proxy/txnmanager/transaction.go @@ -7,6 +7,7 @@ import ( b64 "encoding/base64" "encoding/json" "fmt" + "go.dedis.ch/dela/core/validation" "net/http" "strconv" "sync" @@ -32,7 +33,7 @@ const ( // NewTransactionManager returns a new initialized transaction manager func NewTransactionManager(mngr txn.Manager, p pool.Pool, - ctx serde.Context, pk kyber.Point, blocks blockstore.BlockStore, signer crypto.Signer) Manager { + ctx serde.Context, pk kyber.Point, blocks blockstore.BlockStore, signer crypto.Signer, val validation.Service) Manager { logger := dela.Logger.With().Timestamp().Str("role", "proxy-txmanager").Logger() @@ -44,6 +45,7 @@ func NewTransactionManager(mngr txn.Manager, p pool.Pool, pk: pk, blocks: blocks, signer: signer, + val: val, } } @@ -60,6 +62,7 @@ type manager struct { pk kyber.Point blocks blockstore.BlockStore signer crypto.Signer + val validation.Service } // StatusHandlerGet checks if the transaction is included in the blockchain @@ -183,10 +186,19 @@ func (h *manager) checkTxnIncluded(transactionID []byte, lastBlockIdx uint64) (T } // check if the transaction is in the block - transactions := blockLink.GetBlock().GetTransactions() + transactions := blockLink.GetBlock().GetData().GetTransactionResults() //blockLink.GetBlock().GetTransactions() + for _, txn := range transactions { - if bytes.Equal(txn.GetID(), transactionID) { - return IncludedTransaction, blockLink.GetBlock().GetIndex() + + if bytes.Equal(txn.GetTransaction().GetID(), transactionID) { + accepted, reason := txn.GetStatus() + if accepted { + return IncludedTransaction, blockLink.GetBlock().GetIndex() + } else { + println(reason) + return RejectedTransaction, blockLink.GetBlock().GetIndex() + } + } } From 31d1230862bc69eec60aa7874caa73a0ded88b9c Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 12 Jun 2024 21:22:30 +0200 Subject: [PATCH 107/114] fix: code cleaning + continue implem proxy --- contracts/evoting/controller/action.go | 4 + proxy/election.go | 254 ++++++++++++++++++------- proxy/generate_test.go | 26 ++- proxy/types/election.go | 10 +- 4 files changed, 216 insertions(+), 78 deletions(-) diff --git a/contracts/evoting/controller/action.go b/contracts/evoting/controller/action.go index fcd3eb532..2d262ffbc 100644 --- a/contracts/evoting/controller/action.go +++ b/contracts/evoting/controller/action.go @@ -181,6 +181,10 @@ func (a *RegisterAction) Execute(ctx node.Context) error { router.HandleFunc(evotingPathSlash+"addadmin", ep.AddAdmin).Methods("POST") router.HandleFunc(evotingPathSlash+"removeadmin", ep.RemoveAdmin).Methods("POST") router.HandleFunc(evotingPathSlash+"adminlist", ep.AdminList).Methods("GET") + router.HandleFunc(formIDPath+"/addowner", ep.AddOwnerToForm).Methods("POST") + router.HandleFunc(formIDPath+"/removeowner", ep.RemoveOwnerToForm).Methods("POST") + router.HandleFunc(formIDPath+"/addvoter", ep.AddVoterToForm).Methods("POST") + router.HandleFunc(formIDPath+"/removevoter", ep.RemoveVoterToForm).Methods("POST") router.HandleFunc(formPath, ep.NewForm).Methods("POST") router.HandleFunc(formPath, ep.Forms).Methods("GET") router.HandleFunc(formPath, eproxy.AllowCORS).Methods("OPTIONS") diff --git a/proxy/election.go b/proxy/election.go index 530297690..8f7586d8d 100644 --- a/proxy/election.go +++ b/proxy/election.go @@ -587,29 +587,16 @@ func (form *form) DeleteForm(w http.ResponseWriter, r *http.Request) { form.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) } -// TODO CHECK CAUSE NEW // POST /addtoadminlist func (form *form) AddAdmin(w http.ResponseWriter, r *http.Request) { - var req ptypes.AdminRequest - - signed, err := ptypes.NewSignedRequest(r.Body) + req, err := form.getPermissionOpRequest(w, r) if err != nil { - InternalError(w, r, newSignedErr(err), nil) return } - err = signed.GetAndVerify(form.pk, &req) - if err != nil { - InternalError(w, r, getSignedErr(err), nil) - return - } - - targetUserID := req.TargetUserID - performingUserID := req.PerformingUserID - addAdmin := types.AddAdmin{ - TargetUserID: targetUserID, - PerformingUserID: performingUserID, + TargetUserID: req.TargetUserID, + PerformingUserID: req.PerformingUserID, } data, err := addAdmin.Serialize(form.context) @@ -620,7 +607,6 @@ func (form *form) AddAdmin(w http.ResponseWriter, r *http.Request) { // create the transaction and add it to the pool txnID, lastBlock, err := form.mngr.SubmitTxn(r.Context(), evoting.CmdAddAdmin, evoting.FormArg, data) - println("TXAddAdmin ID: " + hex.EncodeToString(txnID)) if err != nil { http.Error(w, "failed to submit txn: "+err.Error(), http.StatusInternalServerError) return @@ -632,100 +618,196 @@ func (form *form) AddAdmin(w http.ResponseWriter, r *http.Request) { // POST /removetoadminlist func (form *form) RemoveAdmin(w http.ResponseWriter, r *http.Request) { - var req ptypes.AdminRequest + req, err := form.getPermissionOpRequest(w, r) + if err != nil { + return + } - signed, err := ptypes.NewSignedRequest(r.Body) + removeAdmin := types.RemoveAdmin{ + TargetUserID: req.TargetUserID, + PerformingUserID: req.PerformingUserID, + } + + data, err := removeAdmin.Serialize(form.context) if err != nil { - InternalError(w, r, newSignedErr(err), nil) + InternalError(w, r, xerrors.Errorf("failed to marshal RemoveAdmin: %v", err), nil) return } - err = signed.GetAndVerify(form.pk, &req) + // create the transaction and add it to the pool + txnID, lastBlock, err := form.mngr.SubmitTxn(r.Context(), evoting.CmdRemoveAdmin, evoting.FormArg, data) if err != nil { - InternalError(w, r, getSignedErr(err), nil) + http.Error(w, "failed to submit txn: "+err.Error(), http.StatusInternalServerError) return } - targetUserID := req.TargetUserID - performingUserID := req.PerformingUserID + form.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) +} - removeAdmin := types.RemoveAdmin{ - TargetUserID: targetUserID, - PerformingUserID: performingUserID, +// GET /adminlist +func (form *form) AdminList(w http.ResponseWriter, r *http.Request) { + adminList, err := types.AdminListFromStore(form.context, form.adminFac, form.orderingSvc.GetStore(), evoting.AdminListId) + if err != nil { + InternalError(w, r, xerrors.Errorf("failed to get form: %v", err), nil) + return } - data, err := removeAdmin.Serialize(form.context) + // Used to check whether it is the last SCIPER printed + count := 0 + lenAdminList := len(adminList.AdminList) + + myAdminList := "{" + for id := range adminList.AdminList { + count++ + + // If last element, does not add ', ' otherwise add ', ' + if count == lenAdminList { + myAdminList += strconv.Itoa(adminList.AdminList[id]) + } else { + myAdminList += strconv.Itoa(adminList.AdminList[id]) + ", " + } + + } + myAdminList += "}" + + txnmanager.SendResponse(w, myAdminList) +} + +// POST /forms/{formID}/addowner +func (form *form) AddOwnerToForm(w http.ResponseWriter, r *http.Request) { + req, err := form.getPermissionOpRequest(w, r) if err != nil { - InternalError(w, r, xerrors.Errorf("failed to marshal RemoveAdmin: %v", err), nil) + return + } + + formID, hasFailed := form.extractAndRetrieveFormID(w, r) + if hasFailed { + return + } + + addOwner := types.AddOwner{ + FormID: formID, + TargetUserID: req.TargetUserID, + PerformingUserID: req.PerformingUserID, + } + + data, err := addOwner.Serialize(form.context) + if err != nil { + InternalError(w, r, xerrors.Errorf("failed to marshal AddOwner: %v", err), nil) return } // create the transaction and add it to the pool - txnID, lastBlock, err := form.mngr.SubmitTxn(r.Context(), evoting.CmdRemoveAdmin, evoting.FormArg, data) + txnID, lastBlock, err := form.mngr.SubmitTxn(r.Context(), evoting.CmdAddOwnerForm, evoting.FormArg, data) if err != nil { http.Error(w, "failed to submit txn: "+err.Error(), http.StatusInternalServerError) return } - println("TXRemoveAdmin ID: " + hex.EncodeToString(txnID)) - // send the transaction's information - // hash the transaction - hash := sha256.New() - hash.Write(txnID) - formID := hash.Sum(nil) + form.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) +} - // create it to get the token - transactionClientInfo, err := form.mngr.CreateTransactionResult(txnID, lastBlock, txnmanager.UnknownTransactionStatus) +// POST /forms/{formID}/removeowner +func (form *form) RemoveOwnerToForm(w http.ResponseWriter, r *http.Request) { + req, err := form.getPermissionOpRequest(w, r) if err != nil { - http.Error(w, "failed to create transaction info: "+err.Error(), http.StatusInternalServerError) return } - response := ptypes.CreateFormResponse{ - FormID: hex.EncodeToString(formID), - Token: transactionClientInfo.Token, + formID, hasFailed := form.extractAndRetrieveFormID(w, r) + if hasFailed { + return } - println("\n\nnew code ...\n") + removeOwner := types.RemoveOwner{ + FormID: formID, + TargetUserID: req.TargetUserID, + PerformingUserID: req.PerformingUserID, + } - // send the response json - err = txnmanager.SendResponse(w, response) + data, err := removeOwner.Serialize(form.context) if err != nil { - fmt.Printf("Caught unhandled error: %+v", err) + InternalError(w, r, xerrors.Errorf("failed to marshal RemoveOwner: %v", err), nil) + return } - //form.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) + // create the transaction and add it to the pool + txnID, lastBlock, err := form.mngr.SubmitTxn(r.Context(), evoting.CmdRemoveOwnerForm, evoting.FormArg, data) + if err != nil { + http.Error(w, "failed to submit txn: "+err.Error(), http.StatusInternalServerError) + return + } + form.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) } -// GET /adminlist -func (form *form) AdminList(w http.ResponseWriter, r *http.Request) { - adminList, err := types.AdminListFromStore(form.context, form.adminFac, form.orderingSvc.GetStore(), evoting.AdminListId) +// POST /forms/{formID}/addvoter +func (form *form) AddVoterToForm(w http.ResponseWriter, r *http.Request) { + req, err := form.getPermissionOpRequest(w, r) if err != nil { - InternalError(w, r, xerrors.Errorf("failed to get form: %v", err), nil) return } - myAdminList := "{" - for id := range adminList.AdminList { - myAdminList += strconv.Itoa(adminList.AdminList[id]) + ", " + formID, hasFailed := form.extractAndRetrieveFormID(w, r) + if hasFailed { + return } - myAdminList += "}" - txnmanager.SendResponse(w, myAdminList) -} + addVoter := types.AddVoter{ + FormID: formID, + TargetUserID: req.TargetUserID, + PerformingUserID: req.PerformingUserID, + } -// POST /forms/{formID}/addowner -func (form *form) AddOwnerToForm(http.ResponseWriter, *http.Request) {} + data, err := addVoter.Serialize(form.context) + if err != nil { + InternalError(w, r, xerrors.Errorf("failed to marshal AddVoter: %v", err), nil) + return + } -// POST /forms/{formID}/removeowner -func (form *form) RemoveOwnerToForm(http.ResponseWriter, *http.Request) {} + // create the transaction and add it to the pool + txnID, lastBlock, err := form.mngr.SubmitTxn(r.Context(), evoting.CmdAddVoterForm, evoting.FormArg, data) + if err != nil { + http.Error(w, "failed to submit txn: "+err.Error(), http.StatusInternalServerError) + return + } -// POST /forms/{formID}/addvoter -func (form *form) AddVoterToForm(http.ResponseWriter, *http.Request) {} + form.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) +} // POST /forms/{formID}/removevoter -func (form *form) RemoveVoterToForm(http.ResponseWriter, *http.Request) {} +func (form *form) RemoveVoterToForm(w http.ResponseWriter, r *http.Request) { + req, err := form.getPermissionOpRequest(w, r) + if err != nil { + return + } + + formID, hasFailed := form.extractAndRetrieveFormID(w, r) + if hasFailed { + return + } + + removeVoter := types.RemoveVoter{ + FormID: formID, + TargetUserID: req.TargetUserID, + PerformingUserID: req.PerformingUserID, + } + + data, err := removeVoter.Serialize(form.context) + if err != nil { + InternalError(w, r, xerrors.Errorf("failed to marshal RemoveVoter: %v", err), nil) + return + } + + // create the transaction and add it to the pool + txnID, lastBlock, err := form.mngr.SubmitTxn(r.Context(), evoting.CmdRemoveVoterForm, evoting.FormArg, data) + if err != nil { + http.Error(w, "failed to submit txn: "+err.Error(), http.StatusInternalServerError) + return + } + + form.mngr.SendTransactionInfo(w, txnID, lastBlock, txnmanager.UnknownTransactionStatus) +} // ===== HELPER ===== @@ -749,3 +831,47 @@ func (form *form) getFormsMetadata() (types.FormsMetadata, error) { return md, nil } + +func (form *form) getPermissionOpRequest(w http.ResponseWriter, r *http.Request) (ptypes.PermissionOperationRequest, error) { + var req ptypes.PermissionOperationRequest + + // get the signed request + signed, err := ptypes.NewSignedRequest(r.Body) + if err != nil { + InternalError(w, r, newSignedErr(err), nil) + return ptypes.PermissionOperationRequest{}, err + } + + // get the request and verify the signature + err = signed.GetAndVerify(form.pk, &req) + if err != nil { + InternalError(w, r, getSignedErr(err), nil) + return ptypes.PermissionOperationRequest{}, err + } + return req, err +} + +func (form *form) extractAndRetrieveFormID(w http.ResponseWriter, r *http.Request) (string, bool) { + vars := mux.Vars(r) + + // check if the formID is valid + if vars == nil || vars["formID"] == "" { + http.Error(w, fmt.Sprintf("formID not found: %v", vars), http.StatusInternalServerError) + return "", true + } + + formID := vars["formID"] + + elecMD, err := form.getFormsMetadata() + if err != nil { + http.Error(w, "failed to get form metadata", http.StatusNotFound) + return "", true + } + + // check if the form exists + if elecMD.FormsIDs.Contains(formID) < 0 { + http.Error(w, "the form does not exist", http.StatusNotFound) + return "", true + } + return formID, false +} diff --git a/proxy/generate_test.go b/proxy/generate_test.go index 1348207b8..4a0effd27 100644 --- a/proxy/generate_test.go +++ b/proxy/generate_test.go @@ -9,16 +9,30 @@ import ( "testing" ) -func TestGenerateSignature(t *testing.T) { - msg := `{"TargetUserID" : "654321", "PerformingUserID" : "123456"}` +/* +TestGenerateSignatureAndB64Payload is a code snippet that help developer +to generate Signature and Base64 Payload to create cURL request for debug environment. + +How to use it: +- Feel free to change the INPUT following docs/api.md +- Run the test and use the provided result as a cURL request. +*/ +func TestGenerateSignatureAndB64Payload(t *testing.T) { + // #### INPUT #### + // rawPayload must be built following docs/api.md + rawPayload := `{"TargetUserID" : "654321", "PerformingUserID" : "123456"}` - payload := base64.URLEncoding.EncodeToString([]byte(msg)) + // pk must be set according to the public key used to run the system. + pk := "6aadf480d068ac896330b726802abd0da2a5f3824f791fe8dbd4cd555e80b809" + // #### END INPUT #### + + // #### DO NOT MODIFY BELOW #### + payload := base64.URLEncoding.EncodeToString([]byte(rawPayload)) hash := sha256.New() hash.Write([]byte(payload)) md := hash.Sum(nil) - pk := "6aadf480d068ac896330b726802abd0da2a5f3824f791fe8dbd4cd555e80b809" pkhex, err := hex.DecodeString(pk) require.NoError(t, err) @@ -31,8 +45,8 @@ func TestGenerateSignature(t *testing.T) { signature, err := schnorr.Sign(suite, point, md) require.NoError(t, err) - println(hex.EncodeToString(signature)) - println(payload) + println("Signature: " + hex.EncodeToString(signature)) + println("Payload: " + payload) } /* diff --git a/proxy/types/election.go b/proxy/types/election.go index c02d54061..343709eeb 100644 --- a/proxy/types/election.go +++ b/proxy/types/election.go @@ -10,14 +10,8 @@ type CreateFormRequest struct { Configuration etypes.Configuration } -// AdminRequest defines the HTTP request for adding an admin -type AdminRequest struct { - TargetUserID string - PerformingUserID string -} - -// RemoveAdminRequest defines the HTTP request for Removing an admin -type RemoveAdminRequest struct { +// PermissionOperationRequest defines the HTTP request for performing an operation request +type PermissionOperationRequest struct { TargetUserID string PerformingUserID string } From 3cc3b98f6ccb61c0a5af202f2a61ab72fc01145d Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Sun, 16 Jun 2024 22:59:58 +0200 Subject: [PATCH 108/114] fix: remove commented query for testing --- proxy/generate_test.go | 27 --------------------------- 1 file changed, 27 deletions(-) diff --git a/proxy/generate_test.go b/proxy/generate_test.go index 4a0effd27..a4148893c 100644 --- a/proxy/generate_test.go +++ b/proxy/generate_test.go @@ -48,30 +48,3 @@ func TestGenerateSignatureAndB64Payload(t *testing.T) { println("Signature: " + hex.EncodeToString(signature)) println("Payload: " + payload) } - -/* -CURL to add 123456 as an admin --- -curl -XPOST -H "Content-type: application/json" -d '{ -"Payload":"eyJUYXJnZXRVc2VySUQiIDogIjEyMzQ1NiIsICJQZXJmb3JtaW5nVXNlcklEIiA6ICIxMjM0NTYifQ==", "Signature":"942501b9ae78b63aafcfd65b582087de93c877c53754fdb6221de0444bd6d56240882042395a79b601e6cce36e10b474c42b96b12d7a0cb5909c725025978f09"}' 'http://172.19.44.254:8080/evoting/addadmin' -*/ - -/* -CURL to add 654321 as an admin --- -curl -XPOST -H "Content-type: application/json" -d '{ -"Payload":"eyJUYXJnZXRVc2VySUQiIDogIjY1NDMyMSIsICJQZXJmb3JtaW5nVXNlcklEIiA6ICIxMjM0NTYifQ==", "Signature":"b02557ce9133fe945dc3dd47e53883e007f06c30031b7e42159b38623923d19a5b05f1012edc8ea580fbff233ab819bd1d6b9dc72b881c2d1c9dd9f681d07a0a"}' 'http://172.19.44.254:8080/evoting/addadmin' -*/ - -/* -CURL to remove 654321 as an admin --- -curl -XPOST -H "Content-type: application/json" -d '{ -"Payload":"eyJUYXJnZXRVc2VySUQiIDogIjY1NDMyMSIsICJQZXJmb3JtaW5nVXNlcklEIiA6ICIxMjM0NTYifQ==", "Signature":"b02557ce9133fe945dc3dd47e53883e007f06c30031b7e42159b38623923d19a5b05f1012edc8ea580fbff233ab819bd1d6b9dc72b881c2d1c9dd9f681d07a0a"}' 'http://172.19.44.254:8080/evoting/removeadmin' -*/ - -/* -CURL to get admin list --- -curl -XGET -H "Content-type: application/json" 'http://172.19.44.254:8080/evoting/adminlist' -*/ From 1f1435119bc0265c850a2a2061a5b5965c9e53aa Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Sun, 16 Jun 2024 23:06:10 +0200 Subject: [PATCH 109/114] fix: improve comments to make govet happy --- proxy/generate_test.go | 3 ++- proxy/types/election.go | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/proxy/generate_test.go b/proxy/generate_test.go index a4148893c..8fa88d38e 100644 --- a/proxy/generate_test.go +++ b/proxy/generate_test.go @@ -11,7 +11,8 @@ import ( /* TestGenerateSignatureAndB64Payload is a code snippet that help developer -to generate Signature and Base64 Payload to create cURL request for debug environment. +to generate Signature and Base64 Payload to create cURL request for +debug environment. How to use it: - Feel free to change the INPUT following docs/api.md diff --git a/proxy/types/election.go b/proxy/types/election.go index 343709eeb..8058b50b4 100644 --- a/proxy/types/election.go +++ b/proxy/types/election.go @@ -10,7 +10,8 @@ type CreateFormRequest struct { Configuration etypes.Configuration } -// PermissionOperationRequest defines the HTTP request for performing an operation request +// PermissionOperationRequest defines the HTTP request for performing +// an operation request type PermissionOperationRequest struct { TargetUserID string PerformingUserID string From 148b6ca8c827247caf78779276b92028e411df97 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Sun, 16 Jun 2024 23:27:51 +0200 Subject: [PATCH 110/114] fix: clean the code --- proxy/election.go | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/proxy/election.go b/proxy/election.go index 8f7586d8d..d60499725 100644 --- a/proxy/election.go +++ b/proxy/election.go @@ -112,8 +112,6 @@ func (form *form) NewForm(w http.ResponseWriter, r *http.Request) { return } - println("TXNewForm ID: " + hex.EncodeToString(txnID)) - // hash the transaction hash := sha256.New() hash.Write(txnID) @@ -550,8 +548,7 @@ func (form *form) DeleteForm(w http.ResponseWriter, r *http.Request) { http.Error(w, "the form does not exist", http.StatusNotFound) return } - - // TODO double check + // get the signed request signed, err := ptypes.NewSignedRequest(r.Body) if err != nil { From a91682dfaea85151addea3319d16ad72fbf6ff0b Mon Sep 17 00:00:00 2001 From: Maxime <61186830+MaximeZmt@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:10:06 +0200 Subject: [PATCH 111/114] fix: remove debug print --- proxy/types/signed.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/proxy/types/signed.go b/proxy/types/signed.go index 2cfe146d0..7c1402317 100644 --- a/proxy/types/signed.go +++ b/proxy/types/signed.go @@ -5,7 +5,6 @@ import ( "encoding/base64" "encoding/hex" "encoding/json" - "fmt" "io" "go.dedis.ch/kyber/v3" @@ -26,8 +25,6 @@ func NewSignedRequest(r io.Reader) (SignedRequest, error) { return req, xerrors.Errorf("failed to decode signed request: %v", err) } - println(fmt.Sprintf("helloReq: %v", req)) - return req, nil } From cdda328d69adc2dcd4593cd3ac841c9deef18d25 Mon Sep 17 00:00:00 2001 From: Maxime <61186830+MaximeZmt@users.noreply.github.com> Date: Thu, 20 Jun 2024 15:10:51 +0200 Subject: [PATCH 112/114] fix: revert change --- scripts/run_docker.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/run_docker.sh b/scripts/run_docker.sh index 67195bf1c..630af08bb 100755 --- a/scripts/run_docker.sh +++ b/scripts/run_docker.sh @@ -70,7 +70,7 @@ function init_dela() { function local_admin() { echo "adding local user $REACT_APP_SCIPER_ADMIN to admins"; docker compose exec backend npx cli addAdmin --sciper "$REACT_APP_SCIPER_ADMIN"; - docker compose exec backend npx cli addAdmin --sciper 654321; + docker compose exec backend npx cli addAdmin --sciper 987654; docker compose restart backend; } From 05b3d33c69c33046f7dbd884752d94deb7194e48 Mon Sep 17 00:00:00 2001 From: Maxime Zammit Date: Wed, 26 Jun 2024 23:47:43 +0200 Subject: [PATCH 113/114] docs: update api.md --- docs/api.md | 183 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 179 insertions(+), 4 deletions(-) diff --git a/docs/api.md b/docs/api.md index bd8fc1264..318970bfd 100644 --- a/docs/api.md +++ b/docs/api.md @@ -1,6 +1,6 @@ # API documentation -_Documentation Last Review: 11.04.2022_ +_Documentation Last Review: 27.06.2024_ ## Regular workflow: @@ -274,7 +274,7 @@ Return: ``` -# SC?: Form cancel 🔐 +# SC7: Form cancel 🔐 | | | | ------ | ------------------------- | @@ -291,6 +291,7 @@ Return: Return: `200 OK` + ```json { "Status": 0, @@ -298,7 +299,7 @@ Return: } ``` -# SC?: Form delete +# SC8: Form delete | | | | ------- | -------------------------- | @@ -317,6 +318,7 @@ formID: Return: `200 OK` + ```json { "Status": 0, @@ -324,7 +326,7 @@ Return: } ``` -# SC?: Form infos from all forms +# SC9: Form infos from all forms | | | | ------ | ---------------- | @@ -349,6 +351,106 @@ Return: } ``` +# SC10: Add an owner to a form 🔐 + +| | | +| ------ |-----------------------------------| +| URL | `/evoting/form/{formID}/addowner` | +| Method | `POST` | +| Input | `application/json` | +```json +{ + "TargetUserID": "", + "PerformingUserID": "" +} +``` + +Return: + +`200 OK` + +```json +{ + "Status": 0, + "Token": "" +} +``` + +# SC11: Remove an owner from the form 🔐 + +| | | +|--------|--------------------------------------| +| URL | `/evoting/form/{formID}/removeowner` | +| Method | `POST` | +| Input | `application/json` | +```json +{ + "TargetUserID": "", + "PerformingUserID": "" +} +``` + +Return: + +`200 OK` + +```json +{ + "Status": 0, + "Token": "" +} +``` + +# SC12: Add a voter to the Form 🔐 + +| | | +| ------ |-----------------------------------| +| URL | `/evoting/form/{formID}/addvoter` | +| Method | `POST` | +| Input | `application/json` | +```json +{ + "TargetUserID": "", + "PerformingUserID": "" +} +``` + +Return: + +`200 OK` + +```json +{ + "Status": 0, + "Token": "" +} +``` + +# SC13: Remove a voter from the Form 🔐 + +| | | +|--------|--------------------------------------| +| URL | `/evoting/form/{formID}/removevoter` | +| Method | `POST` | +| Input | `application/json` | +```json +{ + "TargetUserID": "", + "PerformingUserID": "" +} +``` + +Return: + +`200 OK` + +```json +{ + "Status": 0, + "Token": "" +} +``` + # DK1: DKG init 🔐 | | | @@ -467,3 +569,76 @@ Status can be: - 2: transaction not included The token is an updated version of the token in the URL that can be used to check again the status of the transaction if it is not yet included. + +# A1: Add an admin to the AdminList 🔐 + +| | | +| ------ |---------------------| +| URL | `/evoting/addadmin` | +| Method | `POST` | +| Input | `application/json` | +```json +{ + "TargetUserID": "", + "PerformingUserID": "" +} +``` + +Return: + +`200 OK` + +```json +{ + "Status": 0, + "Token": "" +} +``` + +# A2: Remove an admin from the AdminList 🔐 + +| | | +| ------ |------------------------| +| URL | `/evoting/removeadmin` | +| Method | `POST` | +| Input | `application/json` | + +```json +{ + "TargetUserID": "", + "PerformingUserID": "" +} +``` + +Return: + +`200 OK` + +```json +{ + "Status": 0, + "Token": "" +} +``` + +# A3: Get the AdminList + + + +| | | +| ------ |----------------------| +| URL | `/evoting/adminlist` | +| Method | `GET` | +| Input | | + +Return: + +`200 OK` + +```json +{ + SCIPERs List +} +``` + + From 98fa438511be9fc38e8137470018e9aeef59424d Mon Sep 17 00:00:00 2001 From: Maxime <61186830+MaximeZmt@users.noreply.github.com> Date: Tue, 2 Jul 2024 15:29:16 +0200 Subject: [PATCH 114/114] Update api.md --- docs/api.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api.md b/docs/api.md index 318970bfd..fc989f297 100644 --- a/docs/api.md +++ b/docs/api.md @@ -637,7 +637,7 @@ Return: ```json { - SCIPERs List + "", "", "..." } ```