syntax = "proto3";
package cometbft.abci.v2;

import "cometbft/crypto/v1/proof.proto";
import "cometbft/types/v2/params.proto";
import "cometbft/types/v2/validator.proto";
import "gogoproto/gogo.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.proto";

option go_package = "github.com/cometbft/cometbft/api/cometbft/abci/v2";

// ----------------------------------------
// Request types

// Request represents a request to the ABCI application.
message Request {
  // Sum of all possible messages.
  oneof value {
    EchoRequest                echo                  = 1;
    FlushRequest               flush                 = 2;
    InfoRequest                info                  = 3;
    InitChainRequest           init_chain            = 5;
    QueryRequest               query                 = 6;
    CheckTxRequest             check_tx              = 8;
    CommitRequest              commit                = 11;
    ListSnapshotsRequest       list_snapshots        = 12;
    OfferSnapshotRequest       offer_snapshot        = 13;
    LoadSnapshotChunkRequest   load_snapshot_chunk   = 14;
    ApplySnapshotChunkRequest  apply_snapshot_chunk  = 15;
    PrepareProposalRequest     prepare_proposal      = 16;
    ProcessProposalRequest     process_proposal      = 17;
    ExtendVoteRequest          extend_vote           = 18;
    VerifyVoteExtensionRequest verify_vote_extension = 19;
    FinalizeBlockRequest       finalize_block        = 20;
  }
  reserved 4, 7, 9, 10; // SetOption, BeginBlock, DeliverTx, EndBlock
}

// EchoRequest is a request to "echo" the given string.
message EchoRequest {
  string message = 1;
}

// FlushRequest is a request to flush the write buffer.
message FlushRequest {}

// InfoRequest is a request for the ABCI application version.
message InfoRequest {
  string version       = 1;
  uint64 block_version = 2;
  uint64 p2p_version   = 3;
  string abci_version  = 4;
}

// InitChainRequest is a request to initialize the blockchain.
message InitChainRequest {
  google.protobuf.Timestamp         time             = 1 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
  string                            chain_id         = 2;
  cometbft.types.v2.ConsensusParams consensus_params = 3;
  repeated ValidatorUpdate          validators       = 4 [(gogoproto.nullable) = false];
  bytes                             app_state_bytes  = 5;
  int64                             initial_height   = 6;
}

// QueryRequest is a request to query the application state.
message QueryRequest {
  bytes  data   = 1;
  string path   = 2;
  int64  height = 3;
  bool   prove  = 4;
}

// Type of the transaction check request.
//
// This enumeration is incompatible with the CheckTxType definition in
// cometbft.abci.v1beta1 and therefore shall not be used in encoding with the same
// field number.
enum CheckTxType {
  option (gogoproto.goproto_enum_prefix) = false;

  // Unknown
  CHECK_TX_TYPE_UNKNOWN = 0;
  // Recheck (2nd, 3rd, etc.)
  CHECK_TX_TYPE_RECHECK = 1;
  // Check (1st time)
  CHECK_TX_TYPE_CHECK = 2;
}

// CheckTxRequest is a request to check that the transaction is valid.
message CheckTxRequest {
  bytes       tx   = 1;
  CheckTxType type = 3;
  reserved 2; // v1beta1.CheckTxType type
}

// CommitRequest is a request to commit the pending application state.
message CommitRequest {}

// Request to list available snapshots.
message ListSnapshotsRequest {}

// Request offering a snapshot to the application.
message OfferSnapshotRequest {
  Snapshot snapshot = 1; // snapshot offered by peers
  bytes    app_hash = 2; // light client-verified app hash for snapshot height
}

// Request to load a snapshot chunk.
message LoadSnapshotChunkRequest {
  uint64 height = 1;
  uint32 format = 2;
  uint32 chunk  = 3;
}

// Request to apply a snapshot chunk.
message ApplySnapshotChunkRequest {
  uint32 index  = 1;
  bytes  chunk  = 2;
  string sender = 3;
}

// PrepareProposalRequest is a request for the ABCI application to prepare a new
// block proposal.
message PrepareProposalRequest {
  // the modified transactions cannot exceed this size.
  int64 max_tx_bytes = 1;
  // txs is an array of transactions that will be included in a block,
  // sent to the app for possible modifications.
  repeated bytes            txs                  = 2;
  ExtendedCommitInfo        local_last_commit    = 3 [(gogoproto.nullable) = false];
  repeated Misbehavior      misbehavior          = 4 [(gogoproto.nullable) = false];
  int64                     height               = 5;
  google.protobuf.Timestamp time                 = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
  bytes                     next_validators_hash = 7;
  // address of the public key of the validator proposing the block.
  bytes proposer_address = 8;
}

