syntax = "proto3";

import "google/protobuf/empty.proto";
import "types/types.proto";

package remote;

option go_package = "./remote;remote";

service ETHBACKEND {
  rpc Etherbase(EtherbaseRequest) returns (EtherbaseReply);

  rpc NetVersion(NetVersionRequest) returns (NetVersionReply);

  rpc NetPeerCount(NetPeerCountRequest) returns (NetPeerCountReply);

  // ------------------------------------------------------------------------
  // Engine API RPC requests natively implemented in the Erigon node backend
  // See https://github.com/ethereum/execution-apis/blob/main/src/engine/specification.md

  // Validate and possibly execute the payload.
  rpc EngineNewPayload(types.ExecutionPayload) returns (EnginePayloadStatus);

  // Update fork choice
  rpc EngineForkChoiceUpdated(EngineForkChoiceUpdatedRequest) returns (EngineForkChoiceUpdatedResponse);

  // Fetch Execution Payload using its ID.
  rpc EngineGetPayload(EngineGetPayloadRequest) returns (EngineGetPayloadResponse);

  rpc EngineGetPayloadBodiesByHashV1(EngineGetPayloadBodiesByHashV1Request) returns (EngineGetPayloadBodiesV1Response);

  rpc EngineGetPayloadBodiesByRangeV1(EngineGetPayloadBodiesByRangeV1Request) returns (EngineGetPayloadBodiesV1Response);

  // Fetch the blobs bundle using its ID.
  rpc EngineGetBlobsBundleV1(EngineGetBlobsBundleRequest) returns (types.BlobsBundleV1);

  // End of Engine API requests
  // ------------------------------------------------------------------------

  // Version returns the service version number
  rpc Version(google.protobuf.Empty) returns (types.VersionReply);

  // ProtocolVersion returns the Ethereum protocol version number (e.g. 66 for ETH66).
  rpc ProtocolVersion(ProtocolVersionRequest) returns (ProtocolVersionReply);

  // ClientVersion returns the Ethereum client version string using node name convention (e.g. TurboGeth/v2021.03.2-alpha/Linux).
  rpc ClientVersion(ClientVersionRequest) returns (ClientVersionReply);

  rpc Subscribe(SubscribeRequest) returns (stream SubscribeReply);

  // Only one subscription is needed to serve all the users, LogsFilterRequest allows to dynamically modifying the subscription
  rpc SubscribeLogs(stream LogsFilterRequest) returns (stream SubscribeLogsReply);

  // High-level method - can read block from db, snapshots or apply any other logic
  // it doesn't provide consistency
  // Request fields are optional - it's ok to request block only by hash or only by number
  rpc Block(BlockRequest) returns (BlockReply);

  // High-level method - can find block number by txn hash
  // it doesn't provide consistency
  rpc TxnLookup(TxnLookupRequest) returns (TxnLookupReply);

  // NodeInfo collects and returns NodeInfo from all running sentry instances.
  rpc NodeInfo(NodesInfoRequest) returns (NodesInfoReply);

  // Peers collects and returns peers information from all running sentry instances.
  rpc Peers(google.protobuf.Empty) returns (PeersReply);

  rpc PendingBlock(google.protobuf.Empty) returns (PendingBlockReply);
}

enum Event {
  HEADER = 0;
  PENDING_LOGS = 1;
  PENDING_BLOCK = 2;
  // NEW_SNAPSHOT - one or many new snapshots (of snapshot sync) were created,
  // client need to close old file descriptors and open new (on new segments),
  // then server can remove old files
  NEW_SNAPSHOT = 3;
}

message EtherbaseRequest {}

message EtherbaseReply { types.H160 address = 1; }

message NetVersionRequest {}

message NetVersionReply { uint64 id = 1; }

message NetPeerCountRequest {}

message NetPeerCountReply { uint64 count = 1; }


message EngineGetPayloadRequest {
  uint64 payloadId = 1;
}

message EngineGetBlobsBundleRequest {
  uint64 payloadId = 1;
}

enum EngineStatus {
  VALID = 0;
  INVALID = 1;
  SYNCING = 2;
  ACCEPTED = 3;
  INVALID_BLOCK_HASH = 4;
}

message EnginePayloadStatus {
  EngineStatus status = 1;
  types.H256 latestValidHash = 2;
  string validationError = 3;
}

message EnginePayloadAttributes {
  uint32 version = 1; // v1 - no withdrawals, v2 - with withdrawals
  uint64 timestamp = 2;
  types.H256 prevRandao = 3;
  types.H160 suggestedFeeRecipient = 4;
  repeated types.Withdrawal withdrawals = 5;
}

message EngineForkChoiceState {
  types.H256 headBlockHash = 1;
  types.H256 safeBlockHash = 2;
  types.H256 finalizedBlockHash = 3;
}

message EngineForkChoiceUpdatedRequest {
  EngineForkChoiceState forkchoiceState = 1;
  EnginePayloadAttributes payloadAttributes = 2;
}

message EngineForkChoiceUpdatedResponse {
  EnginePayloadStatus payloadStatus = 1;
  uint64 payloadId = 2;
}

message EngineGetPayloadResponse {
  types.ExecutionPayload executionPayload = 1;
  types.H256 blockValue = 2;
}

message ProtocolVersionRequest {}

message ProtocolVersionReply { uint64 id = 1; }

message ClientVersionRequest {}

message ClientVersionReply { string nodeName = 1; }

message SubscribeRequest {
  Event type = 1;
}

message SubscribeReply {
  Event type = 1;
  bytes data = 2;  //  serialized data
}

message LogsFilterRequest {
  bool allAddresses = 1;
  repeated types.H160 addresses = 2;
  bool allTopics = 3;
  repeated types.H256 topics = 4;
}

message SubscribeLogsReply {
  types.H160 address = 1;
  types.H256 blockHash = 2;
  uint64 blockNumber = 3;
  bytes data = 4;
  uint64 logIndex = 5;
  repeated types.H256 topics = 6;
  types.H256 transactionHash = 7;
  uint64 transactionIndex = 8;
  bool removed = 9;
}

message BlockRequest {
  uint64 blockHeight = 2;
  types.H256 blockHash = 3;
}

message BlockReply {
  bytes blockRlp = 1;
  bytes senders = 2;
}

message TxnLookupRequest {
  types.H256 txnHash = 1;
}

message TxnLookupReply {
  uint64 blockNumber = 1;
}

message NodesInfoRequest {
  uint32 limit = 1;
}

message NodesInfoReply {
  repeated types.NodeInfoReply nodesInfo = 1;
}

message PeersReply {
  repeated types.PeerInfo peers = 1;
}

message PendingBlockReply {
  bytes blockRlp = 1;
}

message EngineGetPayloadBodiesByHashV1Request {
  repeated types.H256 hashes = 1;
}

message EngineGetPayloadBodiesByRangeV1Request {
  uint64 start = 1;
  uint64 count = 2;
}

message EngineGetPayloadBodiesV1Response {
  repeated types.ExecutionPayloadBodyV1 bodies = 1;
}
