syntax = "proto3";

package sf.antelope.type.v1;

option go_package = "github.com/streamingfast/firehose-antelope/types/pb/sf/antelope/type/v1;pbantelope";

import "google/protobuf/timestamp.proto";

message ActionTraces {
  repeated ActionTrace action_traces = 1;
}

message TransactionTraces {
  repeated TransactionTrace transaction_traces = 1;
}

message DBOps {
  repeated DBOp db_ops = 1;
}

message Block {
  string id = 1;
  uint32 number = 2;
  uint32 version = 3;

  BlockHeader header = 4;
  string producer_signature = 5;
  repeated Extension block_extensions = 7;
  uint32 dpos_proposed_irreversible_blocknum = 8;
  uint32 dpos_irreversible_blocknum = 9;
  BlockRootMerkle blockroot_merkle = 11;
  repeated ProducerToLastProduced producer_to_last_produced = 12;
  repeated ProducerToLastImpliedIRB producer_to_last_implied_irb = 13;
  repeated uint32 confirm_count = 15;
  PendingProducerSchedule pending_schedule = 16;
  ActivatedProtocolFeatures activated_protocol_features = 17;

  // EOS 2.1.x feature, did not make it into leap
  // bool validated = 18;
  reserved 18;

  repeated RlimitOp rlimit_ops = 19;

  // The unfiltered transactions in this block when NO filtering has been applied,
  // (i.e. `filtering_applied = false`). When filtering has been applied on this block,
  // (i.e. `filtering_applied = true`), this field will be set to `nil` and instead, the
  // `filtered_transactions` will be populated with only filtered transactions.
  //
  // Use the helper getter method `Transactions()` to automatically pick the correct
  // field to use (`unfiltered_transactions` when `filtering_applied == false` and
  // `filtered_transactions` when `filtering_applied == true`).
  repeated TransactionReceipt unfiltered_transactions = 6;

  // The filtered transactions in this block when filtering has been applied,
  // (i.e. `filtering_applied = true`). This will be only the transactions
  // that matched the include filter CEL expression and did NOT match the exclude
  // filter CEL expression.
  //
  // Use the helper getter method `Transactions()` to automatically the correct
  // field (`unfiltered_transaction` when `filtering_applied == false` and
  // `filtered_transactions` when `filtering_applied == true`).
  repeated TransactionReceipt filtered_transactions = 47;

  // Number of transaction executed within this block when no filtering
  // is applied (`filtering_applied == false`).
  uint32 unfiltered_transaction_count = 22;

  // Number of transaction that were successfully executed within this block that are found in
  // the `filtered_transactions` array. This field is populated only when the flag
  // `filtering_applied` is `true`.
  uint32 filtered_transaction_count = 48;

  // The unfiltered implicit transaction ops in this block when NO filtering has been applied,
  // (i.e. `filtering_applied = false`). When filtering has been applied on this block,
  // (i.e. `filtering_applied = true`), this field will be set to `nil` and instead, the
  // `filtered_implicit_transaction_ops` will be populated with only filtered implicit
  // transaction ops.
  //
  // Use the helper getter method `ImplicitTransactionOps()` to automatically pick the correct
  // field to use (`unfiltered_implicit_transaction_ops` when `filtering_applied == false` and
  // `filtered_implicit_transaction_ops` when `filtering_applied == true`).
  repeated TrxOp unfiltered_implicit_transaction_ops = 20;

  // The filtered implicit transaction ops in this block when filtering has been applied,
  // (i.e. `filtering_applied = true`). This will be only the implicit transaction ops
  // that matched the include filter CEL expression and did NOT match the exclude
  // filter CEL expression.
  //
  // Use the helper getter method `ImplicitTransactionOps()` to automatically the correct
  // field (`unfiltered_implicit_transaction_ops` when `filtering_applied == false` and
  // `filtered_implicit_transaction_ops` when `filtering_applied == true`).
  repeated TrxOp filtered_implicit_transaction_ops = 49;

  // The unfiltered transaction traces in this block when NO filtering has been applied,
  // (i.e. `filtering_applied = false`). When filtering has been applied on this block,
  // (i.e. `filtering_applied = true`), this field will be set to `nil` and instead, the
  // `filtered_transaction_traces` will be populated with only filtered transactions.
  //
  // Use the helper getter method `TransactionTraces()` to automatically pick the correct
  // field to use (`unfiltered_transaction_traces` when `filtering_applied == false` and
  // `filtered_transaction_traces` when `filtering_applied == true`).
  repeated TransactionTrace unfiltered_transaction_traces = 21;

  // The filtered transaction traces in this block when filtering has been applied,
  // (i.e. `filtering_applied = true`). This will be only the transaction trace
  // that matched the include filter CEL expression and did NOT match the exclude
  // filter CEL expression.
  //
  // Use the helper getter method `TransactionTraces()` to automatically pick the correct
  // field to use (`unfiltered_transaction_traces` when `filtering_applied == false` and
  // `filtered_transaction_traces` when `filtering_applied == true`).
  repeated TransactionTrace filtered_transaction_traces = 46;

  // Number of transaction trace executed within this block when no filtering
  // is applied (`filtering_applied == false`).
  uint32 unfiltered_transaction_trace_count = 23;

  // Number of transaction trace that were successfully executed within this block that are found in
  // the `filtered_transaction_traces` array. This field is populated only when the flag
  // `filtering_applied` is `true`.
  uint32 filtered_transaction_trace_count = 43;

  // Number of top-level actions that were successfully executed within this block when no filtering
  // is applied (`filtering_applied == false`).
  uint32 unfiltered_executed_input_action_count = 24;

  // Number of top-level actions that were successfully executed within this block that are found in
  // the `filtered_transaction_traces` array. This field is populated only when the flag
  // `filtering_applied` is `true`.
  uint32 filtered_executed_input_action_count = 44;

  // Number of actions that were successfully executed within this block when no filtering
  // is applied (`filtering_applied == false`).
  uint32 unfiltered_executed_total_action_count = 25;

  // Number of actions that were successfully executed within this block that are found in
  // the `filtered_transaction_traces` array. This field is populated only when the flag
  // `filtering_applied` is `true`.
  uint32 filtered_executed_total_action_count = 45;

  // Reserved 26 to 29

  /// EOSIO 1.x only

  // This was a single string element representing a public key (eos-go#ecc.PublicKey).
  // It has been replaced by `valid_block_signing_authority_v2`.
  string block_signing_key = 14;

  // This was a list of `{name, publicKey}` elements, each block being signed by a single key,
  // the schedule was simply a list of pair, each pair being the producer name and it's public key
  // used to sign the block.
  ProducerSchedule active_schedule_v1 = 10;

  /// EOSIO 2.0.x only

  // This replaces `block_signing_key` with a richer structure
  // able to handle the weighted threshold multisig for block producers.
  //
  // This can be downgraded to the old `block_signing_key` simply by taking
  // the first key present in the list. This is of course simple and not
  // accurate anymore in EOSIO 2.0 system where `WTMSIG_BLOCK_SIGNATURES`
  // has been activated AND block producers starts signing blocks with
  // more than one key.
  //
  // See BlockSigningAuthority for further details
  BlockSigningAuthority valid_block_signing_authority_v2 = 30;

  // This repleaces the old type `ProducerSchedule` for the `active_schedule`
  // field. This was only a type change in EOSIO 2.0, the field's name remained
  // the same.
  //
  // This is the new schedule data layout which is richer than it's oldest
  // counterpart. The inner element for a producer can then be composed with
  // multiple keys, each with their own weight and the threshold required to
  // accept the block signature.
  ProducerAuthoritySchedule active_schedule_v2 = 31;

  // Wheter or not a filtering process was run on this block. The filtering process sets to nil
  // the `unfiltered_transaction_traces` to `nil` and populate the `filtered_transaction_traces`
  // according to the `filtering_include_filter_expr` and `filtering_exclude_filter_expr` CEL
  // expressions. A transaction will be present in the `filtered_transaction_traces` array if
  // it matched the `filtering_include_filter_expr` and did *NOT* match the `filtering_exclude_filter_expr`.
  //
  // Moreover, each matching action that brought the transaction to be in `filtered_transaction_traces`
  // array will have a `filtering_matched` flag set on it to broadcast the fact that this action
  // match the inclusion/exclusion list.
  //
  // This flag controls all `filtered_*` and `unfiltered_*` elements on the Block structure and on
  // substructures if present.
  bool filtering_applied = 40;

  // The CEL filter expression used to include transaction in `filtered_transaction_traces` array, works
  // in combination with `filtering_exclude_filter_expr` value.
  string filtering_include_filter_expr = 41;

  // The CEL filter expression used to exclude transaction in `filtered_transaction_traces` array, works
  // in combination with `filtering_include_filter_expr` value.
  string filtering_exclude_filter_expr = 42;

  // The CEL filter expression used to include system actions, required by some systems, works
  // in combination with the two other filters above.
  string filtering_system_actions_include_filter_expr = 50;
}

// BlockWithRefs is a lightweight block, with traces and transactions
// purged from the `block` within, and only.  It is used in transports
// to pass block data around.
message BlockWithRefs {
  string id = 1;
  Block block = 2;
  TransactionRefs implicit_transaction_refs = 3;  // TODO: Triple check that that's the right thing
  TransactionRefs transaction_refs = 4;
  TransactionRefs transaction_trace_refs = 5;

  bool irreversible = 6;
}

message TransactionRefs {repeated bytes hashes = 1;}

message ActivatedProtocolFeatures {repeated bytes protocol_features = 1;}

message PendingProducerSchedule {
  uint32 schedule_lib_num = 1;
  bytes schedule_hash = 2;

  /// EOSIO 1.x only

  // See Block#active_schedule_v1 for further details, this is the same change
  // as the active schedule, but applied to the pending field.
  ProducerSchedule schedule_v1 = 3;

  /// EOSIO 2.0.x only

  // See Block#active_schedule_v2 for further details, this is the same change
  // as the active schedule, but applied to the pending field.
  ProducerAuthoritySchedule schedule_v2 = 4;
}

// Present in EOSIO 1.x only
message ProducerSchedule {
  uint32 version = 1;
  repeated ProducerKey producers = 2;
}

// Present in EOSIO 1.x only
message ProducerKey {
  string account_name = 1;
  string block_signing_key = 2;
}

// Present in EOSIO 2.x only
//
// This is the new schedule data layout which is richer than it's oldest
// counterpart. The inner element for a producer can then be composed with
// multiple keys, each with their own weight and the threshold required to
// accept the block signature.
message ProducerAuthoritySchedule {
  uint32 version = 1;
  repeated ProducerAuthority producers = 2;
}

// Present in EOSIO 2.x only
message ProducerAuthority {
  string account_name = 1;
  BlockSigningAuthority block_signing_authority = 2;
}

// Present in EOSIO 2.x only
//
// This represents the signatures that were used to signed the block. Previously,
// in EOSIO 1.x, this was a simple public key since only one key could sign a block.
// In EOSIO 2.x, when `WTMSIG_BLOCK_SIGNATURES` feature is active, the block can be
// signed with a set of different public keys, each with its own weight as well as
// the threshold at which point the signatures are accepted.
//
// This is actually implemented as a `fc::variant` type in the C++ code, this tainted
// our own implementation where multiple types can be represented using a `oneof`.
//
// Know current types (and version they were introduced):
// - `BlockSigningAuthorityV0` [Type 0] (EOSIO 2.0)
//
message BlockSigningAuthority {
  oneof variant {BlockSigningAuthorityV0 v0 = 1;}
}

// Present in EOSIO 2.x only
message BlockSigningAuthorityV0 {
  uint32 threshold = 1;
  repeated KeyWeight keys = 2;
}

message BlockRootMerkle {
  uint32 node_count = 1;
  repeated bytes active_nodes = 2;
}

message ProducerToLastProduced {
  string name = 1;
  uint32 last_block_num_produced = 2;
}
message ProducerToLastImpliedIRB {
  string name = 1;
  uint32 last_block_num_produced = 2;
}

message TransactionReceipt {
  string id = 4;
  uint64 index = 6; // within the SignedBlock

  TransactionStatus status = 1;
  uint32 cpu_usage_micro_seconds = 2;
  uint32 net_usage_words = 3;

  PackedTransaction packed_transaction = 5; // present if not deferred
}

message PackedTransaction {
  repeated string signatures = 1;
  uint32 compression = 2;
  bytes packed_context_free_data = 3;
  bytes packed_transaction = 4;
}