// ProcessProposalRequest is a request for the ABCI application to process a proposal
// received from another validator.
message ProcessProposalRequest {
  repeated bytes       txs                  = 1;
  CommitInfo           proposed_last_commit = 2 [(gogoproto.nullable) = false];
  repeated Misbehavior misbehavior          = 3 [(gogoproto.nullable) = false];
  // Merkle root hash of the fields of the proposed block.
  bytes                     hash                 = 4;
  int64                     height               = 5;
  google.protobuf.Timestamp time                 = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
  bytes                     next_validators_hash = 7;
  // address of the public key of the original proposer of the block.
  bytes proposer_address = 8;
}

// ExtendVoteRequest extends a precommit vote with application-injected data.
message ExtendVoteRequest {
  // the hash of the block that this vote may be referring to
  bytes hash = 1;
  // the height of the extended vote
  int64 height = 2;
  // info of the block that this vote may be referring to
  google.protobuf.Timestamp time                 = 3 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
  repeated bytes            txs                  = 4;
  CommitInfo                proposed_last_commit = 5 [(gogoproto.nullable) = false];
  repeated Misbehavior      misbehavior          = 6 [(gogoproto.nullable) = false];
  bytes                     next_validators_hash = 7;
  // address of the public key of the original proposer of the block.
  bytes proposer_address = 8;
}

// VerifyVoteExtensionRequest is a request for the application to verify a vote extension
// produced by a different validator.
// The request contains two vote extension fields: one that is replay-protected ('vote_extension')
// and one that is not ('non_rp_vote_extension').
message VerifyVoteExtensionRequest {
  // the hash of the block that this received vote corresponds to
  bytes hash = 1;
  // the validator that signed the vote extension
  bytes validator_address = 2;
  int64 height            = 3;
  // replay-protected vote extension
  bytes vote_extension = 4;
  // non-replay-protected vote extension
  bytes non_rp_vote_extension = 5;
}

// FinalizeBlockRequest is a request to finalize the block.
message FinalizeBlockRequest {
  repeated bytes       txs                 = 1;
  CommitInfo           decided_last_commit = 2 [(gogoproto.nullable) = false];
  repeated Misbehavior misbehavior         = 3 [(gogoproto.nullable) = false];
  // Merkle root hash of the fields of the decided block.
  bytes                     hash                 = 4;
  int64                     height               = 5;
  google.protobuf.Timestamp time                 = 6 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
  bytes                     next_validators_hash = 7;
  // address of the public key of the original proposer of the block.
  bytes proposer_address = 8;
  // If the node is syncing/replaying blocks - target height. If not, syncing_to == height.
  int64 syncing_to_height = 9;
}

// ----------------------------------------
// Response types

// Response represents a response from the ABCI application.
message Response {
  // Sum of all possible messages.
  oneof value {
    ExceptionResponse           exception             = 1;
    EchoResponse                echo                  = 2;
    FlushResponse               flush                 = 3;
    InfoResponse                info                  = 4;
    InitChainResponse           init_chain            = 6;
    QueryResponse               query                 = 7;
    CheckTxResponse             check_tx              = 9;
    CommitResponse              commit                = 12;
    ListSnapshotsResponse       list_snapshots        = 13;
    OfferSnapshotResponse       offer_snapshot        = 14;
    LoadSnapshotChunkResponse   load_snapshot_chunk   = 15;
    ApplySnapshotChunkResponse  apply_snapshot_chunk  = 16;
    PrepareProposalResponse     prepare_proposal      = 17;
    ProcessProposalResponse     process_proposal      = 18;
    ExtendVoteResponse          extend_vote           = 19;
    VerifyVoteExtensionResponse verify_vote_extension = 20;
    FinalizeBlockResponse       finalize_block        = 21;
  }
  reserved 5, 8, 10, 11; // SetOption, BeginBlock, DeliverTx, EndBlock
}

// nondeterministic
message ExceptionResponse {
  string error = 1;
}

// EchoResponse indicates that the connection is still alive.
message EchoResponse {
  string message = 1;
}

// FlushResponse indicates that the write buffer was flushed.
message FlushResponse {}

