// Copyright the Hyperledger Fabric contributors. All rights reserved.
//
// SPDX-License-Identifier: Apache-2.0

syntax = "proto3";

option go_package = "github.com/hyperledger/fabric-protos-go/common";
option java_package = "org.hyperledger.fabric.protos.common";

package common;

import "google/protobuf/timestamp.proto";

// These status codes are intended to resemble selected HTTP status codes
enum Status {
    UNKNOWN = 0;
    SUCCESS = 200;
    BAD_REQUEST = 400;
    FORBIDDEN = 403;
    NOT_FOUND = 404;
    REQUEST_ENTITY_TOO_LARGE = 413;
    INTERNAL_SERVER_ERROR = 500;
    NOT_IMPLEMENTED = 501;
    SERVICE_UNAVAILABLE = 503;
}

enum HeaderType {
    reserved 7, 8, 9;
    reserved "PEER_RESOURCE_UPDATE", "PEER_ADMIN_OPERATION", "TOKEN_TRANSACTION";

    MESSAGE = 0;                                 // Used for messages which are signed but opaque
    CONFIG = 1;                                  // Used for messages which express the channel config
    CONFIG_UPDATE = 2;                           // Used for transactions which update the channel config
    ENDORSER_TRANSACTION = 3;                    // Used by the SDK to submit endorser based transactions
    ORDERER_TRANSACTION = 4 [deprecated = true]; // Was used internally by the orderer for management, no longer used since system channel was removed
    DELIVER_SEEK_INFO = 5;                       // Used as the type for Envelope messages submitted to instruct the Deliver API to seek
    CHAINCODE_PACKAGE = 6;                       // Used for packaging chaincode artifacts for install
}

// This enum enlists indexes of the block metadata array
enum BlockMetadataIndex {
    SIGNATURES = 0;                    // Block metadata array position for block signatures
    LAST_CONFIG = 1 [deprecated=true]; // Block metadata array position to store last configuration block sequence number
    TRANSACTIONS_FILTER = 2;           // Block metadata array position to store serialized bit array filter of invalid transactions
    ORDERER = 3 [deprecated=true];     // Block metadata array position to store operational metadata for orderers
    COMMIT_HASH = 4;                   /* Block metadata array position to store the hash of TRANSACTIONS_FILTER, State Updates,
                                          and the COMMIT_HASH of the previous block */
}

// LastConfig is the encoded value for the Metadata message which is encoded in the LAST_CONFIGURATION block metadata index
message LastConfig {
    uint64 index  = 1;
}

// Metadata is a common structure to be used to encode block metadata
message Metadata {
    bytes value = 1;
    repeated MetadataSignature signatures = 2;
}

message MetadataSignature {
    bytes signature_header = 1; // An encoded SignatureHeader
    bytes signature = 2;       // The signature over the concatenation of the Metadata value bytes, signatureHeader, and block header
    bytes identifier_header = 3; // An encoded IdentifierHeader. If the signature header is empty, this is used to identify the creator by id
}

// IdentifierHeader is used as an alternative to a SignatureHeader when the creator can be referenced by id
message IdentifierHeader {
    uint32 identifier = 1; // A unique identifier that represents the creator of the message
    bytes nonce = 2; // Arbitrary number that may only be used once. Can be used to detect replay attacks.
}

message Header {
    bytes channel_header = 1;
    bytes signature_header = 2;
}

// Header is a generic replay prevention and identity message to include in a signed payload
message ChannelHeader {
    int32 type = 1; // Header types 0-10000 are reserved and defined by HeaderType

    // Version indicates message protocol version
    int32 version = 2;

    // Timestamp is the local time when the message was created
    // by the sender
    google.protobuf.Timestamp timestamp = 3;

    // Identifier of the channel this message is bound for
    string channel_id = 4;

    // An unique identifier that is used end-to-end.
    //  -  set by higher layers such as end user or SDK
    //  -  passed to the endorser (which will check for uniqueness)
    //  -  as the header is passed along unchanged, it will be
    //     be retrieved by the committer (uniqueness check here as well)
    //  -  to be stored in the ledger
    string tx_id = 5;

    // The epoch in which this header was generated, where epoch is defined based on block height
    // Epoch in which the response has been generated. This field identifies a
    // logical window of time. A proposal response is accepted by a peer only if
    // two conditions hold:
    // 1. the epoch specified in the message is the current epoch
    // 2. this message has been only seen once during this epoch (i.e. it hasn't
    //    been replayed)
    uint64 epoch = 6;

    // Extension that may be attached based on the header type
    bytes extension = 7;

    // If mutual TLS is employed, this represents
    // the hash of the client's TLS certificate
    bytes tls_cert_hash = 8;
}

message SignatureHeader {
    // Creator of the message, a marshaled msp.SerializedIdentity
    bytes creator = 1;

    // Arbitrary number that may only be used once. Can be used to detect replay attacks.
    bytes nonce = 2;
}

// Payload is the message contents (and header to allow for signing)
message Payload {

    // Header is included to provide identity and prevent replay
    Header header = 1;

    // Data, the encoding of which is defined by the type in the header
    bytes data = 2;
}

// Envelope wraps a Payload with a signature so that the message may be authenticated
message Envelope {
    // A marshaled Payload
    bytes payload = 1;

    // A signature by the creator specified in the Payload header
    bytes signature = 2;
}

// This is finalized block structure to be shared among the orderer and peer
// Note that the BlockHeader chains to the previous BlockHeader, and the BlockData hash is embedded
// in the BlockHeader.  This makes it natural and obvious that the Data is included in the hash, but
// the Metadata is not.
message Block {
    BlockHeader header = 1;
    BlockData data = 2;
    BlockMetadata metadata = 3;
}

// BlockHeader is the element of the block which forms the block chain
// The block header is hashed using the configured chain hashing algorithm
// over the ASN.1 encoding of the BlockHeader
message BlockHeader {
    uint64 number = 1; // The position in the blockchain
    bytes previous_hash = 2; // The hash of the previous block header
    bytes data_hash = 3; // The hash of the BlockData, by MerkleTree
}

message BlockData {
    repeated bytes data = 1;
}

message BlockMetadata {
    repeated bytes metadata = 1;
}

// OrdererBlockMetadata defines metadata that is set by the ordering service.
message OrdererBlockMetadata {
    LastConfig last_config = 1;
    bytes consenter_metadata = 2;
}