message BlockHeader {
  google.protobuf.Timestamp timestamp = 3;
  string producer = 4;
  uint32 confirmed = 5; // uint16
  string previous = 6;
  bytes transaction_mroot = 7;
  bytes action_mroot = 8;
  uint32 schedule_version = 9;
  repeated Extension header_extensions = 11;

  // EOSIO 1.x only
  //
  // A change to producer schedule was reported as a `NewProducers` field on the
  // `BlockHeader` in EOSIO 1.x. In EOSIO 2.x, when feature `WTMSIG_BLOCK_SIGNATURES`
  // is activated, the `NewProducers` field is not present anymore and the schedule change
  // is reported through a `BlockHeaderExtension` on the the `BlockHeader` struct.
  //
  // If you need to access the old value, you can
  ProducerSchedule new_producers_v1 = 10;
}

enum BlockReversibility {
  BLOCKREVERSIBILITY_NONE = 0; // there is no block
  BLOCKREVERSIBILITY_REVERSIBLE = 1;
  BLOCKREVERSIBILITY_IRREVERSIBLE = 2;
  BLOCKREVERSIBILITY_STALE = 3;
  BLOCKREVERSIBILITY_MAYBESTALE = 4; // behind lib, but we have not confirmed irreversibility
}

// TransactionEvent are elements that contribute to a view of the
// whole transaction lifecycle. They can be extracted from block logs,
// or from storage, and merged together to form an up-to-date
// TransactionLifecycle.
message TransactionEvent {
  string id = 1;
  string block_id = 2;
  uint32 block_num = 3;
  bool irreversible = 4;

  oneof event {
    AddedInternally internal_addition = 5;
    Added addition = 6;
    Executed execution = 7;
    DtrxScheduled dtrx_scheduling = 8;
    DtrxCanceled dtrx_cancellation = 9;
  }

  // This is an implicit transaction, like `onblock` and `onerror` that is extracted
  // separately from the block itself.
  // TODO: does it have a receipt? It probably has
  message AddedInternally {
    SignedTransaction transaction = 1;
  }
  // This is the transaction that is added into a block, in the list of transactions there.
  message Added {
    TransactionReceipt receipt = 1;
    SignedTransaction transaction = 2;
    PublicKeys public_keys = 3;
  }
  // Executed contributes the traces of executions
  message Executed {
    TransactionTrace trace = 1;
    BlockHeader blockHeader = 2;
  }
  message DtrxScheduled {
    ExtDTrxOp created_by = 1;
    SignedTransaction transaction = 2;
  }
  message DtrxCanceled {
    ExtDTrxOp canceled_by = 1;
  }
}

message PublicKeys {
  repeated string public_keys = 1;
}

message TransactionLifecycle {
  string id = 1;

  TransactionStatus transaction_status = 2;

  TransactionReceipt transaction_receipt = 36; // FIXME: this is currently missing from our data
  SignedTransaction transaction = 10;
  repeated string public_keys = 19;

  TransactionTrace execution_trace = 11;
  BlockHeader execution_block_header = 12;

  // We have TransactionReceipt` missing here

  reserved 13 to 18; // previously dtrx_ops, creation_tree, db_ops, ram_ops, table_ops, feature_ops but were all duplicates of what's already in the TransactionTrace of `execution_trace`

  ExtDTrxOp created_by = 20;
  ExtDTrxOp canceled_by = 21;

  reserved 22 to 32;

  // BlockState creation_block_state = 30;
  // BlockState execution_block_state = 31;
  // BlockState cancelation_block_state = 32;

  bool creation_irreversible = 33;
  bool execution_irreversible = 34;
  bool cancelation_irreversible = 35;
}

enum TransactionStatus {
  TRANSACTIONSTATUS_NONE = 0;
  TRANSACTIONSTATUS_EXECUTED = 1;
  TRANSACTIONSTATUS_SOFTFAIL = 2;
  TRANSACTIONSTATUS_HARDFAIL = 3;
  TRANSACTIONSTATUS_DELAYED = 4;
  TRANSACTIONSTATUS_EXPIRED = 5;
  TRANSACTIONSTATUS_UNKNOWN = 6;
  TRANSACTIONSTATUS_CANCELED = 7;
}

message SignedTransaction {
  Transaction transaction = 1;
  repeated string signatures = 2;
  repeated bytes context_free_data = 3;
}