// InfoResponse contains the ABCI application version information.
message InfoResponse {
  string data = 1;

  string version     = 2;
  uint64 app_version = 3;

  int64 last_block_height   = 4;
  bytes last_block_app_hash = 5;

  map<string, uint32> lane_priorities = 6;
  string              default_lane    = 7;
}

// InitChainResponse contains the ABCI application's hash and updates to the
// validator set and/or the consensus params, if any.
message InitChainResponse {
  cometbft.types.v2.ConsensusParams consensus_params = 1;
  repeated ValidatorUpdate          validators       = 2 [(gogoproto.nullable) = false];
  bytes                             app_hash         = 3;
}

// QueryResponse contains the ABCI application data along with a proof.
message QueryResponse {
  uint32 code = 1;
  // bytes data = 2; // use "value" instead.
  string                      log       = 3; // nondeterministic
  string                      info      = 4; // nondeterministic
  int64                       index     = 5;
  bytes                       key       = 6;
  bytes                       value     = 7;
  cometbft.crypto.v1.ProofOps proof_ops = 8;
  int64                       height    = 9;
  string                      codespace = 10;
}

// CheckTxResponse shows if the transaction was deemed valid by the ABCI
// application.
message CheckTxResponse {
  uint32         code       = 1;
  bytes          data       = 2;
  string         log        = 3; // nondeterministic
  string         info       = 4; // nondeterministic
  int64          gas_wanted = 5 [json_name = "gas_wanted"];
  int64          gas_used   = 6 [json_name = "gas_used"];
  repeated Event events     = 7
      [(gogoproto.nullable) = false,
       (gogoproto.jsontag)  = "events,omitempty"]; // nondeterministic
  string codespace = 8;

  // These reserved fields were used till v0.37 by the priority mempool (now
  // removed).
  reserved 9 to 11;
  reserved "sender", "priority", "mempool_error";

  string lane_id = 12;
}

// CommitResponse indicates how much blocks should CometBFT retain.
message CommitResponse {
  reserved 1, 2; // data was previously returned here
  int64 retain_height = 3;
}

// ListSnapshotsResponse contains the list of snapshots.
message ListSnapshotsResponse {
  repeated Snapshot snapshots = 1;
}

// OfferSnapshotResponse indicates the ABCI application decision whenever to
// provide a snapshot to the requester or not.
message OfferSnapshotResponse {
  OfferSnapshotResult result = 1;
}

// The result of offering a snapshot.
enum OfferSnapshotResult {
  option (gogoproto.goproto_enum_prefix) = false;

  // Unknown result, abort all snapshot restoration
  OFFER_SNAPSHOT_RESULT_UNKNOWN = 0;
  // Snapshot accepted, apply chunks
  OFFER_SNAPSHOT_RESULT_ACCEPT = 1;
  // Abort all snapshot restoration
  OFFER_SNAPSHOT_RESULT_ABORT = 2;
  // Reject this specific snapshot, try others
  OFFER_SNAPSHOT_RESULT_REJECT = 3;
  // Reject all snapshots of this format, try others
  OFFER_SNAPSHOT_RESULT_REJECT_FORMAT = 4;
  // Reject all snapshots from the sender(s), try others
  OFFER_SNAPSHOT_RESULT_REJECT_SENDER = 5;
}

// LoadSnapshotChunkResponse returns a snapshot's chunk.
message LoadSnapshotChunkResponse {
  bytes chunk = 1;
}

// ApplySnapshotChunkResponse returns a result of applying the specified chunk.
message ApplySnapshotChunkResponse {
  ApplySnapshotChunkResult result         = 1;
  repeated uint32          refetch_chunks = 2; // Chunks to refetch and reapply
  repeated string          reject_senders = 3; // Chunk senders to reject and ban
}

// The result of applying a snapshot chunk.
enum ApplySnapshotChunkResult {
  option (gogoproto.goproto_enum_prefix) = false;

  // Unknown result, abort all snapshot restoration
  APPLY_SNAPSHOT_CHUNK_RESULT_UNKNOWN = 0;
  // Chunk successfully accepted
  APPLY_SNAPSHOT_CHUNK_RESULT_ACCEPT = 1;
  // Abort all snapshot restoration
  APPLY_SNAPSHOT_CHUNK_RESULT_ABORT = 2;
  // Retry chunk (combine with refetch and reject)
  APPLY_SNAPSHOT_CHUNK_RESULT_RETRY = 3;
  // Retry snapshot (combine with refetch and reject)
  APPLY_SNAPSHOT_CHUNK_RESULT_RETRY_SNAPSHOT = 4;
  // Reject this snapshot, try others
  APPLY_SNAPSHOT_CHUNK_RESULT_REJECT_SNAPSHOT = 5;
}

