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

syntax = "proto3";

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

package protos;

import "peer/chaincode_event.proto";
import "peer/proposal.proto";
import "google/protobuf/timestamp.proto";

message ChaincodeMessage {
    enum Type {
        UNDEFINED = 0;
        REGISTER = 1;
        REGISTERED = 2;
        INIT = 3;
        READY = 4;
        TRANSACTION = 5;
        COMPLETED = 6;
        ERROR = 7;
        GET_STATE = 8;
        PUT_STATE = 9;
        DEL_STATE = 10;
        INVOKE_CHAINCODE = 11;
        RESPONSE = 13;
        GET_STATE_BY_RANGE = 14;
        GET_QUERY_RESULT = 15;
        QUERY_STATE_NEXT = 16;
        QUERY_STATE_CLOSE = 17;
        KEEPALIVE = 18;
        GET_HISTORY_FOR_KEY = 19;
        GET_STATE_METADATA = 20;
        PUT_STATE_METADATA = 21;
        GET_PRIVATE_DATA_HASH = 22;
        PURGE_PRIVATE_DATA = 23;
        WRITE_BATCH_STATE = 24;
        GET_STATE_MULTIPLE = 25;
    }

    Type type = 1;
    google.protobuf.Timestamp timestamp = 2;
    bytes payload = 3;
    string txid = 4;

    SignedProposal proposal = 5;

    //event emitted by chaincode. Used only with Init or Invoke.
    // This event is then stored (currently)
    //with Block.NonHashData.TransactionResult
    ChaincodeEvent chaincode_event = 6;

    //channel id
    string channel_id = 7;
}

// TODO: We need to finalize the design on chaincode container
// compatibility upon upgrade, see FAB-5777.

// GetState is the payload of a ChaincodeMessage. It contains a key which
// is to be fetched from the ledger. If the collection is specified, the key
// would be fetched from the collection (i.e., private state)
message GetState {
    string key = 1;
    string collection = 2;
}

message GetStateMetadata {
    string key = 1;
    string collection = 2;
}

// GetStateMultiple is the payload of the ChaincodeMessage.
// It contains the keys to be retrieved from the ledger.
// If a collection is specified, the keys will be retrieved
// from the collection (i.e., the private state).
message GetStateMultiple {
    repeated string keys = 1;
    string collection = 2;
}

// GetStateMultipleResult is result of executing the GetStateMiltiple request
message GetStateMultipleResult {
    repeated bytes values = 1;
}

// PutState is the payload of a ChaincodeMessage. It contains a key and value
// which needs to be written to the transaction's write set. If the collection is
// specified, the key and value would be written to the transaction's private
// write set.
message PutState {
    string key = 1;
    bytes value = 2;
    string collection = 3;
}

message PutStateMetadata {
    string key = 1;
    string collection = 3;
    StateMetadata metadata = 4;
}

// WriteBatchState - set of records for state changes sent by the batch
message WriteBatchState {
    repeated WriteRecord rec = 1;
}

// WriteRecord - single record with changes in the state of different types.
// Filled in depending on the type.
message WriteRecord {
    enum Type {
        UNDEFINED = 0;
        PUT_STATE = 9;
        DEL_STATE = 10;
        PUT_STATE_METADATA = 21;
        PURGE_PRIVATE_DATA = 23;
    }

    string key = 1;
    bytes value = 2;
    string collection = 3;
    StateMetadata metadata = 4;
    Type type = 5;
}

// DelState is the payload of a ChaincodeMessage. It contains a key which
// needs to be recorded in the transaction's write set as a delete operation.
// If the collection is specified, the key needs to be recorded in the
// transaction's private write set as a delete operation.
message DelState {
    string key = 1;
    string collection = 2;
}

message PurgePrivateState {
    string key = 1;
    string collection = 2;
}

// GetStateByRange is the payload of a ChaincodeMessage. It contains a start key and
// a end key required to execute range query. If the collection is specified,
// the range query needs to be executed on the private data. The metadata hold
// the byte representation of QueryMetadata.
message GetStateByRange {
    string startKey = 1;
    string endKey = 2;
    string collection = 3;
    bytes metadata = 4;
}

// GetQueryResult is the payload of a ChaincodeMessage. It contains a query
// string in the form that is supported by the underlying state database.
// If the collection is specified, the query needs to be executed on the
// private data.  The metadata hold the byte representation of QueryMetadata.
message GetQueryResult {
    string query = 1;
    string collection = 2;
    bytes metadata = 3;
}

// QueryMetadata is the metadata of a GetStateByRange and GetQueryResult.
// It contains a pageSize which denotes the number of records to be fetched
// and a bookmark.
message QueryMetadata {
    int32 pageSize = 1;
    string bookmark = 2;
}

// GetHistoryForKey is the payload of a ChaincodeMessage. It contains a key
// for which the historical values need to be retrieved.
message GetHistoryForKey {
    string key = 1;
}

message QueryStateNext {
    string id = 1;
}

message QueryStateClose {
    string id = 1;
}

// QueryResultBytes hold the byte representation of a record returned by the peer.
message QueryResultBytes {
    bytes resultBytes = 1;
}

// QueryResponse is returned by the peer as a result of a GetStateByRange,
// GetQueryResult, and GetHistoryForKey. It holds a bunch of records in
// results field, a flag to denote whether more results need to be fetched from
// the peer in has_more field, transaction id in id field, and a QueryResponseMetadata
// in metadata field.
message QueryResponse {
    repeated QueryResultBytes results = 1;
    bool has_more = 2;
    string id = 3;
    bytes metadata = 4;
}

// QueryResponseMetadata is the metadata of a QueryResponse. It contains a count
// which denotes the number of records fetched from the ledger and a bookmark.
message QueryResponseMetadata {
    int32 fetched_records_count = 1;
    string bookmark = 2;
}

message StateMetadata {
    string metakey = 1;
    bytes value = 2;
}

message StateMetadataResult {
    repeated StateMetadata entries = 1;
}

// Interface that provides support to chaincode execution. ChaincodeContext
// provides the context necessary for the server to respond appropriately.
service ChaincodeSupport {
    rpc Register(stream ChaincodeMessage) returns (stream ChaincodeMessage);
}

// Chaincode as a server - peer establishes a connection to the chaincode as a client
// Currently only supports a stream connection.
service Chaincode {
    rpc Connect(stream ChaincodeMessage) returns (stream ChaincodeMessage);
}