message Transaction {
  TransactionHeader header = 1;
  repeated Action context_free_actions = 2;
  repeated Action actions = 3;
  repeated Extension extensions = 4;
}

message TransactionHeader {
  google.protobuf.Timestamp expiration = 1;
  uint32 ref_block_num = 2;
  uint32 ref_block_prefix = 3;
  uint32 max_net_usage_words = 4;
  uint32 max_cpu_usage_ms = 5;
  uint32 delay_sec = 6;
}

message TransactionTrace {

  // SHA-256 (FIPS 180-4) of the FCBUFFER-encoded packed transaction
  string id = 1;

  // Reference to the block number in which this transaction was executed.
  uint64 block_num = 2;

  // Index within block's unfiltered execution traces
  uint64 index = 26;

  // Reference to the block time this transaction was executed in
  google.protobuf.Timestamp block_time = 3;

  // Reference to the block ID this transaction was executed in
  string producer_block_id = 4;

  // Receipt of execution of this transaction
  TransactionReceiptHeader receipt = 5;

  int64 elapsed = 6;

  uint64 net_usage = 7;

  // Whether this transaction was taken from a scheduled transactions pool for
  // execution (delayed)
  bool scheduled = 8;

  // Traces of each action within the transaction, including all notified and
  // nested actions.
  repeated ActionTrace action_traces = 9;

  // Trace of a failed deferred transaction, if any.
  TransactionTrace failed_dtrx_trace = 10;

  // Exception leading to the failed dtrx trace.
  Exception exception = 15;

  uint64 error_code = 16;

  // List of database operations this transaction entailed
  repeated DBOp db_ops = 17;

  // List of KV operations this transaction entailed
  //
  // This was added in EOSIO 2.1.x but did not make it into the leap code
  // repeated KVOp kv_ops = 30;
  reserved 30;

  // List of deferred transactions operations this transaction entailed
  repeated DTrxOp dtrx_ops = 18;

  // List of feature switching operations (changes to feature switches in
  // nodeos) this transaction entailed
  repeated FeatureOp feature_ops = 19;

  // List of permission changes operations
  repeated PermOp perm_ops = 20;

  // List of RAM consumption/redemption
  repeated RAMOp ram_ops = 21;

  // List of RAM correction operations (happens only once upon feature
  // activation)
  repeated RAMCorrectionOp ram_correction_ops = 22;

  // List of changes to rate limiting values
  repeated RlimitOp rlimit_ops = 23;

  // List of table creations/deletions
  repeated TableOp table_ops = 24;

  // Tree of creation, rather than execution
  repeated CreationFlatNode creation_tree = 25;
}

message TransactionReceiptHeader {
  TransactionStatus status = 1;
  uint32 cpu_usage_micro_seconds = 2;
  uint32 net_usage_words = 3;
}

message Action {
  string account = 1;
  string name = 2;
  repeated PermissionLevel authorization = 3;
  string json_data = 4;
  bytes raw_data = 5;
}

message ActionTrace {
  string receiver = 11;
  ActionReceipt receipt = 1;
  Action action = 2;
  bool context_free = 3;
  int64 elapsed = 4;
  string console = 5;
  string transaction_id = 6;
  uint64 block_num = 7;
  string producer_block_id = 8;
  google.protobuf.Timestamp block_time = 9;
  repeated AccountRAMDelta account_ram_deltas = 10;

  // AccountDiskDeltas has been added in EOSIO 2.1.x for DISK resource (which is not part of the release oddly)
  // this has not (yet) made it into leap
  // repeated AccountDelta account_disk_deltas = 40;
  reserved 40;

  // ReturnValue has been added in EOSIO 2.1.x as something that can be returned from the execution
  // of an action.
  //
  // See https://github.com/EOSIO/eos/pull/8327
  bytes raw_return_value = 41;
  string json_return_value = 42;

  Exception exception = 15;
  uint64 error_code = 20; // https://github.com/EOSIO/eos/pull/7108
  uint32 action_ordinal = 16;
  uint32 creator_action_ordinal = 17;
  uint32 closest_unnotified_ancestor_action_ordinal = 18;
  uint32 execution_index = 19;

  // Whether this action trace was a successful match, present only when filtering was applied on block. This
  // will be `true` if the Block `filtering_applied` is `true`, if the include CEL filter matched and
  // if the exclude CEL filter did NOT match.
  bool filtering_matched = 30;

  // Whether this action trace was a successful system match, present only when filtering was applied on block.
  // This will be `true` if the Block `filtering_applied` is `true`, if the system actions include CEL filter
  // matched, supersedes any exclude CEL filter.
  bool filtering_matched_system_action_filter = 31;
}

message ActionReceipt {
  string receiver = 1;
  string digest = 2;
  uint64 global_sequence = 3;
  repeated AuthSequence auth_sequence = 4;
  uint64 recv_sequence = 5;
  uint64 code_sequence = 6;
  uint64 abi_sequence = 7;
}

message AuthSequence {
  string account_name = 1;
  uint64 sequence = 2;
}

message AccountRAMDelta {
  string account = 1;
  int64 delta = 2;
}

message AccountDelta {
  string account = 1;
  int64 delta = 2;
}

message Extension {
  uint32 type = 1;
  bytes data = 2;
}

// FIXME: this is really just an output of the implicit transactions, isn't it? We don't have
// other operations here.. do we?  What's the `name` anyway?
message TrxOp {
  Operation operation = 1;
  string name = 2;
  string transaction_id = 3;
  SignedTransaction transaction = 4;

  enum Operation {
    OPERATION_UNKNOWN = 0;
    OPERATION_CREATE = 1;
  }
}

message DBOp {
  Operation operation = 1;
  uint32 action_index = 2;
  string code = 3;
  string scope = 4;
  string table_name = 5;
  string primary_key = 6;
  string old_payer = 7;
  string new_payer = 8;
  bytes old_data = 9;
  bytes new_data = 10;

  enum Operation {
    OPERATION_UNKNOWN = 0;
    OPERATION_INSERT = 1;
    OPERATION_UPDATE = 2;
    OPERATION_REMOVE = 3;
  }
}

message RAMOp {
  // Operation is the legacy operation tag that we used initially. This is replaced
  // by a combination of `Namespce` and `Action`.
  //
  // Deprecated: Use `Namespace` and `Action` instead to determine what the RAM operation represents
  Operation operation = 1;
  uint32 action_index = 2;
  string payer = 3;
  int64 delta = 4;
  uint64 usage = 5;

  // Namespace representing the category the RAM operation belong to, like
  // account, table_row, table, etc.
  //
  // This coupled with `action` replaces the `operation` field.
  Namespace namespace = 6;

  // Namespace representing the action the RAM operation did, like
  // add, delete or remove an object.
  //
  // This coupled with `action` replaces the `operation` field.
  Action action = 7;

  // UniqueKey gives a unique key to the operation, this unique key is opaque,
  // does not necessarly represents anything and should uniquely represents the
  // RAM Operation within a given timeframe of block (a key should never overlap
  // any other keys (per namespace), on any blocks span).
  string unique_key = 8;

  enum Operation {
    OPERATION_UNKNOWN = 0;
    OPERATION_CREATE_TABLE = 1;
    OPERATION_DEFERRED_TRX_ADD = 2;
    OPERATION_DEFERRED_TRX_CANCEL = 3;
    OPERATION_DEFERRED_TRX_PUSHED = 4;
    OPERATION_DEFERRED_TRX_RAM_CORRECTION = 5;
    OPERATION_DEFERRED_TRX_REMOVED = 6;
    OPERATION_DELETEAUTH = 7;
    OPERATION_LINKAUTH = 8;
    OPERATION_NEWACCOUNT = 9;
    OPERATION_PRIMARY_INDEX_ADD = 10;
    OPERATION_PRIMARY_INDEX_REMOVE = 11;
    OPERATION_PRIMARY_INDEX_UPDATE = 12;
    OPERATION_PRIMARY_INDEX_UPDATE_ADD_NEW_PAYER = 13;
    OPERATION_PRIMARY_INDEX_UPDATE_REMOVE_OLD_PAYER = 14;
    OPERATION_REMOVE_TABLE = 15;
    OPERATION_SECONDARY_INDEX_ADD = 16;
    OPERATION_SECONDARY_INDEX_REMOVE = 17;
    OPERATION_SECONDARY_INDEX_UPDATE_ADD_NEW_PAYER = 18;
    OPERATION_SECONDARY_INDEX_UPDATE_REMOVE_OLD_PAYER = 19;
    OPERATION_SETABI = 20;
    OPERATION_SETCODE = 21;
    OPERATION_UNLINKAUTH = 22;
    OPERATION_UPDATEAUTH_CREATE = 23;
    OPERATION_UPDATEAUTH_UPDATE = 24;

    // For newer RAM Ops that are registered by Deep Mind, their `Operation` value will be
    // Deprecated until we remove the operation completely. Use instead the `Namespace`
    // and `Action` fields to take a decision about what the RAM operation is doing.
    OPERATION_DEPRECATED = 25;
  }

  enum Namespace {
    NAMESPACE_UNKNOWN = 0;
    NAMESPACE_ABI = 1;
    NAMESPACE_ACCOUNT = 2;
    NAMESPACE_AUTH = 3;
    NAMESPACE_AUTH_LINK = 4;
    NAMESPACE_CODE = 5;
    NAMESPACE_DEFERRED_TRX = 6;
    NAMESPACE_SECONDARY_INDEX = 7;
    NAMESPACE_TABLE = 8;
    NAMESPACE_TABLE_ROW = 9;

    // Added in EOSIO 2.1.x, removed in leap
    // NAMESPACE_KV = 10;
    reserved 10;
  }

  enum Action {
    ACTION_UNKNOWN = 0;
    ACTION_ADD = 1;
    ACTION_CANCEL = 2;
    ACTION_CORRECTION = 3;
    ACTION_PUSH = 4;
    ACTION_REMOVE = 5;
    ACTION_UPDATE = 6;
  }
}
message RAMCorrectionOp {
  string correction_id = 1;
  string unique_key = 2;
  string payer = 3;
  int64 delta = 4;
}