// PrepareProposalResponse contains a list of transactions, which will form a block.
message PrepareProposalResponse {
  repeated bytes txs = 1;
}

// ProcessProposalResponse indicates the ABCI application's decision whenever
// the given proposal should be accepted or not.
message ProcessProposalResponse {
  ProcessProposalStatus status = 1;
}

// ProcessProposalStatus is the status of the proposal processing.
enum ProcessProposalStatus {
  option (gogoproto.goproto_enum_prefix) = false;

  // Unknown
  PROCESS_PROPOSAL_STATUS_UNKNOWN = 0;
  // Accepted
  PROCESS_PROPOSAL_STATUS_ACCEPT = 1;
  // Rejected
  PROCESS_PROPOSAL_STATUS_REJECT = 2;
}

// ExtendVoteResponse contains the vote extension that the application would like to
// attach to its next precommit vote.
// Information in `vote_extension` will be replay-protected.
// Information in `non_rp_extension` will not be replay-protected.
message ExtendVoteResponse {
  bytes vote_extension   = 1; // this extension's signature is replay-protected
  bytes non_rp_extension = 2; // this extension's signature is _not_ replay-protected
}

// VerifyVoteExtensionResponse indicates the ABCI application's decision
// whenever the vote extension should be accepted or not.
message VerifyVoteExtensionResponse {
  VerifyVoteExtensionStatus status = 1;
}

// VerifyVoteExtensionStatus is the status of the vote extension verification.
enum VerifyVoteExtensionStatus {
  option (gogoproto.goproto_enum_prefix) = false;

  // Unknown
  VERIFY_VOTE_EXTENSION_STATUS_UNKNOWN = 0;
  // Accepted
  VERIFY_VOTE_EXTENSION_STATUS_ACCEPT = 1;
  // Rejecting the vote extension will reject the entire precommit by the sender.
  // Incorrectly implementing this thus has liveness implications as it may affect
  // CometBFT's ability to receive 2/3+ valid votes to finalize the block.
  // Honest nodes should never be rejected.
  VERIFY_VOTE_EXTENSION_STATUS_REJECT = 2;
}

// FinalizeBlockResponse contains the result of executing the block.
message FinalizeBlockResponse {
  // set of block events emitted as part of executing the block
  repeated Event events = 1
      [(gogoproto.nullable) = false,
       (gogoproto.jsontag)  = "events,omitempty"]; // nondeterministic
  // the result of executing each transaction including the events
  // the particular transaction emitted. This should match the order
  // of the transactions delivered in the block itself
  repeated ExecTxResult tx_results = 2;
  // a list of updates to the validator set. These will reflect the validator set at current height + 2.
  repeated ValidatorUpdate validator_updates = 3 [(gogoproto.nullable) = false];
  // updates to the consensus params, if any.
  cometbft.types.v2.ConsensusParams consensus_param_updates = 4;
  // app_hash is the hash of the applications' state which is used to confirm
  // that execution of the transactions was deterministic.
  // It is up to the application to decide which algorithm to use.
  bytes app_hash = 5;
  // delay between the time when this block is committed and the next height is started.
  // previously `timeout_commit` in config.toml
  google.protobuf.Duration next_block_delay = 6 [(gogoproto.nullable) = false, (gogoproto.stdduration) = true];
}

// ----------------------------------------
// Misc.

// CommitInfo contains votes for the particular round.
message CommitInfo {
  int32             round = 1;
  repeated VoteInfo votes = 2 [(gogoproto.nullable) = false];
}

// ExtendedCommitInfo is similar to CommitInfo except that it is only used in
// the PrepareProposal request such that Tendermint can provide vote extensions
// to the application.
message ExtendedCommitInfo {
  // The round at which the block proposer decided in the previous height.
  int32 round = 1;
  // List of validators' addresses in the last validator set with their voting
  // information, including vote extensions.
  repeated ExtendedVoteInfo votes = 2 [(gogoproto.nullable) = false];
}

