Commit 8ade9e29 authored by Caro Axel's avatar Caro Axel Committed by Loïck Bonniot

[c][t] Add TTP calls from client

parent 1d07c0d8
Pipeline #1826 failed with stage
...@@ -78,13 +78,6 @@ var signCmd = &cobra.Command{ ...@@ -78,13 +78,6 @@ var signCmd = &cobra.Command{
os.Exit(1) os.Exit(1)
} }
// Persist evidencies, if any
err = manager.PersistSignaturesToFile()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
fmt.Println("Signature complete! See .proof file for evidences.") fmt.Println("Signature complete! See .proof file for evidences.")
}, },
} }
......
...@@ -4,6 +4,11 @@ import ( ...@@ -4,6 +4,11 @@ import (
"errors" "errors"
) )
// SequenceCoordinate : contains both the sequence id of a signer, and the index of the occurence in the sequence
type SequenceCoordinate struct {
Signer, Index uint32
}
// FindNextIndex analyses the specified sequence and tries to find the next occurence of id after the specified index (excluded) // 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 // Therefore to find the first occurence of the id in the sequence, use -1 as the index
// //
...@@ -30,8 +35,8 @@ func FindNextIndex(s []uint32, id uint32, index int) (int, error) { ...@@ -30,8 +35,8 @@ func FindNextIndex(s []uint32, id uint32, index int) (int, error) {
// //
// 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 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 // 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) { func GetPendingSet(s []uint32, id uint32, index int) ([]SequenceCoordinate, error) {
res := []uint32{} res := []SequenceCoordinate{}
if index >= len(s) || index < 0 { if index >= len(s) || index < 0 {
return res, errors.New("Index out of range") return res, errors.New("Index out of range")
...@@ -44,8 +49,8 @@ func GetPendingSet(s []uint32, id uint32, index int) ([]uint32, error) { ...@@ -44,8 +49,8 @@ func GetPendingSet(s []uint32, id uint32, index int) ([]uint32, error) {
for curIndex > -1 && s[curIndex] != id { for curIndex > -1 && s[curIndex] != id {
curID := s[curIndex] curID := s[curIndex]
if !contains(res, curID) { if !containsCoordinate(res, curID) {
res = append(res, curID) res = append(res, SequenceCoordinate{Signer: curID, Index: uint32(curIndex)})
} }
curIndex-- curIndex--
} }
...@@ -59,8 +64,8 @@ func GetPendingSet(s []uint32, id uint32, index int) ([]uint32, error) { ...@@ -59,8 +64,8 @@ func GetPendingSet(s []uint32, id uint32, index int) ([]uint32, error) {
// //
// 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 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 // 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) { func GetSendSet(s []uint32, id uint32, index int) ([]SequenceCoordinate, error) {
res := []uint32{} res := []SequenceCoordinate{}
if index >= len(s) || index < 0 { if index >= len(s) || index < 0 {
return res, errors.New("Index out of range") return res, errors.New("Index out of range")
...@@ -73,8 +78,8 @@ func GetSendSet(s []uint32, id uint32, index int) ([]uint32, error) { ...@@ -73,8 +78,8 @@ func GetSendSet(s []uint32, id uint32, index int) ([]uint32, error) {
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 !containsCoordinate(res, curID) {
res = append(res, curID) res = append(res, SequenceCoordinate{Signer: curID, Index: uint32(curIndex)})
} }
curIndex++ curIndex++
} }
...@@ -82,7 +87,17 @@ func GetSendSet(s []uint32, id uint32, index int) ([]uint32, error) { ...@@ -82,7 +87,17 @@ func GetSendSet(s []uint32, id uint32, index int) ([]uint32, error) {
return res, nil return res, nil
} }
// contains determines if s contains e // containsCoordinate: determines if s contains the specified signer sequence id e
func containsCoordinate(s []SequenceCoordinate, e uint32) bool {
for _, a := range s {
if a.Signer == e {
return true
}
}
return false
}
// 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 {
...@@ -108,7 +123,17 @@ func GetAllButOne(s []uint32, e uint32) []uint32 { ...@@ -108,7 +123,17 @@ func GetAllButOne(s []uint32, e uint32) []uint32 {
return res return res
} }
// Remove an ID from the sequence // RemoveCoordinate : removes the first occurence of an ID from the coordinates array
func RemoveCoordinate(s []SequenceCoordinate, e uint32) ([]SequenceCoordinate, error) {
for i, a := range s {
if a.Signer == e {
return append(s[:i], s[i+1:]...), nil
}
}
return s, errors.New("ID not in sequence")
}
// Remove the first occurence of an ID from the ids array
func Remove(s []uint32, e uint32) ([]uint32, error) { func Remove(s []uint32, e uint32) ([]uint32, error) {
for i, a := range s { for i, a := range s {
if a == e { if a == e {
......
...@@ -50,19 +50,24 @@ func TestGetPendingSet(t *testing.T) { ...@@ -50,19 +50,24 @@ func TestGetPendingSet(t *testing.T) {
res, err = GetPendingSet(s, id, 1) res, err = GetPendingSet(s, id, 1)
assert.Equal(t, len(res), 1) assert.Equal(t, len(res), 1)
assert.Equal(t, res[0], uint32(0)) assert.Equal(t, res[0].Signer, uint32(0))
assert.Equal(t, res[0].Index, uint32(0))
assert.Equal(t, err, nil) assert.Equal(t, err, nil)
res, err = GetPendingSet(s, id, 2) res, err = GetPendingSet(s, id, 2)
assert.Equal(t, len(res), 2) assert.Equal(t, len(res), 2)
assert.Equal(t, res[0], uint32(1)) assert.Equal(t, res[0].Signer, uint32(1))
assert.Equal(t, res[1], uint32(0)) assert.Equal(t, res[0].Index, uint32(1))
assert.Equal(t, res[1].Signer, uint32(0))
assert.Equal(t, res[1].Index, uint32(0))
assert.Equal(t, err, nil) assert.Equal(t, err, nil)
res, err = GetPendingSet(s, id, 5) res, err = GetPendingSet(s, id, 5)
assert.Equal(t, len(res), 2) assert.Equal(t, len(res), 2)
assert.Equal(t, res[0], uint32(1)) assert.Equal(t, res[0].Signer, uint32(1))
assert.Equal(t, res[1], uint32(0)) assert.Equal(t, res[0].Index, uint32(4))
assert.Equal(t, res[1].Signer, uint32(0))
assert.Equal(t, res[1].Index, uint32(3))
assert.Equal(t, err, nil) assert.Equal(t, err, nil)
res, err = GetPendingSet(s, id, -1) res, err = GetPendingSet(s, id, -1)
...@@ -76,11 +81,23 @@ func TestGetPendingSet(t *testing.T) { ...@@ -76,11 +81,23 @@ func TestGetPendingSet(t *testing.T) {
s = []uint32{0, 1, 0, 2} s = []uint32{0, 1, 0, 2}
res, err = GetPendingSet(s, id, 3) res, err = GetPendingSet(s, id, 3)
assert.Equal(t, len(res), 2) assert.Equal(t, len(res), 2)
assert.Equal(t, res[0], uint32(0)) assert.Equal(t, res[0].Signer, uint32(0))
assert.Equal(t, res[1], uint32(1)) assert.Equal(t, res[0].Index, uint32(2))
assert.Equal(t, res[1].Signer, uint32(1))
assert.Equal(t, res[1].Index, uint32(1))
assert.Equal(t, err, nil) assert.Equal(t, err, nil)
} }
func TestContainsCoordinate(t *testing.T) {
var s []SequenceCoordinate
s = append(s, SequenceCoordinate{Signer: 0, Index: 0})
s = append(s, SequenceCoordinate{Signer: 1, Index: 1})
assert.Equal(t, containsCoordinate(s, 0), true)
assert.Equal(t, containsCoordinate(s, 1), true)
assert.Equal(t, containsCoordinate(s, 2), false)
}
func TestContains(t *testing.T) { func TestContains(t *testing.T) {
s := []uint32{0, 1} s := []uint32{0, 1}
...@@ -95,19 +112,24 @@ func TestGetSendSet(t *testing.T) { ...@@ -95,19 +112,24 @@ func TestGetSendSet(t *testing.T) {
res, err := GetSendSet(s, id, 3) res, err := GetSendSet(s, id, 3)
assert.Equal(t, len(res), 2) assert.Equal(t, len(res), 2)
assert.Equal(t, res[0], uint32(1)) assert.Equal(t, res[0].Signer, uint32(1))
assert.Equal(t, res[1], uint32(2)) assert.Equal(t, res[0].Index, uint32(4))
assert.Equal(t, res[1].Signer, uint32(2))
assert.Equal(t, res[1].Index, uint32(5))
assert.Equal(t, err, nil) assert.Equal(t, err, nil)
res, err = GetSendSet(s, id, 0) res, err = GetSendSet(s, id, 0)
assert.Equal(t, len(res), 2) assert.Equal(t, len(res), 2)
assert.Equal(t, res[0], uint32(1)) assert.Equal(t, res[0].Signer, uint32(1))
assert.Equal(t, res[1], uint32(2)) assert.Equal(t, res[0].Index, uint32(1))
assert.Equal(t, res[1].Signer, uint32(2))
assert.Equal(t, res[1].Index, uint32(2))
assert.Equal(t, err, nil) assert.Equal(t, err, nil)
res, err = GetSendSet(s, 1, 4) res, err = GetSendSet(s, 1, 4)
assert.Equal(t, len(res), 1) assert.Equal(t, len(res), 1)
assert.Equal(t, res[0], uint32(2)) assert.Equal(t, res[0].Signer, uint32(2))
assert.Equal(t, res[0].Index, uint32(5))
assert.Equal(t, err, nil) assert.Equal(t, err, nil)
res, err = GetSendSet(s, 2, 5) res, err = GetSendSet(s, 2, 5)
...@@ -139,6 +161,46 @@ func TestGetAllButOne(t *testing.T) { ...@@ -139,6 +161,46 @@ func TestGetAllButOne(t *testing.T) {
assert.Equal(t, res[2], uint32(2)) assert.Equal(t, res[2], uint32(2))
} }
func TestRemoveCoordinate(t *testing.T) {
var s []SequenceCoordinate
s = append(s, SequenceCoordinate{Signer: 0, Index: 0})
s = append(s, SequenceCoordinate{Signer: 1, Index: 1})
assert.Equal(t, len(s), 2)
assert.Equal(t, containsCoordinate(s, 0), true)
assert.Equal(t, containsCoordinate(s, 1), true)
s2, err := RemoveCoordinate(s, 3)
assert.Equal(t, err.Error(), "ID not in sequence")
assert.Equal(t, len(s2), 2)
assert.Equal(t, containsCoordinate(s2, 0), true)
assert.Equal(t, containsCoordinate(s2, 1), true)
s3, err := RemoveCoordinate(s, 0)
assert.Equal(t, err, nil)
assert.Equal(t, len(s3), 1)
assert.Equal(t, containsCoordinate(s3, 0), false)
assert.Equal(t, containsCoordinate(s3, 1), true)
}
func TestRemove(t *testing.T) {
s := []uint32{0, 1}
assert.Equal(t, len(s), 2)
s2, err := Remove(s, 3)
assert.Equal(t, err.Error(), "ID not in sequence")
assert.Equal(t, len(s2), 2)
assert.Equal(t, contains(s2, 0), true)
assert.Equal(t, contains(s2, 1), true)
s3, err := Remove(s, 0)
assert.Equal(t, err, nil)
assert.Equal(t, len(s3), 1)
assert.Equal(t, contains(s3, 0), false)
assert.Equal(t, contains(s3, 1), true)
}
func ExampleFindNextIndex() { func ExampleFindNextIndex() {
s := []uint32{0, 1, 2, 0, 1, 2} s := []uint32{0, 1, 2, 0, 1, 2}
id := uint32(2) id := uint32(2)
...@@ -153,6 +215,6 @@ func ExampleFindNextIndex() { ...@@ -153,6 +215,6 @@ func ExampleFindNextIndex() {
fmt.Println("Send Set:", sSet) fmt.Println("Send Set:", sSet)
// Output: // Output:
// First index: 2 // First index: 2
// Pending Set: [1 0] // Pending Set: [{1 1} {0 0}]
// Send Set: [0 1] // Send Set: [{0 3} {1 4}]
} }
package sign package sign
import ( import (
"encoding/hex"
"errors" "errors"
"time" "time"
...@@ -14,20 +15,23 @@ func (m *SignatureManager) createContext(from, to uint32) (*cAPI.Context, error) ...@@ -14,20 +15,23 @@ func (m *SignatureManager) createContext(from, to uint32) (*cAPI.Context, error)
if int(from) >= len(m.keyHash) || int(to) >= len(m.keyHash) { if int(from) >= len(m.keyHash) || int(to) >= len(m.keyHash) {
return nil, errors.New("Invalid id for context creation") return nil, errors.New("Invalid id for context creation")
} }
h, _ := hex.DecodeString(m.contract.File.Hash)
return &cAPI.Context{ return &cAPI.Context{
RecipientKeyHash: m.keyHash[to], RecipientKeyHash: m.keyHash[to],
SenderKeyHash: m.keyHash[from], SenderKeyHash: m.keyHash[from],
Sequence: m.sequence, Sequence: m.sequence,
Signers: m.keyHash, Signers: m.keyHash,
ContractDocumentHash: []byte(m.contract.File.Hash), ContractDocumentHash: h,
SignatureUUID: m.uuid, SignatureUUID: m.uuid,
Seal: m.seal, Seal: m.seal,
}, nil }, nil
} }
// CreatePromise creates a promise from 'from' to 'to', in the context of the SignatureManager // CreatePromise creates a promise from 'from' to 'to', in the context of the SignatureManager
// provided the specified sequence indexes are valid // provided that the specified sequence indexes are valid
func (m *SignatureManager) CreatePromise(from, to uint32) (*cAPI.Promise, error) { func (m *SignatureManager) CreatePromise(from, to, at uint32) (*cAPI.Promise, error) {
context, err := m.createContext(from, to) context, err := m.createContext(from, to)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -38,7 +42,7 @@ func (m *SignatureManager) CreatePromise(from, to uint32) (*cAPI.Promise, error) ...@@ -38,7 +42,7 @@ func (m *SignatureManager) CreatePromise(from, to uint32) (*cAPI.Promise, error)
} }
return &cAPI.Promise{ return &cAPI.Promise{
Index: uint32(m.currentIndex), Index: at,
Context: context, Context: context,
Payload: []byte{0x41}, Payload: []byte{0x41},
}, nil }, nil
...@@ -69,7 +73,6 @@ func (m *SignatureManager) SendEvidence(promise *cAPI.Promise, signature *cAPI.S ...@@ -69,7 +73,6 @@ func (m *SignatureManager) SendEvidence(promise *cAPI.Promise, signature *cAPI.S
m.archives.mutex.Lock() m.archives.mutex.Lock()
if promise != nil { if promise != nil {
dAPI.DLog("sent promise to " + mail) dAPI.DLog("sent promise to " + mail)
m.archives.sentPromises = append(m.archives.sentPromises, promise)
} else { } else {
dAPI.DLog("sent signature to " + mail) dAPI.DLog("sent signature to " + mail)
m.archives.sentSignatures = append(m.archives.sentSignatures, signature) m.archives.sentSignatures = append(m.archives.sentSignatures, signature)
......
...@@ -2,12 +2,19 @@ ...@@ -2,12 +2,19 @@
package sign package sign
import ( import (
"bytes"
"errors"
"fmt" "fmt"
"io/ioutil"
"time" "time"
cAPI "dfss/dfssc/api" cAPI "dfss/dfssc/api"
"dfss/dfssc/common" "dfss/dfssc/common"
dAPI "dfss/dfssd/api" dAPI "dfss/dfssd/api"
tAPI "dfss/dfsst/api"
"dfss/net"
"golang.org/x/net/context"
"google.golang.org/grpc"
) )
// Sign performs all the message exchanges for the contract to be signed // Sign performs all the message exchanges for the contract to be signed
...@@ -24,7 +31,7 @@ func (m *SignatureManager) Sign() error { ...@@ -24,7 +31,7 @@ func (m *SignatureManager) Sign() error {
m.closeConnections() m.closeConnections()
}() }()
myID, nextIndex, err := m.Initialize() nextIndex, err := m.Initialize()
if err != nil { if err != nil {
return err return err
} }
...@@ -45,24 +52,27 @@ func (m *SignatureManager) Sign() error { ...@@ -45,24 +52,27 @@ func (m *SignatureManager) Sign() error {
dAPI.DLog("starting round at index [" + fmt.Sprintf("%d", m.currentIndex) + "] with nextIndex=" + fmt.Sprintf("%d", nextIndex)) dAPI.DLog("starting round at index [" + fmt.Sprintf("%d", m.currentIndex) + "] with nextIndex=" + fmt.Sprintf("%d", nextIndex))
// Set of promises we are waiting for // Set of promises we are waiting for
var pendingSet []uint32 var pendingSet []common.SequenceCoordinate
pendingSet, err = common.GetPendingSet(m.sequence, myID, m.currentIndex) pendingSet, err = common.GetPendingSet(m.sequence, m.myID, m.currentIndex)
if err != nil { if err != nil {
return err return err
} }
// Set of the promises we must send // Set of the promises we must send
var sendSet []uint32 var sendSet []common.SequenceCoordinate
sendSet, err = common.GetSendSet(m.sequence, myID, m.currentIndex) sendSet, err = common.GetSendSet(m.sequence, m.myID, m.currentIndex)
if err != nil { if err != nil {
return err return err
} }
// Exchange messages // Exchange messages
m.promiseRound(pendingSet, sendSet, myID) err = m.promiseRound(pendingSet, sendSet)
if err != nil {
return err
}
m.currentIndex = nextIndex m.currentIndex = nextIndex
nextIndex, err = common.FindNextIndex(m.sequence, myID, m.currentIndex) nextIndex, err = common.FindNextIndex(m.sequence, m.myID, m.currentIndex)
if err != nil { if err != nil {
return err return err
} }
...@@ -78,7 +88,7 @@ func (m *SignatureManager) Sign() error { ...@@ -78,7 +88,7 @@ func (m *SignatureManager) Sign() error {
dAPI.DLog("exiting signature round") dAPI.DLog("exiting signature round")
m.OnProgressUpdate(seqLen+1, seqLen+1) m.OnProgressUpdate(seqLen+1, seqLen+1)
return nil return m.PersistSignaturesToFile()
} }
// GetClient retrieves the Client to the specified sequence id provided it exists // GetClient retrieves the Client to the specified sequence id provided it exists
...@@ -98,45 +108,52 @@ func (m *SignatureManager) makeSignersHashToIDMap() { ...@@ -98,45 +108,52 @@ func (m *SignatureManager) makeSignersHashToIDMap() {
} }
// promiseRound describes a promise round: reception and sending // promiseRound describes a promise round: reception and sending
func (m *SignatureManager) promiseRound(pendingSet, sendSet []uint32, myID uint32) { func (m *SignatureManager) promiseRound(pendingSet, sendSet []common.SequenceCoordinate) error {
// Reception of the due promises // Reception of the due promises
var promises []*cAPI.Promise
for len(pendingSet) > 0 { for len(pendingSet) > 0 {
select { select {
case promiseIface := <-m.cServerIface.incomingPromises: case promiseIface := <-m.cServerIface.incomingPromises:
promise := (promiseIface).(*cAPI.Promise) promise := (promiseIface).(*cAPI.Promise)
senderID, exist := m.hashToID[fmt.Sprintf("%x", promise.Context.SenderKeyHash)] valid, senderID := m.checkPromise(pendingSet, promise)
if exist { if valid {
var err error var err error
pendingSet, err = common.Remove(pendingSet, senderID) pendingSet, err = common.RemoveCoordinate(pendingSet, senderID)
if err != nil { if err != nil {
continue continue
} }
m.archives.receivedPromises = append(m.archives.receivedPromises, promise) promises = append(promises, promise)
} else {
return m.resolve()
} }
case <-time.After(time.Minute): case <-time.After(time.Minute):
// TODO contact TTP return m.resolve()
return
} }
} }
// Now that we received everything, we update the evidence we will give to the ttp
m.updateReceivedPromises(promises)
m.lastValidIndex = m.currentIndex
c := make(chan *cAPI.Promise, chanBufferSize) c := make(chan *cAPI.Promise, chanBufferSize)
// Sending of due promises // Sending of due promises
for _, id := range sendSet { for _, coord := range sendSet {
go func(id uint32, m *SignatureManager) { go func(coord common.SequenceCoordinate, m *SignatureManager) {
promise, err := m.CreatePromise(myID, id) promise, err := m.CreatePromise(m.myID, coord.Signer, uint32(m.currentIndex))
if err == nil { if err == nil {
_ = m.SendEvidence(promise, nil, id) _ = m.SendEvidence(promise, nil, coord.Signer)
} }
c <- promise c <- promise
}(id, m) }(coord, m)
} }
// Verifying we sent all the due promises // Verifying we sent all the due promises
for range sendSet { for range sendSet {
<-c <-c
} }
return nil
} }
// closeConnections tries to close all established connection with other peers and platform. // closeConnections tries to close all established connection with other peers and platform.
...@@ -149,3 +166,108 @@ func (m *SignatureManager) closeConnections() { ...@@ -149,3 +166,108 @@ func (m *SignatureManager) closeConnections() {
} }
m.cServer.Stop() m.cServer.Stop()
} }