signatures.go 3.28 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
package sign

import (
	"dfss/dfssc/common"
	"errors"
	"fmt"
	"time"

	cAPI "dfss/dfssc/api"
	dAPI "dfss/dfssd/api"
	pAPI "dfss/dfssp/api"

	"golang.org/x/net/context"
	"google.golang.org/grpc"
)

// SendAllSigns creates and sends signatures to all the signers of the contract
func (m *SignatureManager) SendAllSigns() error {
19 20 21 22

	allRecieved := make(chan error)
	go m.RecieveAllSigns(allRecieved)

23 24 25 26 27 28 29 30
	myID, err := m.FindID()
	if err != nil {
		return err
	}

	// compute a set of all signers exept me
	sendSet := common.GetAllButOne(m.sequence, myID)

31 32
	errorChan := make(chan error)

33
	for _, id := range sendSet {
34 35 36 37 38 39
		go func(id uint32) {
			signature, err := m.CreateSignature(myID, id)
			if err != nil {
				errorChan <- err
				return
			}
40

41 42 43 44 45 46 47 48 49 50 51 52 53 54
			dAPI.DLog("{" + fmt.Sprintf("%d", myID) + "} Send sign to " + fmt.Sprintf("%d", id))
			_, err = m.SendSignature(signature, id)
			if err != nil {
				errorChan <- err
				return
			}

			errorChan <- nil
			return
		}(id)
	}

	for range sendSet {
		err = <-errorChan
55 56 57 58 59
		if err != nil {
			return err
		}
	}

60 61 62 63 64
	err = <-allRecieved
	if err != nil {
		return err
	}

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 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
	return nil
}

// CreateSignature creates a signature from a sequence ID to another
// provided the specified sequence indexes are valid
// TODO Implement a true cryptographic signature
func (m *SignatureManager) CreateSignature(from, to uint32) (*cAPI.Signature, error) {
	if int(from) >= len(m.keyHash) || int(to) >= len(m.keyHash) {
		return &cAPI.Signature{}, errors.New("Invalid id for signature creation")
	}
	signature := &cAPI.Signature{
		RecipientKeyHash: m.keyHash[to],
		SenderKeyHash:    m.keyHash[from],
		Signature:        "Signature",
		SignatureUuid:    m.uuid,
		ContractUuid:     m.contract.UUID,
	}
	return signature, nil
}

// SendSignature sends the specified signature to the specified peer
func (m *SignatureManager) SendSignature(signature *cAPI.Signature, to uint32) (*pAPI.ErrorCode, error) {
	connection, err := m.GetClient(to)
	if err != nil {
		return &pAPI.ErrorCode{}, err
	}

	// Handle the timeout
	ctx, cancel := context.WithTimeout(context.Background(), 10*time.Minute)
	defer cancel()

	errCode, err := (*connection).TreatSignature(ctx, signature)
	if err == grpc.ErrClientConnTimeout {
		dAPI.DLog("Signature timeout for [" + fmt.Sprintf("%d", to) + "]")
		return &pAPI.ErrorCode{Code: pAPI.ErrorCode_TIMEOUT, Message: "signature timeout"}, err
	} else if err != nil {
		return &pAPI.ErrorCode{Code: pAPI.ErrorCode_INTERR, Message: "internal server error"}, err
	}

	m.archives.sentSignatures = append(m.archives.sentSignatures, signature)

	return errCode, nil
}

109 110
// RecieveAllSigns recieve all the signatures
func (m *SignatureManager) RecieveAllSigns(out chan error) {
111 112
	myID, err := m.FindID()
	if err != nil {
113 114
		out <- err
		return
115 116 117 118 119 120 121 122
	}

	// compute a set of all signers exept me
	pendingSet := common.GetAllButOne(m.sequence, myID)

	// TODO this ctx needs a timeout !
	for len(pendingSet) > 0 {
		signature := <-incomingSignatures
123
		senderID, exist := hashToID[fmt.Sprintf("%x", signature.SenderKeyHash)]
124 125 126 127 128 129 130 131 132 133 134 135
		if exist {
			var err error
			pendingSet, err = common.Remove(pendingSet, senderID)
			if err != nil {
				// Recieve unexpected signature, ignore ?
			}
			m.archives.recievedSignatures = append(m.archives.recievedSignatures, signature)
		} else {
			// Wrong sender keyHash
		}
	}

136 137
	out <- nil
	return
138
}