// Keep up to date with latest protobuf definitions.
//
// @see https://github.com/dfuse-io/proto/blob/master/dfuse/bstream/v1/bstream.proto
syntax = "proto3";

package dfuse.bstream.v1;

import "google/protobuf/timestamp.proto";
import "google/protobuf/any.proto";

option go_package = "github.com/dfuse-io/pbgo/dfuse/bstream/v1;pbbstream";

service BlockStream {
  rpc Blocks(BlockRequest) returns (stream Block);
}

service BlockStreamV2 {
  rpc Blocks(BlocksRequestV2) returns (stream BlockResponseV2);
}

// Version 1 request

message BlockRequest {
  // Number of blocks we want to get in burst upon connection, on a best effort basis.
  int64 burst = 1;

  // Type of blocks we're after here, is it 'ethereum' data, 'eos', etc.. The server can fail early
  // if he doesn't match the data he serves (services mismatch, etc..)
  string content_type = 2;

  // Whether we can assume the data will come ordered, unless there is a chain reorganization.
  // mindreaders output ordered data, whereas relayers can output unordered data.
  // The server can fail early if the assumption of the caller cannot be fulfilled.
  enum Order {
    UNSPECIFIED = 0;
    ORDERED = 1;
    UNORDERED = 2;
  }
  Order order = 3;

  string requester = 4;
}

// Version 2 request

message IrreversibleBlocksRequestV2 {
  int64 start_block_num = 1;
}

// For historical segments, forks are not passed
message BlocksRequestV2 {
  // Controls where the stream of blocks will start.
  //
  // The stream will start **inclusively** at the requested block num.
  //
  // When not provided, starts at first streamable block of the chain. Not all
  // chain starts at the same block number, so you might get an higher block than
  // requested when using default value of 0.
  //
  // Can be negative, will be resolved relative to the chain head block, assuming
  // a chain at head block #100, then using `-50` as the value will start at block
  // #50. If it resolves before first streamable block of chain, we assume start
  // of chain.
  //
  // If `start_cursor` is passed, this value is ignored and the stream instead starts
  // immediately after the Block pointed by the opaque `start_cursor` value.
  int64 start_block_num = 1;

  // Controls where the stream of blocks will start which will be immediately after
  // the Block pointed by this opaque cursor.
  //
  // Obtain this value from a previously received BlockResponseV2.cursor.
  //
  // This value takes precedence over `start_block_num`.
  string start_cursor = 13;

  // When non-zero, controls where the stream of blocks will stop.
  //
  // The stream will close **after** that block has passed so the boundary is
  // **inclusive**.
  uint64 stop_block_num = 5;

  // Filter the steps you want to see. If not specified, defaults to all steps.
  //
  // Most common steps will be [STEP_IRREVERSIBLE], or [STEP_NEW, STEP_UNDO, STEP_IRREVERSIBLE].
  repeated ForkStep fork_steps = 8;

  // The CEL filter expression used to include transactions, specific to the target protocol,
  // works in combination with `exclude_filter_expr` value.
  string include_filter_expr = 10;

  // The CEL filter expression used to exclude transactions, specific to the target protocol, works
  // in combination with `include_filter_expr` value.
  string exclude_filter_expr = 11;

  // **Warning** Experimental API, controls how blocks are trimmed for extraneous information before
  // being sent back. The actual trimming is chain dependent.
  BlockDetails details = 15;
}

message BlockResponseV2 {
  // Chain specific block payload, one of:
  //  - dfuse.ethereum.codec.v1.Block
  //  - dfuse.eosio.codec.v1.Block
  google.protobuf.Any block = 1;
  ForkStep step = 6;
  string cursor = 10;
}

enum ForkStep {
  STEP_UNKNOWN = 0;
  STEP_NEW = 1; // The first time we see a block, that is linear with the previous block
  STEP_UNDO = 2; // A block seen previously, that is to be undone
  reserved 3; // was STEP_REDO
  STEP_IRREVERSIBLE = 4;
  reserved 5 ; // was STEP_STALLED
}

enum BlockDetails {
  BLOCK_DETAILS_FULL = 0;
  BLOCK_DETAILS_LIGHT = 1;
}

message Cursor {
  BlockRef block = 1;
  BlockRef head_block = 2;
  BlockRef lib = 3;
  ForkStep step = 4;
}

// General response and structs

message Block {
  uint64 number = 1;
  string id = 2;
  string previous_id = 3;
  google.protobuf.Timestamp timestamp = 4;
  uint64 lib_num = 5;

  Protocol payload_kind = 6;
  int32 payload_version = 7;
  bytes payload_buffer = 8;
}

message BlockRef {
  uint64 num = 1;
  string id = 2;
}

enum Protocol {
  UNKNOWN = 0;
  EOS = 1;
  ETH = 2;
}