aboutsummaryrefslogtreecommitdiff
path: root/instance.go
blob: a67307f7c3326fddf5f26d9b433c772ce6966e67 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
package stfe

import (
	"crypto"
	"fmt"
	"strings"
	"time"

	"net/http"

	"github.com/google/trillian"
	"github.com/system-transparency/stfe/namespace"
)

// Instance is an instance of a particular log front-end
type Instance struct {
	Client        trillian.TrillianLogClient
	SthSource     SthSource
	LogParameters *LogParameters
}

// LogParameters is a collection of log parameters
type LogParameters struct {
	LogId      []byte                   // used externally by everyone
	TreeId     int64                    // used internally by Trillian
	Prefix     string                   // e.g., "test" for <base>/test
	MaxRange   int64                    // max entries per get-entries request
	Submitters *namespace.NamespacePool // trusted submitters
	Witnesses  *namespace.NamespacePool // trusted witnesses
	Deadline   time.Duration            // gRPC deadline
	Interval   time.Duration            // cosigning sth frequency
	Signer     crypto.Signer            // interface to access private key
	HashType   crypto.Hash              // hash function used by Trillian
}

// Endpoint is a named HTTP API endpoint
type Endpoint string

const (
	EndpointAddEntry            = Endpoint("add-entry")
	EndpointAddCosi             = Endpoint("add-cosi") // TODO: name?
	EndpointGetEntries          = Endpoint("get-entries")
	EndpointGetAnchors          = Endpoint("get-anchors")
	EndpointGetProofByHash      = Endpoint("get-proof-by-hash")
	EndpointGetConsistencyProof = Endpoint("get-consistency-proof")
	EndpointGetSth              = Endpoint("get-sth")
	EndpointGetStableSth        = Endpoint("get-stable-sth") // TODO: name?
	EndpointGetCosi             = Endpoint("get-cosi")       // TODO: name?
)

func (i Instance) String() string {
	return fmt.Sprintf("%s\n", i.LogParameters)
}

func (lp LogParameters) String() string {
	return fmt.Sprintf("LogId(%s) TreeId(%d) Prefix(%s) MaxRange(%d) Submitters(%d) Witnesses(%d) Deadline(%v) Interval(%v)", lp.id(), lp.TreeId, lp.Prefix, lp.MaxRange, len(lp.Submitters.List()), len(lp.Witnesses.List()), lp.Deadline, lp.Interval)
}

func (e Endpoint) String() string {
	return string(e)
}

// NewInstance creates a new STFE instance
func NewInstance(lp *LogParameters, client trillian.TrillianLogClient, source SthSource) *Instance {
	return &Instance{
		LogParameters: lp,
		Client:        client,
		SthSource:     source,
	}
}

// NewLogParameters creates new log parameters.  Note that the signer is
// assumed to be an ed25519 signing key.  Could be fixed at some point.
func NewLogParameters(signer crypto.Signer, logId *namespace.Namespace, treeId int64, prefix string, submitters, witnesses *namespace.NamespacePool, maxRange int64, interval, deadline time.Duration) (*LogParameters, error) {
	if signer == nil {
		return nil, fmt.Errorf("need a signer but got none")
	}
	if maxRange < 1 {
		return nil, fmt.Errorf("max range must be at least one")
	}
	lid, err := logId.Marshal()
	if err != nil {
		return nil, fmt.Errorf("failed encoding log identifier: %v", err)
	}
	return &LogParameters{
		LogId:      lid,
		TreeId:     treeId,
		Prefix:     prefix,
		MaxRange:   maxRange,
		Submitters: submitters,
		Witnesses:  witnesses,
		Deadline:   deadline,
		Interval:   interval,
		Signer:     signer,
		HashType:   crypto.SHA256, // STFE assumes RFC 6962 hashing
	}, nil
}

// Handlers returns a list of STFE handlers
func (i *Instance) Handlers() []Handler {
	return []Handler{
		Handler{instance: i, handler: addEntry, endpoint: EndpointAddEntry, method: http.MethodPost},
		Handler{instance: i, handler: addCosi, endpoint: EndpointAddCosi, method: http.MethodPost},
		Handler{instance: i, handler: getEntries, endpoint: EndpointGetEntries, method: http.MethodGet},
		Handler{instance: i, handler: getAnchors, endpoint: EndpointGetAnchors, method: http.MethodGet},
		Handler{instance: i, handler: getProofByHash, endpoint: EndpointGetProofByHash, method: http.MethodGet},
		Handler{instance: i, handler: getConsistencyProof, endpoint: EndpointGetConsistencyProof, method: http.MethodGet},
		Handler{instance: i, handler: getSth, endpoint: EndpointGetSth, method: http.MethodGet},
		Handler{instance: i, handler: getStableSth, endpoint: EndpointGetStableSth, method: http.MethodGet},
		Handler{instance: i, handler: getCosi, endpoint: EndpointGetCosi, method: http.MethodGet},
	}
}

// id formats the log's identifier as base64
func (i *LogParameters) id() string {
	return b64(i.LogId)
}

// Path joins a number of components to form a full endpoint path, e.g., base
// ("example.com"), prefix ("st/v1"), and the endpoint itself ("get-sth").
func (e Endpoint) Path(components ...string) string {
	return strings.Join(append(components, string(e)), "/")
}