Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
284 changes: 186 additions & 98 deletions HIP/hip-1056.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ hip: 1056
title: Block Streams
author: >-
Jasper Potts <@jasperpotts>, Richard Bair <@rbair23>, Nana Essilfie-Conduah <@Nana-EC>,
Mark Blackman <mark@swirldslabs.com>, Edward Wertz<@edward-swirldslabs>
Mark Blackman <mark@swirldslabs.com>, Edward Wertz<@edward-swirldslabs>, Michael Tinker <@tinker-michaelj>
working-group: >-
Jasper Potts <@jasperpotts>, Richard Bair <@rbair23>, Nana Essilfie-Conduah <@Nana-EC>,
Mark Blackman <mark@swirldslabs.com>, Leemon Baird, Joseph Sinclair <@jsync-swirlds>, Nick Poorman <@nickpoorman>,
Expand Down Expand Up @@ -503,16 +503,18 @@ in. Block items removed from a filtered stream are represented by one or more
`FilteredItemHash`’s which provide the missing hashes required to validate the
filtered stream with the same block proof as the full stream.

> The parent-child relationship of some transactions is preserved in the Block
> Streams and will see the appropriate `BlockItem`s for each level. For example,
> a `CryptoTransfer` transaction to a non existing EVM address results in the
> auto creation of a new Account with the said EVM address. In the Block Streams
> the `CryptoTransfer` transaction will be described by its `EventTransaction`,
> `TransactionResult`, `TransactionOutput` and `StateChange` `BlockItem`s. The
> `CryptoCreate` transaction will also be described by its own
> `EventTransaction`, `TransactionResult`, `TransactionOutput and `StateChange`
> `BlockItem`s. In this way a transactions input, output and impacts on the
> network are clearly described.
The parent-child relationship of some transactions is preserved in the Block
Streams and will see the appropriate `BlockItem`s for each level. For example,
a `CryptoTransfer` transaction to a non existing EVM address results in the
auto creation of a new Account with the said EVM address. In the Block Streams
the `CryptoTransfer` transaction will be described by its `EventTransaction`,
`TransactionResult`, and `TransactionOutput` and `BlockItem`s. The `CryptoCreate`
transaction will also be described by its own `EventTransaction`,
`TransactionResult`, and `TransactionOutput and `BlockItem`s. However, because
both logical transactions are in the **same Hiero transactional unit**, only
the parent `CryptoTransfer` will have a `StateChanges` item; and that item will
include all changes for the entire transactional unit. In this way a transactions
input, output and impacts on the network are clearly described.
Comment thread
mgarbs marked this conversation as resolved.

##### Forward Compatibility

Expand Down Expand Up @@ -547,7 +549,6 @@ and a new "BridgeTransform" which is in Trace Data.
* The "ConsensusTransform" is field 20 (20 modulo 10 is 0, so it is a Consensus Header).
* The "BridgeTransform" field is 24 (24 modulo 10 is 4, so it is Trace Data).


#### BlockHeader