message TableOp {
  Operation operation = 1;
  uint32 action_index = 2;
  string payer = 3;
  string code = 4;
  string scope = 5;
  string table_name = 6;

  enum Operation {
    OPERATION_UNKNOWN = 0;
    OPERATION_INSERT = 1;
    OPERATION_REMOVE = 2;
  }
}

message DTrxOp {
  Operation operation = 1;
  uint32 action_index = 2;
  string sender = 3;
  string sender_id = 4;
  string payer = 5;
  string published_at = 6;
  string delay_until = 7;
  string expiration_at = 8;
  string transaction_id = 9;
  SignedTransaction transaction = 10;

  enum Operation {
    OPERATION_UNKNOWN = 0;
    OPERATION_CREATE = 1;
    OPERATION_PUSH_CREATE = 2;
    OPERATION_FAILED = 3;
    OPERATION_CANCEL = 4;
    OPERATION_MODIFY_CANCEL = 5;
    OPERATION_MODIFY_CREATE = 6;
  }
}

message ExtDTrxOp {
  string source_transaction_id = 1;
  uint64 block_num = 2;
  string block_id = 3;
  google.protobuf.Timestamp block_time = 4;

  DTrxOp dtrx_op = 5;
}

message FeatureOp {
  string kind = 1;
  uint32 action_index = 2;
  string feature_digest = 3;
  Feature feature = 4;

  enum Kind {
    KIND_UNKNOWN = 0;
    KIND_PRE_ACTIVATE = 1;
    KIND_ACTIVATE = 2;
  }
}

message CreationFlatNode {
  int32 creator_action_index = 1;
  uint32 execution_action_index = 2;
}

message PermOp {
  Operation operation = 1;
  uint32 action_index = 2;
  PermissionObject old_perm = 8;
  PermissionObject new_perm = 9;

  enum Operation {
    OPERATION_UNKNOWN = 0;
    OPERATION_INSERT = 1;
    OPERATION_UPDATE = 2;
    OPERATION_REMOVE = 3;
  }
}

message PermissionObject {
  // Id represents the EOSIO internal id of this permission object.
  uint64 id = 10;

  // ParentId represents the EOSIO internal id of the parent's of this permission object.
  uint64 parent_id = 11;

  // Owner is the account for which this permission was set
  string owner = 1;

  // Name is the permission's name this permission object is known as.
  string name = 2;
  google.protobuf.Timestamp last_updated = 3;
  Authority authority = 4;
}

