All Downloads are FREE. Search and download functionalities are using the official Maven repository.

stream.output.state_changes.proto Maven / Gradle / Ivy

There is a newer version: 0.54.0
Show newest version
/**
 * # State Changes
 * Serialization of change records which describe the mutation of state
 * during a block.
 *
 * The _ordered_ application of all `StateChanges` in a block to an initial
 * state that matches network state at the beginning of that block MUST produce
 * a resultant state that matches the network state at the end of that block.
 *
 * ### Keywords
 * The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT",
 * "SHOULD", "SHOULD NOT", "RECOMMENDED", "MAY", and "OPTIONAL" in this
 * document are to be interpreted as described in
 * [RFC2119](https://www.ietf.org/rfc/rfc2119) and clarified in
 * [RFC8174](https://www.ietf.org/rfc/rfc8174).
 */
syntax = "proto3";

package com.hedera.hapi.block.stream.output;

/*
 * Copyright (C) 2024 Hedera Hashgraph, LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

option java_package = "com.hedera.hapi.block.stream.output.protoc";
// <<>> This comment is special code for setting PBJ Compiler java package
option java_multiple_files = true;

import "google/protobuf/wrappers.proto";
import "basic_types.proto";
import "exchange_rate.proto";
import "state/addressbook/node.proto";
import "state/blockrecords/block_info.proto";
import "state/blockrecords/running_hashes.proto";
import "state/blockstream/block_stream_info.proto";
import "state/congestion/congestion_level_starts.proto";
import "state/consensus/topic.proto";
import "state/contract/bytecode.proto";
import "state/contract/storage_slot.proto";
import "state/file/file.proto";
import "state/recordcache/recordcache.proto";
import "state/roster/roster.proto";
import "state/roster/roster_state.proto";
import "state/schedule/schedule.proto";
import "state/throttles/throttle_usage_snapshots.proto";
import "state/token/account.proto";
import "state/token/account_pending_airdrop.proto";
import "state/token/network_staking_rewards.proto";
import "state/token/nft.proto";
import "state/token/staking_node_info.proto";
import "state/token/token.proto";
import "state/token/token_relation.proto";
import "state/platform_state.proto";
import "timestamp.proto";

/**
 * A set of state changes.
 *
 * Each set of changes in the network deterministically mutates the
 * current state to a new state, and all nodes MUST apply the same
 * changes in the same order.
* Each change set described in the block stream SHALL describe an * ordered set of mutations which mutate the previous valid state to * produce a new valid state.
* The order of state change sets SHALL be determined by the * `consensus_timestamp`, which is a strictly ascending value * determined by network consensus. * * ### Consensus Timestamp * This value enables a consumer of the block stream to order state * changes by a consistent ascending value that is determined by network * consensus. A primary use case would be to enter state changes in a * time-series database.
* This value depends on the cause of the state change. * 1. For transactions, this is the transaction consensus timestamp. * 1. For events without transactions, this is the consensus timestamp of * the event (round?). * 1. For changes that are not the result of a transaction, but still follow * a transaction within an event, this is the consensus timestamp of the * preceding transaction. */ message StateChanges { /** * The consensus timestamp of this set of changes. *

* This value SHALL be deterministic with the cause of the state change. */ proto.Timestamp consensus_timestamp = 1; /** * An ordered list of individual changes. *

* These changes MUST be applied in the order listed to produce * a correct modified state. */ repeated StateChange state_changes = 2; } /** * A change to any item in the merkle tree. * * A State change SHALL represent one mutation of the network state merkle * tree. The state changes published in the block stream MAY be combined * into an ordered set of state mutations that transform the tree from any * initial state to a destination state.
* When the full set of state change items from the block stream for a round * is applied to the network state at the start of that round the result * SHALL match the network state at the end of the round. * TODO: Need documentation for how the merkle tree is constructed. * Need to reference that document, stored in platform docs?, here. */ message StateChange { /** * A state identifier.
* The reason we use an integer field here, and not an enum field is to * better support forward compatibility. There will be many cases when a * block node or other client (such as a dApp) with HAPI version N wants * to process blocks from HAPI version N+1, for example. If we use a * protobuf enum then when that is mapped Java or Rust it would not be * parsed as an enum value because those languages do not support unknown * enum values. ProtoC has a workaround for this but it is complex and * requires non-deterministic parsing. Our solution to create an integer * field and provide an enumeration for mapping that integer is intended * as an acceptable compromise solution. *

* This number SHALL identify the merkle subtree "state" to be modified and * often corresponds to a `VirtualMap` identifier. * This number SHALL be a valid value for the `StateIdentifier` enum. */ uint32 state_id = 1; oneof change_operation { /** * Addition of a new state.
* This may be a singleton, virtual map, or queue state. */ NewStateChange state_add = 2; /** * Removal of an existing state.
* The entire singleton, virtual map, or queue state is removed, * and not just the contents. */ RemovedStateChange state_remove = 3; /** * An add or update to a `Singleton` state. */ SingletonUpdateChange singleton_update = 4; /** * An add or update to a single item in a `VirtualMap`. */ MapUpdateChange map_update = 5; /** * A removal of a single item from a `VirtualMap`. */ MapDeleteChange map_delete = 6; /** * Addition of an item to a `Queue` state. */ QueuePushChange queue_push = 7; /** * Removal of an item from a `Queue` state. */ QueuePopChange queue_pop = 8; } } /** * An informational enumeration of all known states. * This enumeration is included here So that people know the mapping from * integer to state "name". * * State changes are expressed in terms of changes to named states at the * high level conceptual model of the state type like map key/values or * queue appends. To say which state the change is on we will include an * `integer` number for the state name. This is done for performance and * efficiency as there will be 10s of thousands of state changes in a block. * * We use an integer, and provide this enumeration, for the following reasons. * - If we have a extra 8-10 bytes per state change at 40-50K state changes * per second then that is an extra 2.5-4 megabits of bandwidth. Compression * should help a lot but that is not guaranteed. * - When the state name is used as part of complex key in the big state * merkle map. The smaller the key is, in bytes, the more efficient the * database is, because more keys can fit in a single disk page. * - When parsing keys, parsing a UTF-8 string to a Java String is a many * times more expensive than parsing a VARINT to an integer. * * Note: This enumeration is never transmitted directly in the block stream. * This enumeration is provided for clients to _interpret_ the value * of the `StateChange`.`state_id` field. */ enum StateIdentifier { /** * A state identifier for the Topics state. */ STATE_ID_TOPICS = 0; /** * A state identifier for the next entity Identifier. */ STATE_ID_ENTITY_ID = 1; /** * A state identifier for the Accounts state. */ STATE_ID_ACCOUNTS = 2; /** * A state identifier for account aliases. */ STATE_ID_ALIASES = 3; /** * A state identifier for contract storage slots. */ STATE_ID_CONTRACT_STORAGE = 4; /** * A state identifier for contract bytecode. */ STATE_ID_CONTRACT_BYTECODE = 5; /** * A state identifier for Hedera File Service (HFS). */ STATE_ID_FILES = 6; /** * A state identifier for Hedera Token Service (HTS). */ STATE_ID_TOKENS = 7; /** * A state identifier for non-fungible/unique tokens. */ STATE_ID_NFTS = 8; /** * A state identifier for token relationships. */ STATE_ID_TOKEN_RELATIONS = 9; /** * A state identifier for network staking information. */ STATE_ID_STAKING_INFO = 10; /** * A state identifier for network staking rewards. */ STATE_ID_NETWORK_REWARDS = 11; /** * A state identifier for throttle usage. */ STATE_ID_THROTTLE_USAGE = 12; /** * A state identifier for network congestion start times. */ STATE_ID_CONGESTION_STARTS = 13; /** * A state identifier for scheduled transactions. */ STATE_ID_SCHEDULES_BY_ID = 14; /** * A state identifier for scheduled transaction expiration. */ STATE_ID_SCHEDULES_BY_EXPIRY = 15; /** * A state identifier for scheduled transaction deduplication. */ STATE_ID_SCHEDULES_BY_EQUALITY = 16; /** * A state identifier for conversion rate updates. */ STATE_ID_MIDNIGHT_RATES = 17; /** * A state identifier for the network running hash(es). */ STATE_ID_RUNNING_HASHES = 18; /** * A state identifier for network block information. */ STATE_ID_BLOCK_INFO = 19; /** * A state identifier for address book nodes. */ STATE_ID_NODES = 20; /** * A state identifier for the next "upgrade" file. */ STATE_ID_UPGRADE_FILE = 21; /** * A state identifier for the hash of the next "upgrade" file. */ STATE_ID_UPGRADE_FILE_HASH = 22; /** * A state identifier for the next network freeze time. */ STATE_ID_FREEZE_TIME = 23; /** * A state identifier for the block stream status singleton. */ STATE_ID_BLOCK_STREAM_INFO = 24; /** * A state identifier for pending airdrops. */ STATE_ID_PENDING_AIRDROPS = 25; /** * A state identifier for the platform state singleton. */ STATE_ID_PLATFORM_STATE = 26; /** * A state identifier for the roster state singleton. */ STATE_ID_ROSTER_STATE = 27; /** * A state identifier for the rosters key/value map. */ STATE_ID_ROSTERS = 28; /** * A state identifier for the round receipts queue. */ STATE_ID_TRANSACTION_RECEIPTS_QUEUE = 126; /** * A state for the `150` upgrade file data */ STATE_ID_UPGRADE_DATA_150 = 10001; /** * A state for the `151` upgrade file data */ STATE_ID_UPGRADE_DATA_151 = 10002; /** * A state for the `152` upgrade file data */ STATE_ID_UPGRADE_DATA_152 = 10003; /** * A state for the `153` upgrade file data */ STATE_ID_UPGRADE_DATA_153 = 10004; /** * A state for the `154` upgrade file data */ STATE_ID_UPGRADE_DATA_154 = 10005; /** * A state for the `155` upgrade file data */ STATE_ID_UPGRADE_DATA_155 = 10006; /** * A state for the `156` upgrade file data */ STATE_ID_UPGRADE_DATA_156 = 10007; /** * A state for the `157` upgrade file data */ STATE_ID_UPGRADE_DATA_157 = 10008; /** * A state for the `158` upgrade file data */ STATE_ID_UPGRADE_DATA_158 = 10009; /** * A state for the `159` upgrade file data */ STATE_ID_UPGRADE_DATA_159 = 10010; } /** * An addition of a new named state. * * Adding a new named state SHALL only require the name and type.
* The content of the new state SHALL be filled in via subsequent * state change items specific to the type of state * (e.g. SingletonUpdateChange or MapUpdateChange). */ message NewStateChange { /** * The type (e.g. Singleton, Virtual Map, Queue) of state to add. */ NewStateType state_type = 1; } /** * An enumeration of the types of named states.
* The default, Singleton, is the type of state most frequently * added and removed. */ enum NewStateType { SINGLETON = 0; VIRTUAL_MAP = 1; QUEUE = 2; } /** * A removal of a named state. * * Removing a named state does not, currently, require additional * information beyond the state name common to all state changes.
* A named state, other than a singleton, SHOULD be empty before it is removed. */ message RemovedStateChange { } /** * An update to a `Singleton` state. */ message SingletonUpdateChange { oneof new_value { /** * A change to the block info singleton. *

* The `BlockInfo` SHALL be updated at the end of every block and * SHALL store, among other fields, the last 256 block hash values. *

REVIEW NOTE
* The full BlockInfo will be in the state proof, and may not be * necessary here.
*/ proto.BlockInfo block_info_value = 1; /** * A change to the congestion level starts singleton. *

* This change SHALL be present if congestion level pricing for * general fees or gas fees started during the current block. */ proto.CongestionLevelStarts congestion_level_starts_value = 2; /** * A change to the Entity Identifier singleton. *

* The Entity Identifier singleton SHALL track the highest entity * identifier used for the current shard and realm and SHALL be used * to issue new entity numbers. */ google.protobuf.UInt64Value entity_number_value = 3; /** * A change to the exchange rates singleton. *

* This change SHALL be present if the HBAR<=>USD exchange * rate, as stored in the "midnight rates" singleton changed * during the current block. */ proto.ExchangeRateSet exchange_rate_set_value = 4; /** * A change to the network staking rewards singleton. *

* Network staking rewards SHALL be updated for every non-empty block. */ proto.NetworkStakingRewards network_staking_rewards_value = 5; /** * A change to a raw byte array singleton. *

* This change SHALL present a change made to a raw byte array * singleton.
* The "upgrade file hash" state is an example of a raw byte * array singleton. */ google.protobuf.BytesValue bytes_value = 6; /** * A change to a raw string singleton. *

*

Note
There are no current examples of a raw string * singleton state.
*/ google.protobuf.StringValue string_value = 7; /** * A change to the running hashes singleton. *

* Running hashes SHALL be updated for each transaction. *

*

REVIEW NOTE
* Running hashes is a record stream item. Can it be elided from * the block stream? It's not written to the record stream, as far * as I can tell. If we do write this it's adding over 144 bytes * for every transaction. It's also not clear how we'll calculate * this, as it's a hash of the records currently, so it would have * to be a hash of the block items, including this one... *
*/ proto.RunningHashes running_hashes_value = 8; /** * A change to the throttle usage snapshots singleton. *

* Throttle usage snapshots SHALL be updated for _every transaction_ * to reflect the amount used for each tps throttle and * for the gas throttle. */ proto.ThrottleUsageSnapshots throttle_usage_snapshots_value = 9; /** * A change to a raw `Timestamp` singleton.
* An example of a raw `Timestamp` singleton is the * "network freeze time" singleton state, which, if set, stores * the time for the next scheduled freeze. */ proto.Timestamp timestamp_value = 10; /** * A change to the block stream status singleton. *

* This MUST be updated at the beginning of a block, with the * information for the immediately prior block. */ com.hedera.hapi.node.state.blockstream.BlockStreamInfo block_stream_info_value = 11; /** * A change to the platform state singleton. */ com.hedera.hapi.platform.state.PlatformState platform_state_value = 12; /** * A change to the roster state singleton. */ com.hedera.hapi.node.state.roster.RosterState roster_state_value = 13; } } /** * An update to a single item in a `VirtualMap`.
* Each update consists of a "key" and a "value". * Keys are often identifiers or scalar values. * Values are generally full messages or byte arrays. * * The key presented here is not mutable, we do not update map keys.
* The value associated to the key provided is updated, or the value is * added and associated with that key.
* A change of key would be expressed as removal of the prior key and * an addition for the new key. */ message MapUpdateChange { /** * A key in a virtual map. *

* This key MUST be mapped to the value added or updated.
* This field is REQUIRED. */ MapChangeKey key = 1; /** * A value in a virtual map. *

* This value MUST correctly represent the state of the map entry * _after_ the asserted update.
* This value MAY be reduced to only transmit fields that differ * from the prior state.
* This field is REQUIRED. */ MapChangeValue value = 2; } /** * A removal of a single item from a `VirtualMap`. */ message MapDeleteChange { /** * A key in a virtual map. *

* This key SHALL be removed.
* The mapped value SHALL also be removed.
* This field is REQUIRED. */ MapChangeKey key = 1; } /** * A key identifying a specific entry in a key-value "virtual map". */ message MapChangeKey { oneof key_choice { /** * A key for a change affecting a map keyed by an Account identifier. */ proto.AccountID account_id_key = 1; /** * A change to the token relationships virtual map.
* This map is keyed by the pair of account identifier and * token identifier. */ proto.TokenAssociation token_relationship_key = 2; /** * A change to a map keyed by an EntityNumber (which is a whole number). *

* This SHOULD NOT be used. Virtual maps SHOULD be keyed to * full identifiers that include shard and realm information. */ google.protobuf.UInt64Value entity_number_key = 3; /** * A change to a virtual map keyed by File identifier. */ proto.FileID file_id_key = 4; /** * A change to a virtual map keyed by NFT identifier. */ proto.NftID nft_id_key = 5; /** * A change to a virtual map keyed by a byte array. */ google.protobuf.BytesValue proto_bytes_key = 6; /** * A change to a virtual map keyed by an int64 value. */ google.protobuf.Int64Value proto_long_key = 7; /** * A change to a virtual map keyed by a string value. */ google.protobuf.StringValue proto_string_key = 8; /** * A change to a virtual map keyed by a Schedule identifier. */ proto.ScheduleID schedule_id_key = 9; /** * A change to the EVM storage "slot" virtual map. */ proto.SlotKey slot_key_key = 10; /** * A change to a virtual map keyed by a Token identifier. */ proto.TokenID token_id_key = 11; /** * A change to a virtual map keyed by a Topic identifier. */ proto.TopicID topic_id_key = 12; /** * A change to a virtual map keyed by contract id identifier. */ proto.ContractID contract_id_key = 13; /** * A change to a virtual map keyed by pending airdrop id identifier. */ proto.PendingAirdropId pending_airdrop_id_key = 14; } } /** * A value updated in, or added to, a virtual map. * */ message MapChangeValue { oneof value_choice { /** * An account value. */ proto.Account account_value = 1; /** * An account identifier.
* In some cases a map is used to connect a value or identifier * to another identifier. */ proto.AccountID account_id_value = 2; /** * Compiled EVM bytecode. */ proto.Bytecode bytecode_value = 3; /** * An Hedera "file" value. *

*

REVIEW NOTE
* A file can become quite large (up to 1048576 bytes).
* Do we want to structure file changes separately?
* Perhaps a file metadata update and a separate byte array for * just the bytes appended (or initial bytes on create). We only * allow create/append/delete, so the separate byte array would work * and keep the size below 6K per state change. *
*/ proto.File file_value = 4; /** * A non-fungible/unique token value. */ proto.Nft nft_value = 5; /** * A string value. */ google.protobuf.StringValue proto_string_value = 6; /** * A scheduled transaction value. */ proto.Schedule schedule_value = 7; /** * A list of scheduled transactions.
* An example for this value is the map of consensus second to * scheduled transactions that expire at that consensus time. */ proto.ScheduleList schedule_list_value = 8; /** * An EVM storage slot value. */ proto.SlotValue slot_value_value = 9; /** * An updated set of staking information for all nodes in * the address book. */ proto.StakingNodeInfo staking_node_info_value = 10; /** * An HTS token value. */ proto.Token token_value = 11; /** * A token relationship value.
* These values track which accounts are willing to transact * in specific HTS tokens. */ proto.TokenRelation token_relation_value = 12; /** * An HCS topic value. */ proto.Topic topic_value = 13; /** * An network node value. */ com.hedera.hapi.node.state.addressbook.Node node_value = 14; /** * A pending airdrop value. */ proto.AccountPendingAirdrop account_pending_airdrop_value = 15; /** * A roster value. */ com.hedera.hapi.node.state.roster.Roster roster_value = 16; } } /** * Addition of an item to a `Queue` state.
* * The new item SHALL be added after the current "last" element in the * queue.
* The new item MUST be the same type of value as all other items in the queue. */ message QueuePushChange { oneof value { /** * A byte array added to the queue state. */ google.protobuf.BytesValue proto_bytes_element = 1; /** * A string added to the queue state. */ google.protobuf.StringValue proto_string_element = 2; /** * All transaction receipts for a round added to queue state. */ proto.TransactionReceiptEntries transaction_receipt_entries_element = 3; } } /** * Removal of an item from a `Queue` state.
* * The item removed SHALL be the current "front" (or "head") of the queue.
* Removing from a queue "head" does not, currently, require additional * information beyond the state name common to all state changes. */ message QueuePopChange { }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy