Skip to content

Instantly share code, notes, and snippets.

@protolambda
Last active June 4, 2024 12:18
Show Gist options
  • Save protolambda/23bd106b66f6d4bb854ce46044aa3ca3 to your computer and use it in GitHub Desktop.
Save protolambda/23bd106b66f6d4bb854ce46044aa3ca3 to your computer and use it in GitHub Desktop.
How the blob_versioned_hashes offset is calculated.
class SignedBlobTransaction(Container):
message: BlobTransaction
signature: ECDSASignature
class BlobTransaction(Container):
chain_id: uint256
nonce: uint64
max_priority_fee_per_gas: uint256
max_fee_per_gas: uint256
gas: uint64
to: Union[None, Address] # Address = Bytes20
value: uint256
data: ByteList[MAX_CALLDATA_SIZE]
access_list: List[AccessTuple, MAX_ACCESS_LIST_SIZE]
max_fee_per_data_gas: uint256 # new in PR 5707, a.k.a. fee market change of EIP-4844
blob_versioned_hashes: List[VersionedHash, MAX_VERSIONED_HASHES_LIST_SIZE]
class AccessTuple(Container):
address: Address # Bytes20
storage_keys: List[Hash, MAX_ACCESS_LIST_STORAGE_KEYS]
class ECDSASignature(Container):
y_parity: boolean
r: uint256
s: uint256
path to get blob_versioned_hashes:
message > blob_versioned_hashes
Format in fixed and dynamic ssz sections:
message: 4 bytes - offset to A
signature: 1 + 32 + 32 = 65 bytes
A:
chain_id: 32 bytes
nonce: 8 bytes
priority_fee_per_gas: 32 bytes
max_basefee_per_gas: 32 bytes
gas: 8 bytes
to: 4 bytes - offset to B (relative to A)
value: 32 bytes
data: 4 bytes - offset to C (relative to A)
access_list: 4 bytes - offset to D (relative to A)
max_fee_per_data_gas: 32 bytes
blob_versioned_hashes: 4 bytes - offset to E (relative to A)
B:
to content: 0 or 20 bytes
C:
data content: (dynamic) bytes
D:
acces_list content: (dynamic) bytes
E:
repeated 32 bytes until end of scope
To get to hashes in E directly:
1. we don't really need to read the offset to A, it's always at 4+65 because it's the first offset
2. read offset to E, which is at position A+(fixed data up to offset) == (4+65)+(32+8+32+32+8+4+32+4+32+4) == 4 + 65 + 188 = 257
- parse byte x = input[257:257+4] as a uint32 to get the offset integer
3. iterate from x to end of data, in steps of 32, to get all hashes
@roberto-bayardo
Copy link

roberto-bayardo commented Oct 5, 2022

couple possible errors:
L38: signature should be 65 bytes
L64: 96->65 , and also last 32+4 -> 4+32 to make it match the layout. (Having it swapped confused me for a bit...)

@protolambda
Copy link
Author

@roberto-bayardo
96 -> 65: nice catch, the ECDSASignature is 1+32+32=65. In the consensus specs we use the offset, so the size didn't affect things there.

32+4 -> 4+32

👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment