syntax = "proto3";
package tendermint.abci.types;
option  go_package = "github.com/tendermint/tendermint/abci/types";

// For more information on gogo.proto, see:
// https://github.com/gogo/protobuf/blob/master/extensions.md
import "gogoproto/gogo.proto";
import "tendermint/crypto/merkle/merkle.proto";
import "tendermint/libs/kv/types.proto";
import "google/protobuf/timestamp.proto";
import "google/protobuf/duration.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;
	uint64 block_version = 2;
	uint64 p2p_version = 3;
}

// 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 ValidatorUpdate  validators = 4 [(gogoproto.nullable) = false];
	bytes                     app_state_bytes = 5;
}

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

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];
}

enum CheckTxType {
	New = 0;
	Recheck = 1;
}

message RequestCheckTx {
	bytes       tx = 1;
	CheckTxType type = 2;
}

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;
	uint64 app_version = 3;

	int64 last_block_height = 4;
	bytes last_block_app_hash = 5;
}

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

message ResponseInitChain {
	ConsensusParams          consensus_params = 1;
	repeated ValidatorUpdate 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;
	tendermint.crypto.merkle.Proof proof = 8;
	int64                          height = 9;
	string                         codespace = 10;
}

message ResponseBeginBlock {
	repeated Event events = 1
	[(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,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 Event events = 7
	[(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"];
	string codespace = 8;
}

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 Event events = 7
	[(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,omitempty"];
	string codespace = 8;
}

message ResponseEndBlock {
	repeated ValidatorUpdate validator_updates = 1 [(gogoproto.nullable) = false];
	ConsensusParams          consensus_param_updates = 2;
	repeated Event           events = 3
	[(gogoproto.nullable) = false, (gogoproto.jsontag) = "events,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 {
	BlockParams     block = 1;
	EvidenceParams  evidence = 2;
	ValidatorParams validator = 3;
}

// BlockParams contains limits on the block size.
message BlockParams {
	// Note: must be greater than 0
	int64 max_bytes = 1;
	// Note: must be greater or equal to -1
	int64 max_gas = 2;
}

message EvidenceParams {
	// Note: must be greater than 0
	int64                    max_age_num_blocks = 1;
	google.protobuf.Duration max_age_duration = 2
	[(gogoproto.nullable) = false, (gogoproto.stdduration) = true];
}

// ValidatorParams contains limits on validators.
message ValidatorParams {
	repeated string pub_key_types = 1;
}

message LastCommitInfo {
	int32             round = 1;
	repeated VoteInfo votes = 2 [(gogoproto.nullable) = false];
}

message Event {
	string   type = 1;
	repeated tendermint.libs.kv.Pair attributes = 2
	[(gogoproto.nullable) = false, (gogoproto.jsontag) = "attributes,omitempty"];
}

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

message Header {
	// basic block info
	Version                   version = 1 [(gogoproto.nullable) = false];
	string                    chain_id = 2 [(gogoproto.customname) = "ChainID"];
	int64                     height = 3;
	google.protobuf.Timestamp time = 4 [(gogoproto.nullable) = false, (gogoproto.stdtime) = true];

	// prev block info
	BlockID last_block_id = 5 [(gogoproto.nullable) = false];

	// hashes of block data
	bytes last_commit_hash = 6;  // commit from validators from the last block
	bytes data_hash = 7;  // transactions

	// hashes from the app output from the prev block
	bytes validators_hash = 8;   // validators for the current block
	bytes next_validators_hash = 9;   // validators for the next block
	bytes consensus_hash = 10;  // consensus params for current block
	bytes app_hash = 11;  // state after txs from the previous block
	bytes last_results_hash = 12;  // root hash of all results from the txs from the previous block

	// consensus info
	bytes evidence_hash = 13;  // evidence included in the block
	bytes proposer_address = 14;  // original proposer of the block
}

message Version {
	uint64 Block = 1;
	uint64 App = 2;
}

message BlockID {
	bytes         hash = 1;
	PartSetHeader parts_header = 2 [(gogoproto.nullable) = false];
}

message PartSetHeader {
	int32 total = 1;
	bytes hash = 2;
}

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

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

// VoteInfo
message VoteInfo {
	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);
}
