Commit 1b61bc0e authored by Richer Maximilien's avatar Richer Maximilien Committed by Loïck Bonniot

[c] Persist contract signatures to a JSON file

- Signatures are written to a file called `$email-$contractUUID.proof`
- Close connection client-side
- Preserve peer connections
parent 6c665a0c
......@@ -54,5 +54,13 @@ func signContract(args []string) {
fmt.Fprintln(os.Stderr, err)
os.Exit(5)
}
// Persist evidencies, if any
err = manager.PersistSignaturesToFile()
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(5)
}
fmt.Println("Signature complete ! See .proof file for evidences.")
}
package sign
/*
import (
"fmt"
"io/ioutil"
......@@ -59,4 +58,3 @@ func TestComputeFile(t *testing.T) {
assert.Equal(t, "37fd29decfb2d689439478b1f64b60441534c1e373a7023676c94ac6772639edab46f80139d167a2741f159e62b3064eca58bb331d32cd10770f29064af2a9de", fmt.Sprintf("%x", m.hash))
assert.Equal(t, "contract.txt", m.filename)
}
*/
package sign
import (
"encoding/json"
"fmt"
"io/ioutil"
cAPI "dfss/dfssc/api"
"dfss/dfssp/contract"
)
// SignedContractJSON is an union of contract and realted signatures
type SignedContractJSON struct {
Contract contract.JSON
Signatures []cAPI.Signature
}
// PersistSignaturesToFile save contract informations and signatures to disk
func (m *SignatureManager) PersistSignaturesToFile() error {
// Check content, don't write an empty file
if len(m.archives.recievedSignatures) == 0 {
return fmt.Errorf("No stored signatures, cannot create an empty file (yes I'm a coward)")
}
// Fill JSON struct
signedContract := SignedContractJSON{
Contract: *m.contract,
Signatures: make(
[]cAPI.Signature,
len(m.archives.sentSignatures)+len(m.archives.recievedSignatures),
),
}
for i, s := range m.archives.sentSignatures {
signedContract.Signatures[i] = *s
}
for i, s := range m.archives.recievedSignatures {
signedContract.Signatures[len(m.archives.sentSignatures)+i] = *s
}
proof, err := json.MarshalIndent(signedContract, "", " ")
if err != nil {
return err
}
return ioutil.WriteFile(m.mail+"-"+m.contract.UUID+".proof", proof, 0600)
}
......@@ -66,6 +66,13 @@ func (m *SignatureManager) Sign() error {
dAPI.DLog("{" + fmt.Sprintf("%d", myID) + "} Exit signature round")
// Network's job is done, cleaning time
// Shutdown and platform client and TODO peer server & connections
err = m.platformConn.Close()
if err != nil {
return err
}
return nil
}
......@@ -144,3 +151,16 @@ func (m *SignatureManager) promiseRound(pendingSet, sendSet []uint32, myID uint3
}
}
}
// closeAllPeerClient tries to close all established connection with other peers
func (m *SignatureManager) closeAllPeerClient() {
for k, client := range m.peersConn {
err := client.Close()
if err != nil {
// We don't care
}
// Remove associated grpc client
delete(m.peers, k)
fmt.Println("- Close connection to " + k)
}
}
......@@ -24,6 +24,8 @@ type SignatureManager struct {
localPort int
contract *contract.JSON // contains the contractUUID, the list of the signers' hashes, the hash of the contract
platform pAPI.PlatformClient
platformConn *grpc.ClientConn
peersConn map[string]*grpc.ClientConn
peers map[string]*cAPI.ClientClient
hashToID map[string]uint32
nbReady int
......@@ -75,7 +77,9 @@ func NewSignatureManager(fileCA, fileCert, fileKey, addrPort, passphrase string,
}
m.platform = pAPI.NewPlatformClient(conn)
m.platformConn = conn
m.peersConn = make(map[string]*grpc.ClientConn)
m.peers = make(map[string]*cAPI.ClientClient)
for _, u := range c.Signers {
if u.Email != m.auth.Cert.Subject.CommonName {
......@@ -139,6 +143,9 @@ func (m *SignatureManager) addPeer(user *pAPI.User) (ready bool, err error) {
client := cAPI.NewClientClient(conn)
lastConnection := m.peers[user.Email]
m.peers[user.Email] = &client
// The connection is encapsulated into the interface, so we
// need to create another way to access it
m.peersConn[user.Email] = conn
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
defer cancel()
......
......@@ -14,6 +14,17 @@ import (
"github.com/bmizerany/assert"
)
// TestSignContract unroll the whole signature process.
//
// GOOD CASE
// - Start platform
// - Register client1, client2 and client3
// - Create contract `contract.txt`
// - Sign it
// - Check if all proof files are present
//
// TODO BAD CASES
func TestSignContract(t *testing.T) {
// Cleanup
eraseDatabase()
......@@ -101,4 +112,20 @@ func TestSignContract(t *testing.T) {
assert.T(t, r.Match(output), "Regex is not satisfied: ", r.String())
}
}
// Ensure that all the files are present
proofFile := regexp.MustCompile(`client[0-9]+@example.com.*\.proof`)
files, _ := ioutil.ReadDir("./")
matches := 0
for _, file := range files {
if proofFile.Match([]byte(file.Name())) {
matches++
err = os.Remove("./" + file.Name())
assert.T(t, err == nil, "Cannot remove .proof matching file")
}
}
assert.T(t, matches == 3, "Missing proof file ?")
time.Sleep(time.Second)
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment