syntax = "proto3";
package types;

// For more information on gogo.proto, see:
// https://github.com/gogo/protobuf/blob/master/extensions.md
import "github.com/gogo/protobuf/gogoproto/gogo.proto";
import "google/protobuf/timestamp.proto";
import "github.com/tendermint/tendermint/libs/common/types.proto";

// This file is copied from http://github.com/tendermint/abci
// NOTE: When using custom types, mind the warnings.
// https://github.com/gogo/protobuf/blob/master/custom_types.md#warnings-and-issues

option (gogoproto.marshaler_all) = true;
option (gogoproto.unmarshaler_all) = true;
option (gogoproto.sizer_all) = true;
option (gogoproto.goproto_registration) = true;
// Generate tests
option (gogoproto.populate_all) = true;
option (gogoproto.equal_all) = true;
option (gogoproto.testgen_all) = true;

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

message Request {
  oneof value {
    RequestEcho echo = 2;
    RequestFlush flush = 3;
    RequestInfo info = 4;
    RequestSetOption set_option = 5;
    RequestInitChain init_chain = 6;
    RequestQuery query = 7;
    RequestBeginBlock begin_block = 8;
    RequestCheckTx check_tx = 9;
    RequestDeliverTx deliver_tx = 19;
    RequestEndBlock end_block = 11;
    RequestCommit commit = 12;
  }
}

message RequestEcho {
  string message = 1;
}

message RequestFlush {
}

message RequestInfo {
  string version = 1;
}

// nondeterministic
message RequestSetOption {
  string key = 1;
  string value = 2;
}

message RequestInitChain {
  google.protobuf.Timestamp time = 1  [(gogoproto.nullable)=false, (gogoproto.stdtime)=true];
  string chain_id = 2;
  ConsensusParams consensus_params = 3;
  repeated Validator validators = 4  [(gogoproto.nullable)=false];
  bytes app_state_bytes = 5;
}

message RequestQuery {
  bytes data = 1;
  string path = 2;
  int64 height = 3;
  bool prove = 4;
}

// NOTE: validators here have empty pubkeys.
message RequestBeginBlock {
  bytes hash = 1;
  Header header = 2 [(gogoproto.nullable)=false];
  LastCommitInfo last_commit_info = 3 [(gogoproto.nullable)=false];
  repeated Evidence byzantine_validators = 4 [(gogoproto.nullable)=false];
}

message RequestCheckTx {
  bytes tx = 1;
}

message RequestDeliverTx {
  bytes tx = 1;
}

message RequestEndBlock {
  int64 height = 1;
}

message RequestCommit {
}

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

message Response {
  oneof value {
    ResponseException exception = 1;
    ResponseEcho echo = 2;
    ResponseFlush flush = 3;
    ResponseInfo info = 4;
    ResponseSetOption set_option = 5;
    ResponseInitChain init_chain = 6;
    ResponseQuery query = 7;
    ResponseBeginBlock begin_block = 8;
    ResponseCheckTx check_tx = 9;
    ResponseDeliverTx deliver_tx = 10;
    ResponseEndBlock end_block = 11;
    ResponseCommit commit = 12;
  }
}

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

message ResponseEcho {
  string message = 1;
}

message ResponseFlush {
}

message ResponseInfo {
  string data = 1;
  string version = 2;
  int64 last_block_height = 3;
  bytes last_block_app_hash = 4;
}

// nondeterministic
message ResponseSetOption {
  uint32 code = 1;
  // bytes data = 2;
  string log = 3;
  string info = 4;
}

message ResponseInitChain {
  ConsensusParams consensus_params = 1;
  repeated Validator validators = 2 [(gogoproto.nullable)=false];
}

message ResponseQuery {
  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;
  bytes proof = 8;
  int64 height = 9;
}

message ResponseBeginBlock {
  repeated common.KVPair tags = 1 [(gogoproto.nullable)=false, (gogoproto.jsontag)="tags,omitempty"];
}

