diff --git a/contracts/evoting/admin_test.go b/contracts/evoting/admin_test.go new file mode 100644 index 00000000..dee5ddde --- /dev/null +++ b/contracts/evoting/admin_test.go @@ -0,0 +1,48 @@ +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() +} + +// 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) { + 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 00000000..29255548 --- /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) { + 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) { + 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 c9845338..be6023ad 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 00000000..e5d26706 --- /dev/null +++ b/contracts/evoting/types/admin.go @@ -0,0 +1,74 @@ +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) + if err != nil { + return adminForm, xerrors.Errorf("While deserializing: %v", err) + } + + adminForm, ok := message.(AdminForm) + if !ok { + return adminForm, xerrors.Errorf("Wrong message type: %T", message) + } + + return adminForm, nil +}