A `BlockHeader` is one type of `output` BlockItem and will always be the first element in a Block. It contains Block
Expand Down Expand Up @@ -874,20 +875,22 @@ message TransactionOutput {
```

```protobuf
message ContractCallOutput {
message CallContractOutput {
Comment thread
mgarbs marked this conversation as resolved.
/**
* Result details for an EVM transaction execution
* An EVM transaction result. Contains just the information not already
* externalized in the matching transaction body.
*/
EVMTransactionResult evm_transaction_result = 1;
proto.EvmTransactionResult evm_transaction_result = 1;
}
```

```protobuf
message ContractCreateOutput {
message CreateContractOutput {
/**
* Result details for an EVM transaction execution
* An EVM transaction result. Contains just the information not already
* externalized in the matching transaction body.
*/
EVMTransactionResult evm_transaction_result = 1;
proto.EvmTransactionResult evm_transaction_result = 1;
}
```

Expand All @@ -902,10 +905,21 @@ message CreateAccountOutput {

```protobuf
message EthereumOutput {
/**
* Result details for an EVM transaction execution
*/
EVMTransactionResult evm_transaction_result = 1;
oneof transaction_result {
/**
* An EVM transaction result for an Ethereum transaction executed as a
* call. Contains just the information not already externalized in the
* matching transaction body.
*/
proto.EvmTransactionResult evm_call_transaction_result = 1;

/**
* An EVM transaction result for an Ethereum transaction executed as a
* create. Contains just the information not already externalized in the
* matching transaction body.
*/
proto.EvmTransactionResult evm_create_transaction_result = 2;
}
}
```

Expand Down Expand Up @@ -1790,118 +1804,192 @@ A `TraceData` block item is added to contain all information that could be cosni
The consensus node will export all necessary and important data for a transactions execution in the block streams,
however every byte of information is stored fore er and needed in the proof of the network data. As such it's important
to ensure that data is required but also laid out in a way that makes it easier for filtering by downstream clients.
To this point the `TraceData` would initially contain smart contracts `EVMTraceData` that support traceability information (e.g.
To this point the `TraceData` would initially contain smart contracts `EvmTraceData` that support traceability information (e.g.
contract actions, read values etc). Future trace like data can be added to `TraceData` and Block Nodes, Mirror Nodes and
other block stream parsign clients can decided to store or filter it out based on their needs.
other block stream clients can decided to store or filter it out based on their needs.

```protobuf
message ContractSlotReads {

message SlotRead {
oneof identifier {
/**
* The contract storage slot counter in this block
* This is populated in place of the 256 bit word when the given slot is written to in state changes
*/
int32 index = 1;

/**
* The key of this contratc storage slot, may be left-padded with zeros to form a 256-bit word.
* This is populated when the slot was not written and only read
*/
bytes key = 2;
}

/**
* The storage value in this slot, may be left-padded with zeros to form a 256-bit word.
*/
bytes read_value = 3;
}

/**
* The contract associated with the storage slots this slot belongs to.
*/
ContractID contract_id = 1;

/**
* The storage slots that were read in this EVM exectuion. They may or may not have assocaited slot writes
*/
repeated SlotRead slot_reads = 2;
}

/**
* EVM transaction execution log storage details
* Details maps to the log object in eth_getTransactionReceipt response without repeating info already available in the input transaction
* Log bloom logic is removed as it may be calculated by block parser for both transactions and block level
* EVM trace data, including:
* 1. Initcode used for any internal contract creations.
* 2. Contract actions executed during the transaction (i.e., the call trace)
* 3. Contract slot usages, including reads and writes.
* 4. Events logged during the transaction.
* 5. Full error message, if any, produced by the contract call.
*/
message EVMTransactionLog {
/**
* The contract emitting the log. ContractID vs 20 bye address is used to preserve space
*/
ContractID contract_id = 1;
message EvmTraceData {
/**
* The initcode executed for an internal contract creation.
*/
ExecutedInitcode executed_initcode = 1;
Comment thread
mgarbs marked this conversation as resolved.
Outdated

/**
* The Log data
*/
bytes data = 2;
/**
* All contract actions executed during the transaction.
*/
repeated proto.ContractAction contract_actions = 2;

/**
* The logc topics left padding of 0's by EVM is stripped to save space.
* Indexers should left-pad with zeros to form a 256-bit word.
*/
repeated bytes topics = 3;
/**
* Contract slot usages in the transaction, by contract id.
*/
repeated ContractSlotUsage contract_slot_usages = 3;

/**
* Log events produced during the transaction, by contract id.
*/
repeated EvmTransactionLog logs = 4;

/**
* Additional details of any error message in the EVM transaction result.
* <p>
* This SHALL be unset if the contract call succeeded.
*/
string error_details = 5;
}

/**
* The init bytecode components for child contracts created as part of the contract execution.
* init_bytecode = deploy_bytecode + runtime_byteode + metadata_bytecode
* Usage of a contract's storage slots in an EVM transaction.<br/>
* In the common case that a contract operation is the only EVM
* transaction in its Hiero transactional unit, this message simply
* sets `written_keys_are_non_identical_state_changes` to true;
* meaning a stream consumer should extract the written keys from
* the Hiero unit's SlotKey state changes that match this message's
* `contract_id` (but ignoring any* MapUpdateChange with
* `identical` set to true).
* <p>
* In the less common case that an EVM transaction is one of
* several in its Hiero transactional unit (e.g., because it is
* one of several ContractCalls in an AtomicBatch); this message
* explicitly traces the storage slots that were written during
* its transaction's execution.
*/
message ContractInitByteCode {
message ContractSlotUsage {
/**
* The bytecode that predeces and deploys the runtime bytecode in a contracts deployment
* The contract using the storage slots.
*/
google.protobuf.BytesValue deploy_bytecode = 1;
proto.ContractID contract_id = 1;

oneof written_keys {
/**
* If true, the list of written slot keys is contained in the non-identical
* state changes in the Hiero transactional unit of this EVM transaction.
*/
bool written_keys_are_non_identical_state_changes = 2;
Comment thread
mgarbs marked this conversation as resolved.
Outdated

/**
* When this EVM transaction was one of several within its Hiero
* transactional unit, the storage slots that it wrote.
* <p>
* The written value can be unambiguously derived from the block items
* in this EVM transaction's Hiero transactional unit. In particular,
* 1. If a following EVM trace modifies the same slot, the value written
* in this EVM transaction was whatever value the following trace read.
* 2. If the slot was not modified in a following EVM trace, the value
* is whatever value was committed to the Merkle state for the slot.
*/
WrittenSlotKeys written_slot_keys = 3;
}

/**
* The bytecode that follows the runtime bytecode (found in contract state) in a contracts deployment.
* The storage slots that were read in this EVM execution. They may or
* may not have associated slot writes.
*/
google.protobuf.BytesValue metadata_bytecode = 2;
repeated SlotRead slot_reads = 4;
}

message WrittenSlotKeys {
repeated bytes keys = 1;
}

/**
* A slot read in a contract's storage, as used in an EVM transaction.<br/>
*/
message SlotRead {
oneof identifier {
/**
* If this slot was also written, the index of the written key in the
* ContractSlotUsage#slot_writes list above.
*/
int32 index = 1;

/**
* If this slot was only read, its key represented with minimal bytes
* (no leading zeros); a stream consumer can left-pad this field with
* zeros to form a 32-byte EVM slot key.
*/
bytes key = 2;
}

/**
* The bytecode that defines a deployed contracts logic. Only present if not in state.
* The storage value in this slot, represented with minimal bytes (no
* leading zeros); a stream consumer can left-pad this field with zeros.
* to form a 32-byte EVM slot value.
*/
bytes read_value = 3;
}

/**
* Information about the initcode executed to create a contract.
*/
message ExecutedInitcode {
/**
* The id of the contract created by the initcode.
*/
google.protobuf.BytesValue runtime_bytecode = 3;
proto.ContractID contract_id = 1;

oneof initcode {
/**
* If the runtime bytecode follows the common convention of appearing as a subsequence
* of the initcode, the initcode pieces that surround the runtime bytecode (which is
* necessarily in the Hiero transactional unit's state changes).
*/
InitcodeBookends initcode_bookends = 2;

/**
* If the runtime bytecode is not a subsequence of the initcode, the explicit initcode.
*/
bytes explicit_initcode = 3;
}
}

/**
* EVM tranaction execution trace details
* Details maps to the variable needed for debugging executions
* The initcode bookends of a contract, which are the deploy bytecode and metadata
* bytecode that surround the runtime bytecode in a contract's deployment.
* <p>
* The runtime bytecode is not included here, as it is externalized via a state change
* with the matching contract id in the Hiero transactional unit.
*/
message EVMTraceData {
message InitcodeBookends {
/**
* The init bytecode component for this child contract created as part of the contract execution.
* The bytecode that precedes the runtime bytecode of a contract in initcode.
*/
ContractInitByteCode init_bytecode = 1;
bytes deploy_bytecode = 1;

/**
* The inter contract interaction details. This represents the internal EVM message frames.
* The bytecode that follows the runtime bytecode of a contract in initcode.
*/
repeated ContractAction contract_actions = 2;

bytes metadata_bytecode = 2;
}

/**
* A EVM transaction log; c.f. eth_getTransactionReceipt.<br/>
* Stream consumers may compute bloom values from topics and data if desired.
*/
message EvmTransactionLog {
/**
* Contract slot values that were read during the execution of the EVM transaction. Associated written values will be in state changes
* The contract emitting the log.
*/
repeated ContractSlotReads contract_slot_reads = 3;
proto.ContractID contract_id = 1;

/**
* Any error message produced by the contract call.
* The logged data.
*/
string full_error_message = 4;
bytes data = 2;

/**
* Any Log events produced by this contract call.
* The log's topics represented with minimal bytes (no leading zeros);
* a stream consumer can left-pad with zeros to form a 256-bit words.
*/
repeated EVMTransactionLog logs = 5;
repeated bytes topics = 3;
}
```

Expand Down
Loading