Skip to content

Commit 37eadc1

Browse files
authored
Pimp up 4844 tx type section by adding lots of EIP-7594 related stuff (#4190)
1 parent 622fccb commit 37eadc1

File tree

2 files changed

+121
-36
lines changed

2 files changed

+121
-36
lines changed

packages/tx/README.md

Lines changed: 62 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -183,18 +183,25 @@ console.log(bytesToHex(tx.hash())) // 0x9150cdebad74e88b038e6c6b964d99af705f9c08
183183
For generating access lists from tx data based on a certain network state there is a `reportAccessList` option
184184
on the `VM.runTx()` method of the `@ethereumjs/vm` `TypeScript` VM implementation.
185185

186-
### Blob Transactions (EIP-4844)
186+
### Blob Transactions (EIP-4844 / EIP-7594)
187187

188188
- Class: `BlobEIP4844Tx`
189-
- EIP: [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844)
190-
- Activation: `cancun`
189+
- EIPs: [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844), [EIP-7594](https://eips.ethereum.org/EIPS/eip-7594)
190+
- Activation: `cancun` (EIP-4844), `osaka` (EIP-7594)
191191
- Type: `3`
192192

193+
#### Introduction
194+
193195
This library supports the blob transaction type introduced with [EIP-4844](https://eips.ethereum.org/EIPS/eip-4844).
196+
Additionally it is able to process blobs in the "PeerDAS way" - introduced with [EIP-7594](https://eips.ethereum.org/EIPS/eip-7594) along the
197+
`osaka` hardfork and generate cell proofs instead of blob proofs.
194198

195199
**Note:** This functionality needs a manual KZG library installation and global initialization, see [KZG Setup](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/tx/README.md#kzg-setup) for instructions.
196200

197-
See the following code snippet for an example on how to instantiate:
201+
#### Example
202+
203+
See the following code snippet for an example on how to create a blob transaction, one for EIP-4844 only
204+
and one taking EIP-7594 into the mix:
198205

199206
```ts
200207
// ./examples/blobTx.ts
@@ -208,15 +215,46 @@ import { KZG as microEthKZG } from 'micro-eth-signer/kzg.js'
208215

209216
const main = async () => {
210217
const kzg = new microEthKZG(trustedSetup)
211-
const common = new Common({
218+
// EIP-4844 only
219+
const common4844 = new Common({
212220
chain: Mainnet,
213221
hardfork: Hardfork.Cancun,
214222
customCrypto: { kzg },
215223
})
216224

225+
// EIP-4844 and EIP-7594
226+
const common4844and7594 = new Common({
227+
chain: Mainnet,
228+
hardfork: Hardfork.Osaka,
229+
customCrypto: { kzg },
230+
})
231+
const setups = [
232+
{
233+
title: 'Blob transaction (EIP-4844 only)',
234+
common: common4844,
235+
proofAmountComment: 'one proof per blob'
236+
},
237+
{
238+
title: 'Blob transaction (EIP-4844 + EIP-7594)',
239+
common: common4844and7594,
240+
proofAmountComment: '128 cells per blob + one proof per cell -> NUM_BLOBS * 128 proofs'
241+
},
242+
]
243+
244+
for (const setup of setups) {
245+
console.log(`\n${setup.title}:`)
246+
console.log('---------------------------------------')
247+
248+
const blobsData = ['blob 1', 'blob 2', 'blob 3']
249+
console.log(`Blobs (Data) : "${blobsData.join('", "')}"`)
250+
// Final format, filled with a lot of 0s, added marker
251+
const blobs = getBlobs(blobsData)
252+
253+
console.log('Generating tx...')
254+
217255
const txData: BlobEIP4844TxData = {
218256
data: '0x1a8451e600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
219-
gasLimit: '0x02625a00',
257+
gasLimit: 16_000_000n,
220258
maxPriorityFeePerGas: '0x01',
221259
maxFeePerGas: '0xff',
222260
maxFeePerBlobGas: '0xfff',
@@ -229,18 +267,24 @@ const main = async () => {
229267
chainId: '0x01',
230268
accessList: [],
231269
type: '0x05',
232-
blobs: getBlobs(['blob 1', 'blob 2']),
270+
blobs,
233271
}
234272

235-
const tx = createBlob4844Tx(txData, { common })
273+
const tx = createBlob4844Tx(txData, { common: setup.common })
236274

237-
console.log(`Blob tx created with hash: ${bytesToHex(tx.hash())}`)
238-
console.log(`Tx contains ${tx.numBlobs()} blob`)
239-
console.log(`Blob versioned hashes: ${tx.blobVersionedHashes.join(', ')}`)
275+
console.log(`Tx hash : ${bytesToHex(tx.hash())}`)
276+
console.log(`Num blobs : ${tx.numBlobs()}`)
277+
console.log(`Blob versioned hashes : ${tx.blobVersionedHashes.join(', ')}`)
278+
console.log(`KZG commitments : ${tx.kzgCommitments!.join(', ')}`)
279+
console.log(`First KZG (cell) proof: ${tx.kzgProofs![0]}`)
280+
console.log(`Num KZG (cell) proofs : ${tx.kzgProofs!.length} (${setup.proofAmountComment})`)
281+
}
240282

241-
// To send a transaction via RPC, you can do something like this:
283+
// To send a transaction via RPC, you can something like this:
242284
// const rawTx = tx.sign(privateKeyBytes).serializeNetworkWrapper()
243285
// myRPCClient.request('eth_sendRawTransaction', [rawTx]) // submits a transaction via RPC
286+
//
287+
// Also see ./sendRawSepoliaTx.ts example
244288
}
245289

246290
void main()
@@ -249,15 +293,19 @@ void main()
249293

250294
**Note:** `versionedHashes` and `kzgCommitments` have a real length of 32 bytes, `blobs` have a real length of `4096` bytes and values are trimmed here for brevity.
251295

252-
You can either pass in blobs as the initial `blobsData` - and the final `blobs` format will be derived for you - or you can pass in the final `blobs` format directly as bytes. `versionedHashes`, `kzgCommitments` and `kzgProofs` are either derived or taken from the values passed in.
296+
You can either pass in blobs as the initial `blobsData` (the data you want to store in the blob) - and the final `blobs` format (filled with a lot of 0s, added marker) will be derived for you - or you can pass in the final `blobs` format directly as bytes. `versionedHashes`, `kzgCommitments` and `kzgProofs` are either derived or taken from the values passed in.
297+
298+
The `kzgProofs` field is used for both blob proofs (EIP-4844) and cell proofs (EIP-7594). Note that the amount of proofs increases by a factor of 128 when EIP-7594 is activated, since proofs are then computed per cell instead of per blob (128 cells per blob).
253299

254300
For manually deriving commitments, proofs and versioned hashes, there are dedicated helpers available in the [@ethereumjs/util](https://github.com/ethereumjs/ethereumjs-monorepo/tree/master/packages/util) package.
255301

256302
#### Serialization
257303

258304
Blob transactions can be serialized in two ways.
259305
1) `tx.serialize()` - the standard serialization returns an RLP-encoded `Uint8Array` that conforms to the transaction as represented after it is included in a block
260-
2) `tx.serializeNetworkWrapper()` - this serialization format includes the `blobs` in the encoded data and is the format specified for transactions that are being submitted to/gossipped around the mempool. If you are constructing a transaction to submit via JSON-RPC, use this format.
306+
2) `tx.serializeNetworkWrapper()` - this serialization format includes the `blobs` in the encoded data and is the format specified for transactions that are being submitted to/gossipped around the mempool. **If you are constructing a transaction to submit via JSON-RPC, use this format.**
307+
308+
See the [Send Raw Sepolia Tx](./examples/sendRawSepoliaTx.ts) example for a detailed example on how to send a blob transaction via JSON-RPC.
261309

262310
See the [Blob Transaction Tests](./test/eip4844.spec.ts) for additional examples of usage in instantiating, serializing, and deserializing these transactions.
263311

packages/tx/examples/blobTx.ts

Lines changed: 59 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -7,39 +7,76 @@ import { KZG as microEthKZG } from 'micro-eth-signer/kzg.js'
77

88
const main = async () => {
99
const kzg = new microEthKZG(trustedSetup)
10-
const common = new Common({
10+
// EIP-4844 only
11+
const common4844 = new Common({
1112
chain: Mainnet,
1213
hardfork: Hardfork.Cancun,
1314
customCrypto: { kzg },
1415
})
1516

16-
const txData: BlobEIP4844TxData = {
17-
data: '0x1a8451e600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
18-
gasLimit: '0x02625a00',
19-
maxPriorityFeePerGas: '0x01',
20-
maxFeePerGas: '0xff',
21-
maxFeePerBlobGas: '0xfff',
22-
nonce: '0x00',
23-
to: '0xcccccccccccccccccccccccccccccccccccccccc',
24-
value: '0x0186a0',
25-
v: '0x01',
26-
r: '0xafb6e247b1c490e284053c87ab5f6b59e219d51f743f7a4d83e400782bc7e4b9',
27-
s: '0x479a268e0e0acd4de3f1e28e4fac2a6b32a4195e8dfa9d19147abe8807aa6f64',
28-
chainId: '0x01',
29-
accessList: [],
30-
type: '0x05',
31-
blobs: getBlobs(['blob 1', 'blob 2']),
32-
}
17+
// EIP-4844 and EIP-7594
18+
const common4844and7594 = new Common({
19+
chain: Mainnet,
20+
hardfork: Hardfork.Osaka,
21+
customCrypto: { kzg },
22+
})
23+
const setups = [
24+
{
25+
title: 'Blob transaction (EIP-4844 only)',
26+
common: common4844,
27+
proofAmountComment: 'one proof per blob',
28+
},
29+
{
30+
title: 'Blob transaction (EIP-4844 + EIP-7594)',
31+
common: common4844and7594,
32+
proofAmountComment: '128 cells per blob + one proof per cell -> NUM_BLOBS * 128 proofs',
33+
},
34+
]
35+
36+
for (const setup of setups) {
37+
console.log(`\n${setup.title}:`)
38+
console.log('---------------------------------------')
3339

34-
const tx = createBlob4844Tx(txData, { common })
40+
const blobsData = ['blob 1', 'blob 2', 'blob 3']
41+
console.log(`Blobs (Data) : "${blobsData.join('", "')}"`)
42+
// Final format, filled with a lot of 0s, added marker
43+
const blobs = getBlobs(blobsData)
3544

36-
console.log(`Blob tx created with hash: ${bytesToHex(tx.hash())}`)
37-
console.log(`Tx contains ${tx.numBlobs()} blob`)
38-
console.log(`Blob versioned hashes: ${tx.blobVersionedHashes.join(', ')}`)
45+
console.log('Generating tx...')
46+
47+
const txData: BlobEIP4844TxData = {
48+
data: '0x1a8451e600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000',
49+
gasLimit: 16_000_000n,
50+
maxPriorityFeePerGas: '0x01',
51+
maxFeePerGas: '0xff',
52+
maxFeePerBlobGas: '0xfff',
53+
nonce: '0x00',
54+
to: '0xcccccccccccccccccccccccccccccccccccccccc',
55+
value: '0x0186a0',
56+
v: '0x01',
57+
r: '0xafb6e247b1c490e284053c87ab5f6b59e219d51f743f7a4d83e400782bc7e4b9',
58+
s: '0x479a268e0e0acd4de3f1e28e4fac2a6b32a4195e8dfa9d19147abe8807aa6f64',
59+
chainId: '0x01',
60+
accessList: [],
61+
type: '0x05',
62+
blobs,
63+
}
64+
65+
const tx = createBlob4844Tx(txData, { common: setup.common })
66+
67+
console.log(`Tx hash : ${bytesToHex(tx.hash())}`)
68+
console.log(`Num blobs : ${tx.numBlobs()}`)
69+
console.log(`Blob versioned hashes : ${tx.blobVersionedHashes.join(', ')}`)
70+
console.log(`KZG commitments : ${tx.kzgCommitments!.join(', ')}`)
71+
console.log(`First KZG (cell) proof: ${tx.kzgProofs![0]}`)
72+
console.log(`Num KZG (cell) proofs : ${tx.kzgProofs!.length} (${setup.proofAmountComment})`)
73+
}
3974

4075
// To send a transaction via RPC, you can something like this:
4176
// const rawTx = tx.sign(privateKeyBytes).serializeNetworkWrapper()
4277
// myRPCClient.request('eth_sendRawTransaction', [rawTx]) // submits a transaction via RPC
78+
//
79+
// Also see ./sendRawSepoliaTx.ts example
4380
}
4481

4582
void main()

0 commit comments

Comments
 (0)