-
Notifications
You must be signed in to change notification settings - Fork 150
WIP: minimalistic Monitor #709
Conversation
|
|
||
| ENV VERBOSITY=1 | ||
|
|
||
| ADD keytransparency/genfiles/* /kt/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try following rob's example
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done. I opened an issue for our other Dockerfiles (#712)
cmd/keytransparency-monitor/main.go
Outdated
| ktURL = flag.String("kt-url", "localhost:8080", "URL of key-server.") | ||
| ktPEM = flag.String("kt-key", "genfiles/server.crt", "Path to kt-server's public key") | ||
| // TODO(ismail): are the IDs actually needed for verification operations? | ||
| mapID = flag.Int64("map-id", 0, "Trillian map ID") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you can remove mapID and logID
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| "google.golang.org/grpc/credentials" | ||
| "google.golang.org/grpc/reflection" | ||
| ) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add TODO for a prometheus variable that tracks Valid / Invalid for each Tree Head
| // limitations under the License. | ||
|
|
||
| //go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/ -I=$GOPATH/src/github.com/googleapis/googleapis --go_out=:. keytransparency_v1_types.proto | ||
| //go:generate protoc -I=. -I=$GOPATH/src/ -I=$GOPATH/src/github.com/google/trillian/vendor/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis/ -I=$GOPATH/src/github.com/google/trillian/ --go_out=:. keytransparency_v1_types.proto |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
revert local changes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
try rebasing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
| } | ||
|
|
||
| message GetMonitoringResponse { | ||
| // smr contains the map root for the sparse Merkle Tree signed with the |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For convenience: a pass / fail field.
Proof fields for each type of failure.
- Invalid root sig
- Invalid mutation from epoch e to e+1 (current interval)
- inclusion to leaf at epoch e
- inclusion to leaf at epoch e+1
- Set of mutations does not produce new map root
- map root A
- inclusion proofs for changed leaves.
TODO: put this in a markdown document
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! I've updated your comment to clarify that the "invalid mutations" case is only from epoch e to e+1. My understanding still is that the "storage-less" monitor doesn't have all information if it doesn't additionally store the inclusion proofs (and the corresponding index) at each epoch e. As the monitor can not know in advance (at epoch e) if there will be an error at e+1. Is that correct or do I miss sth?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gdbelvin I've added documenting this in a markdown document to the issue's TODO list so we won't forget about it.
Note to myself: the new inclusion proof (e+1) can be computed using the mutations and the old inclusion proof.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've added proto messages for the above cases here: 5ed5f8a
Let me know what you think.
impl/monitor/monitor.go
Outdated
| } | ||
|
|
||
| // GetSignedMapRootStream is a streaming API similar to GetSignedMapRoot. | ||
| func (s *server) GetSignedMapRootStream(in *ktpb.GetMonitoringRequest, stream mspb.MonitorService_GetSignedMapRootStreamServer) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove functions that you don't want to implement. -- including from proto
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
removed the stream API as I'm definitely not finishing with this PR.
impl/monitor/monitor.go
Outdated
| got.GetMapRevision() == want.GetMapRevision() { | ||
| // We already processed this SMR. Do not update seen SMRs. Do not scroll | ||
| // pages for further mutations. Return empty mutations list. | ||
| glog.Info("Already processed this SMR. Continuing.") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
include revision number
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
impl/monitor/monitor.go
Outdated
| return nil, nil | ||
| } | ||
|
|
||
| mutations := make([]*ktpb.Mutation, pageSize*2) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put the code to iterate through pages in a function
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
impl/monitor/monitor.go
Outdated
| // Verify the mutation’s validity against the previous leaf. | ||
| // Compute the new leaf and store the intermediate hashes locally. | ||
| // Compute the new root using local intermediate hashes from epoch e. | ||
| for _, m := range mutations { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Put verification code in it's own function too
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done. though, the verification code does not really verify anything yet
impl/monitor/monitor.go
Outdated
|
|
||
| tree *tv.Verifier | ||
| // TODO(ismail) abstract this into a storage interface and have an in-memory version | ||
| seenSMRs []*trillian.SignedMapRoot |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe create a struct for this:
- SMR
- Was it valid? / Error type / status
- Time observed
a7bcc64 to
96723ec
Compare
cmd/keytransparency-monitor/main.go
Outdated
| "strings" | ||
| "time" | ||
|
|
||
| mopb "github.com/google/keytransparency/impl/proto/monitor_v1_service" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please place this import group at the bottom of import(
cmd/keytransparency-monitor/main.go
Outdated
|
|
||
| var ( | ||
| addr = flag.String("addr", ":8099", "The ip:port combination to listen on") | ||
| keyFile = flag.String("key", "genfiles/server.key", "TLS private key file") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Key and cert are slightly ambiguous. Should we use tls-key and tls-cert?
cmd/keytransparency-monitor/main.go
Outdated
| ktURL = flag.String("kt-url", "localhost:8080", "URL of key-server.") | ||
| ktPEM = flag.String("kt-key", "genfiles/server.crt", "Path to kt-server's public key") | ||
| // TODO(ismail): remove mapID | ||
| mapID = flag.Int64("map-id", 0, "Trillian map ID") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You will need the public key of the map and log
| // smr will be empty. The epochs are encoded into the smr map_revision. | ||
| trillian.SignedMapRoot smr = 1; | ||
|
|
||
| // seen_timestamp_nanos contains the time in nanoseconds where this particular |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might need to create a signed version of this, but let's discuss that in the design document
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We might reuse SignedEntryTimestamp in trillian.proto
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Brainstorming a few options:
- Update the signature field in SMR to be a set of signature timestamps.
- Defining an equals method on
SignedMapRootto determine that signatures of of the same object. - Possible further ideas from
RoughTime
impl/monitor/monitor.go
Outdated
| } | ||
|
|
||
| func (s *Server) pollMutations(ctx context.Context, opts ...grpc.CallOption) ([]*ktpb.Mutation, error) { | ||
| req := &ktpb.GetMutationsRequest{PageSize: pageSize, Epoch: s.nextRevToQuery()} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When creating protobufs, consider putting each item on it's own line, or even creating the request proto inside the GetMutation line
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
impl/monitor/monitor.go
Outdated
|
|
||
| mutations := make([]*ktpb.Mutation, pageSize*2) | ||
| mutations = append(mutations, resp.GetMutations()...) | ||
| if err := s.pageMutations(ctx, resp, mutations, opts...); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there a reason pageMutations isn't creating and returning the list of mutations inside of it?
In Go, we try to avoid returning values through arguments.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
impl/monitor/monitor.go
Outdated
| // Update seen/processed signed map roots: | ||
| s.proccessedSMRs = append(s.proccessedSMRs, | ||
| &ktpb.GetMonitoringResponse{ | ||
| Smr: &trillian.SignedMapRoot{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this just be resp.GetSmr() with an updated sig field?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As discussed there will be 2 PRs. One monitor that doesn't do anything and just signs what it sees and a separate pull for the verification logic.
impl/monitor/monitor.go
Outdated
| return mutations, nil | ||
| } | ||
|
|
||
| func (s *Server) verifyMutations(ms []*ktpb.Mutation, expectedRoot []byte) error { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
the verification logic probably deserves it's own file
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done
impl/monitor/monitor.go
Outdated
| for _, m := range ms { | ||
| idx := m.GetProof().GetLeaf().GetIndex() | ||
| nbrs := m.GetProof().GetInclusion() | ||
| if err := s.tree.VerifyProof(nbrs, idx, m.GetProof().GetLeaf().GetLeafValue(), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Try using the trillian verification logic
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Will be moved out of this PR. But done
| return nil | ||
| } | ||
|
|
||
| func (s *Server) lastSeenSMR() *trillian.SignedMapRoot { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Functions that implement the proto interface also probably deserve their own file
# Conflicts: # core/client/kt/requests.go # core/mutator/entry/entry.go # core/mutator/entry/entry_test.go # impl/proto/monitor_v1_service/gen.go
# Conflicts: # docker-compose.yml
cmd/keytransparency-monitor/main.go
Outdated
| return nil, err | ||
| } | ||
| var creds credentials.TransportCredentials | ||
| if caFile != "" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
follow the example in the key transparency client, splitting up getTransportCreds
core/monitor/monitor.go
Outdated
| trusted trillian.SignedLogRoot | ||
| } | ||
|
|
||
| func New(hasher hashers.MapHasher, mapPubKey, logPubKey crypto.PublicKey, logVerifier merkle.LogVerifier) *Monitor { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe pass in the tree structs and compute the rest locally
| newLeaves := make([]merkle.HStar2LeafHash, 0, len(muts)) | ||
| mutator := entry.New() | ||
| oldProofNodes := make(map[string][]byte) | ||
| hasher := coniks.Default |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull from tree config
| // store the proof hashes locally to recompute the tree below: | ||
| sibIDs := newLeafnID.Siblings() | ||
| for level, proof := range m.GetProof().GetInclusion() { | ||
| pID := sibIDs[level] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
try iterating over sibIDs
This will be split up into small separate PRs(related to #679).As discussed with Gary this will be merge as a single PR.After further offline discussion this will be split up into two parts:
Implemented:
Missing:
implvscore)