// 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/discovery";
option java_package = "org.hyperledger.fabric.protos.discovery";

package discovery;

import "gossip/message.proto";
import "msp/msp_config.proto";
import "peer/proposal_response.proto";

// Discovery defines a service that serves information about the fabric network
// like which peers, orderers, chaincodes, etc.
service Discovery {
    // Discover receives a signed request, and returns a response.
    rpc Discover (SignedRequest) returns (Response);
}

// SignedRequest contains a serialized Request in the payload field
// and a signature.
// The identity that is used to verify the signature
// can be extracted from the authentication field of type AuthInfo
// in the Request itself after deserializing it.
message SignedRequest {
    bytes payload   = 1;
    bytes signature = 2;
}

// Request contains authentication info about the client that sent the request
// and the queries it wishes to query the service
message Request {
    // authentication contains information that the service uses to check
    // the client's eligibility for the queries.
    AuthInfo authentication = 1;
    // queries
    repeated Query queries = 2;
}

message Response {
    // The results are returned in the same order of the queries
    repeated QueryResult results = 1;
}

// AuthInfo aggregates authentication information that the server uses
// to authenticate the client
message AuthInfo {
    // This is the identity of the client that is used to verify the signature
    // on the SignedRequest's payload.
    // It is a msp.SerializedIdentity in bytes form
    bytes client_identity = 1;

    // This is the hash of the client's TLS cert.
    // When the network is running with TLS, clients that don't include a certificate
    // will be denied access to the service.
    // Since the Request is encapsulated with a SignedRequest (which is signed),
    // this binds the TLS session to the enrollement identity of the client and
    // therefore both authenticates the client to the server,
    // and also prevents the server from relaying the request message to another server.
    bytes client_tls_cert_hash = 2;
}

// Query asks for information in the context of a specific channel
message Query {
    string channel = 1;
    oneof query {
        // ConfigQuery is used to query for the configuration of the channel,
        // such as FabricMSPConfig, and rorderer endpoints.
        // The client has to query a peer it trusts as it doesn't have means to self-verify
        // the authenticity of the returned result.
        // The result is returned in the form of ConfigResult.
        ConfigQuery config_query = 2;

        // PeerMembershipQuery queries for peers in a channel context,
        // and returns PeerMembershipResult
        PeerMembershipQuery peer_query = 3;

        // ChaincodeQuery queries for chaincodes by their name and version.
        // An empty version means any version can by returned.
        ChaincodeQuery cc_query = 4;

        // LocalPeerQuery queries for peers in a non channel context,
        // and returns PeerMembershipResult
        LocalPeerQuery local_peers = 5;
    }
}

// QueryResult contains a result for a given Query.
// The corresponding Query can be inferred by the index of the QueryResult from
// its enclosing Response message.
// QueryResults are ordered in the same order as the Queries are ordered in their enclosing Request.
message QueryResult {
    oneof result {
        // Error indicates failure or refusal to process the query
        Error error = 1;

        // ConfigResult contains the configuration of the channel,
        // such as FabricMSPConfig and orderer endpoints
        ConfigResult config_result = 2;

        // ChaincodeQueryResult contains information about chaincodes,
        // and their corresponding endorsers
        ChaincodeQueryResult cc_query_res = 3;

        // PeerMembershipResult contains information about peers,
        // such as their identity, endpoints, and channel related state.
        PeerMembershipResult members = 4;
    }
}

// ConfigQuery requests a ConfigResult
message ConfigQuery {

}

message ConfigResult {
    // msps is a map from MSP_ID to FabricMSPConfig
    map<string, msp.FabricMSPConfig> msps = 1;
    // orderers is a map from MSP_ID to endpoint lists of orderers
    map<string, Endpoints> orderers = 2;
}

// PeerMembershipQuery requests PeerMembershipResult.
// The filter field may be optionally populated in order
// for the peer membership to be filtered according to
// chaincodes that are installed on peers and collection
// access control policies.
message PeerMembershipQuery {
    protos.ChaincodeInterest filter = 1;
}

// PeerMembershipResult contains peers mapped by their organizations (MSP_ID)
message PeerMembershipResult {
    map<string, Peers> peers_by_org = 1;
}

// ChaincodeQuery requests ChaincodeQueryResults for a given
// list of chaincode invocations.
// Each invocation is a separate one, and the endorsement policy
// is evaluated independantly for each given interest.
message ChaincodeQuery {
    repeated protos.ChaincodeInterest interests = 1;
}

// ChaincodeQueryResult contains EndorsementDescriptors for
// chaincodes
message ChaincodeQueryResult {
    repeated EndorsementDescriptor content = 1;
}

// LocalPeerQuery queries for peers in a non channel context
message LocalPeerQuery {
}

// EndorsementDescriptor contains information about which peers can be used
// to request endorsement from, such that the endorsement policy would be fulfilled.
// Here is how to compute a set of peers to ask an endorsement from, given an EndorsementDescriptor:
// Let e: G --> P be the endorsers_by_groups field that maps a group to a set of peers.
// Note that applying e on a group g yields a set of peers.
// 1) Select a layout l: G --> N out of the layouts given.
//    l is the quantities_by_group field of a Layout, and it maps a group to an integer.
// 2) R = {}  (an empty set of peers)
// 3) For each group g in the layout l, compute n = l(g)
//    3.1) Denote P_g as a set of n random peers {p0, p1, ... p_n} selected from e(g)
//    3.2) R = R U P_g  (add P_g to R)
// 4) The set of peers R is the peers the client needs to request endorsements from
message EndorsementDescriptor {
    string chaincode = 1;
    // Specifies the endorsers, separated to groups.
    map<string, Peers> endorsers_by_groups = 2;

    // Specifies options of fulfulling the endorsement policy.
    // Each option lists the group names, and the amount of signatures needed
    // from each group.
    repeated Layout layouts = 3;
}

// Layout contains a mapping from a group name to number of peers
// that are needed for fulfilling an endorsement policy
message Layout {
    // Specifies how many non repeated signatures of each group
    // are needed for endorsement
    map<string, uint32> quantities_by_group = 1;
}

// Peers contains a list of Peer(s)
message Peers {
    repeated Peer peers = 1;
}

// Peer contains information about the peer such as its channel specific
// state, and membership information.
message Peer {
    // This is an Envelope of a GossipMessage with a gossip.StateInfo message
    gossip.Envelope state_info = 1;
    // This is an Envelope of a GossipMessage with a gossip.AliveMessage message
    gossip.Envelope membership_info = 2;

    // This is the msp.SerializedIdentity of the peer, represented in bytes.
    bytes identity = 3;
}

// Error denotes that something went wrong and contains the error message
message Error {
    string content = 1;
}

// Endpoints is a list of Endpoint(s)
message Endpoints {
    repeated Endpoint endpoint = 1;
}

// Endpoint is a combination of a host and a port
message Endpoint {
    string host = 1;
    uint32 port = 2;
}
