protocol.go 3.82 KB
Newer Older
1
// Package sign handles contract and signature operations.
2
3
4
5
package sign

import (
	"fmt"
6
	"time"
7
8
9

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

13
// Sign performs all the message exchanges for the contract to be signed
14
15
16
17
18
19
//
// * Initialize the SignatureManager from starter.go
// * Compute the reversed map [mail -> ID] of signers
// * Make channels for handlers
// * Promises rounds
// * Signature round
20
func (m *SignatureManager) Sign() error {
21
	myID, nextIndex, err := m.Initialize()
22
23
24
25
	if err != nil {
		return err
	}

26
	m.makeSignersHashToIDMap()
27
28
	m.cServerIface.incomingPromises = make(chan interface{}, chanBufferSize)
	m.cServerIface.incomingSignatures = make(chan interface{}, chanBufferSize)
29

30
31
	// Cooldown delay, let other clients wake-up their channels
	time.Sleep(time.Second)
32

Loïck Bonniot's avatar
Loïck Bonniot committed
33
34
	seqLen := len(m.sequence)

35
	// Promess rounds
36
	// Follow the sequence until there is no next occurence of me
37
	for m.currentIndex >= 0 {
Loïck Bonniot's avatar
Loïck Bonniot committed
38
		m.OnProgressUpdate(m.currentIndex, seqLen+1)
39
		dAPI.DLog("starting round at index [" + fmt.Sprintf("%d", m.currentIndex) + "] with nextIndex=" + fmt.Sprintf("%d", nextIndex))
Richer Maximilien's avatar
Richer Maximilien committed
40

Loïck Bonniot's avatar
Loïck Bonniot committed
41
		// Set of promises we are waiting for
42
43
44
45
		var pendingSet []uint32
		pendingSet, err = common.GetPendingSet(m.sequence, myID, m.currentIndex)
		if err != nil {
			return err
46
47
		}

48
		// Set of the promises we must send
49
50
51
52
		var sendSet []uint32
		sendSet, err = common.GetSendSet(m.sequence, myID, m.currentIndex)
		if err != nil {
			return err
53
54
		}

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

58
		m.currentIndex = nextIndex
59
60
61
		nextIndex, err = common.FindNextIndex(m.sequence, myID, m.currentIndex)
		if err != nil {
			return err
62
63
64
		}
	}

Loïck Bonniot's avatar
Loïck Bonniot committed
65
	m.OnProgressUpdate(seqLen, seqLen+1)
66
	dAPI.DLog("entering signature round")
67
	// Signature round
68
	err = m.ExchangeAllSignatures()
69
70
71
	if err != nil {
		return err
	}
72
	dAPI.DLog("exiting signature round")
Loïck Bonniot's avatar
Loïck Bonniot committed
73
	m.OnProgressUpdate(seqLen+1, seqLen+1)
74

75
76
	// Network's job is done, cleaning time
	// Shutdown and platform client and TODO peer server & connections
77
	return m.platformConn.Close()
78
79
80
}

// GetClient retrieves the Client to the specified sequence id provided it exists
81
82
83
84
func (m *SignatureManager) GetClient(to uint32) (client *cAPI.ClientClient, mail string) {
	mail = m.contract.Signers[to].Email
	client = m.peers[mail]
	return
85
86
}

87
// makeSignersHashToIDMap builds an association to reverse a hash to the sequence ID
88
89
func (m *SignatureManager) makeSignersHashToIDMap() {
	m.hashToID = make(map[string]uint32)
90
91
	signers := m.contract.Signers
	for id, signer := range signers {
92
		m.hashToID[signer.Hash] = uint32(id)
93
94
95
	}
}

96
// promiseRound describes a promise round: reception and sending
97
98
99
100
func (m *SignatureManager) promiseRound(pendingSet, sendSet []uint32, myID uint32) {

	// Reception of the due promises
	for len(pendingSet) > 0 {
101
102
103
104
105
106
107
108
109
110
111
		select {
		case promiseIface := <-m.cServerIface.incomingPromises:
			promise := (promiseIface).(*cAPI.Promise)
			senderID, exist := m.hashToID[fmt.Sprintf("%x", promise.Context.SenderKeyHash)]
			if exist {
				var err error
				pendingSet, err = common.Remove(pendingSet, senderID)
				if err != nil {
					continue
				}
				m.archives.receivedPromises = append(m.archives.receivedPromises, promise)
112
			}
113
114
115
116

		case <-time.After(time.Minute):
			// TODO contact TTP
			return
117
		}
118
119
	}

120
	c := make(chan *cAPI.Promise, chanBufferSize)
121
122
123
124
	// Sending of due promises
	for _, id := range sendSet {
		go func(id uint32, m *SignatureManager) {
			promise, err := m.CreatePromise(myID, id)
125
126
			if err == nil {
				_ = m.SendEvidence(promise, nil, id)
127
128
129
			}
			c <- promise
		}(id, m)
130
131
	}

132
	// Verifying we sent all the due promises
133
	for range sendSet {
Loïck Bonniot's avatar
Loïck Bonniot committed
134
		<-c
135
136
	}
}
137
138
139
140

// closeAllPeerClient tries to close all established connection with other peers
func (m *SignatureManager) closeAllPeerClient() {
	for k, client := range m.peersConn {
141
		_ = client.Close()
142
143
144
145
		// Remove associated grpc client
		delete(m.peers, k)
	}
}