protocol.go 3.34 KB
Newer Older
1
2
3
4
5
6
7
8
9
package sign

import (
	"fmt"

	cAPI "dfss/dfssc/api"
	"dfss/dfssc/common"
)

10
11
12
13
14
15
16
17
18
19
20
21
22
var (
	hashToID           map[string]uint32
	incomingPromises   chan *cAPI.Promise
	incomingSignatures chan *cAPI.Signature
)

// Sign performe all the message exchange for the contract to be signed
//
// * Initialize the SignatureManager from starter.go
// * Compute the reversed map [mail -> ID] of signers
// * Make channels for handlers
// * Promises rounds
// * Signature round
23
func (m *SignatureManager) Sign() error {
24
25

	myID, nextIndex, err := m.Initialize()
26
27
28
29
	if err != nil {
		return err
	}

30
31
32
33
34
	hashToID = m.makeSignersHashToIDMap()

	incomingPromises = make(chan *cAPI.Promise)
	incomingSignatures = make(chan *cAPI.Signature)

35
	// Promess rounds
36
37
38
39
40
	// Follow the sequence until there is no next occurence of me
	for nextIndex > 0 {

		// Set of the promise we are waiting for
		pendingSet, err1 := common.GetPendingSet(m.sequence, myID, m.currentIndex)
41
42
		if err1 != nil {
			return err1 // err is renamed to avoid shadowing err on linter check
43
44
		}

45
46
		// Set of the promises we must send
		sendSet, err1 := common.GetSendSet(m.sequence, myID, m.currentIndex)
47
48
		if err1 != nil {
			return err1
49
50
		}

51
52
		// Exchange messages
		m.promiseRound(pendingSet, sendSet, myID)
53

54
55
		m.currentIndex = nextIndex
		nextIndex, err1 = common.FindNextIndex(m.sequence, myID, m.currentIndex)
56
57
		if err1 != nil {
			return err1
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
		}
	}

	// Signature round
	err = m.SendAllSigns()
	if err != nil {
		return err
	}
	err = m.RecieveAllSigns()
	if err != nil {
		return err
	}

	return 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
}

85
86
// makeEMailMap build an association to reverse a hash to the sequence ID
func (m *SignatureManager) makeSignersHashToIDMap() map[string]uint32 {
87

88
	hashToID := make(map[string]uint32)
89

90
91
92
	signers := m.contract.Signers
	for id, signer := range signers {
		hashToID[signer.Hash] = uint32(id)
93
	}
94
	return hashToID
95
96
}

97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
func (m *SignatureManager) promiseRound(pendingSet, sendSet []uint32, myID uint32) {

	// Reception of the due promises
	// TODO this ctx needs a timeout !
	for len(pendingSet) > 0 {
		promise := <-incomingPromises
		senderID, exist := hashToID[string(promise.SenderKeyHash)]
		if exist {
			var err error
			pendingSet, err = common.Remove(pendingSet, senderID)
			if err != nil {
				// Recieve unexpected promise, ignore ?
			}
			m.archives.recievedPromises = append(m.archives.recievedPromises, promise)
		} else {
			// Wrong sender keyHash
		}
114
115
	}

116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
	c := make(chan *cAPI.Promise)
	// Sending of due promises
	for _, id := range sendSet {
		// The signature manager is read only - safe !
		go func(id uint32, m *SignatureManager) {
			promise, err := m.CreatePromise(myID, id)
			if err != nil {
				// Failed to create promise
			}
			_, err = m.SendPromise(promise, id)
			if err != nil {
				// We don't check if the promise has been recieved
			}
			c <- promise
		}(id, m)
131
132
	}

133
134
135
136
137
138
139
140
	// Verifying we sent all the due promesses
	for _ = range sendSet {
		promise := <-c
		if promise != nil {
			m.archives.sentPromises = append(m.archives.sentPromises, promise)
		} else {
			// something appened during the goroutine
		}
141
142
	}
}