Commit 7e4ef127 authored by Caro Axel's avatar Caro Axel Committed by Loïck Bonniot

[c] Add sequence analysis functions and skeleton

parent 94c7a2a2
package common
import (
"errors"
)
// FindNextIndex analyses the specified sequence and tries to find the next occurence of id after the specified index (excluded)
// Therefore to find the first occurence of the id in the sequence, use -1 as the index
//
// If there is no occurence of id, then -1 is returned
//
// The sequence is supposed to be correct (in regards to its mathematical definition), and id is supposed to be a valid id for the sequence
func FindNextIndex(s []uint32, id uint32, index int) (int, error) {
if index >= len(s) || index < -1 {
return -1, errors.New("Index out of range")
}
for i := index+1; i < len(s); i++ {
if s[i] == id {
return i, nil
}
}
return -1, nil
}
// GetPendingSet analyses the specified sequence and computes the set of ids occuring between index (excluded) and the previous occurence of id
//
// The sequence is supposed to be correct (in regards to its mathematical definition), and id is supposed to be a valid id for the sequence
//
// If the index is not the one of the specified id in the sequence, the result still holds, but may be incomplete for your needs
// If the id is not valid for the specified sequence, the result will be the set of ids of the sequence
func GetPendingSet(s []uint32, id uint32, index int) ([]uint32, error) {
res := []uint32{}
if index >= len(s) || index < 0 {
return res, errors.New("Index out of range")
}
curIndex := index-1
if curIndex < 0 {
return res, nil
}
for curIndex > -1 && s[curIndex] != id {
curId := s[curIndex]
if !contains(res, curId) {
res = append(res, curId)
}
curIndex--
}
return res, nil
}
// GetSendSet analyses the specified sequence and computes the set of ids occuring between index (excluded) and the next occurence of id
//
// The sequence is supposed to be correct (in regards to its mathematical definition), and id is supposed to be a valid id for the sequence
//
// If the index is not the one of the specified id in the sequence, the result still holds, but may be incomplete for your needs
// If the id is not valid for the specified sequence, the result will be the set of ids of the sequence
func GetSendSet(s []uint32, id uint32, index int) ([]uint32, error) {
res := []uint32{}
if index >= len(s) || index < 0 {
return res, errors.New("Index out of range")
}
curIndex := index+1
if curIndex >= len(s) {
return res, nil
}
for curIndex < len(s) && s[curIndex] != id {
curId := s[curIndex]
if !contains(res, curId) {
res = append(res, curId)
}
curIndex++
}
return res, nil
}
// contains determines if s contains e
func contains(s []uint32, e uint32) bool {
for _, a := range s {
if a == e {
return true
}
}
return false
}
\ No newline at end of file
package common
import (
"fmt"
"testing"
"github.com/bmizerany/assert"
)
func TestFindNextIndex(t *testing.T) {
s := []uint32{0, 1, 2, 0, 1, 2}
id := uint32(2)
res, err := FindNextIndex(s, id, 0)
assert.Equal(t, res, 2)
assert.Equal(t, err, nil)
res, err = FindNextIndex(s, id, 2)
assert.Equal(t, res, 5)
assert.Equal(t, err, nil)
res, err = FindNextIndex(s, id, 5)
assert.Equal(t, res, -1)
assert.Equal(t, err, nil)
res, err = FindNextIndex(s, id, -2)
assert.Equal(t, res, -1)
assert.Equal(t, err.Error(), "Index out of range")
res, err = FindNextIndex(s, id, len(s))
assert.Equal(t, res, -1)
assert.Equal(t, err.Error(), "Index out of range")
res, err = FindNextIndex(s, 0, -1)
assert.Equal(t, res, 0)
assert.Equal(t, err, nil)
res, err = FindNextIndex(s, 0, 0)
assert.Equal(t, res, 3)
assert.Equal(t, err, nil)
}
func TestGetPendingSet(t *testing.T) {
s := []uint32{0, 1, 2, 0, 1, 2}
id := uint32(2)
res, err := GetPendingSet(s, id, 0)
assert.Equal(t, len(res), 0)
assert.Equal(t, err, nil)
res, err = GetPendingSet(s, id, 1)
assert.Equal(t, len(res), 1)
assert.Equal(t, res[0], uint32(0))
assert.Equal(t, err, nil)
res, err = GetPendingSet(s, id, 2)
assert.Equal(t, len(res), 2)
assert.Equal(t, res[0], uint32(1))
assert.Equal(t, res[1], uint32(0))
assert.Equal(t, err, nil)
res, err = GetPendingSet(s, id, 5)
assert.Equal(t, len(res), 2)
assert.Equal(t, res[0], uint32(1))
assert.Equal(t, res[1], uint32(0))
assert.Equal(t, err, nil)
res, err = GetPendingSet(s, id, -1)
assert.Equal(t, len(res), 0)
assert.Equal(t, err.Error(), "Index out of range")
res, err = GetPendingSet(s, id, len(s))
assert.Equal(t, len(res), 0)
assert.Equal(t, err.Error(), "Index out of range")
s = []uint32{0, 1, 0, 2}
res, err = GetPendingSet(s, id, 3)
assert.Equal(t, len(res), 2)
assert.Equal(t, res[0], uint32(0))
assert.Equal(t, res[1], uint32(1))
assert.Equal(t, err, nil)
}
func TestContains(t *testing.T) {
s := []uint32{0, 1}
assert.Equal(t, contains(s, 0), true)
assert.Equal(t, contains(s, 1), true)
assert.Equal(t, contains(s, 2), false)
}
func TestGetSendSet(t *testing.T) {
s := []uint32{0, 1, 2, 0, 1, 2}
id := uint32(0)
res, err := GetSendSet(s, id, 3)
assert.Equal(t, len(res), 2)
assert.Equal(t, res[0], uint32(1))
assert.Equal(t, res[1], uint32(2))
assert.Equal(t, err, nil)
res, err = GetSendSet(s, id, 0)
assert.Equal(t, len(res), 2)
assert.Equal(t, res[0], uint32(1))
assert.Equal(t, res[1], uint32(2))
assert.Equal(t, err, nil)
res, err = GetSendSet(s, 1, 4)
assert.Equal(t, len(res), 1)
assert.Equal(t, res[0], uint32(2))
assert.Equal(t, err, nil)
res, err = GetSendSet(s, 2, 5)
assert.Equal(t, len(res), 0)
assert.Equal(t, err, nil)
res, err = GetSendSet(s, id, -1)
assert.Equal(t, len(res), 0)
assert.Equal(t, err.Error(), "Index out of range")
res, err = GetSendSet(s, id, len(s))
assert.Equal(t, len(res), 0)
assert.Equal(t, err.Error(), "Index out of range")
}
func ExampleSequenceAnalysis() {
s := []uint32{0, 1, 2, 0, 1, 2}
id := uint32(2)
index, _ := FindNextIndex(s, id, -1)
fmt.Println("First index:", index)
pSet, _ := GetPendingSet(s, id, index)
fmt.Println("Pending Set:", pSet)
sSet, _ := GetSendSet(s, id, index)
fmt.Println("Send Set:", sSet)
// Output:
// First index: 2
// Pending Set: [1 0]
// Send Set: [0 1]
}
\ No newline at end of file
package sign
/*
import (
"fmt"
"io/ioutil"
......@@ -58,3 +58,4 @@ func TestComputeFile(t *testing.T) {
assert.Equal(t, "37fd29decfb2d689439478b1f64b60441534c1e373a7023676c94ac6772639edab46f80139d167a2741f159e62b3064eca58bb331d32cd10770f29064af2a9de", fmt.Sprintf("%x", m.hash))
assert.Equal(t, "contract.txt", m.filename)
}
*/
\ No newline at end of file
......@@ -9,6 +9,7 @@ import (
"dfss"
cAPI "dfss/dfssc/api"
"dfss/dfssc/common"
"dfss/dfssc/security"
pAPI "dfss/dfssp/api"
"dfss/dfssp/contract"
......@@ -28,6 +29,7 @@ type SignatureManager struct {
cServer *grpc.Server
sequence []uint32
uuid string
mail string
}
// NewSignatureManager populates a SignatureManager and connects to the platform.
......@@ -38,11 +40,13 @@ func NewSignatureManager(fileCA, fileCert, fileKey, addrPort, passphrase string,
contract: c,
}
var err error
_, _, _, err = m.auth.LoadFiles()
_, x509cert, _, err := m.auth.LoadFiles()
if err != nil {
return nil, err
}
m.mail = x509cert.Subject.CommonName
m.cServer = m.GetServer()
go func() { log.Fatalln(net.Listen("0.0.0.0:"+strconv.Itoa(port), m.cServer)) }()
......@@ -174,3 +178,94 @@ func (m *SignatureManager) SendReadySign() (signatureUUID string, err error) {
signatureUUID = m.uuid
return
}
// Sign make the SignatureManager perform its specified signature
func (m *SignatureManager) Sign() error {
mySeqId, err := m.FindId()
if (err != nil) {
return err
}
curIndex, err := common.FindNextIndex(m.sequence, mySeqId, -1)
if (err != nil) {
return err
}
nextIndex, err := common.FindNextIndex(m.sequence, mySeqId, curIndex)
// Promess tounds
for (nextIndex != -1) {
pendingSet, err := common.GetPendingSet(m.sequence, mySeqId, curIndex)
if (err != nil) {
return err
}
sendSet, err := common.GetSendSet(m.sequence, mySeqId, curIndex)
if (err != nil) {
return err
}
// Reception of the due promesses
for (len(pendingSet) != 0) {
i := 0
// TODO
// Improve, because potential memory leak
// see https://github.com/golang/go/wiki/SliceTricks
pendingSet = append(pendingSet[:i], pendingSet[i+1:]...)
}
c := make(chan int)
// Sending of the due promesses
/*
for _, id := range sendSet {
go func(id) {
promise := m.CreatePromise(id)
recpt := m.SendPromise(promise, id)
c <- id
}(id)
}
*/
// Verifying we sent all the due promesses
for _ = range sendSet {
<- c
}
}
// Signature round
m.SendAllSigns()
m.RecieveAllSigns()
return nil
}
// findId finds the sequence id for the user's email and the contract to sign
func (m *SignatureManager) FindId() (uint32, error) {
signers := m.contract.Signers
for id, signer := range signers {
if (signer.Email == m.mail) {
return uint32(id), nil
}
}
return 0, errors.New("Mail couldn't be found amongst signers")
}
// TODO
func (m *SignatureManager) CreatePromise(id uint32) error {
return nil
}
// TODO
func (m *SignatureManager) SendPromise(id uint32) error {
return nil
}
// TODO
func (m *SignatureManager) SendAllSigns() error {
return nil
}
// TODO
func (m *SignatureManager) RecieveAllSigns() error {
return nil
}
\ No newline at end of file
package sign
import (
"testing"
"dfss/dfssp/contract"
"github.com/bmizerany/assert"
)
func TestFindId(t *testing.T) {
mail := "signer2@foo.foo"
s1 := contract.SignerJSON{ Email: "signer1@foo.foo" }
s2 := contract.SignerJSON{ Email: mail }
s3 := contract.SignerJSON{ Email: "signer3@foo.foo" }
contract := &contract.JSON{
Signers: []contract.SignerJSON{s1, s2, s3},
}
sequence := []uint32{0, 1, 2, 0, 1, 2, 0, 1, 2}
sm := &SignatureManager{
contract: contract,
sequence: sequence,
mail: mail,
}
id, err := sm.FindId()
assert.Equal(t, err, nil)
assert.Equal(t, id, uint32(1))
sm.mail = ""
id, err = sm.FindId()
assert.Equal(t, err.Error(), "Mail couldn't be found amongst signers")
assert.Equal(t, id, uint32(0))
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment