Commit 9bc1fb12 authored by Axel's avatar Axel Committed by Loïck Bonniot
Browse files

[c] Add promise/signature emission and archiving

parent 7e4ef127
...@@ -15,7 +15,7 @@ func FindNextIndex(s []uint32, id uint32, index int) (int, error) { ...@@ -15,7 +15,7 @@ func FindNextIndex(s []uint32, id uint32, index int) (int, error) {
return -1, errors.New("Index out of range") return -1, errors.New("Index out of range")
} }
for i := index+1; i < len(s); i++ { for i := index + 1; i < len(s); i++ {
if s[i] == id { if s[i] == id {
return i, nil return i, nil
} }
...@@ -37,15 +37,15 @@ func GetPendingSet(s []uint32, id uint32, index int) ([]uint32, error) { ...@@ -37,15 +37,15 @@ func GetPendingSet(s []uint32, id uint32, index int) ([]uint32, error) {
return res, errors.New("Index out of range") return res, errors.New("Index out of range")
} }
curIndex := index-1 curIndex := index - 1
if curIndex < 0 { if curIndex < 0 {
return res, nil return res, nil
} }
for curIndex > -1 && s[curIndex] != id { for curIndex > -1 && s[curIndex] != id {
curId := s[curIndex] curID := s[curIndex]
if !contains(res, curId) { if !contains(res, curID) {
res = append(res, curId) res = append(res, curID)
} }
curIndex-- curIndex--
} }
...@@ -66,15 +66,15 @@ func GetSendSet(s []uint32, id uint32, index int) ([]uint32, error) { ...@@ -66,15 +66,15 @@ func GetSendSet(s []uint32, id uint32, index int) ([]uint32, error) {
return res, errors.New("Index out of range") return res, errors.New("Index out of range")
} }
curIndex := index+1 curIndex := index + 1
if curIndex >= len(s) { if curIndex >= len(s) {
return res, nil return res, nil
} }
for curIndex < len(s) && s[curIndex] != id { for curIndex < len(s) && s[curIndex] != id {
curId := s[curIndex] curID := s[curIndex]
if !contains(res, curId) { if !contains(res, curID) {
res = append(res, curId) res = append(res, curID)
} }
curIndex++ curIndex++
} }
...@@ -84,10 +84,24 @@ func GetSendSet(s []uint32, id uint32, index int) ([]uint32, error) { ...@@ -84,10 +84,24 @@ func GetSendSet(s []uint32, id uint32, index int) ([]uint32, error) {
// contains determines if s contains e // contains determines if s contains e
func contains(s []uint32, e uint32) bool { func contains(s []uint32, e uint32) bool {
for _, a := range s { for _, a := range s {
if a == e { if a == e {
return true return true
} }
} }
return false return false
} }
\ No newline at end of file
// GetAllButOne creates the slice of all sequence ids, except the one specified
func GetAllButOne(s []uint32, e uint32) []uint32 {
res := make([]uint32, 0)
for i := 0; i < len(s); i++ {
curID := s[i]
if !contains(res, curID) && curID != e {
res = append(res, curID)
}
}
return res
}
...@@ -2,8 +2,8 @@ package common ...@@ -2,8 +2,8 @@ package common
import ( import (
"fmt" "fmt"
"testing"
"github.com/bmizerany/assert" "github.com/bmizerany/assert"
"testing"
) )
func TestFindNextIndex(t *testing.T) { func TestFindNextIndex(t *testing.T) {
...@@ -122,6 +122,22 @@ func TestGetSendSet(t *testing.T) { ...@@ -122,6 +122,22 @@ func TestGetSendSet(t *testing.T) {
assert.Equal(t, err.Error(), "Index out of range") assert.Equal(t, err.Error(), "Index out of range")
} }
func TestGetAllButOne(t *testing.T) {
s := []uint32{0, 1, 2, 0, 1, 2}
id := uint32(2)
res := GetAllButOne(s, id)
assert.Equal(t, len(res), 2)
assert.Equal(t, res[0], uint32(0))
assert.Equal(t, res[1], uint32(1))
res = GetAllButOne(s, uint32(42))
assert.Equal(t, len(res), 3)
assert.Equal(t, res[0], uint32(0))
assert.Equal(t, res[1], uint32(1))
assert.Equal(t, res[2], uint32(2))
}
func ExampleSequenceAnalysis() { func ExampleSequenceAnalysis() {
s := []uint32{0, 1, 2, 0, 1, 2} s := []uint32{0, 1, 2, 0, 1, 2}
id := uint32(2) id := uint32(2)
...@@ -138,4 +154,4 @@ func ExampleSequenceAnalysis() { ...@@ -138,4 +154,4 @@ func ExampleSequenceAnalysis() {
// First index: 2 // First index: 2
// Pending Set: [1 0] // Pending Set: [1 0]
// Send Set: [0 1] // Send Set: [0 1]
} }
\ No newline at end of file
package sign package sign
/* /*
import ( import (
"fmt" "fmt"
...@@ -58,4 +59,4 @@ func TestComputeFile(t *testing.T) { ...@@ -58,4 +59,4 @@ func TestComputeFile(t *testing.T) {
assert.Equal(t, "37fd29decfb2d689439478b1f64b60441534c1e373a7023676c94ac6772639edab46f80139d167a2741f159e62b3064eca58bb331d32cd10770f29064af2a9de", fmt.Sprintf("%x", m.hash)) assert.Equal(t, "37fd29decfb2d689439478b1f64b60441534c1e373a7023676c94ac6772639edab46f80139d167a2741f159e62b3064eca58bb331d32cd10770f29064af2a9de", fmt.Sprintf("%x", m.hash))
assert.Equal(t, "contract.txt", m.filename) assert.Equal(t, "contract.txt", m.filename)
} }
*/ */
\ No newline at end of file
...@@ -29,7 +29,17 @@ type SignatureManager struct { ...@@ -29,7 +29,17 @@ type SignatureManager struct {
cServer *grpc.Server cServer *grpc.Server
sequence []uint32 sequence []uint32
uuid string uuid string
mail string keyHash [][]byte
mail string
archives *Archives
}
// Archives stores the recieved and sent messages, as evidence if needed
type Archives struct {
sentPromises []*cAPI.Promise
recievedPromises []*cAPI.Promise
sentSignatures []*cAPI.Signature
recievedSignatures []*cAPI.Signature
} }
// NewSignatureManager populates a SignatureManager and connects to the platform. // NewSignatureManager populates a SignatureManager and connects to the platform.
...@@ -38,14 +48,20 @@ func NewSignatureManager(fileCA, fileCert, fileKey, addrPort, passphrase string, ...@@ -38,14 +48,20 @@ func NewSignatureManager(fileCA, fileCert, fileKey, addrPort, passphrase string,
auth: security.NewAuthContainer(fileCA, fileCert, fileKey, addrPort, passphrase), auth: security.NewAuthContainer(fileCA, fileCert, fileKey, addrPort, passphrase),
localPort: port, localPort: port,
contract: c, contract: c,
archives: &Archives{
sentPromises: make([]*cAPI.Promise, 0),
recievedPromises: make([]*cAPI.Promise, 0),
sentSignatures: make([]*cAPI.Signature, 0),
recievedSignatures: make([]*cAPI.Signature, 0),
},
} }
var err error var err error
_, x509cert, _, err := m.auth.LoadFiles() _, _, _, err = m.auth.LoadFiles()
if err != nil { if err != nil {
return nil, err return nil, err
} }
m.mail = x509cert.Subject.CommonName m.mail = m.auth.Cert.Subject.CommonName
m.cServer = m.GetServer() m.cServer = m.GetServer()
go func() { log.Fatalln(net.Listen("0.0.0.0:"+strconv.Itoa(port), m.cServer)) }() go func() { log.Fatalln(net.Listen("0.0.0.0:"+strconv.Itoa(port), m.cServer)) }()
...@@ -175,38 +191,32 @@ func (m *SignatureManager) SendReadySign() (signatureUUID string, err error) { ...@@ -175,38 +191,32 @@ func (m *SignatureManager) SendReadySign() (signatureUUID string, err error) {
m.sequence = launch.Sequence m.sequence = launch.Sequence
m.uuid = launch.SignatureUuid m.uuid = launch.SignatureUuid
m.keyHash = launch.KeyHash
signatureUUID = m.uuid signatureUUID = m.uuid
return return
} }
// Sign make the SignatureManager perform its specified signature // Sign makes the SignatureManager perform its specified signature
func (m *SignatureManager) Sign() error { func (m *SignatureManager) Sign() error {
mySeqId, err := m.FindId() myID, currentIndex, nextIndex, err := m.Initialize()
if (err != nil) { if err != nil {
return err
}
curIndex, err := common.FindNextIndex(m.sequence, mySeqId, -1)
if (err != nil) {
return err return err
} }
nextIndex, err := common.FindNextIndex(m.sequence, mySeqId, curIndex) // Promess rounds
for nextIndex != -1 {
// Promess tounds pendingSet, err := common.GetPendingSet(m.sequence, myID, currentIndex)
for (nextIndex != -1) { if err != nil {
pendingSet, err := common.GetPendingSet(m.sequence, mySeqId, curIndex)
if (err != nil) {
return err return err
} }
sendSet, err := common.GetSendSet(m.sequence, mySeqId, curIndex) sendSet, err := common.GetSendSet(m.sequence, myID, currentIndex)
if (err != nil) { if err != nil {
return err return err
} }
// Reception of the due promesses // Reception of the due promesses
for (len(pendingSet) != 0) { for len(pendingSet) != 0 {
i := 0 i := 0
// TODO // TODO
// Improve, because potential memory leak // Improve, because potential memory leak
...@@ -217,55 +227,189 @@ func (m *SignatureManager) Sign() error { ...@@ -217,55 +227,189 @@ func (m *SignatureManager) Sign() error {
c := make(chan int) c := make(chan int)
// Sending of the due promesses // Sending of the due promesses
/* /*
for _, id := range sendSet { for _, id := range sendSet {
go func(id) { go func(id) {
promise := m.CreatePromise(id) promise, err := m.CreatePromise(id)
recpt := m.SendPromise(promise, id) recpt := m.SendPromise(promise, id)
c <- id c <- id
}(id) }(id)
} }
*/ */
// Verifying we sent all the due promesses // Verifying we sent all the due promesses
for _ = range sendSet { for _ = range sendSet {
<- c <-c
}
currentIndex = nextIndex
nextIndex, err = common.FindNextIndex(m.sequence, myID, currentIndex)
if err != nil {
return err
} }
} }
// Signature round // Signature round
m.SendAllSigns() err = m.SendAllSigns()
m.RecieveAllSigns() if err != nil {
return err
}
err = m.RecieveAllSigns()
if err != nil {
return err
}
return nil return nil
} }
// findId finds the sequence id for the user's email and the contract to sign // Initialize computes the values needed for the start of the signing
func (m *SignatureManager) FindId() (uint32, error) { func (m *SignatureManager) Initialize() (uint32, int, int, error) {
myID, err := m.FindID()
if err != nil {
return 0, 0, 0, err
}
currentIndex, err := common.FindNextIndex(m.sequence, myID, -1)
if err != nil {
return 0, 0, 0, err
}
nextIndex, err := common.FindNextIndex(m.sequence, myID, currentIndex)
if err != nil {
return 0, 0, 0, err
}
return myID, currentIndex, nextIndex, 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 signers := m.contract.Signers
for id, signer := range signers { for id, signer := range signers {
if (signer.Email == m.mail) { if signer.Email == m.mail {
return uint32(id), nil return uint32(id), nil
} }
} }
return 0, errors.New("Mail couldn't be found amongst signers") return 0, errors.New("Mail couldn't be found amongst signers")
} }
// TODO // CreatePromise creates a promise from 'from' to 'to', in the context of the SignatureManager
func (m *SignatureManager) CreatePromise(id uint32) error { // provided the specified sequence indexes are valid
return nil func (m *SignatureManager) CreatePromise(from, to uint32) (*cAPI.Promise, error) {
if int(from) >= len(m.keyHash) || int(to) >= len(m.keyHash) {
return &cAPI.Promise{}, errors.New("Invalid id for promise creation")
}
promise := &cAPI.Promise{
RecipientKeyHash: m.keyHash[to],
SenderKeyHash: m.keyHash[from],
SignatureUuid: m.uuid,
ContractUuid: m.contract.UUID,
}
return promise, nil
} }
// SendPromise sends the specified promise to the specified peer
// TODO // TODO
func (m *SignatureManager) SendPromise(id uint32) error { func (m *SignatureManager) SendPromise(promise *cAPI.Promise, to uint32) (*pAPI.ErrorCode, error) {
return nil connection, err := m.GetClient(to)
if err != nil {
return &pAPI.ErrorCode{}, err
}
// TODO
// Handle the timeout
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer cancel()
errCode, err := (*connection).TreatPromise(ctx, promise)
if err != nil {
return &pAPI.ErrorCode{}, err
}
m.archives.sentPromises = append(m.archives.sentPromises, promise)
return errCode, nil
} }
// GetClient retrieves the Client to the specified sequence id provided it exists
func (m *SignatureManager) GetClient(to uint32) (*cAPI.ClientClient, error) {
mailto := m.contract.Signers[to].Email
if _, ok := m.peers[mailto]; !ok {
return nil, fmt.Errorf("No connection to user %s", mailto)
}
return m.peers[mailto], nil
}
// SendAllSigns creates and sends signatures to all the signers of the contract
// TODO // TODO
// Use goroutines to send in parallel
func (m *SignatureManager) SendAllSigns() error { func (m *SignatureManager) SendAllSigns() error {
myID, err := m.FindID()
if err != nil {
return err
}
sendSet := common.GetAllButOne(m.sequence, myID)
for _, id := range sendSet {
signature, err := m.CreateSignature(myID, id)
if err != nil {
return err
}
_, err = m.SendSignature(signature, id)
if err != nil {
return err
}
}
return nil return nil
} }
// CreateSignature creates a signature from from to to, in the context of the SignatureManager
// provided the specified sequence indexes are valid
// TODO
// Implement a true cryptographic signature
func (m *SignatureManager) CreateSignature(from, to uint32) (*cAPI.Signature, error) {
if int(from) >= len(m.keyHash) || int(to) >= len(m.keyHash) {
return &cAPI.Signature{}, errors.New("Invalid id for signature creation")
}
signature := &cAPI.Signature{
RecipientKeyHash: m.keyHash[to],
SenderKeyHash: m.keyHash[from],
Signature: "Signature",
SignatureUuid: m.uuid,
ContractUuid: m.contract.UUID,
}
return signature, nil
}
// SendSignature sends the specified signature to the specified peer
// TODO
func (m *SignatureManager) SendSignature(signature *cAPI.Signature, to uint32) (*pAPI.ErrorCode, error) {
connection, err := m.GetClient(to)
if err != nil {
return &pAPI.ErrorCode{}, err
}
// TODO
// Handle the timeout
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
defer cancel()
errCode, err := (*connection).TreatSignature(ctx, signature)
if err != nil {
return &pAPI.ErrorCode{}, err
}
m.archives.sentSignatures = append(m.archives.sentSignatures, signature)
return errCode, nil
}
// RecieveAllSigns is not done yet
// TODO // TODO
func (m *SignatureManager) RecieveAllSigns() error { func (m *SignatureManager) RecieveAllSigns() error {
return nil return nil
} }
\ No newline at end of file
...@@ -11,9 +11,9 @@ import ( ...@@ -11,9 +11,9 @@ import (
func TestFindId(t *testing.T) { func TestFindId(t *testing.T) {
mail := "signer2@foo.foo" mail := "signer2@foo.foo"
s1 := contract.SignerJSON{ Email: "signer1@foo.foo" } s1 := contract.SignerJSON{Email: "signer1@foo.foo"}
s2 := contract.SignerJSON{ Email: mail } s2 := contract.SignerJSON{Email: mail}
s3 := contract.SignerJSON{ Email: "signer3@foo.foo" } s3 := contract.SignerJSON{Email: "signer3@foo.foo"}
contract := &contract.JSON{ contract := &contract.JSON{
Signers: []contract.SignerJSON{s1, s2, s3}, Signers: []contract.SignerJSON{s1, s2, s3},
...@@ -27,12 +27,12 @@ func TestFindId(t *testing.T) { ...@@ -27,12 +27,12 @@ func TestFindId(t *testing.T) {
mail: mail, mail: mail,
} }
id, err := sm.FindId() id, err := sm.FindID()
assert.Equal(t, err, nil) assert.Equal(t, err, nil)
assert.Equal(t, id, uint32(1)) assert.Equal(t, id, uint32(1))
sm.mail = "" sm.mail = ""
id, err = sm.FindId() id, err = sm.FindID()
assert.Equal(t, err.Error(), "Mail couldn't be found amongst signers") assert.Equal(t, err.Error(), "Mail couldn't be found amongst signers")
assert.Equal(t, id, uint32(0)) 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