// 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";

option java_multiple_files = true;
option java_package = "com.google.trillian.proto";
option java_outer_classname = "TrillianProto";
option go_package = "github.com/google/trillian";

package trillian;

import "google/protobuf/any.proto";
import "google/protobuf/duration.proto";
import "google/protobuf/timestamp.proto";

// LogRootFormat specifies the fields that are covered by the
// SignedLogRoot signature, as well as their ordering and formats.
enum LogRootFormat {
  LOG_ROOT_FORMAT_UNKNOWN = 0;
  LOG_ROOT_FORMAT_V1 = 1;
}

// What goes in here?
// Things which are exposed through the public trillian APIs.

// Defines the way empty / node / leaf hashes are constructed incorporating
// preimage protection, which can be application specific.
enum HashStrategy {
  // Hash strategy cannot be determined. Included to enable detection of
  // mismatched proto versions being used. Represents an invalid value.
  UNKNOWN_HASH_STRATEGY = 0;

  // Certificate Transparency strategy: leaf hash prefix = 0x00, node prefix =
  // 0x01, empty hash is digest([]byte{}), as defined in the specification.
  RFC6962_SHA256 = 1;

  // Sparse Merkle Tree strategy:  leaf hash prefix = 0x00, node prefix = 0x01,
  // empty branch is recursively computed from empty leaf nodes.
  // NOT secure in a multi tree environment. For testing only.
  TEST_MAP_HASHER = 2;

  // Append-only log strategy where leaf nodes are defined as the ObjectHash.
  // All other properties are equal to RFC6962_SHA256.
  OBJECT_RFC6962_SHA256 = 3;

  // The CONIKS sparse tree hasher with SHA512_256 as the hash algorithm.
  CONIKS_SHA512_256 = 4;

  // The CONIKS sparse tree hasher with SHA256 as the hash algorithm.
  CONIKS_SHA256 = 5;
}

// State of the tree.
enum TreeState {
  // Tree state cannot be determined. Included to enable detection of
  // mismatched proto versions being used. Represents an invalid value.
  UNKNOWN_TREE_STATE = 0;

  // Active trees are able to respond to both read and write requests.
  ACTIVE = 1;

  // Frozen trees are only able to respond to read requests, writing to a frozen
  // tree is forbidden. Trees should not be frozen when there are entries
  // in the queue that have not yet been integrated. See the DRAINING
  // state for this case.
  FROZEN = 2;

  // Deprecated: now tracked in Tree.deleted.
  DEPRECATED_SOFT_DELETED = 3 [deprecated = true];

  // Deprecated: now tracked in Tree.deleted.
  DEPRECATED_HARD_DELETED = 4 [deprecated = true];

  // A tree that is draining will continue to integrate queued entries.
  // No new entries should be accepted.
  DRAINING = 5;
}

// Type of the tree.
enum TreeType {
  // Tree type cannot be determined. Included to enable detection of mismatched
  // proto versions being used. Represents an invalid value.
  UNKNOWN_TREE_TYPE = 0;

  // Tree represents a verifiable log.
  LOG = 1;

  // Tree represents a verifiable pre-ordered log, i.e., a log whose entries are
  // placed according to sequence numbers assigned outside of Trillian.
  PREORDERED_LOG = 3;

  reserved 2;
  reserved "MAP";
}

// Represents a tree.
// Readonly attributes are assigned at tree creation, after which they may not
// be modified.
//
// Note: Many APIs within the rest of the code require these objects to
// be provided. For safety they should be obtained via Admin API calls and
// not created dynamically.
message Tree {
  // ID of the tree.
  // Readonly.
  int64 tree_id = 1;

  // State of the tree.
  // Trees are ACTIVE after creation. At any point the tree may transition
  // between ACTIVE, DRAINING and FROZEN states.
  TreeState tree_state = 2;

  // Type of the tree.
  // Readonly after Tree creation. Exception: Can be switched from
  // PREORDERED_LOG to LOG if the Tree is and remains in the FROZEN state.
  TreeType tree_type = 3;

  // Display name of the tree.
  // Optional.
  string display_name = 8;

  // Description of the tree,
  // Optional.
  string description = 9;

  // Storage-specific settings.
  // Varies according to the storage implementation backing Trillian.
  google.protobuf.Any storage_settings = 13;

  // Interval after which a new signed root is produced even if there have been
  // no submission.  If zero, this behavior is disabled.
  google.protobuf.Duration max_root_duration = 15;

  // Time of tree creation.
  // Readonly.
  google.protobuf.Timestamp create_time = 16;

  // Time of last tree update.
  // Readonly (automatically assigned on updates).
  google.protobuf.Timestamp update_time = 17;

  // If true, the tree has been deleted.
  // Deleted trees may be undeleted during a certain time window, after which
  // they're permanently deleted (and unrecoverable).
  // Readonly.
  bool deleted = 19;

  // Time of tree deletion, if any.
  // Readonly.
  google.protobuf.Timestamp delete_time = 20;

  reserved 4 to 7, 10 to 12, 14, 18;
  reserved "create_time_millis_since_epoch";
  reserved "duplicate_policy";
  reserved "hash_algorithm";
  reserved "hash_strategy";
  reserved "private_key";
  reserved "public_key";
  reserved "signature_algorithm";
  reserved "signature_cipher_suite";
  reserved "update_time_millis_since_epoch";
}

// SignedLogRoot represents a commitment by a Log to a particular tree.
message SignedLogRoot {
  // log_root holds the TLS-serialization of the following structure (described
  // in RFC5246 notation):
  //
  // enum { v1(1), (65535)} Version;
  // struct {
  //   uint64 tree_size;
  //   opaque root_hash<0..128>;
  //   uint64 timestamp_nanos;
  //   uint64 revision;
  //   opaque metadata<0..65535>;
  // } LogRootV1;
  // struct {
  //   Version version;
  //   select(version) {
  //     case v1: LogRootV1;
  //   }
  // } LogRoot;
  //
  // A serialized v1 log root will therefore be laid out as:
  //
  // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+-....--+
  // | ver=1 |          tree_size            |len|    root_hash      |
  // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+-....--+
  //
  // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
  // |        timestamp_nanos        |      revision                 |
  // +---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+---+
  //
  // +---+---+---+---+---+-....---+
  // |  len  |    metadata        |
  // +---+---+---+---+---+-....---+
  //
  // (with all integers encoded big-endian).
  bytes log_root = 8;

  reserved 1 to 7, 9;
  reserved "key_hint";
  reserved "log_id";
  reserved "log_root_signature";
  reserved "root_hash";
  reserved "signature";
  reserved "timestamp_nanos";
  reserved "tree_revision";
  reserved "tree_size";
}

// Proof holds a consistency or inclusion proof for a Merkle tree, as returned
// by the API.
message Proof {
  // leaf_index indicates the requested leaf index when this message is used for
  // a leaf inclusion proof.  This field is set to zero when this message is
  // used for a consistency proof.
  int64 leaf_index = 1;
  repeated bytes hashes = 3;

  reserved 2;
  reserved "proof_node";
}
