diff options
Diffstat (limited to 'sth.go')
-rw-r--r-- | sth.go | 90 |
1 files changed, 49 insertions, 41 deletions
@@ -9,21 +9,22 @@ import ( "github.com/golang/glog" "github.com/google/certificate-transparency-go/schedule" "github.com/google/trillian" - "github.com/google/trillian/types" + ttypes "github.com/google/trillian/types" + "github.com/system-transparency/stfe/types" ) // SthSource provides access to the log's STHs. type SthSource interface { // Latest returns the most reccent signed_tree_head_v*. - Latest(context.Context) (*StItem, error) + Latest(context.Context) (*types.StItem, error) // Stable returns the most recent signed_tree_head_v* that is stable for // some period of time, e.g., 10 minutes. - Stable(context.Context) (*StItem, error) + Stable(context.Context) (*types.StItem, error) // Cosigned returns the most recent cosigned_tree_head_v*. - Cosigned(context.Context) (*StItem, error) + Cosigned(context.Context) (*types.StItem, error) // AddCosignature attempts to add a cosignature to the stable STH. The // passed cosigned_tree_head_v* must have a single verified cosignature. - AddCosignature(context.Context, *StItem) error + AddCosignature(context.Context, *types.StItem) error // Run keeps the STH source updated until cancelled Run(context.Context) } @@ -33,9 +34,9 @@ type SthSource interface { type ActiveSthSource struct { client trillian.TrillianLogClient logParameters *LogParameters - currCosth *StItem // current cosigned_tree_head_v1 (already finalized) - nextCosth *StItem // next cosigned_tree_head_v1 (under preparation) - cosignatureFrom map[string]bool // track who we got cosignatures from in nextCosth + currCosth *types.StItem // current cosigned_tree_head_v1 (already finalized) + nextCosth *types.StItem // next cosigned_tree_head_v1 (under preparation) + cosignatureFrom map[[types.NamespaceFingerprintSize]byte]bool // track who we got cosignatures from in nextCosth mutex sync.RWMutex } @@ -51,10 +52,11 @@ func NewActiveSthSource(cli trillian.TrillianLogClient, lp *LogParameters) (*Act if err != nil { return nil, fmt.Errorf("Latest: %v", err) } + // TODO: load persisted cosigned STH? - s.currCosth = NewCosignedTreeHeadV1(sth.SignedTreeHeadV1, nil) - s.nextCosth = NewCosignedTreeHeadV1(sth.SignedTreeHeadV1, nil) - s.cosignatureFrom = make(map[string]bool) + s.currCosth = types.NewCosignedTreeHeadV1(sth.SignedTreeHeadV1, nil) + s.nextCosth = types.NewCosignedTreeHeadV1(sth.SignedTreeHeadV1, nil) + s.cosignatureFrom = make(map[[types.NamespaceFingerprintSize]byte]bool) return &s, nil } @@ -70,78 +72,84 @@ func (s *ActiveSthSource) Run(ctx context.Context) { // rotate s.mutex.Lock() defer s.mutex.Unlock() - s.rotate(sth) + if err := s.rotate(sth); err != nil { + glog.Warningf("rotate failed: %v", err) + } // TODO: persist cosigned STH? }) } -func (s *ActiveSthSource) Latest(ctx context.Context) (*StItem, error) { +func (s *ActiveSthSource) Latest(ctx context.Context) (*types.StItem, error) { trsp, err := s.client.GetLatestSignedLogRoot(ctx, &trillian.GetLatestSignedLogRootRequest{ LogId: s.logParameters.TreeId, }) - var lr types.LogRootV1 + var lr ttypes.LogRootV1 if errInner := checkGetLatestSignedLogRoot(s.logParameters, trsp, err, &lr); errInner != nil { return nil, fmt.Errorf("invalid signed log root response: %v", errInner) } - return s.logParameters.genV1Sth(NewTreeHeadV1(&lr)) + return s.logParameters.SignTreeHeadV1(NewTreeHeadV1FromLogRoot(&lr)) } -func (s *ActiveSthSource) Stable(_ context.Context) (*StItem, error) { +func (s *ActiveSthSource) Stable(_ context.Context) (*types.StItem, error) { s.mutex.RLock() defer s.mutex.RUnlock() if s.nextCosth == nil { return nil, fmt.Errorf("no stable sth available") } - return &StItem{ - Format: StFormatSignedTreeHeadV1, - SignedTreeHeadV1: &s.nextCosth.CosignedTreeHeadV1.SignedTreeHeadV1, - }, nil + return types.NewSignedTreeHeadV1(&s.nextCosth.CosignedTreeHeadV1.SignedTreeHead.TreeHead, &s.nextCosth.CosignedTreeHeadV1.SignedTreeHead.Signature), nil } -func (s *ActiveSthSource) Cosigned(_ context.Context) (*StItem, error) { +func (s *ActiveSthSource) Cosigned(_ context.Context) (*types.StItem, error) { s.mutex.RLock() defer s.mutex.RUnlock() - if s.currCosth == nil || len(s.currCosth.CosignedTreeHeadV1.SignatureV1) == 0 { + if s.currCosth == nil || len(s.currCosth.CosignedTreeHeadV1.Cosignatures) == 0 { return nil, fmt.Errorf("no cosigned sth available") } return s.currCosth, nil } -func (s *ActiveSthSource) AddCosignature(_ context.Context, costh *StItem) error { +func (s *ActiveSthSource) AddCosignature(_ context.Context, costh *types.StItem) error { s.mutex.Lock() defer s.mutex.Unlock() - if !reflect.DeepEqual(s.nextCosth.CosignedTreeHeadV1.SignedTreeHeadV1, costh.CosignedTreeHeadV1.SignedTreeHeadV1) { + if !reflect.DeepEqual(s.nextCosth.CosignedTreeHeadV1.SignedTreeHead, costh.CosignedTreeHeadV1.SignedTreeHead) { return fmt.Errorf("cosignature covers a different tree head") } - witness := costh.CosignedTreeHeadV1.SignatureV1[0].Namespace.String() - if _, ok := s.cosignatureFrom[witness]; ok { + witness, err := costh.CosignedTreeHeadV1.Cosignatures[0].Namespace.Fingerprint() + if err != nil { + return fmt.Errorf("namespace without fingerprint: %v", err) + } + if _, ok := s.cosignatureFrom[*witness]; ok { return nil // duplicate } - s.cosignatureFrom[witness] = true - s.nextCosth.CosignedTreeHeadV1.SignatureV1 = append(s.nextCosth.CosignedTreeHeadV1.SignatureV1, costh.CosignedTreeHeadV1.SignatureV1[0]) + s.cosignatureFrom[*witness] = true + s.nextCosth.CosignedTreeHeadV1.Cosignatures = append(s.nextCosth.CosignedTreeHeadV1.Cosignatures, costh.CosignedTreeHeadV1.Cosignatures[0]) return nil } // rotate rotates the log's cosigned and stable STH. The caller must aquire the // source's read-write lock if there are concurrent reads and/or writes. -func (s *ActiveSthSource) rotate(fixedSth *StItem) { +func (s *ActiveSthSource) rotate(fixedSth *types.StItem) error { // rotate stable -> cosigned - if reflect.DeepEqual(&s.currCosth.CosignedTreeHeadV1.SignedTreeHeadV1, &s.nextCosth.CosignedTreeHeadV1.SignedTreeHeadV1) { - for _, sigv1 := range s.currCosth.CosignedTreeHeadV1.SignatureV1 { - witness := sigv1.Namespace.String() - if _, ok := s.cosignatureFrom[witness]; !ok { - s.cosignatureFrom[witness] = true - s.nextCosth.CosignedTreeHeadV1.SignatureV1 = append(s.nextCosth.CosignedTreeHeadV1.SignatureV1, sigv1) + if reflect.DeepEqual(&s.currCosth.CosignedTreeHeadV1.SignedTreeHead, &s.nextCosth.CosignedTreeHeadV1.SignedTreeHead) { + for _, sigv1 := range s.currCosth.CosignedTreeHeadV1.Cosignatures { + witness, err := sigv1.Namespace.Fingerprint() + if err != nil { + return fmt.Errorf("namespace without fingerprint: %v", err) + } + if _, ok := s.cosignatureFrom[*witness]; !ok { + s.cosignatureFrom[*witness] = true + s.nextCosth.CosignedTreeHeadV1.Cosignatures = append(s.nextCosth.CosignedTreeHeadV1.Cosignatures, sigv1) } } } - s.currCosth.CosignedTreeHeadV1.SignedTreeHeadV1 = s.nextCosth.CosignedTreeHeadV1.SignedTreeHeadV1 - s.currCosth.CosignedTreeHeadV1.SignatureV1 = make([]SignatureV1, len(s.nextCosth.CosignedTreeHeadV1.SignatureV1)) - copy(s.currCosth.CosignedTreeHeadV1.SignatureV1, s.nextCosth.CosignedTreeHeadV1.SignatureV1) + s.currCosth.CosignedTreeHeadV1.SignedTreeHead = s.nextCosth.CosignedTreeHeadV1.SignedTreeHead + s.currCosth.CosignedTreeHeadV1.Cosignatures = make([]types.SignatureV1, len(s.nextCosth.CosignedTreeHeadV1.Cosignatures)) + copy(s.currCosth.CosignedTreeHeadV1.Cosignatures, s.nextCosth.CosignedTreeHeadV1.Cosignatures) // rotate new stable -> stable - if !reflect.DeepEqual(&s.nextCosth.CosignedTreeHeadV1.SignedTreeHeadV1, fixedSth.SignedTreeHeadV1) { - s.nextCosth = NewCosignedTreeHeadV1(fixedSth.SignedTreeHeadV1, nil) - s.cosignatureFrom = make(map[string]bool) + if !reflect.DeepEqual(&s.nextCosth.CosignedTreeHeadV1.SignedTreeHead, fixedSth.SignedTreeHeadV1) { + s.nextCosth = types.NewCosignedTreeHeadV1(fixedSth.SignedTreeHeadV1, nil) + s.cosignatureFrom = make(map[[types.NamespaceFingerprintSize]byte]bool) } + return nil } |