message Permission {
  string name = 1;
  string parent = 2;
  Authority required_auth = 3;
}

message Authority {
  uint32 threshold = 1;
  repeated KeyWeight keys = 2;
  repeated PermissionLevelWeight accounts = 3;
  repeated WaitWeight waits = 4;
}

message KeyWeight {
  string public_key = 1;
  uint32 weight = 2;
}

message PermissionLevel {
  string actor = 1;
  string permission = 2;
}

message PermissionLevelWeight {
  PermissionLevel permission = 1;
  uint32 weight = 2;
}

message WaitWeight {
  uint32 wait_sec = 1;
  uint32 weight = 2;
}

message RlimitOp {
  Operation operation = 1;

  oneof kind {
    RlimitState state = 2;
    RlimitConfig config = 3;
    RlimitAccountLimits account_limits = 4;
    RlimitAccountUsage account_usage = 5;
  }

  enum Operation {
    OPERATION_UNKNOWN = 0;
    OPERATION_INSERT = 1;
    OPERATION_UPDATE = 2;
  }
}

message RlimitState {
  UsageAccumulator average_block_net_usage = 1;
  UsageAccumulator average_block_cpu_usage = 2;
  uint64 pending_net_usage = 3;
  uint64 pending_cpu_usage = 4;
  uint64 total_net_weight = 5;
  uint64 total_cpu_weight = 6;
  uint64 total_ram_bytes = 7;
  uint64 virtual_net_limit = 8;
  uint64 virtual_cpu_limit = 9;
}

message RlimitConfig {
  ElasticLimitParameters cpu_limit_parameters = 1;
  ElasticLimitParameters net_limit_parameters = 2;
  uint32 account_cpu_usage_average_window = 3;
  uint32 account_net_usage_average_window = 4;
}

message RlimitAccountLimits {
  string owner = 1;
  bool pending = 2;
  int64 net_weight = 3;
  int64 cpu_weight = 4;
  int64 ram_bytes = 5;
}

message RlimitAccountUsage {
  string owner = 1;
  UsageAccumulator net_usage = 2;
  UsageAccumulator cpu_usage = 3;
  uint64 ram_usage = 4;
}

message UsageAccumulator {
  uint32 last_ordinal = 1;
  uint64 value_ex = 2;
  uint64 consumed = 3;
}

message ElasticLimitParameters {
  uint64 target = 1;
  uint64 max = 2;
  uint32 periods = 3;
  uint32 max_multiplier = 4;
  Ratio contract_rate = 5;
  Ratio expand_rate = 6;
}

message Ratio {
  uint64 numerator = 1;
  uint64 denominator = 2;
}

message Exception {
  int32 code = 1;
  string name = 2;
  string message = 3;
  repeated LogMessage stack = 4;

  message LogMessage {
    LogContext context = 1;
    string format = 2;

    // This is actually a Pair<string, any> in C++ which get serialized usually
    // as a JSON object. However, it seems some string sequences could be
    // invalid UTF-8 characters. As such, we decided to use a bytes array. Can
    // be interpreted as a UTF-8 string containing JSON, just be ready to
    // handle UTF-8 errors if they arise.
    bytes data = 4;
  }

  message LogContext {
    string level = 1;
    string file = 2;
    int32 line = 3;
    string method = 4;
    string hostname = 5;
    string thread_name = 6;
    google.protobuf.Timestamp timestamp = 7;
    LogContext context = 8;
  }
}

message Feature {
  string feature_digest = 1;
  SubjectiveRestrictions subjective_restrictions = 2;
  string description_digest = 3;
  repeated string dependencies = 4;
  string protocol_feature_type = 5;
  repeated Specification specification = 6;
}

message SubjectiveRestrictions {
  bool enabled = 1;
  bool preactivation_required = 2;
  string earliest_allowed_activation_time = 3;
}

message Specification {
  string name = 1;
  string value = 2;
}

// AccountCreation represents the time and place where an account was created on an EOSIO chain. The block referenced is expected to be irreversible.
message AccountCreationRef {
  // Account being created
  string account = 1;
  // Account that created the `account`
  string creator = 2;
  // At which block number this happened
  uint64 block_num = 3;
  // At which block ID this happened
  string block_id = 4;
  google.protobuf.Timestamp block_time = 5;
  string transaction_id = 6;
}
