From fb400f712a23766d5afa16a920cd02bfc0913859 Mon Sep 17 00:00:00 2001 From: g11tech Date: Tue, 11 Apr 2023 21:41:34 +0530 Subject: [PATCH] tx: Update eip4844 txs to decoupled blobs spec (#2567) * `Buffer` to `Uint8Array` conversion (#2566) * V7 update to master 1 (#2593) * Added v7 release reference in main README table (#2562) * common: Schedule shanghai on goerli (#2563) * common: Schedule shanghai on goerli * update timestamp * util/tx: Shift ssz back to case dependency free ES2019 compatible version (#2564) * util/tx: Shift ssz back to case dependency free ES2019 compatible version * update package lock * update karma ecma version * VM: some optimization on the bnadd/bnmul precompiles to only copy over the necessary 128 bytes as input for the WASM call (#2568) * EVM: Memory Fix & Other Optimizations (#2570) * EVM: Rename evm debug logger to evm:evm (one for package, one for class), consistency, also, logger will otherwise be left out when run with evm:* * VM: Rename message checkpoint to state checkpoint in debug message (there is a dedicated message checkpoint msg along msg logging) * EVM: CALL/CREATE debug exit msg differentiation * EVM: avoid buffer copy in memory read (performance) * EVM: Rewrite runCall() checkpoint/revert conditional for readability/simplification * EVM: Added EIP check for transient storage checkpointing * EVM: Precompile Debug Logger Improvements (#2572) * EVM: Added general precompile debug logger setup, first ECRECOVER exemplary debug logging * EVM: Added remaining precompile debug loggers * EVM: added error cases to BLS precompile debug log * EVM: Added missing precompile return value debug logs * Small fixes * tx: ensure eip3860 txs can have more than max_initcode_size data if to field is non-empty (#2575) * EVM: Avoid memory.read() Memory Copy (#2573) * EVM: added avoidCopy parameter to memory.read() function, first test on CREATE opcode * EVM: Add direct memory read to all calling opcodes * EVM: Copy over memory on IDENTITY precompile * EVM: remove length checks and return buffer 0-filling in Memory.read() (memory is uncoditionally being extended properly anyhow) * Some optimizations * blockchain: fix merge->clique transition (#2571) * Client: ensure safe/finalized blocks are part of the canonical chain on forkchoiceUpdated (#2577) * client/engine: ensure finalized/safe blocks are in canonical chain * client: engine-api: fix finalized block check * client/tests: fix forkchoice updated test * client: add fcu tests to check if blocks are part of canonical chain * client/engine: ensure payload has a valid timestamp forkchoiceUpdated (#2579) * client/engine: ensure invalid blockhash response matches spec (#2583) * client/engine: delete invalid skeleton blocks (#2584) Co-authored-by: acolytec3 <17355484+acolytec3@users.noreply.github.com> * Setup to dev/test snapsync with sim architecture (#2574) * Setup to dev/test snapsync with sim architecture * modfiy single-run to setup a lodestar<>geth node to snapsync from * setup an ethereumjs inline client and get it to peer with geth * cleanup setup a bit * snapsync run spec * get the snap testdev sim working * finalize the test infra and update usage doc * enhance coverage * Use geth RPC to connect to ethJS * refac wait for snap sync completion --------- Co-authored-by: acolytec3 <17355484+acolytec3@users.noreply.github.com> * client: Add safe and finalized blockoptions to the chain (#2585) * client: Add safe and finalized blockoptions to the chain * fix tests * fix more tests * fix remaining * cleanup * enhance coverage * unset scheduled goerli timestamp based hfs colliding with test * Client: Small Debug Helpers and CLI Improvements (#2586) * Client: new constant MAX_TOLERATED_BLOCK_TIME for execution, added warning for slowly executed blocks * Client -> Execution: NumBlocksPerIteration (default: 50) as an option * Client: only restart RLPx server or log peer stats if max peers is set to be greater than 0 * Apply suggestions from code review Co-authored-by: acolytec3 <17355484+acolytec3@users.noreply.github.com> * Apply suggestions from code review --------- Co-authored-by: acolytec3 <17355484+acolytec3@users.noreply.github.com> * common: Schedule Shanghai on mainnet! (#2591) * common: Schedule Shanghai on mainnet! * clear hf timestamp for test * VM: Diff-based Touched Accounts Checkpointing (#2581) * VM: Switched to a more efficient diff-based way of touched account checkpointing * VM: move accessed storage inefficient checkpointing problem to berlin, haha * EVM: avoid memory copy in MLOAD opcode function * Remove console.log() in EVM * vmState: ensure touched accounts delete stack gets properly updated on commit * vm/eei: save touched height * vm/vmState: new possible fix for touched accounts * vm/vmState: another attempt to fix touched accounts journaling * vm: add journaling * Check correct journal height on revert --------- Co-authored-by: Jochem Brouwer Co-authored-by: acolytec3 <17355484+acolytec3@users.noreply.github.com> --------- Co-authored-by: Holger Drewes Co-authored-by: g11tech Co-authored-by: Jochem Brouwer * First pass - most util changes * Fix most account stuff * Fix account test * Many byte fixes * util: fix constants tests * remaining fixes * Turn off ci jobs * monorepo: bigIntToUnpaddedBuffer -> bigIntToUnpaddedBytes * util: update description of bytes exporT * util: remove unused import * common: use bytesToHex helper instead of toString('hex') * trie: refactor non-test files to Uint8Array * util: add binary string utils * util: remove extra Uint8Array.from * util: remove arrToBufArray util * trie: adjust tests and fix outstanding issues * util: remove binarystring utils and add compareBytes and randomBytes util * common: refactor common with Uint8Array * util: accept 0x-prefixed and non-prefixed hex strings in toBytes * tx: refactor Buffer -> Uint8Array * tx: remove unused import * util: revert toBytes update * block: refactor Buffer -> uint8array * block: adjust import * trie: refactor remaining buffer instances * move devp2p to uint8Array * statemanager: refactor buffer -> uint8array * util: simplify zeros * util: add concatBytesUnsafe * ethash: partial migration * ethash: update examples * ethash: wip fixes * ethash: more WIP * ethash: ensure fnv input is read from mix, not mixView * blockchain: migrate to uint8array * ethash: renable all tests * ethash: fix bytesReverse * Fix miner tests * many hexToBytes moves * most of evm/vm moves * evm: Fix all tests * vm: more fixes * More fixes * vm: fix receipts encoding * vm: fix tester * client: refactor buffer to uint8array * client: additional uint8 adjustments * client: fix most tests * fix remaining client unit tests * reactivate most CI * client: fix les test/protocol * turn client CI on * util: fix name typo * lint * Fix withdrawals * remove buffarraytoarr * Remove bufArrtoArr references * Lint * fix examples * Fix difficulty test * lint * block: update randomBytes import * replace randombytes import * client: fix sim test util * vm: fix example * devp2p: update snappy typing and fix tests * Fix tests * Remove additional buffer references * rustbn fixes * add 0x prefix to precompile address * Remove `node-ip` dependency and buffer references in devp2p * Switch slice to subarray * evm: fix blake2f * Merge fixes * more merge commit fixes * more test fixes * Address all the feedback * fix dns test * Update packages/util/src/bytes.ts Co-authored-by: Jochem Brouwer * Fix return type for baToJSON * util: instantiate hexByByte array * Remove baToJson * rebase fixes * Fix event typing * Revert outdated initcode changes * lint --------- Co-authored-by: Holger Drewes Co-authored-by: g11tech Co-authored-by: Jochem Brouwer Co-authored-by: Gabriel Rocheleau * Devp2p status fix * Remove buffer detritus * Switch db to view * buffer cleanup * Correctly parse heads from DB * Fix encodings * Cast db values to uint8array * Fix db bug in ethash * Remove unused peerId check * Add pow miner test * Finish test * Move pow test to integration tests * client: lint * rename test helper * Add timeout to PoW test * Update eip4844 txs to decoupled blobs spec * fix sharding spec and blobtx * fix the sharding muli client run * fix args * fix compatibility with latest lodestar branch * update test help * Fix fee market test * lint * Move all kzg stuff to util * Various cleanup * Update to latest c-kzg * Fix utils * Remove outdated kzg references * Fix client tests * Update c-kzg dep * Fix karma, remove Buffer references --------- Co-authored-by: acolytec3 <17355484+acolytec3@users.noreply.github.com> Co-authored-by: Holger Drewes Co-authored-by: Jochem Brouwer Co-authored-by: Gabriel Rocheleau --- package-lock.json | 38 ++++++++++------- packages/block/karma.conf.js | 1 + packages/block/package.json | 2 +- packages/block/test/eip4844block.spec.ts | 7 ++-- packages/client/bin/cli.ts | 2 +- .../devnets/4844-interop/tools/txGenerator.ts | 10 +++-- packages/client/package.json | 2 +- .../client/test/miner/pendingBlock.spec.ts | 20 ++++----- .../test/rpc/engine/getBlobsBundleV1.spec.ts | 4 +- .../test/rpc/eth/sendRawTransaction.spec.ts | 28 ++++++------- packages/client/test/sim/4844.md | 28 +++++++++---- packages/client/test/sim/sharding.spec.ts | 26 ++++++++++-- packages/client/test/sim/simutils.ts | 29 ++++++++----- packages/client/test/sim/single-run.sh | 17 ++++++-- packages/client/test/sim/txGenerator.ts | 10 +++-- packages/evm/package.json | 3 +- .../precompiles/14-kzg-point-evaluation.ts | 3 +- .../precompiles/14-pointevaluation.spec.ts | 10 ++++- packages/tx/package.json | 2 +- packages/tx/src/depInterfaces.ts | 20 --------- packages/tx/src/eip4844Transaction.ts | 26 ++++++------ packages/tx/src/index.ts | 2 - packages/tx/src/kzg/kzg.ts | 24 ----------- packages/tx/src/types.ts | 6 +-- packages/tx/test/eip4844.spec.ts | 25 ++++++----- packages/util/package.json | 8 ++++ .../{tx/src/utils => util/src}/blobHelpers.ts | 8 +++- packages/util/src/bytes.ts | 4 -- packages/util/src/index.ts | 2 + packages/util/src/kzg.ts | 42 +++++++++++++++++++ packages/util/src/types.ts | 1 - 31 files changed, 242 insertions(+), 168 deletions(-) delete mode 100644 packages/tx/src/depInterfaces.ts delete mode 100644 packages/tx/src/kzg/kzg.ts rename packages/{tx/src/utils => util/src}/blobHelpers.ts (93%) create mode 100644 packages/util/src/kzg.ts diff --git a/package-lock.json b/package-lock.json index c8ce7feaa1..e3d9ce83b7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4826,11 +4826,12 @@ } }, "node_modules/c-kzg": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/c-kzg/-/c-kzg-1.0.9.tgz", - "integrity": "sha512-5shQs7k/f7cN0Ya7g1bTgCX7CO2emh/2mkPKrjxqkC7Y+tM9YN88MWkop9ftMMZXadvVMrxWfZ/RCqBR8jRQOQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/c-kzg/-/c-kzg-2.0.4.tgz", + "integrity": "sha512-DsHrUSUIvC/k8TuHDTLddMGYBTYfcleyoIjv9k5iv4kJTI4J6gkntEocjKbKDCmohrwms0N4QYqx1ugp3RY3FQ==", "hasInstallScript": true, "dependencies": { + "bindings": "^1.5.0", "node-addon-api": "^5.0.0" } }, @@ -17818,7 +17819,7 @@ }, "devDependencies": { "@types/lru-cache": "^5.1.0", - "c-kzg": "^1.0.8" + "c-kzg": "^2.0.4" }, "engines": { "node": ">=14" @@ -17873,7 +17874,7 @@ "@ethereumjs/vm": "6.4.1", "abstract-level": "^1.0.3", "body-parser": "^1.19.2", - "c-kzg": "^1.0.8", + "c-kzg": "^2.0.4", "chalk": "^4.1.2", "connect": "^3.7.0", "cors": "^2.8.5", @@ -18111,7 +18112,6 @@ "license": "MPL-2.0", "dependencies": { "@ethereumjs/common": "^3.1.1", - "@ethereumjs/tx": "^4.1.1", "@ethereumjs/util": "^8.0.5", "@ethersproject/providers": "^5.7.1", "debug": "^4.3.3", @@ -18128,7 +18128,7 @@ "@types/minimist": "^1.2.2", "@types/node-dir": "^0.0.34", "benchmark": "^2.1.4", - "c-kzg": "^1.0.8", + "c-kzg": "^2.0.4", "level": "^8.0.0", "memory-level": "^1.0.0", "minimist": "^1.2.5", @@ -18245,7 +18245,7 @@ "node": ">=14" }, "peerDependencies": { - "c-kzg": "^1.0.8" + "c-kzg": "^2.0.4" }, "peerDependenciesMeta": { "c-kzg": { @@ -18268,6 +18268,14 @@ }, "engines": { "node": ">=14" + }, + "peerDependencies": { + "c-kzg": "^2.0.4" + }, + "peerDependenciesMeta": { + "c-kzg": { + "optional": true + } } }, "packages/vm": { @@ -19530,7 +19538,7 @@ "@ethereumjs/tx": "^4.1.1", "@ethereumjs/util": "^8.0.5", "@types/lru-cache": "^5.1.0", - "c-kzg": "^1.0.8", + "c-kzg": "^2.0.4", "ethereum-cryptography": "^1.1.2", "ethers": "^5.7.1" } @@ -19578,7 +19586,7 @@ "@types/jwt-simple": "^0.5.33", "abstract-level": "^1.0.3", "body-parser": "^1.19.2", - "c-kzg": "^1.0.8", + "c-kzg": "^2.0.4", "chalk": "^4.1.2", "connect": "^3.7.0", "constants-browserify": "^1.0.0", @@ -19752,7 +19760,6 @@ "requires": { "@ethereumjs/common": "^3.1.1", "@ethereumjs/statemanager": "^1.0.4", - "@ethereumjs/tx": "^4.1.1", "@ethereumjs/util": "^8.0.5", "@ethersproject/abi": "^5.0.12", "@ethersproject/providers": "^5.7.1", @@ -19762,7 +19769,7 @@ "@types/minimist": "^1.2.2", "@types/node-dir": "^0.0.34", "benchmark": "^2.1.4", - "c-kzg": "^1.0.8", + "c-kzg": "^2.0.4", "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", "level": "^8.0.0", @@ -21837,10 +21844,11 @@ "version": "3.1.2" }, "c-kzg": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/c-kzg/-/c-kzg-1.0.9.tgz", - "integrity": "sha512-5shQs7k/f7cN0Ya7g1bTgCX7CO2emh/2mkPKrjxqkC7Y+tM9YN88MWkop9ftMMZXadvVMrxWfZ/RCqBR8jRQOQ==", + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/c-kzg/-/c-kzg-2.0.4.tgz", + "integrity": "sha512-DsHrUSUIvC/k8TuHDTLddMGYBTYfcleyoIjv9k5iv4kJTI4J6gkntEocjKbKDCmohrwms0N4QYqx1ugp3RY3FQ==", "requires": { + "bindings": "^1.5.0", "node-addon-api": "^5.0.0" }, "dependencies": { diff --git a/packages/block/karma.conf.js b/packages/block/karma.conf.js index cb8bed8f8a..81b7570427 100644 --- a/packages/block/karma.conf.js +++ b/packages/block/karma.conf.js @@ -21,6 +21,7 @@ module.exports = function (config) { '../../node_modules/@chainsafe/as-sha256/lib/hashObject.js', }, }, + ignore: ['c-kzg'], }, }, concurrency: 1, diff --git a/packages/block/package.json b/packages/block/package.json index aea98c469b..cca736dd58 100644 --- a/packages/block/package.json +++ b/packages/block/package.json @@ -48,7 +48,7 @@ }, "devDependencies": { "@types/lru-cache": "^5.1.0", - "c-kzg": "^1.0.8" + "c-kzg": "^2.0.4" }, "engines": { "node": ">=14" diff --git a/packages/block/test/eip4844block.spec.ts b/packages/block/test/eip4844block.spec.ts index c38fe88738..9813e03254 100644 --- a/packages/block/test/eip4844block.spec.ts +++ b/packages/block/test/eip4844block.spec.ts @@ -1,11 +1,12 @@ import { Chain, Common, Hardfork } from '@ethereumjs/common' -import { BlobEIP4844Transaction, initKZG } from '@ethereumjs/tx' +import { BlobEIP4844Transaction } from '@ethereumjs/tx' import { blobsToCommitments, commitmentsToVersionedHashes, getBlobs, -} from '@ethereumjs/tx/dist/utils/blobHelpers' -import { randomBytes } from '@ethereumjs/util' + initKZG, + randomBytes, +} from '@ethereumjs/util' import * as kzg from 'c-kzg' import * as tape from 'tape' diff --git a/packages/client/bin/cli.ts b/packages/client/bin/cli.ts index 11c243224e..cc079ae7d4 100755 --- a/packages/client/bin/cli.ts +++ b/packages/client/bin/cli.ts @@ -4,12 +4,12 @@ import { Block } from '@ethereumjs/block' import { Blockchain, parseGethGenesisState } from '@ethereumjs/blockchain' import { Chain, Common, ConsensusAlgorithm, Hardfork } from '@ethereumjs/common' import { RLP } from '@ethereumjs/rlp' -import { initKZG } from '@ethereumjs/tx' import { Address, bytesToHex, bytesToPrefixedHexString, hexStringToBytes, + initKZG, randomBytes, short, toBytes, diff --git a/packages/client/devnets/4844-interop/tools/txGenerator.ts b/packages/client/devnets/4844-interop/tools/txGenerator.ts index 16dd356693..53bd429a0c 100644 --- a/packages/client/devnets/4844-interop/tools/txGenerator.ts +++ b/packages/client/devnets/4844-interop/tools/txGenerator.ts @@ -1,12 +1,16 @@ // Adapted from - https://github.com/Inphi/eip4844-interop/blob/master/blob_tx_generator/blob.js import { Common, Hardfork } from '@ethereumjs/common' -import { BlobEIP4844Transaction, initKZG } from '@ethereumjs/tx' +import { BlobEIP4844Transaction } from '@ethereumjs/tx' import { + Address, + initKZG, blobsToCommitments, commitmentsToVersionedHashes, getBlobs, -} from '@ethereumjs/tx/dist/utils/blobHelpers' -import { Address, bytesToPrefixedHexString, hexStringToBytes } from '@ethereumjs/util' + bytesToPrefixedHexString, + hexStringToBytes, +} from '@ethereumjs/util' + import * as kzg from 'c-kzg' import { randomBytes } from '@ethereumjs/util' import { Client } from 'jayson/promise' diff --git a/packages/client/package.json b/packages/client/package.json index 9fd6496abb..6de352750b 100644 --- a/packages/client/package.json +++ b/packages/client/package.json @@ -70,10 +70,10 @@ "@ethereumjs/vm": "6.4.1", "abstract-level": "^1.0.3", "body-parser": "^1.19.2", + "c-kzg": "^2.0.4", "chalk": "^4.1.2", "connect": "^3.7.0", "cors": "^2.8.5", - "c-kzg": "^1.0.8", "debug": "^4.3.3", "ethereum-cryptography": "^1.1.2", "fs-extra": "^10.1.0", diff --git a/packages/client/test/miner/pendingBlock.spec.ts b/packages/client/test/miner/pendingBlock.spec.ts index cc8f56e820..a6cc28c83d 100644 --- a/packages/client/test/miner/pendingBlock.spec.ts +++ b/packages/client/test/miner/pendingBlock.spec.ts @@ -1,18 +1,17 @@ import { Block, BlockHeader } from '@ethereumjs/block' import { Common, Chain as CommonChain, Hardfork } from '@ethereumjs/common' -import { BlobEIP4844Transaction, Transaction, initKZG } from '@ethereumjs/tx' -import { - blobsToCommitments, - commitmentsToVersionedHashes, - getBlobs, -} from '@ethereumjs/tx/dist/utils/blobHelpers' +import { BlobEIP4844Transaction, Transaction } from '@ethereumjs/tx' import { Account, Address, + blobsToCommitments, bytesToHex, bytesToPrefixedHexString, + commitmentsToVersionedHashes, equalsBytes, + getBlobs, hexStringToBytes, + initKZG, randomBytes, } from '@ethereumjs/util' import { VM } from '@ethereumjs/vm' @@ -260,11 +259,9 @@ tape('[PendingBlock]', async (t) => { t.test('construct blob bundles', async (st) => { try { - kzg.freeTrustedSetup() - } catch { - /** ensure kzg is setup */ - } - initKZG(kzg, __dirname + '/../../lib/trustedSetups/devnet4.txt') + initKZG(kzg, __dirname + '/../../lib/trustedSetups/devnet4.txt') + // eslint-disable-next-line + } catch {} const gethGenesis = require('../../../block/test/testdata/4844-hardfork.json') const common = Common.fromGethGenesis(gethGenesis, { chain: 'customChain', @@ -297,7 +294,6 @@ tape('[PendingBlock]', async (t) => { await pendingBlock.build(payloadId) const pendingBlob = pendingBlock.blobBundles.get(bytesToPrefixedHexString(payloadId))?.blobs[0] st.ok(pendingBlob !== undefined && equalsBytes(pendingBlob, blobs[0])) - kzg.freeTrustedSetup() st.end() }) t.test('should reset td', (st) => { diff --git a/packages/client/test/rpc/engine/getBlobsBundleV1.spec.ts b/packages/client/test/rpc/engine/getBlobsBundleV1.spec.ts index ce608ca7a8..0b976a8580 100644 --- a/packages/client/test/rpc/engine/getBlobsBundleV1.spec.ts +++ b/packages/client/test/rpc/engine/getBlobsBundleV1.spec.ts @@ -1,7 +1,7 @@ import { Hardfork } from '@ethereumjs/common' import { DefaultStateManager } from '@ethereumjs/statemanager' -import { TransactionFactory, initKZG } from '@ethereumjs/tx' -import { Address, hexStringToBytes } from '@ethereumjs/util' +import { TransactionFactory } from '@ethereumjs/tx' +import { Address, hexStringToBytes, initKZG } from '@ethereumjs/util' import * as kzg from 'c-kzg' import * as tape from 'tape' diff --git a/packages/client/test/rpc/eth/sendRawTransaction.spec.ts b/packages/client/test/rpc/eth/sendRawTransaction.spec.ts index e2b4fe3f38..7ed196b5f1 100644 --- a/packages/client/test/rpc/eth/sendRawTransaction.spec.ts +++ b/packages/client/test/rpc/eth/sendRawTransaction.spec.ts @@ -1,18 +1,16 @@ import { BlockHeader } from '@ethereumjs/block' import { Chain, Common, Hardfork } from '@ethereumjs/common' import { DefaultStateManager } from '@ethereumjs/statemanager' -import { - BlobEIP4844Transaction, - FeeMarketEIP1559Transaction, - Transaction, - initKZG, -} from '@ethereumjs/tx' +import { BlobEIP4844Transaction, FeeMarketEIP1559Transaction, Transaction } from '@ethereumjs/tx' import { blobsToCommitments, + bytesToPrefixedHexString, commitmentsToVersionedHashes, getBlobs, -} from '@ethereumjs/tx/dist/utils/blobHelpers' -import { bytesToPrefixedHexString, hexStringToBytes, randomBytes } from '@ethereumjs/util' + hexStringToBytes, + initKZG, + randomBytes, +} from '@ethereumjs/util' import * as kzg from 'c-kzg' import * as tape from 'tape' @@ -220,11 +218,9 @@ tape('blob EIP 4844 transaction', async (t) => { const consensusFormatValidation = BlockHeader.prototype._consensusFormatValidation BlockHeader.prototype._consensusFormatValidation = (): any => {} try { - kzg.freeTrustedSetup() - } catch { - // NOOP - just verifying KZG is ready if not already - } - initKZG(kzg, __dirname + '/../../../lib/trustedSetups/devnet4.txt') + initKZG(kzg, __dirname + '/../../../lib/trustedSetups/devnet4.txt') + // eslint-disable-next-line + } catch {} const gethGenesis = require('../../../../block/test/testdata/4844-hardfork.json') const common = Common.fromGethGenesis(gethGenesis, { chain: 'customChain', @@ -239,14 +235,14 @@ tape('blob EIP 4844 transaction', async (t) => { const blobs = getBlobs('hello world') const commitments = blobsToCommitments(blobs) const versionedHashes = commitmentsToVersionedHashes(commitments) - const proof = kzg.computeAggregateKzgProof(blobs.map((blob) => Uint8Array.from(blob))) + const proofs = blobs.map((blob, ctx) => kzg.computeBlobKzgProof(blob, commitments[ctx])) const pk = randomBytes(32) const tx = BlobEIP4844Transaction.fromTxData( { versionedHashes, blobs, kzgCommitments: commitments, - kzgProof: proof, + kzgProofs: proofs, maxFeePerDataGas: 1000000n, gasLimit: 0xffffn, maxFeePerGas: 10000000n, @@ -261,7 +257,7 @@ tape('blob EIP 4844 transaction', async (t) => { versionedHashes, blobs, kzgCommitments: commitments, - kzgProof: proof, + kzgProofs: proofs, maxFeePerDataGas: 1000000n, gasLimit: 0xfffffn, maxFeePerGas: 100000000n, diff --git a/packages/client/test/sim/4844.md b/packages/client/test/sim/4844.md index 5eaa42b136..dd004b69be 100644 --- a/packages/client/test/sim/4844.md +++ b/packages/client/test/sim/4844.md @@ -4,22 +4,36 @@ Note: All commands should be run from the `client` package directory root (so so ## Running a local devnet -To run a single EthereumJS client <> Lodestar CL client for testing, run the following command: -`NETWORK=sharding EXTRA_CL_PARAMS="--params.CAPELLA_FORK_EPOCH 0 --params.EIP4844_FORK_EPOCH 0" LODE_IMAGE=g11tech/lodestar:4844-ae177e DATADIR=path/to/your/data/directory test/sim/./single-run.sh` +Step 1. To run a single EthereumJS client <> Lodestar CL client for testing, run the following command: +`NETWORK=sharding EXTRA_CL_PARAMS="--params.CAPELLA_FORK_EPOCH 0 --params.DENEB_FORK_EPOCH 0" LODE_IMAGE=g11tech/lodestar:decoupled DATADIR=path/to/your/data/directory test/sim/./single-run.sh` -To run a second EthereumJS <> Lodestar pair, use this command: -`MULTIPEER=syncpeer NETWORK=sharding EXTRA_CL_PARAMS="--params.CAPELLA_FORK_EPOCH 0 --params.EIP4844_FORK_EPOCH 0" LODE_IMAGE=g11tech/lodestar:4844-ae177e DATADIR=path/to/your/data/directory test/sim/./single-run.sh` +Step 2. (Optional) To run a second EthereumJS <> Lodestar pair, use this command: +`MULTIPEER=syncpeer NETWORK=sharding EXTRA_CL_PARAMS="--params.CAPELLA_FORK_EPOCH 0 --params.DENEB_FORK_EPOCH 0" LODE_IMAGE=g11tech/lodestar:decoupled DATADIR=path/to/your/data/directory test/sim/./single-run.sh` -To send a single blob transaction to the network, you can use the `txGenerator.ts` script as follows: +Step 3. To send a single blob transaction to the network, you may just run spec test: +`EXTERNAL_RUN=true npm run tape -- test/sim/sharding.spec.ts` + +OR, you can use the `txGenerator.ts` script as follows: `ts-node test/sim/txGenerator 8545 'hello'`. The first argument is the port number of the EthereumJS client you which to submit the transaction to and the second is any data to include in the blob. This script was adapted from the [interop repo blob script](https://github.com/Inphi/eip4844-interop/blob/master/blob_tx_generator/blob.js) + ## EIP-4844 spec tests -To run the 4844 spec tests contained in `test/sim/sharding.spec.ts`, use the following command: +You don't need to externally start the nodes, the sim tests will do all that for you as well as run the tests against it. + +Run Step 1 & 3 together: + +`LODE_IMAGE=g11tech/lodestar:decoupled DATADIR=path/to/your/data/directory npm run tape -- + test/sim/sharding.spec.ts` + + +### Run Step 1, 2 & 3 together + -`EXTRA_CL_PARAMS="--params.CAPELLA_FORK_EPOCH 0 --params.EIP4844_FORK_EPOCH 0" LODE_IMAGE=g11tech/lodestar:4844-ae177e DATADIR=/absolute/path/to/your/data/dir npm run tape -- test/sim/sharding.spec.ts` +`WITH_PEER=syncpeer LODE_IMAGE=g11tech/lodestar:decoupled DATADIR=path/to/your/data/directory npm run tape -- + test/sim/sharding.spec.ts` Note, these tests are adapted from the specification tests contained in the [EIP-4844 Interop repo](https://github.com/Inphi/eip4844-interop) diff --git a/packages/client/test/sim/sharding.spec.ts b/packages/client/test/sim/sharding.spec.ts index 7393bf018a..59a5a5624f 100644 --- a/packages/client/test/sim/sharding.spec.ts +++ b/packages/client/test/sim/sharding.spec.ts @@ -2,13 +2,14 @@ import { Common } from '@ethereumjs/common' import { TransactionFactory } from '@ethereumjs/tx' import { bytesToPrefixedHexString, hexStringToBytes, privateToAddress } from '@ethereumjs/util' import { Client } from 'jayson/promise' +import { randomBytes } from 'node:crypto' import * as tape from 'tape' import { + createBlobTxs, filterKeywords, filterOutWords, runBlobTx, - runBlobTxsFromFile, runTxHelper, sleep, startNetwork, @@ -28,6 +29,9 @@ export async function runTx(data: string, to?: string, value?: bigint) { } tape('sharding/eip4844 hardfork tests', async (t) => { + if (process.env.EXTRA_CL_PARAMS === undefined) { + process.env.EXTRA_CL_PARAMS = '--params.CAPELLA_FORK_EPOCH 0 --params.DENEB_FORK_EPOCH 0' + } const { teardownCallBack, result } = await startNetwork(network, client, { filterKeywords, filterOutWords, @@ -55,7 +59,9 @@ tape('sharding/eip4844 hardfork tests', async (t) => { client, 2 ** 14, pkey, - '0x3dA33B9A0894b908DdBb00d96399e506515A1009' + '0x3dA33B9A0894b908DdBb00d96399e506515A1009', + undefined, + { common } ) const eth2res = await (await fetch('http://127.0.0.1:9596/eth/v1/beacon/headers')).json() @@ -96,11 +102,23 @@ tape('sharding/eip4844 hardfork tests', async (t) => { }) t.test('data gas fee market tests', async (st) => { - const res = await runBlobTxsFromFile(client, './test/sim/configs/blobs.txt') + const txns = await createBlobTxs( + 4, + 4096, + pkey, + '0x' + randomBytes(20).toString('hex'), + undefined, + { common } + ) + const txHashes = [] + for (const txn of txns) { + const res = await client.request('eth_sendRawTransaction', [txn], 2.0) + txHashes.push(res.result) + } let done = false let txReceipt while (!done) { - txReceipt = await client.request('eth_getTransactionReceipt', [res[0]], 2.0) + txReceipt = await client.request('eth_getTransactionReceipt', [txHashes[0]], 2.0) if (txReceipt.result !== null) { done = true } diff --git a/packages/client/test/sim/simutils.ts b/packages/client/test/sim/simutils.ts index 4efe3d3d7a..e410e14f21 100644 --- a/packages/client/test/sim/simutils.ts +++ b/packages/client/test/sim/simutils.ts @@ -1,15 +1,15 @@ import { Blockchain } from '@ethereumjs/blockchain' -import { BlobEIP4844Transaction, FeeMarketEIP1559Transaction, initKZG } from '@ethereumjs/tx' -import { - blobsToCommitments, - commitmentsToVersionedHashes, - getBlobs, -} from '@ethereumjs/tx/dist/utils/blobHelpers' +import { BlobEIP4844Transaction, FeeMarketEIP1559Transaction } from '@ethereumjs/tx' import { Address, + blobsToCommitments, + blobsToProofs, bytesToHex, bytesToPrefixedHexString, bytesToUtf8, + commitmentsToVersionedHashes, + getBlobs, + initKZG, randomBytes, } from '@ethereumjs/util' import * as kzg from 'c-kzg' @@ -22,6 +22,7 @@ import { EthereumClient } from '../../lib/client' import { Config } from '../../lib/config' import type { Common } from '@ethereumjs/common' +import type { TxOptions } from '@ethereumjs/tx' import type { ChildProcessWithoutNullStreams } from 'child_process' import type { Client } from 'jayson/promise' @@ -297,10 +298,12 @@ export const runBlobTx = async ( blobSize: number, pkey: Uint8Array, to?: string, - value?: bigint + value?: bigint, + opts?: TxOptions ) => { const blobs = getBlobs(bytesToHex(randomBytes(blobSize))) const commitments = blobsToCommitments(blobs) + const proofs = blobsToProofs(blobs, commitments) const hashes = commitmentsToVersionedHashes(commitments) const sender = Address.fromPrivateKey(pkey) @@ -311,6 +314,7 @@ export const runBlobTx = async ( chainId: '0x1', blobs, kzgCommitments: commitments, + kzgProofs: proofs, versionedHashes: hashes, gas: undefined, maxFeePerDataGas: undefined, @@ -327,7 +331,7 @@ export const runBlobTx = async ( txData['gasLimit'] = BigInt(1000000) as any const nonce = await client.request('eth_getTransactionCount', [sender.toString(), 'latest'], 2.0) txData['nonce'] = BigInt(nonce.result) as any - const blobTx = BlobEIP4844Transaction.fromTxData(txData).sign(pkey) + const blobTx = BlobEIP4844Transaction.fromTxData(txData, opts).sign(pkey) const serializedWrapper = blobTx.serializeNetworkWrapper() @@ -359,12 +363,14 @@ export const createBlobTxs = async ( blobSize = 2 ** 17 - 1, pkey: Uint8Array, to?: string, - value?: bigint + value?: bigint, + opts?: TxOptions ) => { - const txHashes: any = [] + const txHashes: string[] = [] const blobs = getBlobs(bytesToHex(randomBytes(blobSize))) const commitments = blobsToCommitments(blobs) + const proofs = blobsToProofs(blobs, commitments) const hashes = commitmentsToVersionedHashes(commitments) for (let x = 1; x <= numTxs; x++) { @@ -376,6 +382,7 @@ export const createBlobTxs = async ( chainId: '0x1', blobs, kzgCommitments: commitments, + kzgProofs: proofs, versionedHashes: hashes, gas: undefined, maxFeePerDataGas: undefined, @@ -391,7 +398,7 @@ export const createBlobTxs = async ( txData['maxFeePerDataGas'] = BigInt(1000) as any txData['gasLimit'] = BigInt(1000000) as any - const blobTx = BlobEIP4844Transaction.fromTxData(txData).sign(pkey) + const blobTx = BlobEIP4844Transaction.fromTxData(txData, opts).sign(pkey) const serializedWrapper = blobTx.serializeNetworkWrapper() await fs.appendFile('./blobs.txt', bytesToPrefixedHexString(serializedWrapper) + '\n') diff --git a/packages/client/test/sim/single-run.sh b/packages/client/test/sim/single-run.sh index 19a2e3bf63..0222cb298f 100755 --- a/packages/client/test/sim/single-run.sh +++ b/packages/client/test/sim/single-run.sh @@ -87,7 +87,7 @@ case $MULTIPEER in echo "ELCLIENT=$ELCLIENT not implemented" esac - CL_PORT_ARGS="--genesisValidators 8 --startValidators 4..7 --enr.tcp 9001 --port 9001 --execution.urls http://localhost:8552 --rest.port 9597 --server http://localhost:9597 --network.connectToDiscv5Bootnodes true --bootnodes $bootEnrs" + CL_PORT_ARGS="--genesisValidators 8 --startValidators 4..7 --enr.tcp 9001 --port 9001 --execution.urls http://localhost:8552 --rest.port 9597 --server http://127.0.0.1:9597 --network.connectToDiscv5Bootnodes true --bootnodes $bootEnrs" ;; * ) @@ -105,7 +105,7 @@ case $MULTIPEER in echo "ELCLIENT=$ELCLIENT not implemented" esac - CL_PORT_ARGS="--enr.ip 127.0.0.1 --enr.tcp 9000 --enr.udp 9000" + CL_PORT_ARGS="--sync.isSingleNode --enr.ip 127.0.0.1 --enr.tcp 9000 --enr.udp 9000" if [ ! -n "$MULTIPEER" ] then echo "setting up to run as a solo node..." @@ -247,8 +247,17 @@ else responseCmd="curl --location --request GET 'http://localhost:9596/eth/v1/beacon/headers/genesis' --header 'Content-Type: application/json' 2>/dev/null | jq \".data.root\"" CL_GENESIS_HASH=$(eval "$responseCmd") done; - # since peer1 is setup get their enr and enode - bootEnrs=$(sudo cat "$origDataDir/peer1/lodestar/enr") + + # We should curl and get boot enr + while [ ! -n "$bootEnrs" ] + do + sleep 3 + echo "Fetching bootEnrs block from peer1/bootnode ..." + ejsId=$(( ejsId +1 )) + responseCmd="curl --location --request GET 'http://localhost:9596/eth/v1/node/identity' --header 'Content-Type: application/json' 2>/dev/null | jq \".data.enr\"" + bootEnrs=$(eval "$responseCmd") + done; + elBootnode=$(cat "$origDataDir/peer1/ethereumjs/$NETWORK/rlpx"); EL_PORT_ARGS="$EL_PORT_ARGS --bootnodes $elBootnode" CL_PORT_ARGS="$CL_PORT_ARGS --bootnodes $bootEnrs" diff --git a/packages/client/test/sim/txGenerator.ts b/packages/client/test/sim/txGenerator.ts index 9f2985c648..ca245b4246 100644 --- a/packages/client/test/sim/txGenerator.ts +++ b/packages/client/test/sim/txGenerator.ts @@ -1,10 +1,14 @@ // Adapted from - https://github.com/Inphi/eip4844-interop/blob/master/blob_tx_generator/blob.js -import { BlobEIP4844Transaction, initKZG } from '@ethereumjs/tx' +import { BlobEIP4844Transaction } from '@ethereumjs/tx' import { + Address, blobsToCommitments, + bytesToPrefixedHexString, commitmentsToVersionedHashes, -} from '@ethereumjs/tx/test/utils/blobHelpers' -import { Address, bytesToPrefixedHexString, hexStringToBytes, randomBytes } from '@ethereumjs/util' + hexStringToBytes, + initKZG, + randomBytes, +} from '@ethereumjs/util' import * as kzg from 'c-kzg' import { Client } from 'jayson/promise' const clientPort = process.argv[2] diff --git a/packages/evm/package.json b/packages/evm/package.json index cffcd0d013..4e27c4f2ff 100644 --- a/packages/evm/package.json +++ b/packages/evm/package.json @@ -48,7 +48,6 @@ }, "dependencies": { "@ethereumjs/common": "^3.1.1", - "@ethereumjs/tx": "^4.1.1", "@ethereumjs/util": "^8.0.5", "@ethersproject/providers": "^5.7.1", "debug": "^4.3.3", @@ -65,7 +64,7 @@ "@types/minimist": "^1.2.2", "@types/node-dir": "^0.0.34", "benchmark": "^2.1.4", - "c-kzg": "^1.0.8", + "c-kzg": "^2.0.4", "level": "^8.0.0", "memory-level": "^1.0.0", "minimist": "^1.2.5", diff --git a/packages/evm/src/precompiles/14-kzg-point-evaluation.ts b/packages/evm/src/precompiles/14-kzg-point-evaluation.ts index 5db899a67b..e257afee43 100644 --- a/packages/evm/src/precompiles/14-kzg-point-evaluation.ts +++ b/packages/evm/src/precompiles/14-kzg-point-evaluation.ts @@ -1,9 +1,10 @@ -import { computeVersionedHash, kzg } from '@ethereumjs/tx' import { bigIntToBytes, bytesToBigInt, bytesToHex, + computeVersionedHash, concatBytesNoTypeCheck, + kzg, setLengthLeft, short, } from '@ethereumjs/util' diff --git a/packages/evm/test/precompiles/14-pointevaluation.spec.ts b/packages/evm/test/precompiles/14-pointevaluation.spec.ts index b6a4ca1863..3e1ab41b7b 100644 --- a/packages/evm/test/precompiles/14-pointevaluation.spec.ts +++ b/packages/evm/test/precompiles/14-pointevaluation.spec.ts @@ -1,6 +1,12 @@ import { Common, Hardfork } from '@ethereumjs/common' -import { computeVersionedHash, initKZG } from '@ethereumjs/tx' -import { bigIntToBytes, bytesToBigInt, concatBytesNoTypeCheck, unpadBytes } from '@ethereumjs/util' +import { + bigIntToBytes, + bytesToBigInt, + computeVersionedHash, + concatBytesNoTypeCheck, + initKZG, + unpadBytes, +} from '@ethereumjs/util' import * as kzg from 'c-kzg' import { hexToBytes } from 'ethereum-cryptography/utils' import * as tape from 'tape' diff --git a/packages/tx/package.json b/packages/tx/package.json index ec4a2579db..77e01e934a 100644 --- a/packages/tx/package.json +++ b/packages/tx/package.json @@ -59,7 +59,7 @@ "@ethersproject/providers": "^5.7.2" }, "peerDependencies": { - "c-kzg": "^1.0.8" + "c-kzg": "^2.0.4" }, "peerDependenciesMeta": { "c-kzg": { diff --git a/packages/tx/src/depInterfaces.ts b/packages/tx/src/depInterfaces.ts deleted file mode 100644 index 6d3e3e5659..0000000000 --- a/packages/tx/src/depInterfaces.ts +++ /dev/null @@ -1,20 +0,0 @@ -/** - * Interface for an externally provided kzg library used when creating blob transactions - */ -export interface Kzg { - loadTrustedSetup(filePath: string): void - freeTrustedSetup(): void - blobToKzgCommitment(blob: Uint8Array): Uint8Array - computeAggregateKzgProof(blobs: Uint8Array[]): Uint8Array - verifyKzgProof( - polynomialKzg: Uint8Array, - z: Uint8Array, - y: Uint8Array, - kzgProof: Uint8Array - ): boolean - verifyAggregateKzgProof( - blobs: Uint8Array[], - expectedKzgCommitments: Uint8Array[], - kzgAggregatedProof: Uint8Array - ): boolean -} diff --git a/packages/tx/src/eip4844Transaction.ts b/packages/tx/src/eip4844Transaction.ts index c40a4048f3..6e270bf8f4 100644 --- a/packages/tx/src/eip4844Transaction.ts +++ b/packages/tx/src/eip4844Transaction.ts @@ -7,23 +7,23 @@ import { bytesToBigInt, bytesToHex, bytesToPrefixedHexString, + computeVersionedHash, concatBytes, ecrecover, hexStringToBytes, + kzg, toBytes, } from '@ethereumjs/util' import { keccak256 } from 'ethereum-cryptography/keccak' import { BaseTransaction } from './baseTransaction' import { LIMIT_BLOBS_PER_TX } from './constants' -import { kzg } from './kzg/kzg' import { BlobNetworkTransactionWrapper, BlobTransactionType, SignedBlobTransactionType, } from './types' import { AccessLists, blobTxToNetworkWrapperDataFormat } from './util' -import { computeVersionedHash } from './utils/blobHelpers' import type { AccessList, @@ -44,14 +44,14 @@ const validateBlobTransactionNetworkWrapper = ( versionedHashes: Uint8Array[], blobs: Uint8Array[], commitments: Uint8Array[], - kzgProof: Uint8Array, + kzgProofs: Uint8Array[], version: number ) => { if (!(versionedHashes.length === blobs.length && blobs.length === commitments.length)) { throw new Error('Number of versionedHashes, blobs, and commitments not all equal') } try { - kzg.verifyAggregateKzgProof(blobs, commitments, kzgProof) + kzg.verifyBlobKzgProofBatch(blobs, commitments, kzgProofs) } catch (e) { throw new Error('KZG proof cannot be verified from blobs/commitments') } @@ -82,7 +82,7 @@ export class BlobEIP4844Transaction extends BaseTransaction toBytes(blob)) this.kzgCommitments = txData.kzgCommitments?.map((commitment) => toBytes(commitment)) - this.aggregateKzgProof = toBytes(txData.kzgProof) + this.kzgProofs = txData.kzgProofs?.map((proof) => toBytes(proof)) const freeze = opts?.freeze ?? true if (freeze) { Object.freeze(this) @@ -216,7 +216,7 @@ export class BlobEIP4844Transaction extends BaseTransaction Uint8Array.from(commitment)) ?? [], tx: { ...blobTxToNetworkWrapperDataFormat(this), ...to }, - kzgAggregatedProof: Uint8Array.from(this.aggregateKzgProof ?? []), + blobKzgProofs: this.kzgProofs?.map((proof) => Uint8Array.from(proof)) ?? [], }) return concatBytes(new Uint8Array([0x05]), serializedTxWrapper) } @@ -459,7 +459,7 @@ export class BlobEIP4844Transaction extends BaseTransaction { const blobs = getBlobs('hello world') const commitments = blobsToCommitments(blobs) const versionedHashes = commitmentsToVersionedHashes(commitments) - const proof = kzg.computeAggregateKzgProof(blobs) + const proofs = blobsToProofs(blobs, commitments) const unsignedTx = BlobEIP4844Transaction.fromTxData( { versionedHashes, blobs, kzgCommitments: commitments, - kzgProof: proof, + kzgProofs: proofs, maxFeePerDataGas: 100000000n, gasLimit: 0xffffffn, to: randomBytes(20), @@ -204,6 +205,7 @@ tape('Network wrapper tests', async (t) => { versionedHashes, blobs: blobs.slice(1), kzgCommitments: commitments, + kzgProofs: proofs, maxFeePerDataGas: 100000000n, gasLimit: 0xffffffn, to: randomBytes(20), @@ -230,6 +232,7 @@ tape('Network wrapper tests', async (t) => { versionedHashes, blobs, kzgCommitments: commitments, + kzgProofs: proofs, maxFeePerDataGas: 100000000n, gasLimit: 0xffffffn, to: randomBytes(20), @@ -255,7 +258,7 @@ tape('Network wrapper tests', async (t) => { versionedHashes, blobs, kzgCommitments: commitments, - kzgProof: proof, + kzgProofs: proofs, maxFeePerDataGas: 100000000n, gasLimit: 0xffffffn, to: randomBytes(20), @@ -289,7 +292,7 @@ tape('hash() and signature verification', async (t) => { chainId: 1, nonce: 1, versionedHashes: [ - hexStringToBytes('01624652859a6e98ffc1608e2af0147ca4e86e1ce27672d8d3f3c9d4ffd6ef7e'), + hexToBytes('01624652859a6e98ffc1608e2af0147ca4e86e1ce27672d8d3f3c9d4ffd6ef7e'), ], maxFeePerDataGas: 10000000n, gasLimit: 123457n, diff --git a/packages/util/package.json b/packages/util/package.json index df6cbee322..86ca7292dd 100644 --- a/packages/util/package.json +++ b/packages/util/package.json @@ -91,6 +91,14 @@ "@types/bn.js": "^5.1.0", "@types/secp256k1": "^4.0.1" }, + "peerDependencies": { + "c-kzg": "^2.0.4" + }, + "peerDependenciesMeta": { + "c-kzg": { + "optional": true + } + }, "engines": { "node": ">=14" } diff --git a/packages/tx/src/utils/blobHelpers.ts b/packages/util/src/blobHelpers.ts similarity index 93% rename from packages/tx/src/utils/blobHelpers.ts rename to packages/util/src/blobHelpers.ts index 3e5808b609..d14924cdba 100644 --- a/packages/tx/src/utils/blobHelpers.ts +++ b/packages/util/src/blobHelpers.ts @@ -1,7 +1,7 @@ import { sha256 } from 'ethereum-cryptography/sha256' import { utf8ToBytes } from 'ethereum-cryptography/utils' -import { kzg } from '../kzg/kzg' +import { kzg } from './kzg' /** * These utilities for constructing blobs are borrowed from https://github.com/Inphi/eip4844-interop.git @@ -63,6 +63,12 @@ export const blobsToCommitments = (blobs: Uint8Array[]) => { return commitments } +export const blobsToProofs = (blobs: Uint8Array[], commitments: Uint8Array[]) => { + const proofs = blobs.map((blob, ctx) => kzg.computeBlobKzgProof(blob, commitments[ctx])) + + return proofs +} + /** * Converts a vector commitment for a given data blob to its versioned hash. For 4844, this version * number will be 0x01 for KZG vector commitments but could be different if future vector commitment diff --git a/packages/util/src/bytes.ts b/packages/util/src/bytes.ts index faaec5d480..904bab1894 100644 --- a/packages/util/src/bytes.ts +++ b/packages/util/src/bytes.ts @@ -186,10 +186,6 @@ export const toBytes = function (v: ToBytesInputTypes): Uint8Array { return new Uint8Array() } - if (Buffer.isBuffer(v)) { - return Uint8Array.from(v) - } - if (Array.isArray(v) || v instanceof Uint8Array) { return Uint8Array.from(v) } diff --git a/packages/util/src/index.ts b/packages/util/src/index.ts index df57cde654..9a05428d06 100644 --- a/packages/util/src/index.ts +++ b/packages/util/src/index.ts @@ -52,6 +52,7 @@ export * from './encoding' * Export ethjs-util methods */ export * from './asyncEventEmitter' +export * from './blobHelpers' export { arrayContainsArray, fromAscii, @@ -64,4 +65,5 @@ export { stripHexPrefix, toAscii, } from './internal' +export * from './kzg' export * from './lock' diff --git a/packages/util/src/kzg.ts b/packages/util/src/kzg.ts new file mode 100644 index 0000000000..05c48fd5f9 --- /dev/null +++ b/packages/util/src/kzg.ts @@ -0,0 +1,42 @@ +/** + * Interface for an externally provided kzg library used when creating blob transactions + */ +export interface Kzg { + loadTrustedSetup(filePath: string): void + blobToKzgCommitment(blob: Uint8Array): Uint8Array + computeBlobKzgProof(blob: Uint8Array, commitment: Uint8Array): Uint8Array + verifyKzgProof( + polynomialKzg: Uint8Array, + z: Uint8Array, + y: Uint8Array, + kzgProof: Uint8Array + ): boolean + verifyBlobKzgProofBatch( + blobs: Uint8Array[], + expectedKzgCommitments: Uint8Array[], + kzgProofs: Uint8Array[] + ): boolean +} + +function kzgNotLoaded(): never { + throw Error('kzg library not loaded') +} + +// eslint-disable-next-line import/no-mutable-exports +export let kzg: Kzg = { + loadTrustedSetup: kzgNotLoaded, + blobToKzgCommitment: kzgNotLoaded, + computeBlobKzgProof: kzgNotLoaded, + verifyKzgProof: kzgNotLoaded, + verifyBlobKzgProofBatch: kzgNotLoaded, +} + +/** + * @param kzgLib a KZG implementation (defaults to c-kzg) + * @param trustedSetupPath the full path (e.g. "/home/linux/devnet4.txt") to a kzg trusted setup text file + */ +export function initKZG(kzgLib: Kzg, trustedSetupPath: string) { + kzg = kzgLib + + kzg.loadTrustedSetup(trustedSetupPath) +} diff --git a/packages/util/src/types.ts b/packages/util/src/types.ts index 144672eb3c..dd6020addb 100644 --- a/packages/util/src/types.ts +++ b/packages/util/src/types.ts @@ -37,7 +37,6 @@ export interface TransformabletoBytes { } export type NestedUint8Array = Array -export type NestedBufferArray = Array /** * Type output options