Commit dd9b187b authored by Loïck Bonniot's avatar Loïck Bonniot

Merge branch '218_promesses_client' into 'master'

218 promesses client



See merge request !80
parents af6a6448 ae6f41fc
Pipeline #2097 failed with stages
......@@ -51,8 +51,13 @@ type Context struct {
ContractDocumentHash []byte `protobuf:"bytes,5,opt,name=contractDocumentHash,proto3" json:"contractDocumentHash,omitempty"`
// / The unique signature attemp ID, as provided by the platform during the ready signal
SignatureUUID string `protobuf:"bytes,6,opt,name=signatureUUID" json:"signatureUUID,omitempty"`
// / The TTP address provided by the platform, to use in case of issue during signature.
// / Empty if no TTP used.
TtpAddrPort string `protobuf:"bytes,7,opt,name=ttpAddrPort" json:"ttpAddrPort,omitempty"`
// / The TTP certificate SHA-512 hash
TtpHash []byte `protobuf:"bytes,8,opt,name=ttpHash,proto3" json:"ttpHash,omitempty"`
// / The signed metadata seal, as provided by the platform during the ready signal
Seal []byte `protobuf:"bytes,7,opt,name=seal,proto3" json:"seal,omitempty"`
Seal []byte `protobuf:"bytes,10,opt,name=seal,proto3" json:"seal,omitempty"`
}
func (m *Context) Reset() { *m = Context{} }
......@@ -262,27 +267,31 @@ var _Client_serviceDesc = grpc.ServiceDesc{
}
var fileDescriptor0 = []byte{
// 348 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x84, 0x91, 0xcf, 0x4e, 0xea, 0x40,
0x14, 0xc6, 0xe9, 0xe5, 0x4f, 0xe1, 0xdc, 0xc2, 0x25, 0x93, 0x6b, 0x32, 0x41, 0x49, 0x48, 0xe3,
0x82, 0x55, 0x49, 0x70, 0xe9, 0x12, 0x4c, 0x30, 0x6e, 0x4c, 0x94, 0x07, 0x18, 0xa7, 0x07, 0x9d,
0xa4, 0x74, 0xea, 0xcc, 0x60, 0xe0, 0x35, 0x7c, 0x02, 0x1f, 0xd5, 0xe9, 0xa9, 0x45, 0x16, 0x26,
0x6e, 0x9a, 0x9e, 0x6f, 0xbe, 0xf3, 0xf5, 0xf7, 0x75, 0xe0, 0x3c, 0xdd, 0x58, 0x3b, 0x2b, 0x1f,
0x72, 0x26, 0x0a, 0x35, 0x93, 0x99, 0xc2, 0xdc, 0x25, 0x85, 0xd1, 0x4e, 0xb3, 0xa6, 0x57, 0x46,
0xe3, 0xa3, 0xa3, 0x20, 0x47, 0x91, 0x09, 0xb7, 0xd1, 0x66, 0x5b, 0x79, 0xe2, 0x8f, 0x00, 0xc2,
0x85, 0xce, 0x1d, 0xee, 0x1d, 0xe3, 0x30, 0x34, 0x28, 0x55, 0x51, 0x46, 0xdc, 0xe1, 0x61, 0x25,
0xec, 0x0b, 0x0f, 0x26, 0xc1, 0x34, 0x62, 0x67, 0xd0, 0xb7, 0x98, 0xa7, 0x68, 0x6a, 0xf9, 0x0f,
0xc9, 0x43, 0xe8, 0x5a, 0x7c, 0xdd, 0x61, 0x2e, 0x91, 0x37, 0x27, 0xcd, 0x69, 0x9f, 0xfd, 0x83,
0xd0, 0xaa, 0xe7, 0x1c, 0x8d, 0xe5, 0x2d, 0x2f, 0x44, 0xec, 0x02, 0xfe, 0x4b, 0x1f, 0x6f, 0x84,
0x74, 0x4b, 0x2d, 0x77, 0x5b, 0x1f, 0x4d, 0x01, 0xed, 0x63, 0xae, 0xb7, 0x0b, 0xb7, 0x33, 0xb8,
0x5e, 0xdf, 0x2e, 0x79, 0xc7, 0xcb, 0x3d, 0x16, 0x41, 0xcb, 0xa2, 0xc8, 0x78, 0x58, 0x9a, 0xe2,
0x15, 0x84, 0xf7, 0x46, 0x6f, 0x95, 0x45, 0x36, 0x86, 0x50, 0x56, 0xb0, 0x04, 0xf6, 0x77, 0x1e,
0x25, 0xbe, 0x53, 0x52, 0x17, 0xe8, 0x43, 0x5b, 0x79, 0xca, 0x3d, 0xe1, 0x11, 0x4c, 0x21, 0x0e,
0x99, 0x16, 0xa9, 0xa7, 0x2b, 0x93, 0xae, 0xa1, 0xf7, 0x50, 0x7f, 0xee, 0xb7, 0xac, 0x93, 0x65,
0x2a, 0x1b, 0x73, 0x68, 0xaf, 0x30, 0xcb, 0x74, 0x79, 0xf2, 0xe6, 0x0b, 0x2a, 0x9d, 0xd3, 0x62,
0x6f, 0xfe, 0x1e, 0x40, 0x67, 0x41, 0x3f, 0x9e, 0x25, 0x10, 0x3d, 0x1a, 0x14, 0xae, 0x06, 0xae,
0x32, 0xbf, 0xa6, 0xd1, 0x80, 0xa6, 0x1b, 0x63, 0xb4, 0x59, 0xe8, 0x14, 0xe3, 0x06, 0x9b, 0xc3,
0x80, 0xfc, 0xdf, 0x58, 0x95, 0xe7, 0x38, 0xff, 0xb0, 0x73, 0x09, 0xdd, 0xa5, 0xb2, 0x52, 0x7b,
0x08, 0x06, 0x74, 0x4a, 0x5c, 0xa3, 0x93, 0xf7, 0xb8, 0xf1, 0xd4, 0xa1, 0xfb, 0xbd, 0xfa, 0x0c,
0x00, 0x00, 0xff, 0xff, 0x64, 0x27, 0xd3, 0xc2, 0x22, 0x02, 0x00, 0x00,
// 404 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0x8c, 0x52, 0xdd, 0xca, 0xda, 0x40,
0x10, 0xf5, 0x3f, 0x3a, 0x46, 0x29, 0x8b, 0x17, 0x21, 0xa5, 0x60, 0x83, 0x14, 0xe9, 0x45, 0x04,
0xfb, 0x04, 0x45, 0x0b, 0x96, 0x52, 0x90, 0xb4, 0x3e, 0xc0, 0x76, 0x33, 0xb6, 0x0b, 0x31, 0x9b,
0xee, 0xae, 0x45, 0x5f, 0xa3, 0xaf, 0xd3, 0x97, 0xeb, 0x66, 0x62, 0xfc, 0x94, 0xcf, 0x8b, 0xef,
0x26, 0xec, 0x39, 0x73, 0x76, 0xce, 0xec, 0xc9, 0xc0, 0xeb, 0x74, 0x6f, 0xcc, 0xa2, 0xfc, 0x88,
0x05, 0x2f, 0xe4, 0x42, 0x64, 0x12, 0x73, 0x1b, 0x17, 0x5a, 0x59, 0xc5, 0xda, 0x8e, 0x09, 0xdf,
0x5c, 0x15, 0x05, 0x29, 0x8a, 0x8c, 0xdb, 0xbd, 0xd2, 0x87, 0x4a, 0x13, 0xfd, 0x6b, 0x81, 0xb7,
0x52, 0xb9, 0xc5, 0x93, 0x65, 0xef, 0xe1, 0x95, 0x46, 0x21, 0x8b, 0xb2, 0xc5, 0x17, 0x3c, 0x6f,
0xb8, 0xf9, 0x15, 0x34, 0xa7, 0xcd, 0xb9, 0x9f, 0x3c, 0xe3, 0xd9, 0x0c, 0x46, 0x06, 0xf3, 0x14,
0x75, 0x2d, 0x6c, 0x91, 0xf0, 0x9e, 0x64, 0x21, 0xf4, 0x0d, 0xfe, 0x3e, 0x62, 0x2e, 0x30, 0x68,
0x4f, 0xdb, 0xf3, 0x51, 0x72, 0xc5, 0x2c, 0x00, 0xcf, 0xc8, 0x9f, 0x39, 0x6a, 0x13, 0x74, 0x5c,
0xc9, 0x4f, 0x6a, 0xc8, 0x96, 0x30, 0x11, 0x6e, 0x24, 0xcd, 0x85, 0x5d, 0x2b, 0x71, 0x3c, 0x38,
0x5b, 0xb2, 0xe8, 0x92, 0xc5, 0xc3, 0x1a, 0xcd, 0xe3, 0xae, 0x73, 0x7b, 0xd4, 0xb8, 0xdb, 0x7d,
0x5e, 0x07, 0x3d, 0x27, 0x1e, 0x24, 0xf7, 0x24, 0x9b, 0xc2, 0xd0, 0xda, 0xe2, 0x63, 0x9a, 0xea,
0xad, 0xd2, 0x36, 0xf0, 0x48, 0x73, 0x4b, 0x95, 0x53, 0x39, 0x48, 0x76, 0x7d, 0xb2, 0xab, 0x21,
0x63, 0xd0, 0x31, 0xc8, 0xb3, 0x00, 0x88, 0xa6, 0x73, 0xc4, 0xc1, 0xdb, 0x6a, 0x75, 0x90, 0x06,
0xd9, 0x3b, 0xf0, 0x44, 0x95, 0x23, 0x65, 0x36, 0x5c, 0xfa, 0xb1, 0x8b, 0x3b, 0xbe, 0x64, 0x9b,
0xd4, 0x45, 0x36, 0x81, 0xae, 0x74, 0x11, 0x9d, 0x28, 0xb0, 0x51, 0x52, 0x81, 0xd2, 0xb6, 0xe0,
0xe7, 0x4c, 0xf1, 0xd4, 0xe5, 0x44, 0xb6, 0x17, 0x18, 0x7d, 0x85, 0xc1, 0xb7, 0xfa, 0x0d, 0x2f,
0x36, 0xb9, 0x69, 0xd7, 0xba, 0x6f, 0xf7, 0x16, 0xba, 0x1b, 0xcc, 0x32, 0x55, 0x4a, 0xfe, 0xb8,
0xb0, 0xa5, 0xca, 0xa9, 0xd5, 0x20, 0xa9, 0xe1, 0xf2, 0x6f, 0x13, 0x7a, 0x2b, 0xda, 0x23, 0x16,
0x83, 0xff, 0x5d, 0x23, 0xb7, 0xf5, 0x23, 0x2b, 0xbb, 0x0b, 0x0a, 0xc7, 0x84, 0x3e, 0x69, 0xad,
0xf4, 0x4a, 0xa5, 0x18, 0x35, 0xdc, 0x9f, 0x1b, 0x93, 0xfe, 0x69, 0xe2, 0x4a, 0x73, 0xc5, 0x0f,
0xee, 0xcc, 0xa0, 0xbf, 0x96, 0x46, 0x28, 0x67, 0xcf, 0x80, 0xaa, 0x34, 0x60, 0x78, 0x73, 0x8e,
0x1a, 0x3f, 0x7a, 0xb4, 0xae, 0x1f, 0xfe, 0x07, 0x00, 0x00, 0xff, 0xff, 0x63, 0xf5, 0x69, 0x69,
0xf1, 0x02, 0x00, 0x00,
}
......@@ -30,8 +30,13 @@ message Context {
bytes contractDocumentHash = 5;
/// The unique signature attemp ID, as provided by the platform during the ready signal
string signatureUUID = 6;
/// The TTP address provided by the platform, to use in case of issue during signature.
/// Empty if no TTP used.
string ttpAddrPort = 7;
/// The TTP certificate SHA-512 hash
bytes ttpHash = 8;
/// The signed metadata seal, as provided by the platform during the ready signal
bytes seal = 7;
bytes seal = 10;
}
message Promise {
......
......@@ -82,13 +82,6 @@ var signCmd = &cobra.Command{
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.")
},
}
......
......@@ -4,6 +4,11 @@ import (
"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)
// 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) {
//
// 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{}
func GetPendingSet(s []uint32, id uint32, index int) ([]SequenceCoordinate, error) {
res := []SequenceCoordinate{}
if index >= len(s) || index < 0 {
return res, errors.New("Index out of range")
......@@ -44,8 +49,8 @@ func GetPendingSet(s []uint32, id uint32, index int) ([]uint32, error) {
for curIndex > -1 && s[curIndex] != id {
curID := s[curIndex]
if !contains(res, curID) {
res = append(res, curID)
if !containsCoordinate(res, curID) {
res = append(res, SequenceCoordinate{Signer: curID, Index: uint32(curIndex)})
}
curIndex--
}
......@@ -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 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{}
func GetSendSet(s []uint32, id uint32, index int) ([]SequenceCoordinate, error) {
res := []SequenceCoordinate{}
if index >= len(s) || index < 0 {
return res, errors.New("Index out of range")
......@@ -73,8 +78,8 @@ func GetSendSet(s []uint32, id uint32, index int) ([]uint32, error) {
for curIndex < len(s) && s[curIndex] != id {
curID := s[curIndex]
if !contains(res, curID) {
res = append(res, curID)
if !containsCoordinate(res, curID) {
res = append(res, SequenceCoordinate{Signer: curID, Index: uint32(curIndex)})
}
curIndex++
}
......@@ -82,7 +87,17 @@ func GetSendSet(s []uint32, id uint32, index int) ([]uint32, error) {
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 {
for _, a := range s {
if a == e {
......@@ -108,7 +123,17 @@ func GetAllButOne(s []uint32, e uint32) []uint32 {
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) {
for i, a := range s {
if a == e {
......
......@@ -50,19 +50,24 @@ func TestGetPendingSet(t *testing.T) {
res, err = GetPendingSet(s, id, 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)
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, res[0].Signer, uint32(1))
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)
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, res[0].Signer, uint32(1))
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)
res, err = GetPendingSet(s, id, -1)
......@@ -76,11 +81,23 @@ func TestGetPendingSet(t *testing.T) {
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, res[0].Signer, uint32(0))
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)
}
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) {
s := []uint32{0, 1}
......@@ -95,19 +112,24 @@ func TestGetSendSet(t *testing.T) {
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, res[0].Signer, uint32(1))
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)
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, res[0].Signer, uint32(1))
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)
res, err = GetSendSet(s, 1, 4)
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)
res, err = GetSendSet(s, 2, 5)
......@@ -139,6 +161,46 @@ func TestGetAllButOne(t *testing.T) {
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() {
s := []uint32{0, 1, 2, 0, 1, 2}
id := uint32(2)
......@@ -153,6 +215,6 @@ func ExampleFindNextIndex() {
fmt.Println("Send Set:", sSet)
// Output:
// First index: 2
// Pending Set: [1 0]
// Send Set: [0 1]
// Pending Set: [{1 1} {0 0}]
// Send Set: [{0 3} {1 4}]
}
package sign
import (
"encoding/hex"
"errors"
"time"
......@@ -14,20 +15,25 @@ func (m *SignatureManager) createContext(from, to uint32) (*cAPI.Context, error)
if int(from) >= len(m.keyHash) || int(to) >= len(m.keyHash) {
return nil, errors.New("Invalid id for context creation")
}
h, _ := hex.DecodeString(m.contract.File.Hash)
return &cAPI.Context{
RecipientKeyHash: m.keyHash[to],
SenderKeyHash: m.keyHash[from],
Sequence: m.sequence,
Signers: m.keyHash,
ContractDocumentHash: []byte(m.contract.File.Hash),
ContractDocumentHash: h,
SignatureUUID: m.uuid,
TtpAddrPort: m.ttpData.Addrport,
TtpHash: m.ttpData.Hash,
Seal: m.seal,
}, nil
}
// CreatePromise creates a promise from 'from' to 'to', in the context of the SignatureManager
// provided the specified sequence indexes are valid
func (m *SignatureManager) CreatePromise(from, to uint32) (*cAPI.Promise, error) {
// provided that the specified sequence indexes are valid
func (m *SignatureManager) CreatePromise(from, to, at uint32) (*cAPI.Promise, error) {
context, err := m.createContext(from, to)
if err != nil {
return nil, err
......@@ -38,7 +44,7 @@ func (m *SignatureManager) CreatePromise(from, to uint32) (*cAPI.Promise, error)
}
return &cAPI.Promise{
Index: uint32(m.currentIndex),
Index: at,
Context: context,
Payload: []byte{0x41},
}, nil
......@@ -68,15 +74,17 @@ func (m *SignatureManager) SendEvidence(promise *cAPI.Promise, signature *cAPI.S
if err == nil && result != nil && result.Code == pAPI.ErrorCode_SUCCESS {
m.archives.mutex.Lock()
if promise != nil {
dAPI.DLog("sent promise to " + mail)
m.archives.sentPromises = append(m.archives.sentPromises, promise)
dAPI.DLog("successfully sent promise to " + mail)
} else {
dAPI.DLog("sent signature to " + mail)
dAPI.DLog("successfully sent signature to " + mail)
m.archives.sentSignatures = append(m.archives.sentSignatures, signature)
}
m.archives.mutex.Unlock()
} else {
dAPI.DLog("unable to send evidence to " + mail)
dAPI.DLog("was unable to send evidence to " + mail)
if err != nil {
return
}
err = errors.New("received wrong error code")
}
......
......@@ -2,14 +2,21 @@
package sign
import (
"bytes"
"errors"
"fmt"
"io/ioutil"
"os"
"time"
cAPI "dfss/dfssc/api"
"dfss/dfssc/common"
dAPI "dfss/dfssd/api"
tAPI "dfss/dfsst/api"
"dfss/net"
"github.com/spf13/viper"
"golang.org/x/net/context"
"google.golang.org/grpc"
)
// Sign performs all the message exchanges for the contract to be signed
......@@ -26,7 +33,7 @@ func (m *SignatureManager) Sign() error {
m.closeConnections()
}()
myID, nextIndex, err := m.Initialize()
nextIndex, err := m.Initialize()
if err != nil {
return err
}
......@@ -42,31 +49,38 @@ func (m *SignatureManager) Sign() error {
// Promess rounds
// Follow the sequence until there is no next occurence of me
round := 0
for m.currentIndex >= 0 {
stopIfNeeded(m.currentIndex)
round = round + 1
stopIfNeeded(round)
m.OnProgressUpdate(m.currentIndex, seqLen+1)
time.Sleep(viper.GetDuration("slowdown"))
dAPI.DLog("starting round at index [" + fmt.Sprintf("%d", m.currentIndex) + "] with nextIndex=" + fmt.Sprintf("%d", nextIndex))
// Set of promises we are waiting for
var pendingSet []uint32
pendingSet, err = common.GetPendingSet(m.sequence, myID, m.currentIndex)
var pendingSet []common.SequenceCoordinate
pendingSet, err = common.GetPendingSet(m.sequence, m.myID, m.currentIndex)
if err != nil {
return err
}
// Set of the promises we must send
var sendSet []uint32
sendSet, err = common.GetSendSet(m.sequence, myID, m.currentIndex)
var sendSet []common.SequenceCoordinate
sendSet, err = common.GetSendSet(m.sequence, m.myID, m.currentIndex)
if err != nil {
return err
}
// Exchange messages
m.promiseRound(pendingSet, sendSet, myID)
var stop bool
stop, err = m.promiseRound(pendingSet, sendSet)
if err != nil || stop {
dAPI.DLog("stopping protocol execution")
return err
}
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 {
return err
}
......@@ -83,7 +97,7 @@ func (m *SignatureManager) Sign() error {
dAPI.DLog("exiting signature round")
m.OnProgressUpdate(seqLen+1, seqLen+1)
return nil
return m.PersistSignaturesToFile()
}
// GetClient retrieves the Client to the specified sequence id provided it exists
......@@ -103,45 +117,59 @@ func (m *SignatureManager) makeSignersHashToIDMap() {
}
// promiseRound describes a promise round: reception and sending
func (m *SignatureManager) promiseRound(pendingSet, sendSet []uint32, myID uint32) {
// returns true if the client has to stop the protocol, false otherwise.
// returns an error if any occured.
func (m *SignatureManager) promiseRound(pendingSet, sendSet []common.SequenceCoordinate) (bool, error) {
// Reception of the due promises
var promises []*cAPI.Promise
for len(pendingSet) > 0 {
select {
case promiseIface := <-m.cServerIface.incomingPromises:
promise := (promiseIface).(*cAPI.Promise)
senderID, exist := m.hashToID[fmt.Sprintf("%x", promise.Context.SenderKeyHash)]
if exist {
valid, senderID := m.checkPromise(pendingSet, promise)
if valid {
var err error
pendingSet, err = common.Remove(pendingSet, senderID)
pendingSet, err = common.RemoveCoordinate(pendingSet, senderID)
if err != nil {
continue
}
m.archives.receivedPromises = append(m.archives.receivedPromises, promise)
promises = append(promises, promise)
} else {
return true, m.resolve()
}
case <-time.After(time.Minute):
// TODO contact TTP
return
case <-time.After(net.DefaultTimeout):
return true, m.resolve()
}
}
c := make(chan *cAPI.Promise, chanBufferSize)
// 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 error, chanBufferSize)
// Sending of due promises
for _, id := range sendSet {
go func(id uint32, m *SignatureManager) {
promise, err := m.CreatePromise(myID, id)
for _, coord := range sendSet {
go func(coord common.SequenceCoordinate, m *SignatureManager) {
promise, err := m.CreatePromise(m.myID, coord.Signer, uint32(m.currentIndex))
if err == nil {
_ = m.SendEvidence(promise, nil, id)
err = m.SendEvidence(promise, nil, coord.Signer)
}
c <- promise
}(id, m)
c <- err
}(coord, m)
}
// Verifying we sent all the due promises
for range sendSet {
<-c
v := <-c
if v != nil {
// We couldn't send a due promise
dAPI.DLog("Couldn't send promise: " + v.Error())
return true, m.resolve()
}
}
return false, nil
}
// closeConnections tries to close all established connection with other peers and platform.
......@@ -155,13 +183,123 @@ func (m *SignatureManager) closeConnections() {
m.cServer.Stop()
}
// updateReceivedPromises : updates the RecievedPromises field of the SignatureManager with the provided promises:
// if we don't yet have a promise from this signer, we add it to the array.
// otherwise we replace the one we have by the provided promise.
func (m *SignatureManager) updateReceivedPromises(promises []*cAPI.Promise) {
for _, p := range promises {
present, index := m.containsPromiseFrom(p.Context.SenderKeyHash, p.Index)
if present {
// it's present, so there is no index error
_ = m.removeReceivedPromise(index)
}
m.archives.receivedPromises = append(m.archives.receivedPromises, p)
}
}
// containsPromiseFrom : determines if the SignatureManager has already archived a promise from the specified signer, previous to the specified index.
func (m *SignatureManager) containsPromiseFrom(signer []byte, index uint32) (bool, int) {
for i, p := range m.archives.receivedPromises {
if bytes.Equal(p.Context.SenderKeyHash, signer) {
return p.Index < index, i
}
}
return false, 0
}
// removeReceivedPromise : removes the promise at the specified index from the archived received promises.
// If the index is invalid, return an error.
// If the promise is not there, does nothing.
func (m *SignatureManager) removeReceivedPromise(index int) error {
promises := m.archives.receivedPromises
if index < 0 || index >= len(promises) {
return errors.New("Index out of range")
}
m.archives.receivedPromises = append(promises[:index], promises[index+1:]...)
return nil
}
// callForResolve : calls the ttp for resolution.
func (m *SignatureManager) callForResolve() (*tAPI.TTPResponse, error) {
selfPromise, err := m.CreatePromise(m.myID, m.myID, uint32(m.lastValidIndex))
if err != nil {
return nil, err
}
toSend := append(m.archives.receivedPromises, selfPromise)
request := &tAPI.AlertRequest{Promises: toSend, Index: uint32(m.lastValidIndex)}
ctx, cancel := context.WithTimeout(context.Background(), net.DefaultTimeout)
defer cancel()
response, err := m.ttp.Alert(ctx, request)
if err != nil {
return nil, errors.New(grpc.ErrorDesc(err))
}
return response, nil
}
// resolve : calls for the resolution, and persists the contract if obtained.
func (m *SignatureManager) resolve() error {
if m.ttp == nil {
dAPI.DLog("unable to contact TTP")
return errors.New("No connection to TTP, aborting!")
}
dAPI.DLog("contacting TTP with resolve index " + fmt.Sprint(m.lastValidIndex))
response, err := m.callForResolve()
if err != nil {
dAPI.DLog("Resolve call generated an error: " + err.Error())
return err
}
if response.Abort {
dAPI.DLog("contacted TTP, received abort token")
return nil
}
dAPI.DLog("contacted TTP, received signed contract")
return ioutil.WriteFile(m.mail+"-"+m.contract.UUID+".proof", response.Contract, 0600)
}
// checkPromise : verifies that the promise is valid wrt the expected promises.
// We assume that the promise data is consistent wrt the platform seal.
func (m *SignatureManager) checkPromise(expected []common.SequenceCoordinate, promise *cAPI.Promise) (bool, uint32) {
// the promise is consistent, but not for the expected signature
// this should not happen
if promise.Context.SignatureUUID != m.uuid {
return false, 0
}
// the promise is not for us
recipientID, exist := m.hashToID[fmt.Sprintf("%x", promise.Context.RecipientKeyHash)]
if !exist || recipientID != m.myID {
return false, 0
}
// we didn't expect a promise from this client
senderID, exist := m.hashToID[fmt.Sprintf("%x", promise.Context.SenderKeyHash)]
if !exist {
return false, 0
}
for _, c := range expected {
if c.Signer == senderID && c.Index == promise.Index {
return true, senderID
}
}
return false, 0
}
func stopIfNeeded(index int) {