Skip to content

Commit

Permalink
Use types.LogRootV1
Browse files Browse the repository at this point in the history
Following google/trillian#1048, use types.LogRootV1 as the local
reference of what the most up-to-date log root is.
  • Loading branch information
gdbelvin committed Mar 14, 2018
1 parent 931e93c commit d4c8e4a
Show file tree
Hide file tree
Showing 9 changed files with 63 additions and 34 deletions.
4 changes: 2 additions & 2 deletions cmd/keytransparency-monitor/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ import (
"github.com/google/keytransparency/core/fake"
"github.com/google/keytransparency/core/monitor"
"github.com/google/keytransparency/core/monitorserver"
"github.com/google/trillian"
"github.com/prometheus/client_golang/prometheus/promhttp"

"github.com/google/trillian/crypto"
"github.com/google/trillian/crypto/keys/pem"
"github.com/google/trillian/types"

"github.com/golang/glog"
"github.com/grpc-ecosystem/go-grpc-prometheus"
Expand Down Expand Up @@ -92,7 +92,7 @@ func main() {
}

// TODO(gbelvin): persist trusted roots
trusted := trillian.SignedLogRoot{}
trusted := types.LogRootV1{}
go mon.ProcessLoop(ctx, *domainID, trusted, *pollPeriod)

// Monitor Server.
Expand Down
2 changes: 1 addition & 1 deletion core/adminserver/admin_server.go
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ func (s *Server) initialize(ctx context.Context, logTree, mapTree *tpb.Tree) err

// If the tree is empty and the map is empty,
// add the empty map root to the log.
if logRoot.GetTreeSize() != 0 ||
if logRoot.TreeSize != 0 ||
mapRoot.GetMapRoot().GetMapRevision() != 0 {
return nil // Init not needed.
}
Expand Down
28 changes: 20 additions & 8 deletions core/client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,15 @@ import (

"github.com/google/trillian"
"github.com/google/trillian/client/backoff"
"github.com/google/trillian/types"

"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

tpb "github.com/google/keytransparency/core/api/type/type_proto"
pb "github.com/google/keytransparency/core/api/v1/keytransparency_proto"
tcrypto "github.com/google/trillian/crypto"
)

const (
Expand Down Expand Up @@ -83,7 +85,7 @@ type Client struct {
domainID string
mutator mutator.Func
RetryDelay time.Duration
trusted trillian.SignedLogRoot
trusted types.LogRootV1
}

// NewFromConfig creates a new client from a config
Expand All @@ -109,11 +111,21 @@ func New(ktClient pb.KeyTransparencyClient,
}
}

func (c *Client) updateTrusted(newTrusted *trillian.SignedLogRoot) {
if newTrusted.TimestampNanos > c.trusted.TimestampNanos &&
newTrusted.TreeSize >= c.trusted.TreeSize {
c.trusted = *newTrusted
// updateTrusted sets the local reference for the latest SignedLogRoot if
// newTrusted is correctly signed and newer than the current stored root.
func (c *Client) updateTrusted(newTrusted *trillian.SignedLogRoot) error {
r, err := tcrypto.VerifySignedLogRoot(c.logVerifier.Pubkey, newTrusted)
if err != nil {
return err
}

if r.TimestampNanos <= c.trusted.TimestampNanos ||
r.TreeSize < c.trusted.TreeSize {
// Valid root, but it's older than the one we currently have.
return nil
}
c.trusted = *r
return nil
}

// GetEntry returns an entry if it exists, and nil if it does not.
Expand Down Expand Up @@ -153,7 +165,7 @@ func (c *Client) ListHistory(ctx context.Context, userID, appID string, start, e
DomainId: c.domainID,
UserId: userID,
AppId: appID,
FirstTreeSize: trustedSnapshot.TreeSize,
FirstTreeSize: int64(trustedSnapshot.TreeSize),
Start: start,
PageSize: min(int32((end-start)+1), pageSize),
}, opts...)
Expand Down Expand Up @@ -235,7 +247,7 @@ func (c *Client) Update(ctx context.Context, u *tpb.User, signers []signatures.S

// QueueMutation signs an entry.Mutation and sends it to the server.
func (c *Client) QueueMutation(ctx context.Context, m *entry.Mutation, signers []signatures.Signer) error {
req, err := m.SerializeAndSign(signers, c.trusted.GetTreeSize())
req, err := m.SerializeAndSign(signers, int64(c.trusted.TreeSize))
if err != nil {
return fmt.Errorf("SerializeAndSign(): %v", err)
}
Expand Down Expand Up @@ -307,7 +319,7 @@ func (c *Client) waitOnceForUserUpdate(ctx context.Context, m *entry.Mutation) (
return nil, fmt.Errorf("nil mutation")
}
// Wait for STH to change.
if err := c.WaitForSTHUpdate(ctx, c.trusted.TreeSize+1); err != nil {
if err := c.WaitForSTHUpdate(ctx, int64(c.trusted.TreeSize)+1); err != nil {
return m, err
}

Expand Down
6 changes: 4 additions & 2 deletions core/client/get_and_verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ func (c *Client) VerifiedGetEntry(ctx context.Context, appID, userID string) (*p
DomainId: c.domainID,
UserId: userID,
AppId: appID,
FirstTreeSize: c.trusted.TreeSize,
FirstTreeSize: int64(c.trusted.TreeSize),
})
if err != nil {
return nil, err
Expand All @@ -36,7 +36,9 @@ func (c *Client) VerifiedGetEntry(ctx context.Context, appID, userID string) (*p
if err := c.VerifyGetEntryResponse(ctx, c.domainID, appID, userID, c.trusted, e); err != nil {
return nil, err
}
c.trusted = *e.GetLogRoot()
if err := c.updateTrusted(e.GetLogRoot()); err != nil {
return nil, err
}
glog.Infof("VerifiedGetEntry: Trusted root updated to TreeSize %v", c.trusted.TreeSize)
Vlog.Printf("✓ Log root updated.")

Expand Down
3 changes: 2 additions & 1 deletion core/client/vectors_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/golang/protobuf/ptypes/timestamp"
"github.com/google/trillian/crypto/keyspb"
"github.com/google/trillian/crypto/sigpb"
"github.com/google/trillian/types"

"github.com/google/keytransparency/core/api/v1/keytransparency_proto"
"github.com/google/trillian"
Expand All @@ -29,7 +30,7 @@ import (
type GetEntryResponseVector struct {
desc string
appID, userID string
trusted trillian.SignedLogRoot
trusted types.LogRootV1
resp *keytransparency_proto.GetEntryResponse
}

Expand Down
10 changes: 5 additions & 5 deletions core/client/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,11 @@ import (
"github.com/google/keytransparency/core/crypto/vrf"
"github.com/google/keytransparency/core/crypto/vrf/p256"
"github.com/google/keytransparency/core/mutator/entry"
"github.com/google/trillian"
"github.com/kr/pretty"

pb "github.com/google/keytransparency/core/api/v1/keytransparency_proto"
tclient "github.com/google/trillian/client"
"github.com/google/trillian/types"
)

var (
Expand Down Expand Up @@ -93,7 +93,7 @@ func (v *Verifier) Index(vrfProof []byte, domainID, appID, userID string) ([]byt
// - Verify consistency proof from log.Root().
// - Verify inclusion proof.
func (v *Verifier) VerifyGetEntryResponse(ctx context.Context, domainID, appID, userID string,
trusted trillian.SignedLogRoot, in *pb.GetEntryResponse) error {
trusted types.LogRootV1, in *pb.GetEntryResponse) error {
glog.V(5).Infof("VerifyGetEntryResponse(%v/%v/%v): %# v", domainID, appID, userID, pretty.Formatter(in))

// Unpack the merkle tree leaf value.
Expand Down Expand Up @@ -142,7 +142,8 @@ func (v *Verifier) VerifyGetEntryResponse(ctx context.Context, domainID, appID,

// Verify consistency proof between root and newroot.
// TODO(gdbelvin): Gossip root.
if err := v.logVerifier.VerifyRoot(&trusted, in.GetLogRoot(), in.GetLogConsistency()); err != nil {
logRoot, err := v.logVerifier.VerifyRoot(&trusted, in.GetLogRoot(), in.GetLogConsistency())
if err != nil {
return fmt.Errorf("logVerifier: VerifyRoot(%v, %v): %v", in.GetLogRoot(), in.GetLogConsistency(), err)
}

Expand All @@ -152,8 +153,7 @@ func (v *Verifier) VerifyGetEntryResponse(ctx context.Context, domainID, appID,
return fmt.Errorf("json.Marshal(): %v", err)
}
logLeafIndex := in.GetSmr().GetMapRevision()
if err := v.logVerifier.VerifyInclusionAtIndex(in.GetLogRoot(), b, logLeafIndex,
in.GetLogInclusion()); err != nil {
if err := v.logVerifier.VerifyInclusionAtIndex(logRoot, b, logLeafIndex, in.GetLogInclusion()); err != nil {
return fmt.Errorf("logVerifier: VerifyInclusionAtIndex(%s, %v, _): %v",
b, in.GetSmr().GetMapRevision(), err)
}
Expand Down
4 changes: 2 additions & 2 deletions core/integration/monitor_tests.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,12 @@ import (
"github.com/google/keytransparency/core/crypto/signatures"
"github.com/google/keytransparency/core/fake"
"github.com/google/keytransparency/core/monitor"
"github.com/google/trillian"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"

"github.com/google/trillian/crypto"
"github.com/google/trillian/crypto/keys/pem"
"github.com/google/trillian/types"

tpb "github.com/google/keytransparency/core/api/type/type_proto"
pb "github.com/google/keytransparency/core/api/v1/keytransparency_proto"
Expand Down Expand Up @@ -117,7 +117,7 @@ func TestMonitor(ctx context.Context, env *Env, t *testing.T) {
}
}

trusted := trillian.SignedLogRoot{}
trusted := types.LogRootV1{}
cctx, cancel := context.WithTimeout(ctx, 2*time.Second)
pollPeriod := 100 * time.Millisecond
if err := mon.ProcessLoop(cctx, env.Domain.DomainId, trusted, pollPeriod); err != context.DeadlineExceeded && status.Code(err) != codes.DeadlineExceeded {
Expand Down
11 changes: 6 additions & 5 deletions core/monitor/monitor.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import (

"github.com/google/trillian"
"github.com/google/trillian/client"
"github.com/google/trillian/types"

"github.com/golang/glog"

Expand All @@ -36,7 +37,7 @@ import (
type Monitor struct {
mClient pb.KeyTransparencyClient
signer *tcrypto.Signer
trusted trillian.SignedLogRoot
trusted types.LogRootV1
logVerifier *client.LogVerifier
mapVerifier *client.MapVerifier
store monitorstorage.Interface
Expand Down Expand Up @@ -102,15 +103,15 @@ func EpochPairs(ctx context.Context, epochs <-chan *pb.Epoch, pairs chan<- Epoch
}

// ProcessLoop continuously fetches mutations and processes them.
func (m *Monitor) ProcessLoop(ctx context.Context, domainID string, trusted trillian.SignedLogRoot, period time.Duration) error {
func (m *Monitor) ProcessLoop(ctx context.Context, domainID string, trusted types.LogRootV1, period time.Duration) error {
mutCli := mutationclient.New(m.mClient, period)
cctx, cancel := context.WithCancel(ctx)
errc := make(chan error)
epochs := make(chan *pb.Epoch)
pairs := make(chan EpochPair)

go func(ctx context.Context) {
errc <- mutCli.StreamEpochs(ctx, domainID, trusted.TreeSize, epochs)
errc <- mutCli.StreamEpochs(ctx, domainID, int64(trusted.TreeSize), epochs)
}(cctx)
go func(ctx context.Context) {
errc <- EpochPairs(ctx, epochs, pairs)
Expand All @@ -126,7 +127,7 @@ func (m *Monitor) ProcessLoop(ctx context.Context, domainID string, trusted tril

var smr *trillian.SignedMapRoot
var errList []error
if errs := m.VerifyEpochMutations(pair.A, pair.B, &trusted, mutations); len(errs) > 0 {
if errs := m.VerifyEpochMutations(pair.A, pair.B, trusted, mutations); len(errs) > 0 {
glog.Infof("Epoch %v did not verify: %v", revision, errs)
errList = errs
} else {
Expand Down Expand Up @@ -155,7 +156,7 @@ func (m *Monitor) ProcessLoop(ctx context.Context, domainID string, trusted tril
}

// VerifyEpochMutations validates that epochA + mutations = epochB.
func (m *Monitor) VerifyEpochMutations(epochA, epochB *pb.Epoch, trusted *trillian.SignedLogRoot, mutations []*pb.MutationProof) []error {
func (m *Monitor) VerifyEpochMutations(epochA, epochB *pb.Epoch, trusted types.LogRootV1, mutations []*pb.MutationProof) []error {
revision := epochB.GetSmr().GetMapRevision()
if errs := m.VerifyEpoch(epochB, trusted); len(errs) > 0 {
glog.Errorf("Invalid Epoch %v: %v", revision, errs)
Expand Down
29 changes: 21 additions & 8 deletions core/monitor/verify.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,10 @@ import (
"google.golang.org/grpc/status"

"github.com/golang/glog"
tcrypto "github.com/google/trillian/crypto"
"github.com/google/trillian/merkle"
"github.com/google/trillian/storage"
"github.com/google/trillian/types"

pb "github.com/google/keytransparency/core/api/v1/keytransparency_proto"
statuspb "google.golang.org/genproto/googleapis/rpc/status"
Expand Down Expand Up @@ -92,12 +94,13 @@ func (e *ErrList) Proto() []*statuspb.Status {

// VerifyEpoch verifies that epoch is correctly signed and included in the append only log.
// VerifyEpoch also verifies that epoch.LogRoot is consistent with the last trusted SignedLogRoot.
func (m *Monitor) VerifyEpoch(epoch *pb.Epoch, trusted *trillian.SignedLogRoot) []error {
func (m *Monitor) VerifyEpoch(epoch *pb.Epoch, trusted types.LogRootV1) []error {
errs := ErrList{}

if err := m.logVerifier.VerifyRoot(trusted, epoch.GetLogRoot(), epoch.GetLogConsistency()); err != nil {
logRoot, err := m.logVerifier.VerifyRoot(&trusted, epoch.GetLogRoot(), epoch.GetLogConsistency())
if err != nil {
// this could be one of ErrInvalidLogSignature, ErrInvalidLogConsistencyProof
errs.AppendStatus(status.Newf(codes.DataLoss, "VerifyRoot: %v", err).WithDetails(trusted, epoch))
errs.AppendStatus(status.Newf(codes.DataLoss, "VerifyRoot: %v", err).WithDetails(epoch))
}
// updated trusted log root
m.updateTrusted(epoch.GetLogRoot())
Expand All @@ -109,7 +112,7 @@ func (m *Monitor) VerifyEpoch(epoch *pb.Epoch, trusted *trillian.SignedLogRoot)
}
leafIndex := epoch.GetSmr().GetMapRevision()
treeSize := epoch.GetLogRoot().GetTreeSize()
if err := m.logVerifier.VerifyInclusionAtIndex(epoch.GetLogRoot(), b, leafIndex, epoch.GetLogInclusion()); err != nil {
if err := m.logVerifier.VerifyInclusionAtIndex(logRoot, b, leafIndex, epoch.GetLogInclusion()); err != nil {
glog.Errorf("m.logVerifier.VerifyInclusionAtIndex((%v, %v, _): %v", leafIndex, treeSize, err)
errs.AppendStatus(status.Newf(codes.DataLoss, "invalid log inclusion: %v", err).WithDetails(epoch))
}
Expand All @@ -122,11 +125,21 @@ func (m *Monitor) VerifyEpoch(epoch *pb.Epoch, trusted *trillian.SignedLogRoot)
return errs
}

func (m *Monitor) updateTrusted(newTrusted *trillian.SignedLogRoot) {
if newTrusted.TimestampNanos > m.trusted.TimestampNanos &&
newTrusted.TreeSize >= m.trusted.TreeSize {
m.trusted = *newTrusted
// updateTrusted sets the local reference for the latest SignedLogRoot if
// newTrusted is correctly signed and newer than the current stored root.
func (m *Monitor) updateTrusted(newTrusted *trillian.SignedLogRoot) error {
r, err := tcrypto.VerifySignedLogRoot(m.logVerifier.Pubkey, newTrusted)
if err != nil {
return err
}

if r.TimestampNanos <= m.trusted.TimestampNanos ||
r.TreeSize < m.trusted.TreeSize {
// Valid root, but it's older than the one we currently have.
return nil
}
m.trusted = *r
return nil
}

func (m *Monitor) verifyMutations(muts []*pb.MutationProof, oldRoot, expectedNewRoot *trillian.SignedMapRoot) []error {
Expand Down

0 comments on commit d4c8e4a

Please sign in to comment.