message ResponseCheckTx {
  uint32 code = 1;
  bytes data = 2;
  string log = 3; // nondeterministic
  string info = 4; // nondeterministic
  int64 gas_wanted  = 5;
  int64 gas_used = 6;
  repeated common.KVPair tags = 7 [(gogoproto.nullable)=false, (gogoproto.jsontag)="tags,omitempty"];
}

message ResponseDeliverTx {
  uint32 code = 1;
  bytes data = 2;
  string log = 3; // nondeterministic
  string info = 4; // nondeterministic
  int64 gas_wanted = 5;
  int64 gas_used = 6;
  repeated common.KVPair tags = 7 [(gogoproto.nullable)=false, (gogoproto.jsontag)="tags,omitempty"];
}

message ResponseEndBlock {
  repeated Validator validator_updates = 1 [(gogoproto.nullable)=false];
  ConsensusParams consensus_param_updates = 2;
  repeated common.KVPair tags = 3 [(gogoproto.nullable)=false, (gogoproto.jsontag)="tags,omitempty"];
}

message ResponseCommit {
  // reserve 1
  bytes data = 2;
}

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

// ConsensusParams contains all consensus-relevant parameters
// that can be adjusted by the abci app
message ConsensusParams {
  BlockSize block_size = 1;
  TxSize tx_size = 2;
  BlockGossip block_gossip = 3;
}

// BlockSize contains limits on the block size.
message BlockSize {
  int32 max_bytes = 1;
  int32 max_txs = 2;
  int64 max_gas = 3;
}

// TxSize contains limits on the tx size.
message TxSize {
  int32 max_bytes = 1;
  int64 max_gas = 2;
}

// BlockGossip determine consensus critical
// elements of how blocks are gossiped
message BlockGossip {
  // Note: must not be 0
  int32 block_part_size_bytes = 1;
}

message LastCommitInfo {
  int32 commit_round = 1;
  repeated SigningValidator validators = 2 [(gogoproto.nullable)=false];
}

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

// just the minimum the app might need
message Header {
  // basics
  string chain_id = 1 [(gogoproto.customname)="ChainID"];
  int64 height = 2;
  google.protobuf.Timestamp time = 3 [(gogoproto.nullable)=false, (gogoproto.stdtime)=true];

  // txs
  int32 num_txs = 4;
  int64 total_txs = 5;

  // hashes
  bytes last_block_hash = 6;
  bytes validators_hash = 7;
  bytes app_hash = 8;

  // consensus
  Validator proposer = 9 [(gogoproto.nullable)=false];
}

// Validator
message Validator {
  bytes address = 1;
  PubKey pub_key = 2 [(gogoproto.nullable)=false];
  int64 power = 3;
}

// Validator with an extra bool
message SigningValidator {
  Validator validator = 1 [(gogoproto.nullable)=false];
  bool signed_last_block = 2;
}

message PubKey {
  string type = 1;
  bytes  data = 2;
}

message Evidence {
  string type = 1;
  Validator validator = 2 [(gogoproto.nullable)=false];
  int64 height = 3;
  google.protobuf.Timestamp time = 4 [(gogoproto.nullable)=false, (gogoproto.stdtime)=true];
  int64 total_voting_power = 5;
}

//----------------------------------------
// Service Definition

service ABCIApplication {
  rpc Echo(RequestEcho) returns (ResponseEcho) ;
  rpc Flush(RequestFlush) returns (ResponseFlush);
  rpc Info(RequestInfo) returns (ResponseInfo);
  rpc SetOption(RequestSetOption) returns (ResponseSetOption);
  rpc DeliverTx(RequestDeliverTx) returns (ResponseDeliverTx);
  rpc CheckTx(RequestCheckTx) returns (ResponseCheckTx);
  rpc Query(RequestQuery) returns (ResponseQuery);
  rpc Commit(RequestCommit) returns (ResponseCommit);
  rpc InitChain(RequestInitChain) returns (ResponseInitChain);
  rpc BeginBlock(RequestBeginBlock) returns (ResponseBeginBlock);
  rpc EndBlock(RequestEndBlock) returns (ResponseEndBlock);
}
