From 3bc1d368cb63dd946201e20c20a5f0f2acbafb31 Mon Sep 17 00:00:00 2001 From: gajinder Date: Sat, 4 Mar 2023 16:36:35 +0530 Subject: [PATCH 1/7] Update EIP-4844: Decouple blobs --- EIPS/eip-4844.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/EIPS/eip-4844.md b/EIPS/eip-4844.md index 14e0cd64263a0d..bae7fdf575d09e 100644 --- a/EIPS/eip-4844.md +++ b/EIPS/eip-4844.md @@ -54,6 +54,7 @@ Compared to full data sharding, this EIP has a reduced cap on the number of thes | `MAX_ACCESS_LIST_SIZE` | `2**24` | | `MAX_ACCESS_LIST_STORAGE_KEYS` | `2**24` | | `MAX_TX_WRAP_KZG_COMMITMENTS` | `2**12` | +| `MAX_TX_WRAP_KZG_PROOFS` | `2**12` | | `LIMIT_BLOBS_PER_TX` | `2**12` | | `DATA_GAS_PER_BLOB` | `2**17` | | `HASH_OPCODE_BYTE` | `Bytes1(0x49)` | @@ -71,12 +72,12 @@ Compared to full data sharding, this EIP has a reduced cap on the number of thes ### Cryptographic Helpers -Throughout this proposal we use cryptographic methods and classes defined in the corresponding [consensus 4844 specs](https://github.com/ethereum/consensus-specs/blob/23d3aeebba3b5da0df4bd25108461b442199f406/specs/eip4844). +Throughout this proposal we use cryptographic methods and classes defined in the corresponding [consensus 4844 specs](https://github.com/ethereum/consensus-specs/tree/86fb82b221474cc89387fa6436806507b3849d88/specs/deneb). -Specifically, we use the following methods from [`polynomial-commitments.md`](https://github.com/ethereum/consensus-specs/blob/23d3aeebba3b5da0df4bd25108461b442199f406/specs/eip4844/polynomial-commitments.md): +Specifically, we use the following methods from [`polynomial-commitments.md`](https://github.com/ethereum/consensus-specs/blob/86fb82b221474cc89387fa6436806507b3849d88/specs/deneb/polynomial-commitments.md): -- [`verify_kzg_proof()`](https://github.com/ethereum/consensus-specs/blob/23d3aeebba3b5da0df4bd25108461b442199f406/specs/eip4844/polynomial-commitments.md#verify_kzg_proof) -- [`verify_aggregate_kzg_proof()`](https://github.com/ethereum/consensus-specs/blob/23d3aeebba3b5da0df4bd25108461b442199f406/specs/eip4844/polynomial-commitments.md#verify_aggregate_kzg_proof) +- [`verify_kzg_proof()`](https://github.com/ethereum/consensus-specs/blob/86fb82b221474cc89387fa6436806507b3849d88/specs/deneb/polynomial-commitments.md#verify_kzg_proof) +- [`verify_kzg_proof_batch()`](https://github.com/ethereum/consensus-specs/blob/86fb82b221474cc89387fa6436806507b3849d88/specs/deneb/polynomial-commitments.md#verify_kzg_proof_batch) ### Helpers @@ -150,13 +151,13 @@ The `TransactionNetworkPayload` wraps a `TransactionPayload` with additional dat this wrapping data SHOULD be verified directly before or after signature verification. When a blob transaction is passed through the network (see the [Networking](#networking) section below), -the `TransactionNetworkPayload` version of the transaction also includes `blobs` and `kzgs` (commitments list). +the `TransactionNetworkPayload` version of the transaction also includes `blobs`, `kzgs` (commitments list) and `proofs`. The execution layer verifies the wrapper validity against the inner `TransactionPayload` after signature verification as: - `blob_versioned_hashes` must not be empty - All hashes in `blob_versioned_hashes` must start with the byte `BLOB_COMMITMENT_VERSION_KZG` - There may be at most `MAX_DATA_GAS_PER_BLOCK // DATA_GAS_PER_BLOB` total blob commitments in a valid block. -- There is an equal amount of versioned hashes, kzg commitments and blobs. +- There is an equal amount of versioned hashes, kzg commitments, blobs and proofs. - The KZG commitments hash to the versioned hashes, i.e. `kzg_to_versioned_hash(kzg[i]) == versioned_hash[i]` - The KZG commitments match the blob contents. (Note: this can be optimized with additional data, using a proof for a random evaluation at two points derived from the commitment and blob data) @@ -231,7 +232,7 @@ For the first post-fork block, `parent.excess_data_gas` is evaluated as `0`. ### Beacon chain validation On the consensus-layer the blobs are now referenced, but not fully encoded, in the beacon block body. -Instead of embedding the full contents in the body, the contents of the blobs are propagated separately, as a "sidecar". +Instead of embedding the full contents in the body, the blobs are propagated separately, as a "sidecar". This "sidecar" design provides forward compatibility for further data increases by black-boxing `is_data_available()`: with full sharding `is_data_available()` can be replaced by data-availability-sampling (DAS) thus avoiding all blobs being downloaded by all beacon nodes on the network. @@ -345,7 +346,7 @@ class BlobTransactionNetworkWrapper(Container): # BLSFieldElement = uint256 blobs: List[Vector[BLSFieldElement, FIELD_ELEMENTS_PER_BLOB], LIMIT_BLOBS_PER_TX] # KZGProof = Bytes48 - kzg_aggregated_proof: KZGProof + blob_proofs: List[KZGProof, MAX_TX_WRAP_KZG_PROOFS] ``` We do network-level validation of `BlobTransactionNetworkWrapper` objects as follows: @@ -355,12 +356,13 @@ def validate_blob_transaction_wrapper(wrapper: BlobTransactionNetworkWrapper): versioned_hashes = wrapper.tx.message.blob_versioned_hashes commitments = wrapper.blob_kzgs blobs = wrapper.blobs + proofs = wrapper.blob_proofs # note: assert blobs are not malformatted assert len(versioned_hashes) == len(commitments) == len(blobs) assert len(versioned_hashes) > 0 - # Verify that commitments match the blobs by checking the KZG proof - assert verify_aggregate_kzg_proof(blobs, commitments, wrapper.kzg_aggregated_proof) + # Verify that commitments match the blobs by checking the KZG proofs + assert verify_blob_kzg_proof_batch(blobs, commitments, proofs) # Now that all commitments have been verified, check that versioned_hashes matches the commitments for versioned_hash, commitment in zip(versioned_hashes, commitments): From 7d8782516f3a43551aec7d1b878c93c46f3a0683 Mon Sep 17 00:00:00 2001 From: gajinder Date: Wed, 15 Mar 2023 15:24:31 +0530 Subject: [PATCH 2/7] apply feedback --- EIPS/eip-4844.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/EIPS/eip-4844.md b/EIPS/eip-4844.md index bae7fdf575d09e..0b3d96467505cb 100644 --- a/EIPS/eip-4844.md +++ b/EIPS/eip-4844.md @@ -54,7 +54,6 @@ Compared to full data sharding, this EIP has a reduced cap on the number of thes | `MAX_ACCESS_LIST_SIZE` | `2**24` | | `MAX_ACCESS_LIST_STORAGE_KEYS` | `2**24` | | `MAX_TX_WRAP_KZG_COMMITMENTS` | `2**12` | -| `MAX_TX_WRAP_KZG_PROOFS` | `2**12` | | `LIMIT_BLOBS_PER_TX` | `2**12` | | `DATA_GAS_PER_BLOB` | `2**17` | | `HASH_OPCODE_BYTE` | `Bytes1(0x49)` | @@ -72,7 +71,7 @@ Compared to full data sharding, this EIP has a reduced cap on the number of thes ### Cryptographic Helpers -Throughout this proposal we use cryptographic methods and classes defined in the corresponding [consensus 4844 specs](https://github.com/ethereum/consensus-specs/tree/86fb82b221474cc89387fa6436806507b3849d88/specs/deneb). +Throughout this proposal we use cryptographic methods and classes defined in the corresponding [consensus 4844 specs](https://github.com/ethereum/consensus-specs/blob/86fb82b221474cc89387fa6436806507b3849d88/specs/deneb). Specifically, we use the following methods from [`polynomial-commitments.md`](https://github.com/ethereum/consensus-specs/blob/86fb82b221474cc89387fa6436806507b3849d88/specs/deneb/polynomial-commitments.md): @@ -346,7 +345,7 @@ class BlobTransactionNetworkWrapper(Container): # BLSFieldElement = uint256 blobs: List[Vector[BLSFieldElement, FIELD_ELEMENTS_PER_BLOB], LIMIT_BLOBS_PER_TX] # KZGProof = Bytes48 - blob_proofs: List[KZGProof, MAX_TX_WRAP_KZG_PROOFS] + blob_proofs: List[KZGProof, MAX_TX_WRAP_KZG_COMMITMENTS] ``` We do network-level validation of `BlobTransactionNetworkWrapper` objects as follows: From 8841f61f773b3e5e95a4454d105fa99f8547a7b5 Mon Sep 17 00:00:00 2001 From: g11tech Date: Thu, 16 Mar 2023 13:10:58 +0530 Subject: [PATCH 3/7] update the proof function to public one Co-authored-by: dankrad --- EIPS/eip-4844.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-4844.md b/EIPS/eip-4844.md index 0b3d96467505cb..42cc4cf8d2701e 100644 --- a/EIPS/eip-4844.md +++ b/EIPS/eip-4844.md @@ -76,7 +76,7 @@ Throughout this proposal we use cryptographic methods and classes defined in the Specifically, we use the following methods from [`polynomial-commitments.md`](https://github.com/ethereum/consensus-specs/blob/86fb82b221474cc89387fa6436806507b3849d88/specs/deneb/polynomial-commitments.md): - [`verify_kzg_proof()`](https://github.com/ethereum/consensus-specs/blob/86fb82b221474cc89387fa6436806507b3849d88/specs/deneb/polynomial-commitments.md#verify_kzg_proof) -- [`verify_kzg_proof_batch()`](https://github.com/ethereum/consensus-specs/blob/86fb82b221474cc89387fa6436806507b3849d88/specs/deneb/polynomial-commitments.md#verify_kzg_proof_batch) +- [`verify_blob_kzg_proof_batch()`](https://github.com/ethereum/consensus-specs/blob/86fb82b221474cc89387fa6436806507b3849d88/specs/deneb/polynomial-commitments.md#verify_blob_kzg_proof_batch) ### Helpers From 55609d29d4759f32e09fe54a031a6d49ef849f57 Mon Sep 17 00:00:00 2001 From: g11tech Date: Thu, 16 Mar 2023 16:09:42 +0530 Subject: [PATCH 4/7] explicity verify proofs number to match commitment and versioned hashes Co-authored-by: dankrad --- EIPS/eip-4844.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EIPS/eip-4844.md b/EIPS/eip-4844.md index 42cc4cf8d2701e..255b112c5e1f2e 100644 --- a/EIPS/eip-4844.md +++ b/EIPS/eip-4844.md @@ -357,7 +357,7 @@ def validate_blob_transaction_wrapper(wrapper: BlobTransactionNetworkWrapper): blobs = wrapper.blobs proofs = wrapper.blob_proofs # note: assert blobs are not malformatted - assert len(versioned_hashes) == len(commitments) == len(blobs) + assert len(versioned_hashes) == len(commitments) == len(blobs) == len(proofs) assert len(versioned_hashes) > 0 # Verify that commitments match the blobs by checking the KZG proofs From d9517d750940faca8668bddd4f2ba66d62ef557a Mon Sep 17 00:00:00 2001 From: gajinder Date: Wed, 22 Mar 2023 20:27:39 +0530 Subject: [PATCH 5/7] rename blob_proofs to more succinct proofs for network wrapper --- EIPS/eip-4844.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EIPS/eip-4844.md b/EIPS/eip-4844.md index 255b112c5e1f2e..c0f6d2f20e66fa 100644 --- a/EIPS/eip-4844.md +++ b/EIPS/eip-4844.md @@ -345,7 +345,7 @@ class BlobTransactionNetworkWrapper(Container): # BLSFieldElement = uint256 blobs: List[Vector[BLSFieldElement, FIELD_ELEMENTS_PER_BLOB], LIMIT_BLOBS_PER_TX] # KZGProof = Bytes48 - blob_proofs: List[KZGProof, MAX_TX_WRAP_KZG_COMMITMENTS] + proofs: List[KZGProof, MAX_TX_WRAP_KZG_COMMITMENTS] ``` We do network-level validation of `BlobTransactionNetworkWrapper` objects as follows: @@ -355,7 +355,7 @@ def validate_blob_transaction_wrapper(wrapper: BlobTransactionNetworkWrapper): versioned_hashes = wrapper.tx.message.blob_versioned_hashes commitments = wrapper.blob_kzgs blobs = wrapper.blobs - proofs = wrapper.blob_proofs + proofs = wrapper.proofs # note: assert blobs are not malformatted assert len(versioned_hashes) == len(commitments) == len(blobs) == len(proofs) assert len(versioned_hashes) > 0 From 656cb21e5ccd625de046687e0d5d2a3538448d9d Mon Sep 17 00:00:00 2001 From: gajinder Date: Thu, 23 Mar 2023 16:54:56 +0530 Subject: [PATCH 6/7] Replace kzgs references with a more generalized term: commitments --- EIPS/eip-4844.md | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/EIPS/eip-4844.md b/EIPS/eip-4844.md index c0f6d2f20e66fa..bb71b232a8d486 100644 --- a/EIPS/eip-4844.md +++ b/EIPS/eip-4844.md @@ -53,7 +53,7 @@ Compared to full data sharding, this EIP has a reduced cap on the number of thes | `MAX_CALLDATA_SIZE` | `2**24` | | `MAX_ACCESS_LIST_SIZE` | `2**24` | | `MAX_ACCESS_LIST_STORAGE_KEYS` | `2**24` | -| `MAX_TX_WRAP_KZG_COMMITMENTS` | `2**12` | +| `MAX_TX_WRAP_COMMITMENTS` | `2**12` | | `LIMIT_BLOBS_PER_TX` | `2**12` | | `DATA_GAS_PER_BLOB` | `2**17` | | `HASH_OPCODE_BYTE` | `Bytes1(0x49)` | @@ -81,8 +81,8 @@ Specifically, we use the following methods from [`polynomial-commitments.md`](ht ### Helpers ```python -def kzg_to_versioned_hash(kzg: KZGCommitment) -> VersionedHash: - return BLOB_COMMITMENT_VERSION_KZG + sha256(kzg)[1:] +def kzg_to_versioned_hash(commitment: KZGCommitment) -> VersionedHash: + return BLOB_COMMITMENT_VERSION_KZG + sha256(commitment)[1:] ``` Approximates `factor * e ** (numerator / denominator)` using Taylor expansion: @@ -150,15 +150,15 @@ The `TransactionNetworkPayload` wraps a `TransactionPayload` with additional dat this wrapping data SHOULD be verified directly before or after signature verification. When a blob transaction is passed through the network (see the [Networking](#networking) section below), -the `TransactionNetworkPayload` version of the transaction also includes `blobs`, `kzgs` (commitments list) and `proofs`. +the `TransactionNetworkPayload` version of the transaction also includes `blobs`, `commitments` and `proofs`. The execution layer verifies the wrapper validity against the inner `TransactionPayload` after signature verification as: - `blob_versioned_hashes` must not be empty - All hashes in `blob_versioned_hashes` must start with the byte `BLOB_COMMITMENT_VERSION_KZG` - There may be at most `MAX_DATA_GAS_PER_BLOCK // DATA_GAS_PER_BLOB` total blob commitments in a valid block. -- There is an equal amount of versioned hashes, kzg commitments, blobs and proofs. -- The KZG commitments hash to the versioned hashes, i.e. `kzg_to_versioned_hash(kzg[i]) == versioned_hash[i]` -- The KZG commitments match the blob contents. (Note: this can be optimized with additional data, using a proof for a +- There is an equal amount of versioned hashes, commitments, blobs and proofs. +- The commitments hash to the versioned hashes, i.e. `kzg_to_versioned_hash(commitment[i]) == versioned_hash[i]` +- The commitments match the blob contents. (Note: this can be optimized with additional data, using a proof for a random evaluation at two points derived from the commitment and blob data) @@ -270,13 +270,13 @@ def point_evaluation_precompile(input: Bytes) -> Bytes: z = input[32:64] y = input[64:96] commitment = input[96:144] - kzg_proof = input[144:192] + proof = input[144:192] # Verify commitment matches versioned_hash assert kzg_to_versioned_hash(commitment) == versioned_hash # Verify KZG proof - assert verify_kzg_proof(commitment, z, y, kzg_proof) + assert verify_kzg_proof(commitment, z, y, proof) # Return FIELD_ELEMENTS_PER_BLOB and BLS_MODULUS as padded 32 byte big endian values return Bytes(U256(FIELD_ELEMENTS_PER_BLOB).to_be_bytes32() + U256(BLS_MODULUS).to_be_bytes32()) @@ -341,11 +341,11 @@ the payload is a SSZ encoded container: class BlobTransactionNetworkWrapper(Container): tx: SignedBlobTransaction # KZGCommitment = Bytes48 - blob_kzgs: List[KZGCommitment, MAX_TX_WRAP_KZG_COMMITMENTS] + commitments: List[KZGCommitment, MAX_TX_WRAP_COMMITMENTS] # BLSFieldElement = uint256 blobs: List[Vector[BLSFieldElement, FIELD_ELEMENTS_PER_BLOB], LIMIT_BLOBS_PER_TX] # KZGProof = Bytes48 - proofs: List[KZGProof, MAX_TX_WRAP_KZG_COMMITMENTS] + proofs: List[KZGProof, MAX_TX_WRAP_COMMITMENTS] ``` We do network-level validation of `BlobTransactionNetworkWrapper` objects as follows: @@ -353,7 +353,7 @@ We do network-level validation of `BlobTransactionNetworkWrapper` objects as fol ```python def validate_blob_transaction_wrapper(wrapper: BlobTransactionNetworkWrapper): versioned_hashes = wrapper.tx.message.blob_versioned_hashes - commitments = wrapper.blob_kzgs + commitments = wrapper.commitments blobs = wrapper.blobs proofs = wrapper.proofs # note: assert blobs are not malformatted @@ -400,7 +400,7 @@ The work that is already done in this EIP includes: The work that remains to be done to get to full sharding includes: -- A low-degree extension of the `blob_kzgs` in the consensus layer to allow 2D sampling +- A low-degree extension of the `commitments` in the consensus layer to allow 2D sampling - An actual implementation of data availability sampling - PBS (proposer/builder separation), to avoid requiring individual validators to process 32 MB of data in one slot - Proof of custody or similar in-protocol requirement for each validator to verify a particular part of the sharded data in each block @@ -423,13 +423,13 @@ For each value it would provide a KZG proof and use the point evaluation precomp and then perform the fraud proof verification on that data as is done today. ZK rollups would provide two commitments to their transaction or state delta data: -the kzg in the blob and some commitment using whatever proof system the ZK rollup uses internally. -They would use a commitment proof of equivalence protocol, using the point evaluation precompile, -to prove that the kzg (which the protocol ensures points to available data) and the ZK rollup's own commitment refer to the same data. +the blob commitment (which the protocol ensures points to available data) and the ZK rollup's own commitment using whatever proof system the rollup uses internally. +They would use a proof of equivalence protocol, using the point evaluation precompile, +to prove that the two commitments refer to the same data. ### Versioned hashes & precompile return data -We use versioned hashes (rather than kzgs) as references to blobs in the execution layer to ensure forward compatibility with future changes. +We use versioned hashes (rather than commitments) as references to blobs in the execution layer to ensure forward compatibility with future changes. For example, if we need to switch to Merkle trees + STARKs for quantum-safety reasons, then we would add a new version, allowing the point evaluation precompile to work with the new format. Rollups would not have to make any EVM-level changes to how they work; From 0132e81422d43c412921e7a8d839d0912407a4aa Mon Sep 17 00:00:00 2001 From: gajinder Date: Tue, 18 Apr 2023 15:06:12 +0530 Subject: [PATCH 7/7] removing redundant blob prefix from versioned hashes in BlobTransaction container --- EIPS/eip-4844.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/EIPS/eip-4844.md b/EIPS/eip-4844.md index bb71b232a8d486..54c5f641789514 100644 --- a/EIPS/eip-4844.md +++ b/EIPS/eip-4844.md @@ -121,7 +121,7 @@ class BlobTransaction(Container): data: ByteList[MAX_CALLDATA_SIZE] access_list: List[AccessTuple, MAX_ACCESS_LIST_SIZE] max_fee_per_data_gas: uint256 - blob_versioned_hashes: List[VersionedHash, MAX_VERSIONED_HASHES_LIST_SIZE] + versioned_hashes: List[VersionedHash, MAX_VERSIONED_HASHES_LIST_SIZE] class AccessTuple(Container): address: Address # Bytes20 @@ -153,8 +153,8 @@ When a blob transaction is passed through the network (see the [Networking](#net the `TransactionNetworkPayload` version of the transaction also includes `blobs`, `commitments` and `proofs`. The execution layer verifies the wrapper validity against the inner `TransactionPayload` after signature verification as: -- `blob_versioned_hashes` must not be empty -- All hashes in `blob_versioned_hashes` must start with the byte `BLOB_COMMITMENT_VERSION_KZG` +- `versioned_hashes` must not be empty +- All hashes in `versioned_hashes` must start with the byte `BLOB_COMMITMENT_VERSION_KZG` - There may be at most `MAX_DATA_GAS_PER_BLOCK // DATA_GAS_PER_BLOB` total blob commitments in a valid block. - There is an equal amount of versioned hashes, commitments, blobs and proofs. - The commitments hash to the versioned hashes, i.e. `kzg_to_versioned_hash(commitment[i]) == versioned_hash[i]` @@ -182,7 +182,7 @@ def signed_tx_hash(tx: SignedBlobTransaction) -> Bytes32: return keccak256(BLOB_TX_TYPE + ssz.serialize(tx)) ``` -Blob transactions with empty `blob_versioned_hashes` are also considered invalid during execution block verification, and must not be included in a valid block. +Blob transactions with empty `versioned_hashes` are also considered invalid during execution block verification, and must not be included in a valid block. ### Header extension @@ -247,8 +247,8 @@ The `ethereum/consensus-specs` repository defines the following beacon-node chan ### Opcode to get versioned hashes We add an opcode `DATAHASH` (with byte value `HASH_OPCODE_BYTE`) which reads `index` from the top of the stack -as big-endian `uint256`, and replaces it on the stack with `tx.message.blob_versioned_hashes[index]` -if `index < len(tx.message.blob_versioned_hashes)`, and otherwise with a zeroed `bytes32` value. +as big-endian `uint256`, and replaces it on the stack with `tx.message.versioned_hashes[index]` +if `index < len(tx.message.versioned_hashes)`, and otherwise with a zeroed `bytes32` value. The opcode has a gas cost of `HASH_OPCODE_GAS`. ### Point evaluation precompile @@ -294,7 +294,7 @@ def calc_data_fee(tx: SignedBlobTransaction, parent: Header) -> int: return get_total_data_gas(tx) * get_data_gasprice(parent) def get_total_data_gas(tx: SignedBlobTransaction) -> int: - return DATA_GAS_PER_BLOB * len(tx.message.blob_versioned_hashes) + return DATA_GAS_PER_BLOB * len(tx.message.versioned_hashes) def get_data_gasprice(header: Header) -> int: return fake_exponential( @@ -320,7 +320,7 @@ def validate_block(block: Block) -> None: # ensure that the user was willing to at least pay the current data gasprice assert tx.message.max_fee_per_data_gas >= get_data_gasprice(parent(block).header) - num_blobs += len(tx.message.blob_versioned_hashes) + num_blobs += len(tx.message.versioned_hashes) # check that the excess data gas is correct expected_edg = calc_excess_data_gas(parent(block).header, num_blobs) @@ -352,7 +352,7 @@ We do network-level validation of `BlobTransactionNetworkWrapper` objects as fol ```python def validate_blob_transaction_wrapper(wrapper: BlobTransactionNetworkWrapper): - versioned_hashes = wrapper.tx.message.blob_versioned_hashes + versioned_hashes = wrapper.tx.message.versioned_hashes commitments = wrapper.commitments blobs = wrapper.blobs proofs = wrapper.proofs