podman/vendor/github.com/google/trillian/trillian_log_api.proto

364 lines
15 KiB
Protocol Buffer

// Copyright 2016 Google LLC. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
syntax = "proto3";
package trillian;
option go_package = "github.com/google/trillian";
option java_multiple_files = true;
option java_outer_classname = "TrillianLogApiProto";
option java_package = "com.google.trillian.proto";
import "google/protobuf/timestamp.proto";
import "google/rpc/status.proto";
import "trillian.proto";
// The TrillianLog service provides access to an append-only Log data structure
// as described in the [Verifiable Data
// Structures](docs/papers/VerifiableDataStructures.pdf) paper.
//
// The API supports adding new entries to the Merkle tree for a specific Log
// instance (identified by its log_id) in two modes:
// - For a normal log, new leaf entries are queued up for subsequent
// inclusion in the log, and the leaves are assigned consecutive leaf_index
// values as part of that integration process.
// - For a 'pre-ordered log', new entries have an already-defined leaf
// ordering, and leaves are only integrated into the Merkle tree when a
// contiguous range of leaves is available.
//
// The API also supports read operations to retrieve leaf contents, and to
// provide cryptographic proofs of leaf inclusion and of the append-only nature
// of the Log.
//
// Each API request also includes a charge_to field, which allows API users
// to provide quota identifiers that should be "charged" for each API request
// (and potentially rejected with codes.ResourceExhausted).
//
// Various operations on the API also allows for 'server skew', which can occur
// when different API requests happen to be handled by different server instances
// that may not all be up to date. An API request that is relative to a specific
// tree size may reach a server instance that is not yet aware of this tree size;
// in this case the server will typically return an OK response that contains:
// - a signed log root that indicates the tree size that it is aware of
// - an empty response otherwise.
service TrillianLog {
// QueueLeaf adds a single leaf to the queue of pending leaves for a normal
// log.
rpc QueueLeaf(QueueLeafRequest) returns (QueueLeafResponse) {}
// GetInclusionProof returns an inclusion proof for a leaf with a given index
// in a particular tree.
//
// If the requested tree_size is larger than the server is aware of, the
// response will include the latest known log root and an empty proof.
rpc GetInclusionProof(GetInclusionProofRequest)
returns (GetInclusionProofResponse) {}
// GetInclusionProofByHash returns an inclusion proof for any leaves that have
// the given Merkle hash in a particular tree.
//
// If any of the leaves that match the given Merkle has have a leaf index that
// is beyond the requested tree size, the corresponding proof entry will be empty.
rpc GetInclusionProofByHash(GetInclusionProofByHashRequest)
returns (GetInclusionProofByHashResponse) {}
// GetConsistencyProof returns a consistency proof between different sizes of
// a particular tree.
//
// If the requested tree size is larger than the server is aware of,
// the response will include the latest known log root and an empty proof.
rpc GetConsistencyProof(GetConsistencyProofRequest)
returns (GetConsistencyProofResponse) {}
// GetLatestSignedLogRoot returns the latest log root for a given tree,
// and optionally also includes a consistency proof from an earlier tree size
// to the new size of the tree.
//
// If the earlier tree size is larger than the server is aware of,
// an InvalidArgument error is returned.
rpc GetLatestSignedLogRoot(GetLatestSignedLogRootRequest)
returns (GetLatestSignedLogRootResponse) {}
// GetEntryAndProof returns a log leaf and the corresponding inclusion proof
// to a specified tree size, for a given leaf index in a particular tree.
//
// If the requested tree size is unavailable but the leaf is
// in scope for the current tree, the returned proof will be for the
// current tree size rather than the requested tree size.
rpc GetEntryAndProof(GetEntryAndProofRequest)
returns (GetEntryAndProofResponse) {}
// InitLog initializes a particular tree, creating the initial signed log
// root (which will be of size 0).
rpc InitLog(InitLogRequest) returns (InitLogResponse) {}
// AddSequencedLeaves adds a batch of leaves with assigned sequence numbers
// to a pre-ordered log. The indices of the provided leaves must be contiguous.
rpc AddSequencedLeaves(AddSequencedLeavesRequest)
returns (AddSequencedLeavesResponse) {}
// GetLeavesByRange returns a batch of leaves whose leaf indices are in a
// sequential range.
rpc GetLeavesByRange(GetLeavesByRangeRequest)
returns (GetLeavesByRangeResponse) {}
}
// ChargeTo describes the user(s) associated with the request whose quota should
// be checked and charged.
message ChargeTo {
// user is a list of personality-defined strings.
// Trillian will treat them as /User/%{user}/... keys when checking and
// charging quota.
// If one or more of the specified users has insufficient quota, the
// request will be denied.
//
// As an example, a Certificate Transparency frontend might set the following
// user strings when sending a QueueLeaf request to the Trillian log:
// - The requesting IP address.
// This would limit the number of requests per IP.
// - The "intermediate-<hash>" for each of the intermediate certificates in
// the submitted chain.
// This would have the effect of limiting the rate of submissions under
// a given intermediate/root.
repeated string user = 1;
}
message QueueLeafRequest {
int64 log_id = 1;
LogLeaf leaf = 2;
ChargeTo charge_to = 3;
}
message QueueLeafResponse {
// queued_leaf describes the leaf which is or will be incorporated into the
// Log. If the submitted leaf was already present in the Log (as indicated by
// its leaf identity hash), then the returned leaf will be the pre-existing
// leaf entry rather than the submitted leaf.
QueuedLogLeaf queued_leaf = 2;
}
message GetInclusionProofRequest {
int64 log_id = 1;
int64 leaf_index = 2;
int64 tree_size = 3;
ChargeTo charge_to = 4;
}
message GetInclusionProofResponse {
// The proof field may be empty if the requested tree_size was larger
// than that available at the server (e.g. because there is skew between
// server instances, and an earlier client request was processed by a
// more up-to-date instance). In this case, the signed_log_root
// field will indicate the tree size that the server is aware of, and
// the proof field will be empty.
Proof proof = 2;
SignedLogRoot signed_log_root = 3;
}
message GetInclusionProofByHashRequest {
int64 log_id = 1;
// The leaf hash field provides the Merkle tree hash of the leaf entry
// to be retrieved.
bytes leaf_hash = 2;
int64 tree_size = 3;
bool order_by_sequence = 4;
ChargeTo charge_to = 5;
}
message GetInclusionProofByHashResponse {
// Logs can potentially contain leaves with duplicate hashes so it's possible
// for this to return multiple proofs. If the leaf index for a particular
// instance of the requested Merkle leaf hash is beyond the requested tree
// size, the corresponding proof entry will be missing.
repeated Proof proof = 2;
SignedLogRoot signed_log_root = 3;
}
message GetConsistencyProofRequest {
int64 log_id = 1;
int64 first_tree_size = 2;
int64 second_tree_size = 3;
ChargeTo charge_to = 4;
}
message GetConsistencyProofResponse {
// The proof field may be empty if the requested tree_size was larger
// than that available at the server (e.g. because there is skew between
// server instances, and an earlier client request was processed by a
// more up-to-date instance). In this case, the signed_log_root
// field will indicate the tree size that the server is aware of, and
// the proof field will be empty.
Proof proof = 2;
SignedLogRoot signed_log_root = 3;
}
message GetLatestSignedLogRootRequest {
int64 log_id = 1;
ChargeTo charge_to = 2;
// If first_tree_size is non-zero, the response will include a consistency
// proof between first_tree_size and the new tree size (if not smaller).
int64 first_tree_size = 3;
}
message GetLatestSignedLogRootResponse {
SignedLogRoot signed_log_root = 2;
// proof is filled in with a consistency proof if first_tree_size in
// GetLatestSignedLogRootRequest is non-zero (and within the tree size
// available at the server).
Proof proof = 3;
}
message GetEntryAndProofRequest {
int64 log_id = 1;
int64 leaf_index = 2;
int64 tree_size = 3;
ChargeTo charge_to = 4;
}
message GetEntryAndProofResponse {
Proof proof = 2;
LogLeaf leaf = 3;
SignedLogRoot signed_log_root = 4;
}
message InitLogRequest {
int64 log_id = 1;
ChargeTo charge_to = 2;
}
message InitLogResponse {
SignedLogRoot created = 1;
}
message AddSequencedLeavesRequest {
int64 log_id = 1;
repeated LogLeaf leaves = 2;
ChargeTo charge_to = 4;
}
message AddSequencedLeavesResponse {
// Same number and order as in the corresponding request.
repeated QueuedLogLeaf results = 2;
}
message GetLeavesByRangeRequest {
int64 log_id = 1;
int64 start_index = 2;
int64 count = 3;
ChargeTo charge_to = 4;
}
message GetLeavesByRangeResponse {
// Returned log leaves starting from the `start_index` of the request, in
// order. There may be fewer than `request.count` leaves returned, if the
// requested range extended beyond the size of the tree or if the server opted
// to return fewer leaves than requested.
repeated LogLeaf leaves = 1;
SignedLogRoot signed_log_root = 2;
}
// QueuedLogLeaf provides the result of submitting an entry to the log.
// TODO(pavelkalinnikov): Consider renaming it to AddLogLeafResult or the like.
message QueuedLogLeaf {
// The leaf as it was stored by Trillian. Empty unless `status.code` is:
// - `google.rpc.OK`: the `leaf` data is the same as in the request.
// - `google.rpc.ALREADY_EXISTS` or 'google.rpc.FAILED_PRECONDITION`: the
// `leaf` is the conflicting one already in the log.
LogLeaf leaf = 1;
// The status of adding the leaf.
// - `google.rpc.OK`: successfully added.
// - `google.rpc.ALREADY_EXISTS`: the leaf is a duplicate of an already
// existing one. Either `leaf_identity_hash` is the same in the `LOG`
// mode, or `leaf_index` in the `PREORDERED_LOG`.
// - `google.rpc.FAILED_PRECONDITION`: A conflicting entry is already
// present in the log, e.g., same `leaf_index` but different `leaf_data`.
google.rpc.Status status = 2;
}
// LogLeaf describes a leaf in the Log's Merkle tree, corresponding to a single log entry.
// Each leaf has a unique leaf index in the scope of this tree. Clients submitting new
// leaf entries should only set the following fields:
// - leaf_value
// - extra_data (optionally)
// - leaf_identity_hash (optionally)
// - leaf_index (iff the log is a PREORDERED_LOG)
message LogLeaf {
// merkle_leaf_hash holds the Merkle leaf hash over leaf_value. This is
// calculated by the Trillian server when leaves are added to the tree, using
// the defined hashing algorithm and strategy for the tree; as such, the client
// does not need to set it on leaf submissions.
bytes merkle_leaf_hash = 1;
// leaf_value holds the data that forms the value of the Merkle tree leaf.
// The client should set this field on all leaf submissions, and is
// responsible for ensuring its validity (the Trillian server treats it as an
// opaque blob).
bytes leaf_value = 2;
// extra_data holds additional data associated with the Merkle tree leaf.
// The client may set this data on leaf submissions, and the Trillian server
// will return it on subsequent read operations. However, the contents of
// this field are not covered by and do not affect the Merkle tree hash
// calculations.
bytes extra_data = 3;
// leaf_index indicates the index of this leaf in the Merkle tree.
// This field is returned on all read operations, but should only be
// set for leaf submissions in PREORDERED_LOG mode (for a normal log
// the leaf index is assigned by Trillian when the submitted leaf is
// integrated into the Merkle tree).
int64 leaf_index = 4;
// leaf_identity_hash provides a hash value that indicates the client's
// concept of which leaf entries should be considered identical.
//
// This mechanism allows the client personality to indicate that two leaves
// should be considered "duplicates" even though their `leaf_value`s differ.
//
// If this is not set on leaf submissions, the Trillian server will take its
// value to be the same as merkle_leaf_hash (and thus only leaves with
// identical leaf_value contents will be considered identical).
//
// For example, in Certificate Transparency each certificate submission is
// associated with a submission timestamp, but subsequent submissions of the
// same certificate should be considered identical. This is achieved
// by setting the leaf identity hash to a hash over (just) the certificate,
// whereas the Merkle leaf hash encompasses both the certificate and its
// submission time -- allowing duplicate certificates to be detected.
//
//
// Continuing the CT example, for a CT mirror personality (which must allow
// dupes since the source log could contain them), the part of the
// personality which fetches and submits the entries might set
// `leaf_identity_hash` to `H(leaf_index||cert)`.
//
// TODO(pavelkalinnikov): Consider instead using `H(cert)` and allowing
// identity hash dupes in `PREORDERED_LOG` mode, for it can later be
// upgraded to `LOG` which will need to correctly detect duplicates with
// older entries when new ones get queued.
bytes leaf_identity_hash = 5;
// queue_timestamp holds the time at which this leaf was queued for
// inclusion in the Log, or zero if the entry was submitted without
// queuing. Clients should not set this field on submissions.
google.protobuf.Timestamp queue_timestamp = 6;
// integrate_timestamp holds the time at which this leaf was integrated into
// the tree. Clients should not set this field on submissions.
google.protobuf.Timestamp integrate_timestamp = 7;
}