protocol.go 3.63 KB
Newer Older
1
2
3
4
package sign

import (
	"fmt"
Richer Maximilien's avatar
Richer Maximilien committed
5
	"log"
6
7
8

	cAPI "dfss/dfssc/api"
	"dfss/dfssc/common"
Richer Maximilien's avatar
Richer Maximilien committed
9
	dAPI "dfss/dfssd/api"
10
11
)

12
13
14
15
16
17
18
19
20
21
22
23
24
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
25
func (m *SignatureManager) Sign() error {
26
27

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

32
33
34
35
36
	hashToID = m.makeSignersHashToIDMap()

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

37
	// Promess rounds
38
	// Follow the sequence until there is no next occurence of me
39
	for m.currentIndex >= 0 {
40

Richer Maximilien's avatar
Richer Maximilien committed
41
42
43
		dAPI.DLog("Starting round at index [" + fmt.Sprintf("%d", m.currentIndex) + "]")
		log.Println("Starting round at index [" + fmt.Sprintf("%d", m.currentIndex) + "]")

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

50
51
		// Set of the promises we must send
		sendSet, err1 := common.GetSendSet(m.sequence, myID, m.currentIndex)
52
53
		if err1 != nil {
			return err1
54
55
		}

56
57
		// Exchange messages
		m.promiseRound(pendingSet, sendSet, myID)
58

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

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

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

93
	hashToID := make(map[string]uint32)
94

95
96
97
	signers := m.contract.Signers
	for id, signer := range signers {
		hashToID[signer.Hash] = uint32(id)
98
	}
99
	return hashToID
100
101
}

102
103
104
105
106
107
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
108
		senderID, exist := hashToID[fmt.Sprintf("%x", promise.SenderKeyHash)]
109
110
111
112
113
114
		if exist {
			var err error
			pendingSet, err = common.Remove(pendingSet, senderID)
			if err != nil {
				// Recieve unexpected promise, ignore ?
			}
Richer Maximilien's avatar
Richer Maximilien committed
115
			dAPI.DLog("Recieved promise from [" + fmt.Sprintf("%d", senderID) + "]")
116
117
118
119
			m.archives.recievedPromises = append(m.archives.recievedPromises, promise)
		} else {
			// Wrong sender keyHash
		}
120
121
	}

122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
	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)
137
138
	}

139
140
141
142
143
144
145
146
	// 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
		}
147
148
	}
}