diff --git a/pkg/api/api.go b/pkg/api/api.go index 2883a8814..32dd15532 100644 --- a/pkg/api/api.go +++ b/pkg/api/api.go @@ -34,6 +34,7 @@ import ( "github.com/sigstore/rekor/pkg/sharding" "github.com/sigstore/rekor/pkg/signer" "github.com/sigstore/rekor/pkg/storage" + "github.com/sigstore/rekor/pkg/util" "github.com/sigstore/sigstore/pkg/cryptoutils" "github.com/sigstore/sigstore/pkg/signature" "github.com/sigstore/sigstore/pkg/signature/options" @@ -82,7 +83,7 @@ func NewAPI(treeID uint) (*API, error) { tid := int64(treeID) if tid == 0 { log.Logger.Info("No tree ID specified, attempting to create a new tree") - t, err := createAndInitTree(ctx, logAdminClient, logClient) + t, err := util.CreateAndInitTree(ctx, logAdminClient, logClient) if err != nil { return nil, fmt.Errorf("create and init tree: %w", err) } diff --git a/pkg/api/entries.go b/pkg/api/entries.go index 294304bc4..4abc5db89 100644 --- a/pkg/api/entries.go +++ b/pkg/api/entries.go @@ -67,7 +67,7 @@ func signEntry(ctx context.Context, signer signature.Signer, entry models.LogEnt } // logEntryFromLeaf creates a signed LogEntry struct from trillian structs -func logEntryFromLeaf(ctx context.Context, signer signature.Signer, tc TrillianClient, leaf *trillian.LogLeaf, +func logEntryFromLeaf(ctx context.Context, signer signature.Signer, tc util.TrillianClient, leaf *trillian.LogLeaf, signedLogRoot *trillian.SignedLogRoot, proof *trillian.Proof, tid int64, ranges sharding.LogRanges) (models.LogEntry, error) { log.ContextLogger(ctx).Debugf("log entry from leaf %d", leaf.GetLeafIndex()) @@ -93,7 +93,7 @@ func logEntryFromLeaf(ctx context.Context, signer signature.Signer, tc TrillianC return nil, fmt.Errorf("signing entry error: %w", err) } - scBytes, err := util.CreateAndSignCheckpoint(ctx, viper.GetString("rekor_server.hostname"), tc.logID, root, api.signer) + scBytes, err := util.CreateAndSignCheckpoint(ctx, viper.GetString("rekor_server.hostname"), tid, root, api.signer) if err != nil { return nil, err } @@ -186,16 +186,16 @@ func createLogEntry(params entries.CreateLogEntryParams) (models.LogEntry, middl return nil, handleRekorAPIError(params, http.StatusInternalServerError, err, failedToGenerateCanonicalEntry) } - tc := NewTrillianClient(ctx) + tc := util.NewTrillianClient(ctx, api.logClient, api.logID) - resp := tc.addLeaf(leaf) + resp := tc.AddLeaf(leaf) // this represents overall GRPC response state (not the results of insertion into the log) - if resp.status != codes.OK { - return nil, handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("grpc error: %w", resp.err), trillianUnexpectedResult) + if resp.Status != codes.OK { + return nil, handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("grpc error: %w", resp.Err), trillianUnexpectedResult) } // this represents the results of inserting the proposed leaf into the log; status is nil in success path - insertionStatus := resp.getAddResult.QueuedLeaf.Status + insertionStatus := resp.GetAddResult.QueuedLeaf.Status if insertionStatus != nil { switch insertionStatus.Code { case int32(code.Code_OK): @@ -212,10 +212,10 @@ func createLogEntry(params entries.CreateLogEntryParams) (models.LogEntry, middl // We made it this far, that means the entry was successfully added. metricNewEntries.Inc() - queuedLeaf := resp.getAddResult.QueuedLeaf.Leaf + queuedLeaf := resp.GetAddResult.QueuedLeaf.Leaf uuid := hex.EncodeToString(queuedLeaf.GetMerkleLeafHash()) - activeTree := fmt.Sprintf("%x", tc.logID) + activeTree := fmt.Sprintf("%x", api.logID) entryIDstruct, err := sharding.CreateEntryIDFromParts(activeTree, uuid) if err != nil { err := fmt.Errorf("error creating EntryID from active treeID %v and uuid %v: %w", activeTree, uuid, err) @@ -271,15 +271,15 @@ func createLogEntry(params entries.CreateLogEntryParams) (models.LogEntry, middl } root := &ttypes.LogRootV1{} - if err := root.UnmarshalBinary(resp.getLeafAndProofResult.SignedLogRoot.LogRoot); err != nil { + if err := root.UnmarshalBinary(resp.GetLeafAndProofResult.SignedLogRoot.LogRoot); err != nil { return nil, handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("error unmarshalling log root: %v", err), sthGenerateError) } hashes := []string{} - for _, hash := range resp.getLeafAndProofResult.Proof.Hashes { + for _, hash := range resp.GetLeafAndProofResult.Proof.Hashes { hashes = append(hashes, hex.EncodeToString(hash)) } - scBytes, err := util.CreateAndSignCheckpoint(ctx, viper.GetString("rekor_server.hostname"), tc.logID, root, api.signer) + scBytes, err := util.CreateAndSignCheckpoint(ctx, viper.GetString("rekor_server.hostname"), api.logID, root, api.signer) if err != nil { return nil, handleRekorAPIError(params, http.StatusInternalServerError, err, sthGenerateError) } @@ -405,22 +405,22 @@ func SearchLogQueryHandler(params entries.SearchLogQueryParams) middleware.Respo for i, hash := range searchHashes { var results map[int64]*trillian.GetEntryAndProofResponse for _, shard := range api.logRanges.AllShards() { - tcs := NewTrillianClientFromTreeID(httpReqCtx, shard) - resp := tcs.getLeafAndProofByHash(hash) - switch resp.status { + tcs := util.NewTrillianClient(httpReqCtx, api.logClient, shard) + resp := tcs.GetLeafAndProofByHash(hash) + switch resp.Status { case codes.OK: - leafResult := resp.getLeafAndProofResult + leafResult := resp.GetLeafAndProofResult if leafResult != nil && leafResult.Leaf != nil { if results == nil { results = map[int64]*trillian.GetEntryAndProofResponse{} } - results[shard] = resp.getLeafAndProofResult + results[shard] = resp.GetLeafAndProofResult } case codes.NotFound: // do nothing here, do not throw 404 error continue default: - return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("error getLeafAndProofByHash(%s): code: %v, msg %v", hex.EncodeToString(hash), resp.status, resp.err), trillianCommunicationError) + return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("error getLeafAndProofByHash(%s): code: %v, msg %v", hex.EncodeToString(hash), resp.Status, resp.Err), trillianCommunicationError) } } searchByHashResults[i] = results @@ -431,7 +431,7 @@ func SearchLogQueryHandler(params entries.SearchLogQueryParams) middleware.Respo if leafResp == nil { continue } - tcs := NewTrillianClientFromTreeID(httpReqCtx, shard) + tcs := util.NewTrillianClient(httpReqCtx, api.logClient, shard) logEntry, err := logEntryFromLeaf(httpReqCtx, api.signer, tcs, leafResp.Leaf, leafResp.SignedLogRoot, leafResp.Proof, shard, api.logRanges) if err != nil { return handleRekorAPIError(params, http.StatusInternalServerError, err, err.Error()) @@ -461,19 +461,19 @@ func retrieveLogEntryByIndex(ctx context.Context, logIndex int) (models.LogEntry log.ContextLogger(ctx).Infof("Retrieving log entry by index %d", logIndex) tid, resolvedIndex := api.logRanges.ResolveVirtualIndex(logIndex) - tc := NewTrillianClientFromTreeID(ctx, tid) + tc := util.NewTrillianClient(ctx, api.logClient, tid) log.ContextLogger(ctx).Debugf("Retrieving resolved index %v from TreeID %v", resolvedIndex, tid) - resp := tc.getLeafAndProofByIndex(resolvedIndex) - switch resp.status { + resp := tc.GetLeafAndProofByIndex(resolvedIndex) + switch resp.Status { case codes.OK: case codes.NotFound, codes.OutOfRange, codes.InvalidArgument: return models.LogEntry{}, ErrNotFound default: - return models.LogEntry{}, fmt.Errorf("grpc err: %w: %s", resp.err, trillianCommunicationError) + return models.LogEntry{}, fmt.Errorf("grpc err: %w: %s", resp.Err, trillianCommunicationError) } - result := resp.getLeafAndProofResult + result := resp.GetLeafAndProofResult leaf := result.Leaf if leaf == nil { return models.LogEntry{}, ErrNotFound @@ -525,13 +525,13 @@ func retrieveUUIDFromTree(ctx context.Context, uuid string, tid int64) (models.L return models.LogEntry{}, types.ValidationError(err) } - tc := NewTrillianClientFromTreeID(ctx, tid) + tc := util.NewTrillianClient(ctx, api.logClient, tid) log.ContextLogger(ctx).Debugf("Attempting to retrieve UUID %v from TreeID %v", uuid, tid) - resp := tc.getLeafAndProofByHash(hashValue) - switch resp.status { + resp := tc.GetLeafAndProofByHash(hashValue) + switch resp.Status { case codes.OK: - result := resp.getLeafAndProofResult + result := resp.GetLeafAndProofResult leaf := result.Leaf if leaf == nil { return models.LogEntry{}, ErrNotFound @@ -546,7 +546,7 @@ func retrieveUUIDFromTree(ctx context.Context, uuid string, tid int64) (models.L case codes.NotFound: return models.LogEntry{}, ErrNotFound default: - log.ContextLogger(ctx).Errorf("Unexpected response code while attempting to retrieve UUID %v from TreeID %v: %v", uuid, tid, resp.status) + log.ContextLogger(ctx).Errorf("Unexpected response code while attempting to retrieve UUID %v from TreeID %v: %v", uuid, tid, resp.Status) return models.LogEntry{}, errors.New("unexpected error") } } diff --git a/pkg/api/public_key.go b/pkg/api/public_key.go index 22e0c0436..e7e6b0fbc 100644 --- a/pkg/api/public_key.go +++ b/pkg/api/public_key.go @@ -26,10 +26,8 @@ import ( ) func GetPublicKeyHandler(params pubkey.GetPublicKeyParams) middleware.Responder { - ctx := params.HTTPRequest.Context() treeID := swag.StringValue(params.TreeID) - tc := NewTrillianClient(ctx) - pk, err := tc.ranges.PublicKey(api.pubkey, treeID) + pk, err := api.logRanges.PublicKey(api.pubkey, treeID) if err != nil { return handleRekorAPIError(params, http.StatusBadRequest, err, "") } diff --git a/pkg/api/tlog.go b/pkg/api/tlog.go index e6bbdcc68..4419a9515 100644 --- a/pkg/api/tlog.go +++ b/pkg/api/tlog.go @@ -36,12 +36,12 @@ import ( // GetLogInfoHandler returns the current size of the tree and the STH func GetLogInfoHandler(params tlog.GetLogInfoParams) middleware.Responder { - tc := NewTrillianClient(params.HTTPRequest.Context()) + tc := util.NewTrillianClient(params.HTTPRequest.Context(), api.logClient, api.logID) // for each inactive shard, get the loginfo var inactiveShards []*models.InactiveShardLogInfo - for _, shard := range tc.ranges.GetInactive() { - if shard.TreeID == tc.ranges.ActiveTreeID() { + for _, shard := range api.logRanges.GetInactive() { + if shard.TreeID == api.logRanges.ActiveTreeID() { break } // Get details for this inactive shard @@ -52,11 +52,11 @@ func GetLogInfoHandler(params tlog.GetLogInfoParams) middleware.Responder { inactiveShards = append(inactiveShards, is) } - resp := tc.getLatest(0) - if resp.status != codes.OK { - return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("grpc error: %w", resp.err), trillianCommunicationError) + resp := tc.GetLatest(0) + if resp.Status != codes.OK { + return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("grpc error: %w", resp.Err), trillianCommunicationError) } - result := resp.getLatestResult + result := resp.GetLatestResult root := &types.LogRootV1{} if err := root.UnmarshalBinary(result.SignedLogRoot.LogRoot); err != nil { @@ -67,7 +67,7 @@ func GetLogInfoHandler(params tlog.GetLogInfoParams) middleware.Responder { treeSize := int64(root.TreeSize) scBytes, err := util.CreateAndSignCheckpoint(params.HTTPRequest.Context(), - viper.GetString("rekor_server.hostname"), tc.ranges.ActiveTreeID(), root, api.signer) + viper.GetString("rekor_server.hostname"), api.logRanges.ActiveTreeID(), root, api.signer) if err != nil { return handleRekorAPIError(params, http.StatusInternalServerError, err, sthGenerateError) } @@ -76,7 +76,7 @@ func GetLogInfoHandler(params tlog.GetLogInfoParams) middleware.Responder { RootHash: &hashString, TreeSize: &treeSize, SignedTreeHead: stringPointer(string(scBytes)), - TreeID: stringPointer(fmt.Sprintf("%d", tc.logID)), + TreeID: stringPointer(fmt.Sprintf("%d", api.logID)), InactiveShards: inactiveShards, } @@ -92,21 +92,21 @@ func GetLogProofHandler(params tlog.GetLogProofParams) middleware.Responder { if *params.FirstSize > params.LastSize { return handleRekorAPIError(params, http.StatusBadRequest, nil, fmt.Sprintf(firstSizeLessThanLastSize, *params.FirstSize, params.LastSize)) } - tc := NewTrillianClient(params.HTTPRequest.Context()) + tc := util.NewTrillianClient(params.HTTPRequest.Context(), api.logClient, api.logID) if treeID := swag.StringValue(params.TreeID); treeID != "" { id, err := strconv.Atoi(treeID) if err != nil { log.Logger.Infof("Unable to convert %s to string, skipping initializing client with Tree ID: %v", treeID, err) } else { - tc = NewTrillianClientFromTreeID(params.HTTPRequest.Context(), int64(id)) + tc = util.NewTrillianClient(params.HTTPRequest.Context(), api.logClient, int64(id)) } } - resp := tc.getConsistencyProof(*params.FirstSize, params.LastSize) - if resp.status != codes.OK { - return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("grpc error: %w", resp.err), trillianCommunicationError) + resp := tc.GetConsistencyProof(*params.FirstSize, params.LastSize) + if resp.Status != codes.OK { + return handleRekorAPIError(params, http.StatusInternalServerError, fmt.Errorf("grpc error: %w", resp.Err), trillianCommunicationError) } - result := resp.getConsistencyProofResult + result := resp.GetConsistencyProofResult var root types.LogRootV1 if err := root.UnmarshalBinary(result.SignedLogRoot.LogRoot); err != nil { @@ -136,12 +136,12 @@ func GetLogProofHandler(params tlog.GetLogProofParams) middleware.Responder { } func inactiveShardLogInfo(ctx context.Context, tid int64) (*models.InactiveShardLogInfo, error) { - tc := NewTrillianClientFromTreeID(ctx, tid) - resp := tc.getLatest(0) - if resp.status != codes.OK { - return nil, fmt.Errorf("resp code is %d", resp.status) + tc := util.NewTrillianClient(ctx, api.logClient, tid) + resp := tc.GetLatest(0) + if resp.Status != codes.OK { + return nil, fmt.Errorf("resp code is %d", resp.Status) } - result := resp.getLatestResult + result := resp.GetLatestResult root := &types.LogRootV1{} if err := root.UnmarshalBinary(result.SignedLogRoot.LogRoot); err != nil { diff --git a/pkg/api/trillian_client.go b/pkg/util/trillian_client.go similarity index 62% rename from pkg/api/trillian_client.go rename to pkg/util/trillian_client.go index f0043d9b4..e1d0d5d6d 100644 --- a/pkg/api/trillian_client.go +++ b/pkg/util/trillian_client.go @@ -13,7 +13,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -package api +package util import ( "context" @@ -22,7 +22,6 @@ import ( "time" "github.com/sigstore/rekor/pkg/log" - "github.com/sigstore/rekor/pkg/sharding" "github.com/transparency-dev/merkle/proof" "github.com/transparency-dev/merkle/rfc6962" @@ -35,38 +34,38 @@ import ( "github.com/google/trillian/types" ) +// TrillianClient provides a wrapper around the Trillian client type TrillianClient struct { client trillian.TrillianLogClient - ranges sharding.LogRanges logID int64 context context.Context } -func NewTrillianClient(ctx context.Context) TrillianClient { +// NewTrillianClient creates a TrillianClient with the given Trillian client and log/tree ID. +func NewTrillianClient(ctx context.Context, logClient trillian.TrillianLogClient, logID int64) TrillianClient { return TrillianClient{ - client: api.logClient, - ranges: api.logRanges, - logID: api.logID, - context: ctx, - } -} - -func NewTrillianClientFromTreeID(ctx context.Context, tid int64) TrillianClient { - return TrillianClient{ - client: api.logClient, - logID: tid, + client: logClient, + logID: logID, context: ctx, } } +// Response includes a status code, an optional error message, and one of the results based on the API call type Response struct { - status codes.Code - err error - getAddResult *trillian.QueueLeafResponse - getProofResult *trillian.GetInclusionProofByHashResponse - getLeafAndProofResult *trillian.GetEntryAndProofResponse - getLatestResult *trillian.GetLatestSignedLogRootResponse - getConsistencyProofResult *trillian.GetConsistencyProofResponse + // Status is the status code of the response + Status codes.Code + // Error contains an error on request or client failure + Err error + // GetAddResult contains the response from queueing a leaf in Trillian + GetAddResult *trillian.QueueLeafResponse + // GetLeafAndProofResult contains the response for fetching an inclusion proof and leaf + GetLeafAndProofResult *trillian.GetEntryAndProofResponse + // GetLatestResult contains the response for the latest checkpoint + GetLatestResult *trillian.GetLatestSignedLogRootResponse + // GetConsistencyProofResult contains the response for a consistency proof between two log sizes + GetConsistencyProofResult *trillian.GetConsistencyProofResponse + // getProofResult contains the response for an inclusion proof fetched by leaf hash + getProofResult *trillian.GetInclusionProofByHashResponse } func unmarshalLogRoot(logRoot []byte) (types.LogRootV1, error) { @@ -88,7 +87,7 @@ func (t *TrillianClient) root() (types.LogRootV1, error) { return unmarshalLogRoot(resp.SignedLogRoot.LogRoot) } -func (t *TrillianClient) addLeaf(byteValue []byte) *Response { +func (t *TrillianClient) AddLeaf(byteValue []byte) *Response { leaf := &trillian.LogLeaf{ LeafValue: byteValue, } @@ -101,18 +100,18 @@ func (t *TrillianClient) addLeaf(byteValue []byte) *Response { // check for error if err != nil || (resp.QueuedLeaf.Status != nil && resp.QueuedLeaf.Status.Code != int32(codes.OK)) { return &Response{ - status: status.Code(err), - err: err, - getAddResult: resp, + Status: status.Code(err), + Err: err, + GetAddResult: resp, } } root, err := t.root() if err != nil { return &Response{ - status: status.Code(err), - err: err, - getAddResult: resp, + Status: status.Code(err), + Err: err, + GetAddResult: resp, } } v := client.NewLogVerifier(rfc6962.DefaultHasher) @@ -123,8 +122,8 @@ func (t *TrillianClient) addLeaf(byteValue []byte) *Response { select { case <-ctx.Done(): return &Response{ - status: codes.DeadlineExceeded, - err: ctx.Err(), + Status: codes.DeadlineExceeded, + Err: ctx.Err(), } case <-time.After(logClient.MinMergeDelay): } @@ -134,7 +133,7 @@ func (t *TrillianClient) addLeaf(byteValue []byte) *Response { if root.TreeSize >= 1 { proofResp := t.getProofByHash(resp.QueuedLeaf.Leaf.MerkleLeafHash) // if this call succeeds or returns an error other than "not found", return - if proofResp.err == nil || (proofResp.err != nil && status.Code(proofResp.err) != codes.NotFound) { + if proofResp.Err == nil || (proofResp.Err != nil && status.Code(proofResp.Err) != codes.NotFound) { return proofResp } // otherwise wait for a root update before trying again @@ -142,19 +141,19 @@ func (t *TrillianClient) addLeaf(byteValue []byte) *Response { if _, err := logClient.WaitForRootUpdate(ctx); err != nil { return &Response{ - status: codes.Unknown, - err: err, + Status: codes.Unknown, + Err: err, } } } } proofResp := waitForInclusion(t.context, resp.QueuedLeaf.Leaf.MerkleLeafHash) - if proofResp.err != nil { + if proofResp.Err != nil { return &Response{ - status: status.Code(proofResp.err), - err: proofResp.err, - getAddResult: resp, + Status: status.Code(proofResp.Err), + Err: proofResp.Err, + GetAddResult: resp, } } @@ -162,41 +161,41 @@ func (t *TrillianClient) addLeaf(byteValue []byte) *Response { if len(proofs) != 1 { err := fmt.Errorf("expected 1 proof from getProofByHash for %v, found %v", hex.EncodeToString(resp.QueuedLeaf.Leaf.MerkleLeafHash), len(proofs)) return &Response{ - status: status.Code(err), - err: err, - getAddResult: resp, + Status: status.Code(err), + Err: err, + GetAddResult: resp, } } leafIndex := proofs[0].LeafIndex - leafResp := t.getLeafAndProofByIndex(leafIndex) - if leafResp.err != nil { + leafResp := t.GetLeafAndProofByIndex(leafIndex) + if leafResp.Err != nil { return &Response{ - status: status.Code(leafResp.err), - err: leafResp.err, - getAddResult: resp, + Status: status.Code(leafResp.Err), + Err: leafResp.Err, + GetAddResult: resp, } } // overwrite queued leaf that doesn't have index set - resp.QueuedLeaf.Leaf = leafResp.getLeafAndProofResult.Leaf + resp.QueuedLeaf.Leaf = leafResp.GetLeafAndProofResult.Leaf return &Response{ - status: status.Code(err), - err: err, - getAddResult: resp, + Status: status.Code(err), + Err: err, + GetAddResult: resp, // include getLeafAndProofResult for inclusion proof - getLeafAndProofResult: leafResp.getLeafAndProofResult, + GetLeafAndProofResult: leafResp.GetLeafAndProofResult, } } -func (t *TrillianClient) getLeafAndProofByHash(hash []byte) *Response { +func (t *TrillianClient) GetLeafAndProofByHash(hash []byte) *Response { // get inclusion proof for hash, extract index, then fetch leaf using index proofResp := t.getProofByHash(hash) - if proofResp.err != nil { + if proofResp.Err != nil { return &Response{ - status: status.Code(proofResp.err), - err: proofResp.err, + Status: status.Code(proofResp.Err), + Err: proofResp.Err, } } @@ -204,31 +203,31 @@ func (t *TrillianClient) getLeafAndProofByHash(hash []byte) *Response { if len(proofs) != 1 { err := fmt.Errorf("expected 1 proof from getProofByHash for %v, found %v", hex.EncodeToString(hash), len(proofs)) return &Response{ - status: status.Code(err), - err: err, + Status: status.Code(err), + Err: err, } } - return t.getLeafAndProofByIndex(proofs[0].LeafIndex) + return t.GetLeafAndProofByIndex(proofs[0].LeafIndex) } -func (t *TrillianClient) getLeafAndProofByIndex(index int64) *Response { +func (t *TrillianClient) GetLeafAndProofByIndex(index int64) *Response { ctx, cancel := context.WithTimeout(t.context, 20*time.Second) defer cancel() - rootResp := t.getLatest(0) - if rootResp.err != nil { + rootResp := t.GetLatest(0) + if rootResp.Err != nil { return &Response{ - status: status.Code(rootResp.err), - err: rootResp.err, + Status: status.Code(rootResp.Err), + Err: rootResp.Err, } } - root, err := unmarshalLogRoot(rootResp.getLatestResult.SignedLogRoot.LogRoot) + root, err := unmarshalLogRoot(rootResp.GetLatestResult.SignedLogRoot.LogRoot) if err != nil { return &Response{ - status: status.Code(rootResp.err), - err: rootResp.err, + Status: status.Code(rootResp.Err), + Err: rootResp.Err, } } @@ -242,24 +241,61 @@ func (t *TrillianClient) getLeafAndProofByIndex(index int64) *Response { if resp != nil && resp.Proof != nil { if err := proof.VerifyInclusion(rfc6962.DefaultHasher, uint64(index), root.TreeSize, resp.GetLeaf().MerkleLeafHash, resp.Proof.Hashes, root.RootHash); err != nil { return &Response{ - status: status.Code(err), - err: err, + Status: status.Code(err), + Err: err, } } return &Response{ - status: status.Code(err), - err: err, - getLeafAndProofResult: &trillian.GetEntryAndProofResponse{ + Status: status.Code(err), + Err: err, + GetLeafAndProofResult: &trillian.GetEntryAndProofResponse{ Proof: resp.Proof, Leaf: resp.Leaf, - SignedLogRoot: rootResp.getLatestResult.SignedLogRoot, + SignedLogRoot: rootResp.GetLatestResult.SignedLogRoot, }, } } return &Response{ - status: status.Code(err), - err: err, + Status: status.Code(err), + Err: err, + } +} + +func (t *TrillianClient) GetLatest(leafSizeInt int64) *Response { + + ctx, cancel := context.WithTimeout(t.context, 20*time.Second) + defer cancel() + + resp, err := t.client.GetLatestSignedLogRoot(ctx, + &trillian.GetLatestSignedLogRootRequest{ + LogId: t.logID, + FirstTreeSize: leafSizeInt, + }) + + return &Response{ + Status: status.Code(err), + Err: err, + GetLatestResult: resp, + } +} + +func (t *TrillianClient) GetConsistencyProof(firstSize, lastSize int64) *Response { + + ctx, cancel := context.WithTimeout(t.context, 20*time.Second) + defer cancel() + + resp, err := t.client.GetConsistencyProof(ctx, + &trillian.GetConsistencyProofRequest{ + LogId: t.logID, + FirstTreeSize: firstSize, + SecondTreeSize: lastSize, + }) + + return &Response{ + Status: status.Code(err), + Err: err, + GetConsistencyProofResult: resp, } } @@ -267,26 +303,26 @@ func (t *TrillianClient) getProofByHash(hashValue []byte) *Response { ctx, cancel := context.WithTimeout(t.context, 20*time.Second) defer cancel() - rootResp := t.getLatest(0) - if rootResp.err != nil { + rootResp := t.GetLatest(0) + if rootResp.Err != nil { return &Response{ - status: status.Code(rootResp.err), - err: rootResp.err, + Status: status.Code(rootResp.Err), + Err: rootResp.Err, } } - root, err := unmarshalLogRoot(rootResp.getLatestResult.SignedLogRoot.LogRoot) + root, err := unmarshalLogRoot(rootResp.GetLatestResult.SignedLogRoot.LogRoot) if err != nil { return &Response{ - status: status.Code(rootResp.err), - err: rootResp.err, + Status: status.Code(rootResp.Err), + Err: rootResp.Err, } } // issue 1308: if the tree is empty, there's no way we can return a proof if root.TreeSize == 0 { return &Response{ - status: codes.NotFound, - err: status.Error(codes.NotFound, "tree is empty"), + Status: codes.NotFound, + Err: status.Error(codes.NotFound, "tree is empty"), } } @@ -302,66 +338,29 @@ func (t *TrillianClient) getProofByHash(hashValue []byte) *Response { for _, proof := range resp.Proof { if err := v.VerifyInclusionByHash(&root, hashValue, proof); err != nil { return &Response{ - status: status.Code(err), - err: err, + Status: status.Code(err), + Err: err, } } } // Return an inclusion proof response with the requested return &Response{ - status: status.Code(err), - err: err, + Status: status.Code(err), + Err: err, getProofResult: &trillian.GetInclusionProofByHashResponse{ Proof: resp.Proof, - SignedLogRoot: rootResp.getLatestResult.SignedLogRoot, + SignedLogRoot: rootResp.GetLatestResult.SignedLogRoot, }, } } return &Response{ - status: status.Code(err), - err: err, - } -} - -func (t *TrillianClient) getLatest(leafSizeInt int64) *Response { - - ctx, cancel := context.WithTimeout(t.context, 20*time.Second) - defer cancel() - - resp, err := t.client.GetLatestSignedLogRoot(ctx, - &trillian.GetLatestSignedLogRootRequest{ - LogId: t.logID, - FirstTreeSize: leafSizeInt, - }) - - return &Response{ - status: status.Code(err), - err: err, - getLatestResult: resp, - } -} - -func (t *TrillianClient) getConsistencyProof(firstSize, lastSize int64) *Response { - - ctx, cancel := context.WithTimeout(t.context, 20*time.Second) - defer cancel() - - resp, err := t.client.GetConsistencyProof(ctx, - &trillian.GetConsistencyProofRequest{ - LogId: t.logID, - FirstTreeSize: firstSize, - SecondTreeSize: lastSize, - }) - - return &Response{ - status: status.Code(err), - err: err, - getConsistencyProofResult: resp, + Status: status.Code(err), + Err: err, } } -func createAndInitTree(ctx context.Context, adminClient trillian.TrillianAdminClient, logClient trillian.TrillianLogClient) (*trillian.Tree, error) { +func CreateAndInitTree(ctx context.Context, adminClient trillian.TrillianAdminClient, logClient trillian.TrillianLogClient) (*trillian.Tree, error) { t, err := adminClient.CreateTree(ctx, &trillian.CreateTreeRequest{ Tree: &trillian.Tree{ TreeType: trillian.TreeType_LOG,