signatures.go 2.1 KB
Newer Older
1 2 3 4
package sign

import (
	"fmt"
5
	"time"
6 7

	cAPI "dfss/dfssc/api"
8
	"dfss/dfssc/common"
9 10
)

11 12
// ExchangeAllSignatures creates and sends signatures to all the signers of the contract
func (m *SignatureManager) ExchangeAllSignatures() error {
13
	allReceived := make(chan error, chanBufferSize)
14
	go m.ReceiveAllSignatures(allReceived)
15

16 17 18 19 20
	myID, err := m.FindID()
	if err != nil {
		return err
	}

21
	// compute a set of all signers except me
22
	sendSet := common.GetAllButOne(m.sequence, myID)
23
	errorChan := make(chan error, chanBufferSize)
24
	for _, id := range sendSet {
25
		go func(id uint32) {
26 27 28
			signature, err2 := m.CreateSignature(myID, id)
			if err2 != nil {
				errorChan <- err2
29 30
				return
			}
31
			err2 = m.SendEvidence(nil, signature, id)
32 33
			if err2 != nil {
				errorChan <- err2
34 35 36 37 38 39 40 41
				return
			}
			errorChan <- nil
		}(id)
	}

	for range sendSet {
		err = <-errorChan
42 43 44 45 46
		if err != nil {
			return err
		}
	}

47
	return <-allReceived
48 49 50 51 52
}

// CreateSignature creates a signature from a sequence ID to another
// provided the specified sequence indexes are valid
func (m *SignatureManager) CreateSignature(from, to uint32) (*cAPI.Signature, error) {
53
	context, err := m.createContext(from, to)
54
	if err != nil {
55
		return nil, err
56 57
	}

58 59 60 61
	return &cAPI.Signature{
		Context: context,
		Payload: []byte{0x42},
	}, nil
62 63
}

64 65
// ReceiveAllSignatures receive all the signatures
func (m *SignatureManager) ReceiveAllSignatures(out chan error) {
66 67
	myID, err := m.FindID()
	if err != nil {
68 69
		out <- err
		return
70 71
	}

72
	// compute a set of all signers except me
73 74 75
	pendingSet := common.GetAllButOne(m.sequence, myID)

	for len(pendingSet) > 0 {
76 77 78 79 80 81 82 83 84 85 86 87 88
		select {
		// Waiting for signatures from grpc handler
		case signatureIface := <-m.cServerIface.incomingSignatures:
			signature := (signatureIface).(*cAPI.Signature)
			senderID, exist := m.hashToID[fmt.Sprintf("%x", signature.Context.SenderKeyHash)]
			if exist {
				pendingSet, _ = common.Remove(pendingSet, senderID)
				m.archives.receivedSignatures = append(m.archives.receivedSignatures, signature)
			}

		case <-time.After(time.Minute):
			out <- fmt.Errorf("Signature reception timeout!")
			return
89 90 91
		}
	}

92 93
	out <- nil
	return
94
}