// Event allows application developers to attach additional information to
// ResponseFinalizeBlock and ResponseCheckTx.
// Up to 0.37, this could also be used in ResponseBeginBlock, ResponseEndBlock,
// and ResponseDeliverTx.
// Later, transactions may be queried using these events.
message Event {
  string                  type       = 1;
  repeated EventAttribute attributes = 2 [(gogoproto.nullable) = false, (gogoproto.jsontag) = "attributes,omitempty"];
}

// EventAttribute is a single key-value pair, associated with an event.
message EventAttribute {
  string key   = 1;
  string value = 2;
  bool   index = 3; // nondeterministic
}

// ExecTxResult contains results of executing one individual transaction.
//
// * Its structure is equivalent to #ResponseDeliverTx which will be deprecated/deleted
message ExecTxResult {
  uint32         code       = 1;
  bytes          data       = 2;
  string         log        = 3; // nondeterministic
  string         info       = 4; // nondeterministic
  int64          gas_wanted = 5 [json_name = "gas_wanted"];
  int64          gas_used   = 6 [json_name = "gas_used"];
  repeated Event events     = 7
      [(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"]; // nondeterministic
  string codespace = 8;
}

// TxResult contains results of executing the transaction.
//
// One usage is indexing transaction results.
message TxResult {
  int64        height = 1;
  uint32       index  = 2;
  bytes        tx     = 3;
  ExecTxResult result = 4 [(gogoproto.nullable) = false];
}

// ----------------------------------------
// Blockchain Types

// Validator in the validator set.
message Validator {
  bytes address = 1; // The first 20 bytes of SHA256(public key)
  // PubKey pub_key = 2 [(gogoproto.nullable)=false];
  int64 power = 3; // The voting power
}

// ValidatorUpdate is a singular update to a validator set.
message ValidatorUpdate {
  int64  power         = 2;
  bytes  pub_key_bytes = 3;
  string pub_key_type  = 4;

  reserved 1; // pub_key
}

// VoteInfo contains the information about the vote.
message VoteInfo {
  Validator                     validator     = 1 [(gogoproto.nullable) = false];
  cometbft.types.v2.BlockIDFlag block_id_flag = 3;

  reserved 2; // signed_last_block
}

// ExtendedVoteInfo extends VoteInfo with the vote extensions (non-deterministic).
message ExtendedVoteInfo {
  // The validator that sent the vote.
  Validator validator = 1 [(gogoproto.nullable) = false];
  // Non-deterministic extension provided by the sending validator's application.
  bytes vote_extension = 3;
  // Vote extension signature created by CometBFT
  bytes extension_signature = 4;
  // block_id_flag indicates whether the validator voted for a block, nil, or did not vote at all
  cometbft.types.v2.BlockIDFlag block_id_flag = 5;
  // Non-deterministic non-replay-protected extension provided by the sending validator's application.
  bytes non_rp_vote_extension = 6;
  // Signature on non-replay-protected extension created by CometBFT
  bytes non_rp_extension_signature = 7;

  reserved 2; // signed_last_block
}

// The type of misbehavior committed by a validator.
enum MisbehaviorType {
  option (gogoproto.goproto_enum_prefix) = false;

  // Unknown
  MISBEHAVIOR_TYPE_UNKNOWN = 0;
  // Duplicate vote
  MISBEHAVIOR_TYPE_DUPLICATE_VOTE = 1;
  // Light client attack
  MISBEHAVIOR_TYPE_LIGHT_CLIENT_ATTACK = 2;
}

// Misbehavior is a type of misbehavior committed by a validator.
message Misbehavior {
  MisbehaviorType type = 1;
  // The offending validator
  Validator validator = 2 [(gogoproto.nullable) = false];
  // The height when the offense occurred
  int64 height = 3;
  // The corresponding time where the offense occurred
  google.protobuf.Timestamp time = 4 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];
  // Total voting power of the validator set in case the ABCI application does
  // not store historical validators.
  // https://github.com/tendermint/tendermint/issues/4581
  int64 total_voting_power = 5;
}

// ----------------------------------------
// State Sync Types

// Snapshot of the ABCI application state.
message Snapshot {
  uint64 height   = 1; // The height at which the snapshot was taken
  uint32 format   = 2; // The application-specific snapshot format
  uint32 chunks   = 3; // Number of chunks in the snapshot
  bytes  hash     = 4; // Arbitrary snapshot hash, equal only if identical
  bytes  metadata = 5; // Arbitrary application metadata
}
